summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@ka-ata-killa.ourano.james.local>2021-03-02 12:54:03 +0000
committerroot <root@ka-ata-killa.ourano.james.local>2021-03-02 12:54:03 +0000
commit8c7ee88332652e7e79f6c1e4baacabe2183f7e8e (patch)
treea26ca60a089015822fa81ef44567927c1d8e334d
parent3d48137c00511b3f2d35511482d1a76f8d06382d (diff)
downloadclock-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--.gitignore1
-rw-r--r--app/ATTIC/gps_neo8.c (renamed from app/gps_neo8.c)20
-rw-r--r--app/Makefile33
-rw-r--r--app/abs.c121
-rw-r--r--app/adc.c137
-rw-r--r--app/cdcacm.c58
-rw-r--r--app/clockv2.ld (renamed from app/roofclock.ld)0
-rw-r--r--app/dcf77.c17
-rw-r--r--app/dfu.c19
-rw-r--r--app/dummy_kb.c26
-rw-r--r--app/events.h1
-rw-r--r--app/gps.c60
-rw-r--r--app/lwip/lwipopts.h8
-rw-r--r--app/lwip/pbuf.h179
-rw-r--r--app/lwip_glue.c42
-rw-r--r--app/main.c140
-rw-r--r--app/max7219.c348
-rw-r--r--app/msf.c21
-rw-r--r--app/ntp.c40
-rw-r--r--app/pins.h4
-rw-r--r--app/pll.c293
-rw-r--r--app/project.h8
-rw-r--r--app/prototypes.h68
-rw-r--r--app/ptp.c274
-rw-r--r--app/ref.c486
-rw-r--r--app/stats.c6
-rw-r--r--app/steth.c314
-rw-r--r--app/sysclk.c3
-rw-r--r--app/ticker.c4
-rw-r--r--app/usart.c44
-rw-r--r--app/usb.c63
-rw-r--r--boot/Makefile4
-rw-r--r--boot/bootloader.c27
-rw-r--r--boot/delay.c1
-rw-r--r--boot/dfu.c4
-rw-r--r--boot/max7219.c169
-rw-r--r--boot/prototypes.h3
-rw-r--r--boot/usb.c4
-rw-r--r--st/siderial_time.c173
-rwxr-xr-xtools/dfuse-pack.py256
40 files changed, 2604 insertions, 875 deletions
diff --git a/.gitignore b/.gitignore
index 1077c0a..142c0f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
*.orig
*.hex
*.map
+*.bin
.*.swp
almanac.c
almanac.alp
diff --git a/app/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
diff --git a/app/abs.c b/app/abs.c
index 7a6b5d5..636b721 100644
--- a/app/abs.c
+++ b/app/abs.c
@@ -1,124 +1,3 @@
#include "project.h"
-static uint32_t high_tick;
-
-#if HW_CLOCK_LEN == 32
-
-#define QUARTER (1UL << 29)
-#define HALF (1UL << 30)
-#define THREE_QUARTERS (HALF+QUARTER)
-#define ONE (~(uint32_t)0)
-
-
-uint64_t abs_extend (uint32_t now)
-{
- static int m;
- uint64_t ret;
-
-
- if (!m) {
- ret = high_tick;
- ret <<= 32;
- ret |= now;
-
-
- if ((now > THREE_QUARTERS) && (now <= ONE)) {
- high_tick++;
- m = 1;
- }
-
- } else {
- if (now < HALF) {
- ret = high_tick;
- ret <<= 32;
- ret |= now;
- } else {
- ret = high_tick - 1;
- ret <<= 32;
- ret |= now;
- }
-
- if ((now > QUARTER) && (now < HALF))
- m = 0;
- }
-
- return ret;
-}
-#elif HW_CLOCK_LEN == 31
-
-#define QUARTER (1UL << 28)
-#define HALF (1UL << 29)
-#define THREE_QUARTERS (HALF+QUARTER)
-#define ONE (0x7fffffff)
-
-
-uint64_t abs_extend (uint32_t now)
-{
- static int m;
- uint64_t ret;
-
-
- if (!m) {
- ret = high_tick;
- ret <<= 31;
- ret |= now;
-
- if ((now > THREE_QUARTERS) && (now <= ONE)) {
- high_tick++;
- m = 1;
- }
-
- } else {
- if (now < HALF) {
- ret = high_tick;
- ret <<= 31;
- ret |= now;
- } else {
- ret = high_tick - 1;
- ret <<= 31;
- ret |= now;
- }
-
- if ((now > QUARTER) && (now < HALF))
- m = 0;
- }
-
- return ret;
-}
-
-
-
-
-
-#else
-#error unknown hardware clock length
-#endif
-
-
-
-
-
-
-
-
-void abs_meh (void)
-{
- printf ("HT %d\n", (int) high_tick);
-}
-
-
-
-
-
-uint64_t abs_get (void)
-{
- uint32_t now = HW_CLOCK_REG;
- return abs_extend (now);
-}
-
-
-void abs_slow_tick()
-{
- abs_get();
-}
diff --git a/app/adc.c b/app/adc.c
new file mode 100644
index 0000000..821bac9
--- /dev/null
+++ b/app/adc.c
@@ -0,0 +1,137 @@
+#include "project.h"
+
+
+#define POT GPIO3
+#define POT_PORT GPIOC
+
+#define POT_CHANNEL ADC_CHANNEL13
+#define VREF_CHANNEL ADC_CHANNEL17
+
+#define ADC_TIMEOUT 1000
+
+static enum {
+ WAIT_VREF,
+ WAIT_POT
+} state = WAIT_VREF;
+
+
+static uint32_t adc_stamp;
+static uint16_t pot, vref;
+
+uint8_t pot_brightness = 0x8;
+
+
+static void start_conversion (uint8_t ch)
+{
+ adc_stamp = ticks;
+ adc_set_regular_sequence (ADC1, 1, &ch);
+ adc_start_conversion_regular (ADC1);
+}
+
+static void calculate_and_set_brightness (void)
+{
+ static uint32_t spot, svref;
+ uint32_t v;
+
+ /* dumb IIR with 16x gain */
+ spot *= 15;
+ spot >>= 4;
+ spot += pot ;
+
+ svref *= 15;
+ svref >>= 4;
+ svref += vref ;
+
+
+ if (svref > 65535) svref = 65535;
+
+ if (spot > 65535) spot = 65535;
+
+ v = spot << 16;
+ v /= svref;
+ v <<= 8;
+ v /= 12014; // vref is 1.2v FSD is 3.3v, 15 brightness levels so (65536 * (3.3/1.2) /15 )
+
+ v >>= 8;
+
+
+ if (v > 15) v = 15;
+
+ pot_brightness = v;
+}
+
+
+void adc_dispatch (void)
+{
+ uint32_t now = ticks;
+ uint32_t ago;
+
+ ago = now - adc_stamp;
+
+ if (ago > ADC_TIMEOUT) {
+ adc_off (ADC1);
+ adc_power_on (ADC1);
+ state = WAIT_VREF;
+ start_conversion (VREF_CHANNEL);
+ return;
+ }
+
+ if (!adc_eoc (ADC1))
+ return;
+
+ switch (state) {
+ case WAIT_VREF:
+ vref = adc_read_regular (ADC1);
+ start_conversion (POT_CHANNEL);
+ state = WAIT_POT;
+ break;
+
+ case WAIT_POT:
+ pot = adc_read_regular (ADC1);
+ start_conversion (VREF_CHANNEL);
+ calculate_and_set_brightness();
+
+ /* fall through */
+ default:
+ state = WAIT_VREF;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void adc_init (void)
+{
+ rcc_periph_clock_enable (RCC_ADC1);
+
+ MAP_ANALOG_INPUT (POT);
+
+ adc_off (ADC1);
+ adc_disable_scan_mode (ADC1);
+ adc_enable_temperature_sensor();
+
+ adc_set_single_conversion_mode (ADC1);
+ adc_enable_temperature_sensor(); /*Enables reference*/
+ adc_set_sample_time (ADC1, POT_CHANNEL, ADC_SMPR_SMP_480CYC);
+ adc_set_sample_time (ADC1, VREF_CHANNEL, ADC_SMPR_SMP_480CYC);
+ adc_enable_external_trigger_regular (ADC1, 0, ADC_CR2_EXTEN_DISABLED);
+ adc_set_right_aligned (ADC1);
+ adc_eoc_after_group (ADC1);
+
+ adc_power_on (ADC1);
+ adc_enable_temperature_sensor(); /*Enables reference*/
+
+ state = WAIT_VREF;
+ start_conversion (VREF_CHANNEL);
+}
+
diff --git a/app/cdcacm.c b/app/cdcacm.c
index 213592e..af45ac6 100644
--- a/app/cdcacm.c
+++ b/app/cdcacm.c
@@ -11,11 +11,15 @@ static uint8_t cdcacm_tx_ring_buf[BUFFER_SIZE];
static int cdcacm_ready = 0;
+#define COMM_EP 0x83
+#define DATA_IN 0x01
+#define DATA_OUT 0x82
+
static const struct usb_endpoint_descriptor comm_endp[] = {
{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 0x83,
+ .bEndpointAddress = COMM_EP,
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
.wMaxPacketSize = 16,
.bInterval = 255,
@@ -26,7 +30,7 @@ static const struct usb_endpoint_descriptor data_endp[] = {
{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 0x01,
+ .bEndpointAddress = DATA_IN,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = 64,
.bInterval = 1,
@@ -34,7 +38,7 @@ static const struct usb_endpoint_descriptor data_endp[] = {
{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 0x82,
+ .bEndpointAddress = DATA_OUT,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = 64,
.bInterval = 1,
@@ -59,7 +63,7 @@ static const struct {
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
.bmCapabilities = 0,
- .bDataInterface = 1,
+ .bDataInterface = 3,
},
.acm = {
.bFunctionLength = sizeof (struct usb_cdc_acm_descriptor),
@@ -71,15 +75,15 @@ static const struct {
.bFunctionLength = sizeof (struct usb_cdc_union_descriptor),
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_UNION,
- .bControlInterface = 0,
- .bSubordinateInterface0 = 1,
+ .bControlInterface = 2,
+ .bSubordinateInterface0 = 3,
}
};
const struct usb_interface_descriptor comm_iface = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
+ .bInterfaceNumber = 2,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_CDC,
@@ -94,7 +98,7 @@ const struct usb_interface_descriptor comm_iface = {
const struct usb_interface_descriptor data_iface = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 1,
+ .bInterfaceNumber = 3,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_DATA,
@@ -105,21 +109,29 @@ const struct usb_interface_descriptor data_iface = {
};
+const struct usb_iface_assoc_descriptor cdc_iface_assoc = {
+ .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 2,
+ .bInterfaceCount = 2,
+ .bFunctionClass = USB_CLASS_CDC,
+ .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
+ .bFunctionProtocol = USB_CDC_PROTOCOL_AT,
+ .iFunction = 6,
+};
+
-static int cdcacm_control_request (usbd_device *usbd_dev,
- struct usb_setup_data *req,
- uint8_t **buf,
- uint16_t *len,
- usbd_control_complete_callback *complete)
+int cdcacm_control_request (usbd_device *usbd_dev,
+ struct usb_setup_data *req,
+ uint8_t **buf,
+ uint16_t *len,
+ usbd_control_complete_callback *complete)
{
(void) complete;
(void) buf;
(void) usbd_dev;
- if (dfu_control_request (usbd_dev, req, buf, len, complete))
- return 1;
-
switch (req->bRequest) {
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
@@ -145,7 +157,7 @@ static int cdcacm_control_request (usbd_device *usbd_dev,
void cdcacm_tick (void)
{
- unsigned ep = 0x82;
+ unsigned ep = DATA_OUT;
uint8_t buf[16];
uint8_t *ptr = buf;
size_t n = 0;
@@ -184,7 +196,7 @@ static void cdcacm_data_rx_cb (usbd_device *usbd_dev, uint8_t ep)
{
(void) ep;
uint8_t buf[64];
- int len = usbd_ep_read_packet (usbd_dev, 0x01, buf, 64);
+ int len = usbd_ep_read_packet (usbd_dev, DATA_IN, buf, 64);
if (len)
ring_write (&cdcacm_rx_ring, buf, len, 0);
@@ -193,14 +205,10 @@ static void cdcacm_data_rx_cb (usbd_device *usbd_dev, uint8_t ep)
void cdcacm_set_config (usbd_device *usbd_dev, uint16_t wValue)
{
(void) wValue;
- usbd_ep_setup (usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
- usbd_ep_setup (usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
- usbd_ep_setup (usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
- usbd_register_control_callback (usbd_dev,
- USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
- USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
- cdcacm_control_request);
+ usbd_ep_setup (usbd_dev, DATA_IN, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
+ usbd_ep_setup (usbd_dev, DATA_OUT, USB_ENDPOINT_ATTR_BULK, 64, NULL);
+ usbd_ep_setup (usbd_dev, COMM_EP, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
cdcacm_ready = 1;
}
diff --git a/app/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);
}
diff --git a/app/dfu.c b/app/dfu.c
index c505585..5aebe34 100644
--- a/app/dfu.c
+++ b/app/dfu.c
@@ -3,7 +3,7 @@
const struct usb_dfu_descriptor dfu_function = {
.bLength = sizeof (struct usb_dfu_descriptor),
.bDescriptorType = DFU_FUNCTIONAL,
- .bmAttributes = USB_DFU_CAN_DOWNLOAD,
+ .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
.wDetachTimeout = 255,
.wTransferSize = 1024,
.bcdDFUVersion = 0x011A,
@@ -12,19 +12,30 @@ const struct usb_dfu_descriptor dfu_function = {
const struct usb_interface_descriptor dfu_iface = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 2,
+ .bInterfaceNumber = 1,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = 0xFE,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 1,
.iInterface = 4,
-
.extra = &dfu_function,
.extralen = sizeof (dfu_function),
};
+const struct usb_iface_assoc_descriptor dfu_iface_assoc = {
+ .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 1,
+ .bInterfaceCount = 1,
+ .bFunctionClass = 0xfe,
+ .bFunctionSubClass = 1,
+ .bFunctionProtocol = 1,
+ .iFunction = 5,
+};
+
+
static int
dfu_detach_complete (usbd_device *usbd_dev, struct usb_setup_data *req)
{
@@ -49,6 +60,8 @@ dfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req,
(void) len;
(void) usbd_dev;
+ printf ("dfu_control_request %02x %02x\n", req->bmRequestType, req->bRequest);
+
if ((req->bmRequestType & 0x7F) != 0x21) {
return 0; /* Only accept class request. */
}
diff --git a/app/dummy_kb.c b/app/dummy_kb.c
new file mode 100644
index 0000000..a1d61c7
--- /dev/null
+++ b/app/dummy_kb.c
@@ -0,0 +1,26 @@
+#include "project.h"
+
+const struct usb_interface_descriptor dummy_kb_iface = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = 0,
+};
+
+
+const struct usb_iface_assoc_descriptor dummy_kb_iface_assoc = {
+ .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 0,
+ .bInterfaceCount = 1,
+ .bFunctionClass = 0xff,
+ .bFunctionSubClass = 0,
+ .bFunctionProtocol = 0,
+ .iFunction = 4,
+};
+
diff --git a/app/events.h b/app/events.h
index 550277d..dc257f9 100644
--- a/app/events.h
+++ b/app/events.h
@@ -2,6 +2,7 @@
#define ERING_MASK (ERING_SIZE -1)
typedef struct {
+ uint64_t ptp;
uint32_t when;
uint32_t value;
} Event;
diff --git a/app/gps.c b/app/gps.c
index 206f0c0..f905091 100644
--- a/app/gps.c
+++ b/app/gps.c
@@ -11,6 +11,14 @@
#define TIMEOUT 4000
+unsigned gps_sats_searching;
+unsigned gps_sats_inop;
+unsigned gps_sats_locked;
+unsigned gps_sats_with_e;
+int gps_initting = 1;
+
+static int chatty_gps = 1;
+
static EPOCH next_sec;
static int ubx_ack = 0;
@@ -47,6 +55,7 @@ void exti9_5_isr (void)
exti_reset_request (EXTI7);
gps_ring.events[gps_ring.tx_ptr].when = now;
+ gps_ring.events[gps_ring.tx_ptr].ptp = ptp_get();
gps_ring.events[gps_ring.tx_ptr].value = v;
gps_ring.tx_ptr = (gps_ring.tx_ptr + 1) & ERING_MASK;
@@ -61,7 +70,7 @@ void exti9_5_isr (void)
static inline int
ubx_recv_byte (uint8_t *v)
{
- return !ring_read_byte (&rx1_ring, v);
+ return !ring_read_byte (&usart1_rx_ring, v);
}
static inline void
@@ -311,8 +320,7 @@ ubx_recv_utc (uint8_t *ptr, unsigned len)
if (gps_happy > 3) {
UTC u;
EPOCH gps_time;
- uint32_t now;
- uint64_t abs;
+ uint64_t abs, ptp;
u.jday = 0;
u.year = year;
@@ -330,12 +338,12 @@ ubx_recv_utc (uint8_t *ptr, unsigned len)
next_sec = gps_time;
- now = HW_CLOCK_REG;
- abs = abs_extend (now);
+ abs = ref_get();
+ ptp = ptp_get();
gps_last_happy = make_happy (abs, 180);
- pll_set_offset (gps_time, abs);
+ pll_set_offset (gps_time, abs, ptp);
} else
printf ("!GPS %s\r\n", gps_info);
@@ -373,7 +381,7 @@ static int ubx_recv_nav_sbas (uint8_t *ptr, unsigned len)
int8_t sys;
uint8_t n;
- if (!chatty_gps) return0 ;
+ if (!chatty_gps) return 0 ;
ptr += ubx_get_u32 (ptr, &d4);
ptr += ubx_get_u8 (ptr, &prn);
@@ -411,6 +419,8 @@ static int ubx_recv_nav_svinfo (uint8_t *ptr, unsigned len)
ptr += ubx_get_u8 (ptr, &flags);
ptr += ubx_get_u16 (ptr, &d2);
+ gps_sats_searching = gps_sats_inop = gps_sats_locked = gps_sats_with_e = 0;
+
while (n--) {
ptr += ubx_get_u8 (ptr, &ch);
ptr += ubx_get_u8 (ptr, &svid);
@@ -419,6 +429,7 @@ static int ubx_recv_nav_svinfo (uint8_t *ptr, unsigned len)
ptr += ubx_get_u8 (ptr, &cno);
ptr += 7;
+
switch (quality) {
case 0:
st = "idle";
@@ -426,30 +437,44 @@ static int ubx_recv_nav_svinfo (uint8_t *ptr, unsigned len)
case 1:
st = "search";
+ gps_sats_searching++;
break;
case 2:
st = "acq";
+ gps_sats_searching++;
break;
case 3:
st = "inop";
+ gps_sats_inop++;
break;
case 4:
st = "lock";
+ gps_sats_locked++;
+
+ if (cflags & 0x04)
+ gps_sats_with_e++;
+
break;
case 5:
case 6:
case 7:
st = "good";
+ gps_sats_locked++;
+
+ if (cflags & 0x04)
+ gps_sats_with_e++;
+
break;
default:
st = "?";
}
+
printf ("GPS SVID:%3d C/N:%3d %c%c%c %s\r\n",
svid, cno,
(cflags & 0x01) ? 'U' : '-',
@@ -743,6 +768,7 @@ static void gps_pps_dispatch (void)
//char buf[80];
uint32_t now;
uint64_t abs;
+ uint64_t ptp;
int v;
//EPOCH e;
//UTC u;
@@ -751,6 +777,7 @@ static void gps_pps_dispatch (void)
v = gps_ring.events[gps_ring.rx_ptr].value;
now = gps_ring.events[gps_ring.rx_ptr].when;
+ ptp = gps_ring.events[gps_ring.rx_ptr].ptp;
if (gps_happy)
led3_set (v);
@@ -761,14 +788,16 @@ static void gps_pps_dispatch (void)
if (!v) return;
- abs = abs_extend (now);
+ abs = ref_extend (now);
- if (gps_happy > 30)
- pll_dispatch (gps_last_happy, abs, "GPS");
+ if (gps_happy > 30) {
+ chatty_gps = 0;
+ pll_dispatch (gps_last_happy, abs, ptp, "GPS");
+ }
- //e = pll_decompose (abs);
+ //e = ref_decompose (abs);
//u = time_epoch_to_utc (e);
@@ -896,7 +925,7 @@ ubx_fetch (uint8_t class, uint8_t id, void *payload, unsigned len,
{
uint8_t *ret;
- while (!ring_empty (&tx1_ring) || !ring_empty (&rx1_ring))
+ while (!ring_empty (&usart1_tx_ring) || !ring_empty (&usart1_rx_ring))
gps_dispatch();
ubx_send (class, id, payload, len);
@@ -1090,7 +1119,7 @@ gps_init (void)
usart1_drain();
- while (!ring_empty (&tx1_ring) || !ring_empty (&rx1_ring))
+ while (!ring_empty (&usart1_tx_ring) || !ring_empty (&usart1_rx_ring))
gps_dispatch();
@@ -1195,6 +1224,7 @@ gps_init (void)
// ubx_aid_ini (522202400, 1279080, 2900, 20000);
printf ("GNSS ready\r\n");
+ gps_initting = 0;
#else
ubx_set_message_rate_port1 (0x01, 0x03, 0);
ubx_set_message_rate_port1 (0x01, 0x21, 0);
@@ -1267,8 +1297,8 @@ void gps_dump_almanac (void)
int gps_bs (void)
{
uint32_t now = HW_CLOCK_REG;
- uint64_t abs = abs_extend (now);
- EPOCH e = pll_decompose (abs);
+ uint64_t abs = ref_extend (now);
+ EPOCH e = ref_decompose (abs);
UTC u = time_epoch_to_utc (e);
uint8_t buf[80], *ptr;
diff --git a/app/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);
}
diff --git a/app/main.c b/app/main.c
index d5b5ec4..da5ffb8 100644
--- a/app/main.c
+++ b/app/main.c
@@ -17,37 +17,73 @@ void exti15_10_isr (void)
-static void cmd_dispatch (void)
+static void process_key (uint8_t c)
{
- uint8_t c;
- while (!ring_read_byte (&rx2_ring, &c)) {
+ static int unlocked;
+ static unsigned unlock_sm;
+ static uint8_t unlock[] = "unlock";
+
+ if (!unlocked) {
+ if (c == unlock[unlock_sm]) {
+ unlock_sm++;
+
+ if (!unlock[unlock_sm]) {
+ unlocked++;
+ printf ("Serial now unlocked\n");
+ }
- printf ("KEY> %c\r\n", c);
+ return;
- switch (c) {
- case 'R':
- scb_reset_system();
+ } else {
+ unlock_sm = 0;
+ printf ("serial locked type unlock to unlock\r\n");
+ return;
+ }
+ }
- break;
- case 'G':
- gps_reset();
- break;
+ printf ("KEY> %c\r\n", c);
+
+
+ switch (c) {
+ case 'R':
+ scb_reset_system();
+ break;
+
+ case 'G':
+ gps_reset();
+ break;
+
+ case 'I':
+ gps_bs();
+ break;
+
+ case 'A':
+ //gps_almanac();
+ gps_dump_almanac();
+ break;
+
+ case 'D':
+ break;
- case 'I':
- gps_bs();
- break;
- case 'A':
- //gps_almanac();
- gps_dump_almanac();
- break;
- }
}
}
+static void cmd_dispatch (void)
+{
+ uint8_t c;
+
+ while (!ring_read_byte (&usart2_rx_ring, &c))
+ process_key (c);
+
+ while (!ring_read_byte (&cdcacm_rx_ring, &c))
+ process_key (c);
+
+}
+
#if 0
static void pd_port (uint32_t p)
{
@@ -271,37 +307,20 @@ static void clock_setup (void)
#define REFCLK_OUT (GPIO8)
#define REFCLK_OUT_PORT GPIOA
-#define REFCLK_IN (GPIO7)
-#define REFCLK_IN_PORT GPIOE
static void timer_setup (void)
{
MAP_INPUT (REFCLK_OUT);
- MAP_INPUT (REFCLK_IN);
MAP_AF (REFCLK_OUT, GPIO_AF0);
- MAP_AF (REFCLK_IN, GPIO_AF1);
-
#if 0
- /* Divide by 2 to trigger TIM2 */
- timer_reset (TIM1);
- timer_set_mode (TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
- timer_set_master_mode (TIM1, TIM_CR2_MMS_UPDATE);
- timer_set_period (TIM1, 1);
- timer_slave_set_filter (TIM1, TIM_SMCR_ETF_OFF);
- timer_slave_set_prescaler (TIM1, TIM_SMCR_ETPS_OFF);
- TIM1_SMCR |= TIM_SMCR_ECE;
- timer_enable_counter (TIM1);
+ /*Old scheme 10MHz -> TIM1 ETR -> TIM2 */
- timer_reset (TIM2);
- timer_set_mode (TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
- timer_slave_set_filter (TIM2, TIM_SMCR_ETF_OFF); /*no filter*/
- timer_slave_set_prescaler (TIM2, TIM_SMCR_ETPS_OFF); /*no prescaler */
- timer_slave_set_polarity (TIM2, TIM_ET_RISING); /*rising edge */
- timer_slave_set_mode (TIM2, TIM_SMCR_SMS_ECM1); /*external clock mode 1*/
- timer_slave_set_trigger (TIM2, TIM_SMCR_TS_ITR0); /*clock from timer 1*/
- timer_enable_counter (TIM2);
-#endif
+#define REFCLK_IN (GPIO7)
+#define REFCLK_IN_PORT GPIOE
+
+ MAP_INPUT (REFCLK_IN);
+ MAP_AF (REFCLK_IN, GPIO_AF1);
@@ -338,6 +357,26 @@ static void timer_setup (void)
timer_slave_set_mode (TIM2, TIM_SMCR_SMS_ECM1); /*external clock mode 1*/
timer_slave_set_trigger (TIM2, TIM_SMCR_TS_ITR0); /*clock from timer 1*/
timer_enable_counter (TIM2);
+#else
+ /* New Scheme 10MHz -> TIM2_ETR */
+
+#define REFCLK_IN (GPIO15)
+#define REFCLK_IN_PORT GPIOA
+
+ MAP_INPUT (REFCLK_IN);
+ MAP_AF (REFCLK_IN, GPIO_AF1);
+
+
+ timer_reset (TIM2);
+ timer_set_mode (TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); /* count up with clock*/
+ timer_slave_set_filter (TIM2, TIM_SMCR_ETF_OFF); /*no filter*/
+ timer_slave_set_prescaler (TIM2, TIM_SMCR_ETPS_OFF); /*no prescaler */
+ timer_slave_set_polarity (TIM2, TIM_ET_RISING); /*rising edge */
+ timer_slave_set_mode (TIM2, TIM_SMCR_SMS_ECM1); /*external clock mode 1*/
+ timer_slave_set_trigger (TIM2, TIM_SMCR_TS_ETRF); /*Trigger from ETRF input */
+ timer_enable_counter (TIM2);
+#endif
+
}
@@ -412,12 +451,14 @@ system_init (void)
ptp_clock_start();
- max7219_init (1, 8);
-
+ max7219_init (1);
+ max7219_dispatch();
gps_init();
ntp_init();
+ adc_init();
+
}
@@ -435,8 +476,8 @@ main (void)
while (1) {
uint32_t now = HW_CLOCK_REG;
- uint64_t abs = abs_extend (now);
- EPOCH e = pll_decompose (abs);
+ uint64_t abs = ref_extend (now);
+ EPOCH e = ref_decompose (abs);
time_print_epoch ("TEST: ", e);
delay_ms (100);
}
@@ -449,8 +490,8 @@ main (void)
#if 0
{
uint32_t now = HW_CLOCK_REG;
- uint64_t abs = abs_extend (now);
- EPOCH e = pll_decompose (abs);
+ uint64_t abs = ref_extend (now);
+ EPOCH e = ref_decompose (abs);
time_print_epoch ("TEST: ", e);
delay_ms (100);
}
@@ -467,6 +508,9 @@ main (void)
dispatch_lwip();
max7219_dispatch();
+ adc_dispatch();
+
+ pll_check();
}
diff --git a/app/max7219.c b/app/max7219.c
index 85e66a7..7d5858e 100644
--- a/app/max7219.c
+++ b/app/max7219.c
@@ -94,7 +94,7 @@ write_reg (uint8_t reg, uint8_t data)
static void
-write_regs (uint8_t reg, uint8_t data1, uint8_t data2, uint8_t data3)
+_write_regs (uint8_t reg, uint8_t *data)
{
while (lock());
@@ -102,134 +102,224 @@ write_regs (uint8_t reg, uint8_t data1, uint8_t data2, uint8_t data3)
set (0, 0, 0);
spip_send_8 (reg);
- spip_send_8 (data3);
+ spip_send_8 (data[2]);
spip_send_8 (reg);
- spip_send_8 (data2);
+ spip_send_8 (data[1]);
spip_send_8 (reg);
- spip_send_8 (data1);
+ spip_send_8 (data[0]);
set (0, 0, 0);
set (0, 1, 0);
unlock();
}
-static void write_triad (uint8_t reg, int d1, int d2, int d3, unsigned dm)
+static void write_regs (uint8_t reg, uint8_t d1, uint8_t d2, uint8_t d3)
{
- write_regs (reg++, (d1 % 10) | ((dm & 0x1) ? 0x80 : 0), (d2 % 10) | ((dm & 0x4) ? 0x80 : 0), (d3 % 10) | ((dm & 0x10) ? 0x80 : 0));
- write_regs (reg, (d1 / 10) | ((dm & 0x2) ? 0x80 : 0), (d2 / 10) | ((dm & 0x8) ? 0x80 : 0), (d3 / 10) | ((dm & 0x20) ? 0x80 : 0));
+ uint8_t d[3] = {d1, d2, d3};
+ _write_regs (reg, d);
}
-#if 0
-static void st_test (void)
+#define SDP 0x80
+#define SA 0x40
+#define SB 0x20
+#define SC 0x10
+#define SD 0x08
+#define SE 0x04
+#define SF 0x02
+#define SG 0x01
+
+static uint8_t hex (unsigned v)
{
+ switch (v) {
+ case 0:
+ case '0':
+ return SA | SF | SB | SE | SC | SD;
- UTC u = { 0 };
- double local_lon = 0.0;
- ST st;
- double ra;
+ case 1:
+ case '1':
+ return SB | SC;
- // LEDS: 12.13.28.00 01.01.29.05 13.27.42.05
+ case 2:
+ case '2':
+ case 'z':
+ return SA | SB | SG | SE | SD;
- u.year = 2021;
- u.month = 1;
- u.mday = 12;
- u.hour = 13;
- u.minute = 28;
+ case 3:
+ case '3':
+ return SA | SB | SG | SC | SD;
- ra = time_utc_to_ra (u);
- st = time_ra_to_st (ra + local_lon);
+ case 4:
+ case '4':
+ return SF | SG | SB | SC;
- printf ("%d:%02d:%02d\n", st.hour, st.minute, st.second);
+ case 5:
+ case '5':
+ case 's':
+ return SA | SF | SG | SC | SD;
- st = time_utc_to_lst (u, local_lon);
+ case 6:
+ case '6':
+ return SA | SF | SG | SE | SC | SD;
- printf ("%d:%02d:%02d\n", st.hour, st.minute, st.second);
+ case 7:
+ case '7':
+ return SA | SB | SC;
- for (;;);
-}
-#endif
+ case 8:
+ case '8':
+ return SA | SF | SB | SG | SE | SC | SD;
+ case 9:
+ case '9':
+ case 'g':
+ return SA | SF | SB | SG | SC | SD;
-unsigned fix_dots, fix_dots_even;
+ case 0xa:
+ case 'a':
+ return SA | SF | SB | SG | SE | SC;
-void max7219_report_fix (char fix, char fix2)
-{
- fix_dots = 0;
+ case 0xb:
+ case 'b':
+ return SF | SG | SE | SC | SD;
+ case 0xc:
+ case 'c':
+ return SG | SE | SD;
- if (fix == 'L')
- fix_dots |= 0x1;
+ case 0xd:
+ case 'd':
+ return SB | SG | SE | SC | SD;
- if (fix2 == 'D') fix_dots |= 0x4;
+ case 0xe:
+ case 'e':
+ return SA | SF | SG | SE | SD;
- if (fix == 'T') fix_dots |= 0x11;
-}
+ case 0xf:
+ case 'f':
+ return SA | SF | SG | SE;
-void max7219_report_svin (int valid, int active)
-{
- fix_dots_even = 0;
+ case 'h':
+ return SF | SG | SE | SC;
+
+ case 'i':
+ return SE;
+
+ case 'j':
+ return SB | SC | SD;
+
+ case 'k':
+ case 'x':
+ return SF | SB | SG | SE | SC;
+
+ case 'l':
+ return SF | SE | SD;
+
+ case 'm':
+ case 'n':
+ return SG | SE | SC;
+
+ case 'o':
+ return SG | SE | SC | SD;
+
+ case 'p':
+ return SA | SF | SB | SG | SE;
+
+ case 'q':
+ return SA | SF | SB | SG | SC;
+
+ case 'r':
+ return SG | SE;
+
+ case 't':
+ return SF | SG | SE | SD;
+
+ case 'u':
+ case 'w':
+ return SE | SC | SD;
+
+ case 'y':
+ return SF | SB | SG | SC | SD;
- if (active || valid) fix_dots_even |= 0x10;
+ case '-':
+ return SG;
+
+ case '.':
+ return SDP;
+
+ }
+
+ return 0;
}
-void max7219_dispatch (void)
+static void _write_triad (uint8_t reg, int *d, int *dp)
{
- uint32_t now = HW_CLOCK_REG;
- uint64_t abs = abs_extend (now);
- static unsigned m;
- EPOCH e;
- UTC u;
- UTC gu;
- ST l;
- unsigned last_dots;
+ uint8_t regs0[3] = {0x0, 0x0, 0x0};
+ uint8_t regs1[3] = {0x0, 0x0, 0x0};
+ unsigned i;
+ for (i = 0; i < 3; ++i) {
- e = pll_decompose (abs);
- u = time_epoch_to_utc (e);
- l = time_utc_to_lst (u, gps_lon);
+ if (d[i] < 0) continue;
- e.s += gps_utc_diff;
- gu = time_epoch_to_utc (e);
+ if (d[i] > 99) continue;
- last_dots = fix_dots;
+ regs0[i] = hex (d[i] % 10);
+ regs1[i] = hex (d[i] / 10);
+ }
- if (u.nanosecond < 500000000) last_dots |= fix_dots_even;
+ for (i = 0; i < 3; ++i)
+ if (dp[i]) regs0[i] |= SDP;
- write_triad (1, u.nanosecond / 10000000, l.nanosecond / 10000000, gu.second, last_dots);
- write_triad (3, u.second, l.second, gu.minute, 0x15);
- write_triad (5, u.minute, l.minute, gu.hour, 0x15);
- write_triad (7, u.hour, l.hour, gps_wday, 0x15);
+ _write_regs (reg++, regs0);
+ _write_regs (reg, regs1);
+}
- if (u.minute == m) return;
+static void write_triad (uint8_t reg, int d1, int d2, int d3, int dp1, int dp2, int dp3)
+{
+ int d[3] = {d1, d2, d3};
+ int dp[3] = {dp1, dp2, dp3};
- m = u.minute;
+ _write_triad (reg, d, dp);
+}
- printf ("LEDS: %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d lon %.6f\r\n",
- u.hour, u.minute, u.second,
- u.nanosecond / 10000000,
- l.hour,
- l.minute,
- l.second,
- l.nanosecond / 10000000,
- gps_wday,
- gu.hour,
- gu.minute,
- gu.second,
- gps_lon);
+static void write_string_over_numbers (char *str, int d1, int d2, int d3, int d4)
+{
+ unsigned reg;
+
+ uint8_t digits[9] = {
+ 0,
+ hex (d4 % 10),
+ hex (d4 / 10),
+ hex (d3 % 10) | SDP,
+ hex (d3 / 10),
+ hex (d2 % 10) | SDP,
+ hex (d2 / 10),
+ hex (d1 % 10) | SDP,
+ hex (d1 / 10)
+ };
+
+ for (reg = 8; reg && *str; reg--, str++)
+ write_regs (reg, hex (*str) | (!str[1] ? SDP : 0), digits[reg], 0);
+
+ for (; reg; reg--)
+ write_regs (reg, 0, digits[reg], 0);
+}
-}
void
-max7219_init (int on, int brightness)
+max7219_init (int on)
{
+ uint8_t d[3] = {0xf, 0xf, 0xf};
+ unsigned i;
+
MAP_OUTPUT_PP (SCK);
MAP_OUTPUT_PP (NCS);
MAP_OUTPUT_PP (MOSI);
@@ -242,17 +332,119 @@ max7219_init (int on, int brightness)
write_reg (0xc, 0x1); //Power up
write_reg (0xf, 0x0); //normal mode
- write_reg (0x9, 0xff); //BCD decode
+ write_reg (0x9, 0x0); //no decode
write_reg (0xb, 0x7); //8 digits
- write_regs (0xa, brightness, brightness, brightness);
+ write_reg (0xa, pot_brightness);
+
+ for (i = 1; i <= 8; ++i)
+ _write_regs (i, d);
+
+
} else {
write_reg (0xc, 0x0); //Power up
}
+}
+
+
+
+static int have_lock, have_dgps, have_time_lock, time_lock_enabled;
+
+void max7219_report_fix (char fix, char fix2)
+{
+
+ have_lock = 0;
+
+ if (fix == 'L')
+ have_lock = 1;
+
+ if (fix2 == 'D') have_dgps = 1;
+ else have_dgps = 0;
+
+ if (fix == 'T') {
+ have_lock = 1;
+ have_time_lock = 1;
+ }
+}
+
+void max7219_report_svin (int valid, int active)
+{
+ time_lock_enabled = 0;
+
+ if (active || valid) time_lock_enabled = 1;
}
+void max7219_dispatch (void)
+{
+ uint64_t abs = ref_get();
+ static uint8_t last_brightness = 255;
+ int wday;
+ EPOCH e;
+ UTC u;
+ UTC gu;
+ ST l;
+
+
+
+ if (last_brightness != pot_brightness) {
+ last_brightness = pot_brightness;
+ write_reg (0xa, last_brightness);
+ }
+
+ if (gps_initting)
+ write_string_over_numbers ("gps init", 0, 0, 0, 0);
+ else if (!ref_valid)
+ write_string_over_numbers ("gps acq", gps_sats_searching, gps_sats_inop, gps_sats_locked, gps_sats_with_e);
+
+ else {
+ static unsigned m;
+
+ e = ref_decompose (abs);
+ u = time_epoch_to_utc (e);
+ l = time_utc_to_lst (u, gps_lon);
+
+ if (have_lock) {
+ e.s += 86400;
+ e.s += gps_utc_diff;
+ gu = time_epoch_to_utc (e);
+ wday = gps_wday;
+ } else {
+ wday = 100;
+ gu.hour = 100;
+ gu.minute = 100;
+ gu.second = 100;
+ }
+
+ write_triad (1, u.nanosecond / 10000000, l.nanosecond / 10000000, gu.second, time_lock_enabled, have_time_lock, have_dgps);
+ write_triad (3, u.second, l.second, gu.minute, 1, 1, 1);
+ write_triad (5, u.minute, l.minute, gu.hour, 1, 1, 1);
+ write_triad (7, u.hour, l.hour, wday, 1, 1, 1);
+
+ if (u.minute == m) return;
+
+ m = u.minute;
+
+ printf ("LEDS: %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d %02d.%02d.%02d.%02d lon %.6f\r\n",
+ u.hour, u.minute, u.second,
+ u.nanosecond / 10000000,
+ l.hour,
+ l.minute,
+ l.second,
+ l.nanosecond / 10000000,
+ gps_wday,
+ gu.hour,
+ gu.minute,
+ gu.second,
+ gps_lon);
+
+ }
+
+
+}
+
+
diff --git a/app/msf.c b/app/msf.c
index ab85cfe..bf7c376 100644
--- a/app/msf.c
+++ b/app/msf.c
@@ -42,6 +42,7 @@ void exti_t_isr (void)
exti_reset_request (EXTI_T);
msf_ring.events[msf_ring.tx_ptr].when = now;
+ msf_ring.events[msf_ring.tx_ptr].ptp = ptp_get();
msf_ring.events[msf_ring.tx_ptr].value = v;
msf_ring.tx_ptr = (msf_ring.tx_ptr + 1) & ERING_MASK;
@@ -79,7 +80,7 @@ static int check_min_ident (uint8_t *i)
-static void process_bits (uint64_t abs)
+static void process_bits (uint64_t abs, uint64_t ptp)
{
UTC u;
EPOCH e;
@@ -112,7 +113,7 @@ static void process_bits (uint64_t abs)
msf_last_happy = make_happy (abs, 0);
- pll_set_offset (e, abs);
+ pll_set_offset (e, abs, ptp);
dump_bits ("msfa", bitsa);
dump_bits ("msfb", bitsb);
@@ -126,14 +127,14 @@ static void process_bits (uint64_t abs)
}
-static void report_bits (uint64_t abs, int second, int a, int b)
+static void report_bits (uint64_t abs, uint64_t ptp, int second, int a, int b)
{
if ((!second) || (second > 59)) return;
bitsa[second] = a;
bitsb[second] = b;
- if (second == 59) process_bits (abs);
+ if (second == 59) process_bits (abs, ptp);
}
@@ -146,6 +147,7 @@ void msf_dispatch (void)
int is_s = 0;
uint32_t now;
+ uint64_t ptp;
int v;
@@ -153,6 +155,7 @@ void msf_dispatch (void)
v = msf_ring.events[msf_ring.rx_ptr].value;
now = msf_ring.events[msf_ring.rx_ptr].when;
+ ptp = msf_ring.events[msf_ring.rx_ptr].ptp;
led1_set (v);
@@ -160,8 +163,8 @@ void msf_dispatch (void)
#if 0
{
- abs = abs_extend (now);
- EPOCH e = pll_decompose (abs);
+ abs = ref_extend (now);
+ EPOCH e = ref_decompose (abs);
UTC u = time_epoch_to_utc (e);
printf (" MSF %d %02d:%02d.%06d\r\n", v, u.minute, u.second, (int) (u.nanosecond / 1000));
@@ -198,16 +201,16 @@ void msf_dispatch (void)
if (is_s) {
- abs = abs_extend (now);
+ abs = ref_extend (now);
msf_last_second = abs;
- pll_dispatch (msf_last_happy, abs, "MSF");
+ pll_dispatch (msf_last_happy, abs, ptp, "MSF");
sprintf (msf_info, "m=%d s=%02d b=%d%d", had_m, second, bita, bitb);
if (had_m) {
- report_bits (abs, second, bita, bitb);
+ report_bits (abs, ptp, second, bita, bitb);
second++;
}
diff --git a/app/ntp.c b/app/ntp.c
index 0bdda4d..2b9e6f3 100644
--- a/app/ntp.c
+++ b/app/ntp.c
@@ -30,7 +30,7 @@ typedef struct {
#if 0
packet (uint8_t *_p)
{
- EPOCH reftime = pll_decompose (pll_last_update);
+ EPOCH reftime = ref_decompose (pll_last_update);
ntp_packet_t rx = (uint8_t *)_p;
ntp_packet_t tx;
@@ -52,10 +52,26 @@ packet (uint8_t *_p)
}
#endif
-static uint64_t ntp_ts (uint64_t v)
+static uint64_t ntp_ts_ref (uint64_t v)
{
uint64_t ret;
- EPOCH e = pll_decompose (v);
+ EPOCH e = ref_decompose (v);
+
+ ret = e.ns;
+ ret <<= 32;
+ ret = ret / 1000000000;
+ ret = htonl (ret);
+ ret <<= 32;
+ ret |= htonl (2208988800UL + e.s);
+
+ return ret;
+}
+
+
+static uint64_t ntp_ts_ptp (uint64_t v)
+{
+ uint64_t ret;
+ EPOCH e = ptp_decompose (v);
ret = e.ns;
ret <<= 32;
@@ -69,7 +85,7 @@ static uint64_t ntp_ts (uint64_t v)
static void ntp_rx (void *arg, struct udp_pcb *s, struct pbuf *p, struct ip_addr *src_addr, u16_t port)
{
- uint32_t now = HW_CLOCK_REG;
+ uint64_t ref = ref_get_irq();
struct ip_addr dst_addr = *src_addr;
ntp_packet_t pkt;
@@ -78,7 +94,7 @@ static void ntp_rx (void *arg, struct udp_pcb *s, struct pbuf *p, struct ip_addr
if (p->len < sizeof (ntp_packet_t)) break;
- if (!pll_valid) break;
+ if (!ref_valid) break;
if (!time_known) break;
@@ -99,13 +115,19 @@ static void ntp_rx (void *arg, struct udp_pcb *s, struct pbuf *p, struct ip_addr
pkt.reference_id = htonl (0x47505300);
pkt.origin_ts = pkt.transmit_ts;
- pkt.receive_ts = ntp_ts (abs_extend (now));
- pkt.reference_ts = ntp_ts (pll_last_update);
+#if 0
+ pkt.receive_ts = ntp_ts_ref (ref);
+#else
+ pkt.receive_ts = ntp_ts_ptp (p->ptp_timestamp);
+#endif
- now = HW_CLOCK_REG;
- pkt.transmit_ts = ntp_ts (abs_extend (now));
+ pkt.receive_ts = ntp_ts_ref (ref);
+ pkt.reference_ts = ntp_ts_ref (ref_last_update);
memcpy (p->payload, &pkt, sizeof (ntp_packet_t));
+ compiler_mb();
+ ref = ref_get_irq();
+ pkt.transmit_ts = ntp_ts_ref (ref);
udp_sendto (s, p, &dst_addr, port);
} while (0);
diff --git a/app/pins.h b/app/pins.h
index 723ca82..9892cf1 100644
--- a/app/pins.h
+++ b/app/pins.h
@@ -49,6 +49,10 @@
gpio_mode_setup( a ## _PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, a ); \
} while (0)
+#define MAP_ANALOG_INPUT(a) do { \
+ gpio_mode_setup( a ## _PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, a ); \
+ } while (0)
+
#define CLEAR(a) gpio_clear( a ## _PORT, a)
#define SET(a) gpio_set( a ## _PORT, a)
diff --git a/app/pll.c b/app/pll.c
index 19681d8..d2d1495 100644
--- a/app/pll.c
+++ b/app/pll.c
@@ -1,293 +1,80 @@
#include "project.h"
-
-#define JUMP_THRESH 0.1
-#define JUMP_TICKS 30
-#define FEEDBACK 0.0001
#define WARM_UP 30
-
-static int64_t offset;
-static int64_t phase;
-int64_t pll_freq = HW_CLOCK_HZ;
-
-static int out_of_lock = JUMP_TICKS + 1;
-
-uint64_t pll_last_update;
-int pll_valid = 0;
-
-int pll_ready = 0;
-
-
-# if 0
-#define PLL_BW 0.01
-#define PLL_DAMP 0.707
-#define PLL_GAIN 0.001
-
-#define F_T1 ((PLL_GAIN)/((PLL_BW)*(PLL_BW)))
-#define F_T2 ((2*(PLL_DAMP))/(PLL_BW))
-
-
-#define F_B0 (((4*(PLL_GAIN))/(F_T1))*(1.0+((F_T2)/(2.0))))
-#define F_B1 ((8*(PLL_GAIN))/(F_T1))
-#define F_B2 (((4*(PLL_GAIN))/(F_T1))*(1.0-((F_T2)/(2.0))))
-
-#define F_A0 (1.0)
-#define F_A1 (-2.0)
-#define F_A2 (1.0)
-
-void pll_dump_filter (void)
-{
- printf ("%g %g %g\n", F_A0, F_A1, F_A2);
- printf ("%g %g %g\n", F_B0, F_B1, F_B2);
-}
-
-
-
-static double filter (double in)
-{
- static double v[3];
- double ret;
-
- v[2] = v[1];
- v[1] = v[0];
- v[0] = in - (v[1] * F_A1) - (v[2] * F_A2);
-
- return (v[0] * F_B0) + (v[1] * F_B1) + (v[2] * F_B2);
-
-}
-#endif
-
-
-#define PLL_ALPHA (0.005)
-#define PLL_BETA (0.5*PLL_ALPHA*PLL_ALPHA)
-
-
-
-
-
-
-
-void pll_meh (void)
-{
- printf (" %"PRId64" %"PRId64" %" PRId64 "\r\n",
- pll_freq, offset, phase);
-
-}
-
-
-static void modify_pll_freq (uint64_t now, int d)
-{
- int64_t pd1, pd2, te;
-
- pd1 = now - phase;
- te = pd1 / pll_freq;
- pd1 %= pll_freq;
-
- if (pd1 > (pll_freq >> 1)) {
- te++;
- pd1 = pd1 - pll_freq;
- }
-
-
- if (d > 0)
- pll_freq += d;
- else
- pll_freq -= -d;
-
-
- pd2 = pd1 + (te * pll_freq);
-
- phase = now - pd2;
-}
-
-uint64_t make_happy (uint64_t abs, int64_t shift)
+void pll_set_offset (EPOCH epoch, uint64_t abs, uint64_t ptp)
{
- shift *= HW_CLOCK_HZ;
-
- if (shift < 0) {
- shift = -shift;
-
- if (abs < (uint64_t) shift) return 0;
- else
- return abs - shift;
- }
-
- return abs + shift;
-
+ ref_set_offset (epoch, abs);
+ ptp_set_offset (epoch, ptp);
}
-void pll_dispatch (uint64_t happy, uint64_t edge, const char *src)
+void pll_dispatch (uint64_t happy, uint64_t edge, uint64_t ptp_edge, const char *src)
{
- double f, g;
- int64_t pd;
-
-
-
-#if 0
- {
- int h1, h2, h3, h4;
- EPOCH e;
- UTC u;
- char s1[80];
- char s2[80];
- char s3[80];
- char s4[80];
-
-
- e = pll_decompose (happy);
- u = time_epoch_to_utc (e);
- utc_to_str (s1, u);
- h1 = e.s;
+ // int64_t delta_f;
- e = pll_decompose (gps_last_happy);
- u = time_epoch_to_utc (e);
- utc_to_str (s2, u);
- h2 = e.s;
-
- e = pll_decompose (dcf77_last_happy);
- u = time_epoch_to_utc (e);
- utc_to_str (s3, u);
- h3 = e.s;
-
- e = pll_decompose (msf_last_happy);
- u = time_epoch_to_utc (e);
- utc_to_str (s4, u);
- h4 = e.s;
-
- printf ("H %d %d %d %d\r\n", h1 - h2, h2 - h2, h3 - h2, h4 - h2);
- // printf ("H %s %s %s %s\r\n",s1,s2,s3,s4);
- }
-#endif
-
-
- if ((!gps_last_happy) && (!dcf77_last_happy) && (!msf_last_happy)) return;
-
- if (happy < gps_last_happy) return;
-
- if (happy < dcf77_last_happy) return;
-
- if (happy < msf_last_happy) return;
-
- if (!pll_ready && (edge < ((uint64_t) WARM_UP * (uint64_t) HW_CLOCK_HZ)))
+ if (((!gps_last_happy) && (!dcf77_last_happy) && (!msf_last_happy)) ||
+ (happy < gps_last_happy) ||
+ (happy < dcf77_last_happy) ||
+ (happy < msf_last_happy) ||
+ (edge < ((uint64_t) WARM_UP * (uint64_t) HW_CLOCK_HZ)))
return;
led_blink (100);
-#if 0
- printf ("EDGE %08x%08x\r\n",
- (unsigned) (edge >> 32),
- (unsigned) (edge & 0xffffffff));
-#endif
-
- {
- int diff, hf;
-
- pd = edge - phase;
- pd %= pll_freq;
-
- hf = (int) (pll_freq >> 1);
-
- diff = (int) pd;
-
- if (diff > hf)
- diff = diff - (int) pll_freq;
-
-
- f = (double) diff;
- g = f / (double) pll_freq;
- }
-
- if ((g > (JUMP_THRESH)) || (g < - (JUMP_THRESH)))
- out_of_lock++;
- else if (out_of_lock <= JUMP_TICKS)
- out_of_lock = 0;
-
- printf ("PLL pd %.3f %.1f pll_freq %d phase %d %s\r\n", (float) g, (float)f, (int) pll_freq, (int) phase, src);
-
- if ((out_of_lock > JUMP_TICKS) || !pll_ready) {
- phase += pd;
- out_of_lock = 0;
- printf ("PLL - jumping\r\n");
- pll_freq = HW_CLOCK_HZ;
- pll_ready = 1;
- } else {
-
- phase += (int) (f * PLL_BETA);
- modify_pll_freq (edge, (int) (f * PLL_ALPHA));
-
- }
-
- pll_last_update = edge;
+ ref_dispatch (edge, src);
+ ptp_dispatch (ptp_edge, src);
}
-
-
-void pll_set_offset (EPOCH epoch, uint64_t abs)
+void pll_check (void)
{
- int64_t new_offset;
- int diff;
+ uint64_t ptp = ptp_get();
+ uint64_t ref = ref_get();
+ EPOCH re, pe;
+ UTC ru, pu;
+ static unsigned m;
- /* Find nearest second to abs*/
- abs += pll_freq >> 2;
- abs -= phase;
- abs /= pll_freq;
- new_offset = epoch.s - abs;
+ re = ref_decompose (ref);
+ ru = time_epoch_to_utc (re);
- if (new_offset != offset) {
- diff = (int) (new_offset - offset);
+ if (m == ru.minute) return;
- printf ("PLL wallclock offset moved by %d\r\n", diff);
- offset = new_offset;
- }
+ m = ru.minute;
- pll_valid = 1;
- time_known = 1;
-}
+ pe = ptp_decompose (ptp);
+ pu = time_epoch_to_utc (pe);
-EPOCH _pll_decompose (uint64_t abs)
-{
- EPOCH ret;
- ret.s = abs / pll_freq;
- abs -= pll_freq * ret.s;
+ printf ("PLL checks: R %04d-%02d-%02d %02d:%02d:%02d.%09d P %04d-%02d-%02d %02d:%02d:%02d.%09d\r\n",
+ ru.year,
+ ru.month + 1,
+ ru.mday,
+ ru.hour,
+ ru.minute,
+ ru.second,
+ ru.nanosecond,
+ pu.year,
+ pu.month + 1,
+ pu.mday,
+ pu.hour,
+ pu.minute,
+ pu.second,
+ pu.nanosecond);
- ret.s += offset;
- abs *= (uint64_t) 1000000000;
- abs = abs / pll_freq;
- ret.ns = abs;
- return ret;
-}
-EPOCH pll_decompose_diff (int64_t diff)
-{
- EPOCH ret;
- if (diff >= 0)
- return _pll_decompose (diff);
- ret = _pll_decompose (-diff);
- ret.s = -ret.s;
- ret.ns = -ret.ns;
-
- return ret;
-}
-EPOCH pll_decompose (uint64_t abs)
-{
+}
- abs -= phase;
- return _pll_decompose (abs);
-}
diff --git a/app/project.h b/app/project.h
index ca623de..fcf16ce 100644
--- a/app/project.h
+++ b/app/project.h
@@ -34,6 +34,7 @@
#include <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
diff --git a/app/usb.c b/app/usb.c
index 053f126..ea432ef 100644
--- a/app/usb.c
+++ b/app/usb.c
@@ -13,12 +13,12 @@ static const struct usb_device_descriptor dev = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = 0x0200,
- .bDeviceClass = USB_CLASS_CDC,
- .bDeviceSubClass = 0,
- .bDeviceProtocol = 0,
+ .bDeviceClass = 0xef,
+ .bDeviceSubClass = 0x02,
+ .bDeviceProtocol = 0x01,
.bMaxPacketSize0 = 64,
- .idVendor = ID_VENDOR,
- .idProduct = ID_PRODUCT,
+ .idVendor = 0x0483,
+ .idProduct = 0xff03,
.bcdDevice = 0x0200,
.iManufacturer = 1,
.iProduct = 2,
@@ -30,15 +30,22 @@ static const struct usb_device_descriptor dev = {
static const struct usb_interface ifaces[] = {
{
.num_altsetting = 1,
- .altsetting = &comm_iface,
+ .altsetting = &dummy_kb_iface,
+ .iface_assoc = &dummy_kb_iface_assoc,
},
{
.num_altsetting = 1,
- .altsetting = &data_iface,
+ .altsetting = &dfu_iface,
+ .iface_assoc = &dfu_iface_assoc,
},
{
.num_altsetting = 1,
- .altsetting = &dfu_iface,
+ .altsetting = &comm_iface,
+ .iface_assoc = &cdc_iface_assoc,
+ },
+ {
+ .num_altsetting = 1,
+ .altsetting = &data_iface,
},
};
@@ -46,7 +53,7 @@ static const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE,
.bDescriptorType = USB_DT_CONFIGURATION,
.wTotalLength = 0,
- .bNumInterfaces = 3,
+ .bNumInterfaces = 4,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0x80,
@@ -55,10 +62,12 @@ static const struct usb_config_descriptor config = {
};
static const char *usb_strings[] = {
- VENDOR_NAME,
- PRODUCT_NAME,
- SERIAL_NUMBER,
- "DFU",
+ VENDOR_NAME, /*1*/
+ PRODUCT_NAME, /*2*/
+ SERIAL_NUMBER, /*3*/
+ "dummy device", /*4*/
+ "Dfu iface", /*5*/
+ "Clock iface", /*6*/
};
void otg_fs_isr (void)
@@ -67,6 +76,30 @@ void otg_fs_isr (void)
}
+static int control_request (usbd_device *usbd_dev,
+ struct usb_setup_data *req,
+ uint8_t **buf,
+ uint16_t *len,
+ usbd_control_complete_callback *complete)
+{
+ if (dfu_control_request (usbd_dev, req, buf, len, complete))
+ return 1;
+
+ return cdcacm_control_request (usbd_dev, req, buf, len, complete);
+}
+
+static void set_config (usbd_device *usbd_dev, uint16_t wValue)
+{
+
+ cdcacm_set_config (usbd_dev, wValue);
+
+ usbd_register_control_callback (usbd_dev,
+ USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
+ USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
+ control_request);
+
+}
+
void usb_init (void)
@@ -79,7 +112,7 @@ void usb_init (void)
&dev,
&config,
usb_strings,
- 4,
+ 6,
usbd_control_buffer,
sizeof (usbd_control_buffer));
@@ -89,7 +122,7 @@ void usb_init (void)
OTG_FS_GCCFG &= ~OTG_GCCFG_VBUSASEN;
OTG_FS_GCCFG &= ~OTG_GCCFG_VBUSBSEN;
- usbd_register_set_config_callback (usb_device, cdcacm_set_config);
+ usbd_register_set_config_callback (usb_device, set_config);
nvic_enable_irq (NVIC_OTG_FS_IRQ);
diff --git a/boot/Makefile b/boot/Makefile
index e744d9a..b4d340c 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -21,6 +21,8 @@
CSRCS=bootloader.c usb.c dfu.c delay.c usart.c max7219.c
PROG = bootloader
+HOST=tick
+
CPROTO=cproto
V=1
BINARY = ${PROG}
@@ -44,6 +46,8 @@ protos: ${CSRCS}
${CPROTO} -E "${CPP} $(CPPFLAGS)" -e -v ${CSRCS} > prototypes.h.tmp
/bin/mv -f prototypes.h.tmp prototypes.h
+fl: ${PROG}.hex
+ ssh ${HOST} flash_stm32 < ${PROG}.hex
tidy:
astyle -A3 -s2 --attach-extern-c -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS}
diff --git a/boot/bootloader.c b/boot/bootloader.c
index 27b6b98..a5932f0 100644
--- a/boot/bootloader.c
+++ b/boot/bootloader.c
@@ -20,7 +20,7 @@
#include "project.h"
-#define BOOTLOADER_BUTTON GPIO15
+#define BOOTLOADER_BUTTON GPIO12
#define BOOTLOADER_BUTTON_PORT GPIOE
@@ -92,12 +92,22 @@ int main (void)
{
rcc_periph_clock_enable (RCC_GPIOE);
+ rcc_periph_clock_enable (RCC_GPIOB);
+ rcc_periph_clock_enable (RCC_GPIOG);
MAP_INPUT_PU (BOOTLOADER_BUTTON);
+ if ((dfu_flag != 0xfee1dead) && (GET (BOOTLOADER_BUTTON))) {
+
- if ((dfu_flag != 0xfee1dead) && (GET(BOOTLOADER_BUTTON))) {
/* Boot the application if it's valid. */
if ((* (volatile uint32_t *)APP_ADDRESS & 0x2FFE0000) == 0x20020000) {
+
+ max7219 ("boot");
+
+ rcc_periph_clock_disable (RCC_GPIOE);
+ rcc_periph_clock_disable (RCC_GPIOB);
+ rcc_periph_clock_disable (RCC_GPIOG);
+
/* Set vector table base address. */
SCB_VTOR = APP_ADDRESS & 0xFFFF;
/* Initialise master stack pointer. */
@@ -106,17 +116,15 @@ int main (void)
"g" (* (volatile uint32_t *)APP_ADDRESS),
"r" (* (uint32_t *) (APP_ADDRESS + 4))
: "memory");
- }
- }
-
-
+ } else
+ max7219 ("nofw dfu");
+ } else
+ max7219 ("dfu");
dfu_flag = 0;
rcc_periph_clock_enable (RCC_SYSCFG);
- rcc_periph_clock_enable (RCC_GPIOB);
- rcc_periph_clock_enable (RCC_GPIOG);
rcc_clock_setup_hsi_3v3 (&hsi_16mhz_3v3_48);
@@ -126,10 +134,9 @@ int main (void)
RCC_AHB2RSTR &= ~RCC_AHB2RSTR_OTGFSRST;
RCC_AHB1RSTR &= ~RCC_AHB1RSTR_ETHMACRST;
- max7219_init();
usart_init();
- usart2_xmit_str("\r\nDFU Bootloader\r\n");
+ usart2_xmit_str ("\r\nDFU Bootloader\r\n");
delay_ms (100);
usart_init();
usart2_xmit_str ("Ready\r\n");
diff --git a/boot/delay.c b/boot/delay.c
index 132081a..d30b6ca 100644
--- a/boot/delay.c
+++ b/boot/delay.c
@@ -36,6 +36,7 @@ delay_ms (uint32_t d)
delay_ms_count = d;
while (delay_ms_count);
+
ticker_off();
}
diff --git a/boot/dfu.c b/boot/dfu.c
index f931a6e..4054520 100644
--- a/boot/dfu.c
+++ b/boot/dfu.c
@@ -36,7 +36,7 @@ static struct {
const struct usb_dfu_descriptor dfu_function = {
.bLength = sizeof (struct usb_dfu_descriptor),
.bDescriptorType = DFU_FUNCTIONAL,
- .bmAttributes = USB_DFU_CAN_DOWNLOAD,
+ .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
.wDetachTimeout = 255,
.wTransferSize = 1024,
.bcdDFUVersion = 0x011A,
@@ -115,6 +115,8 @@ static int usbdfu_getstatus_complete (usbd_device *usbd_dev, struct usb_setup_da
uint32_t *dat = (uint32_t *) (prog.buf + i);
flash_program_word (baseaddr + i, *dat);
}
+
+ max7219_report_addr (baseaddr);
}
flash_lock();
diff --git a/boot/max7219.c b/boot/max7219.c
index 3e06562..7a374eb 100644
--- a/boot/max7219.c
+++ b/boot/max7219.c
@@ -91,32 +91,173 @@ write_regs (uint8_t reg, uint8_t data1, uint8_t data2, uint8_t data3)
set (0, 1, 0);
}
+#define SDP 0x80
+#define SA 0x40
+#define SB 0x20
+#define SC 0x10
+#define SD 0x08
+#define SE 0x04
+#define SF 0x02
+#define SG 0x01
+
+static uint8_t hex (unsigned v)
+{
+ switch (v) {
+ case 0:
+ case '0':
+ return SA | SF | SB | SE | SC | SD;
+
+ case 1:
+ case '1':
+ return SB | SC;
+
+ case 2:
+ case '2':
+ case 'z':
+ return SA | SB | SG | SE | SD;
+
+ case 3:
+ case '3':
+ return SA | SB | SG | SC | SD;
+
+ case 4:
+ case '4':
+ return SF | SG | SB | SC;
+
+ case 5:
+ case '5':
+ case 's':
+ return SA | SF | SG | SC | SD;
+
+ case 6:
+ case '6':
+ return SA | SF | SG | SE | SC | SD;
+
+ case 7:
+ case '7':
+ return SA | SB | SC;
+
+ case 8:
+ case '8':
+ return SA | SF | SB | SG | SE | SC | SD;
+
+ case 9:
+ case '9':
+ case 'g':
+ return SA | SF | SB | SG | SC | SD;
+
+ case 0xa:
+ case 'a':
+ return SA | SF | SB | SG | SE | SC;
+
+ case 0xb:
+ case 'b':
+ return SF | SG | SE | SC | SD;
+
+ case 0xc:
+ case 'c':
+ return SG | SE | SD;
+
+ case 0xd:
+ case 'd':
+ return SB | SG | SE | SC | SD;
+
+ case 0xe:
+ case 'e':
+ return SA | SF | SG | SE | SD;
+
+ case 0xf:
+ case 'f':
+ return SA | SF | SG | SE;
+
+ case 'h':
+ return SF | SG | SE | SC;
+
+ case 'i':
+ return SE;
+
+ case 'j':
+ return SB | SC | SD;
+
+ case 'k':
+ case 'x':
+ return SF | SB | SG | SE | SC;
+
+ case 'l':
+ return SF | SE | SD;
+
+ case 'm':
+ case 'n':
+ return SG | SE | SC;
+
+ case 'o':
+ return SG | SE | SC | SD;
+
+ case 'p':
+ return SA | SF | SB | SG | SE;
+
+ case 'q':
+ return SA | SF | SB | SG | SC;
+
+ case 'r':
+ return SG | SE;
+
+ case 't':
+ return SF | SG | SE | SD;
+
+ case 'u':
+ case 'w':
+ return SE | SC | SD;
+
+ case 'y':
+ return SF | SB | SG | SC | SD;
+
+ case '-':
+ return SG;
+
+ case '.':
+ return SDP;
+
+ }
+
+ return 0;
+}
+
+void max7219_report_addr (uint32_t baseaddr)
+{
+ unsigned i;
+
+ for (i = 1; i <= 8; ++i) {
+ write_regs (i, hex (baseaddr & 0xf), 0, 0);
+ baseaddr >>= 4;
+ }
+}
+
+
void
-max7219_init (void)
+max7219 (const char *str)
{
MAP_OUTPUT_PP (SCK);
MAP_OUTPUT_PP (NCS);
MAP_OUTPUT_PP (MOSI);
+ unsigned reg;
set (0, 1, 0);
- write_reg (0xc, 0x1); //Power up
- write_reg (0xf, 0x0); //normal mode
+ write_reg (0xc, 0x1); //Power up
+ write_reg (0xf, 0x0); //normal mode
+
+ write_reg (0x9, 0x0); //No decode
+ write_reg (0xb, 0x7); //8 digits
+ write_regs (0xa, 15, 15, 15); //max brightness
- write_reg (0x9, 0x0); //No decode
- write_reg (0xb, 0x7); //8 digits
- write_regs (0xa,15,15,15); //max brightness
- write_reg (1,0);
- write_reg (2,0);
- write_reg (3,0);
- write_reg (4,0);
- write_reg (5,0);
- write_regs (6,0xbe,0,0);
- write_regs (7,0x47,0,0);
- write_regs (8,0x3d,0,0);
+ for (reg = 8; reg && *str; reg--, str++)
+ write_regs (reg, hex (*str) | (!str[1] ? SDP : 0), 0, 0);
+ for (; reg; reg--)
+ write_reg (reg, 0);
}
diff --git a/boot/prototypes.h b/boot/prototypes.h
index 17cc0fa..74f6b60 100644
--- a/boot/prototypes.h
+++ b/boot/prototypes.h
@@ -24,4 +24,5 @@ extern void usart2_xmit_xdigit(unsigned d);
extern void usart2_xmit_uint32(uint32_t v);
extern void usart_init(void);
/* max7219.c */
-extern void max7219_init(void);
+extern void max7219_report_addr(uint32_t baseaddr);
+extern void max7219(const char *str);
diff --git a/boot/usb.c b/boot/usb.c
index e8d2e20..1454750 100644
--- a/boot/usb.c
+++ b/boot/usb.c
@@ -15,8 +15,8 @@ const struct usb_device_descriptor dev = {
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = 64,
- .idVendor = ID_VENDOR,
- .idProduct = ID_PRODUCT,
+ .idVendor = 0x0483,
+ .idProduct = 0xdf11,
.bcdDevice = 0x0200,
.iManufacturer = 1,
.iProduct = 2,
diff --git a/st/siderial_time.c b/st/siderial_time.c
new file mode 100644
index 0000000..5175511
--- /dev/null
+++ b/st/siderial_time.c
@@ -0,0 +1,173 @@
+#include <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)