#include <stdio.h>
#include <stdlib.h>
-
-#include <arpa/inet.h>
+#include <string.h>
#include <time.h>
int main(int argc, char **argv)
{
- char *device = argv[1];
- if (!device)
- error("usage: host /dev/ttyACM0");
+ if (argc < 3)
+ error("usage: host /dev/ttyACM0 0 sync");
- header_t head = {};
- sync_msg_t body = {};
+ // Parse args
+ char *opt_tty = argv[1];
+ int opt_device = atoi(argv[2]);
+ int opt_sync = argv[3] && !strcmp(argv[3], "sync") ?
+ MSG_VALID_SYNC : 0;
+ // Lookup current wall-clock time
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
+ // Message buffers
+ header_t head = {};
+ init_msg_t body = {};
+
+ // Set message header
head.header = MSG_HEADER;
- head.msgid = MSG_ID_SYNC;
- head.length = sizeof(sync_msg_t);
+ head.msgid = MSG_ID_INIT;
+ head.length = sizeof(init_msg_t);
head.cksum = 0; // todo
- body.seq = 0;
- body.time.seconds = ts.tv_sec;
- body.time.nanosec = ts.tv_nsec;
+ // Set valid flags
+ body.valid = MSG_VALID_DEVICE
+ | MSG_VALID_START
+ | MSG_VALID_PERIOD
+ | MSG_VALID_WORLD
+ | opt_sync;
- dump("head", (uint8_t*)&head, sizeof(head));
- dump("body", (uint8_t*)&body, sizeof(body));
+ // Set message body
+ body.device = opt_device;
+ body.world.seconds = ts.tv_sec;
+ body.world.nanosec = ts.tv_nsec;
+ body.start.seconds = ts.tv_sec;
+ body.start.nanosec = ts.tv_nsec;
+ body.period.seconds = 1;
+ body.period.nanosec = 0;
- FILE *fd = fopen(device, "a+");
+ // Transmit message
+ FILE *fd = fopen(opt_tty, "a+");
if (!fd) error("opening device");
int len = 0;
len += fwrite(&head, 1, sizeof(head), fd);
len += fwrite(&body, 1, sizeof(body), fd);
fclose(fd);
+ // Debug output
+ dump("head", (uint8_t*)&head, sizeof(head));
+ dump("body", (uint8_t*)&body, sizeof(body));
+
printf("wrote %d bytes\n", len);
return 0;
(uint32_t)(error % (int64_t)NSEC_PER_SEC));
#endif
//#endif
-
- // .000000284
- // .000000253
- // .000000264
- // .000000451
- // .000000284
- // .000000267
- // .000000223
- // .000000326
-
}
void time_printf(const char *label, uint64_t local)
static uint32_t *emit_pcr = 0; // transmit pin name
-static uint64_t emit_start = 0; // transmit start time
+static uint64_t emit_start = 0; // transmit start time (world time)
static uint64_t emit_period = 0; // transmit period
-static uint64_t emit_due = 0; // next transmit time
+static uint64_t emit_due = 0; // next transmit (world time)
static uint32_t emit_slack = 0; // how far ahead we need to schedule
static uint32_t emit_worst = 0; // worst-case latency in task table
emit_slack = 10000; // tune based on emit_worst
- time_printf("scheuled emit - ", emit_due);
+ time_printf("emit scheduled", emit_due);
}
void emit_schedule(uint64_t when)
{
- uint64_t now = tdma_time();
+ uint64_t now = time_to_world(tdma_time());
uint16_t delay = (uint16_t)(when-now);
// Clear pending flags
// Start the timer
TPM0->SC = TPM_SC_TOF_MASK
| TPM_SC_CMOD(1);
+
+ // Debug
+ //sirq_printf("emitting event\r\n");
}
void emit_transmit(void)
static uint64_t prev;
// Get a fresh timestamp
- uint64_t world = tdma_time();
+ uint64_t world = time_to_world(tdma_time());
// Record how how much time we have to reschedule
if (prev && world - prev > emit_worst)
emit_worst = prev;
// Schedule task if needed
- if (world+emit_slack > emit_due)
+ if (emit_due && emit_period &&
+ world+emit_slack > emit_due) {
emit_schedule(emit_due);
+ emit_due += emit_period;
+ }
}
/************************
*/
void serial_handle_init(init_msg_t *msg)
{
+ sirq_printf("initialize: %s %s %s %s %s\r\n",
+ msg->valid & MSG_VALID_DEVICE ? "DEV" : "dev",
+ msg->valid & MSG_VALID_START ? "START" : "start",
+ msg->valid & MSG_VALID_PERIOD ? "PERIOD" : "period",
+ msg->valid & MSG_VALID_WORLD ? "WORLD" : "world",
+ msg->valid & MSG_VALID_SYNC ? "SYNC" : "sync");
+ sirq_printf(" dev -- %d\r\n", msg->device);
+ time_printf(" start ", serial_read_time(msg->start));
+ time_printf(" period", serial_read_time(msg->period));
+ time_printf(" world ", serial_read_time(msg->world));
+
if (msg->valid & MSG_VALID_DEVICE)
serial_device_id = msg->device;
- if ((msg->valid & MSG_VALID_START) ||
- (msg->valid & MSG_VALID_PERIOD)) {
+ if (msg->valid & MSG_VALID_START ||
+ msg->valid & MSG_VALID_PERIOD) {
uint64_t start = serial_read_time(msg->start);
uint64_t period = serial_read_time(msg->period);
emit_enable(start, period);
uint64_t local = tdma_time();
time_ext_init(local, world);
}
+
+ if (msg->valid & MSG_VALID_SYNC)
+ serial_sync_due = tdma_time() + serial_sync_delay;
}
/**
int main(int argc, char **argv)
{
tdma_init();
+ emit_init(4, PTC1, PullDown);
// Open serial ports
sirq_dbg = sirq_open(SIRQ_UART0, USBTX, USBRX, 115200); // to pc