#include <string.h>
#include <time.h>
+#include <getopt.h>
#include "messages.h"
+// Options
+char *opt_tty;
+int opt_pretend;
+int opt_verbose;
+
+int opt_device;
+ntime_t opt_world;
+ntime_t opt_start;
+ntime_t opt_period;
+int opt_relay;
+int opt_sync;
+
+// Helper functions
+uint64_t ipow(int i) {
+ int num = 1;
+ while (i-- > 0)
+ num *= 10;
+ return num;
+}
+
void error(char *msg)
{
printf("Error: %s\n", msg);
printf("\n");
}
-int main(int argc, char **argv)
+ntime_t gettime(const char *str)
{
- if (argc < 3)
- error("usage: control /dev/ttyACM0 0 sync");
+ ntime_t time = {};
+ int start, end;
+ sscanf(str, "%u.%n%u%n", &time.seconds, &start, &time.nanosec, &end);
+ time.nanosec *= ipow(9-(end-start));
+ return time;
+}
- // Parse args
- char *opt_tty = argv[1];
- int opt_device = atoi(argv[2]);
- int opt_sync = argv[3] && !strcmp(argv[3], "sync") ?
- MSG_CTL_VALID_SYNC : 0;
- int opt_relay = opt_device == 2;
+void usage(void)
+{
+ printf("usage: control [OPTIONS] [TTY]\n");
+ printf("\n");
+ printf("Options:\n");
+ printf(" -d,--device=id mbed Device ID\n");
+ printf(" -w,--world=time initial world time\n");
+ printf(" -s,--start=time emit start time\n");
+ printf(" -p,--period=time emit period\n");
+ printf(" -r,--relay enable relay mode\n");
+ printf(" -y,--sync enable time sync\n");
+ printf(" -n,--pretend do not send message\n");
+ printf(" -v,--verbose print debug messages\n");
+ printf(" -h,--help print this usage\n");
+}
- // Lookup current wall-clock time
+// Argument parsing
+void parse(int argc, char **argv)
+{
+ // Get timestamp
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
+ // Default arguments;
+ opt_tty = "/dev/ttyACM0";
+ opt_device = 1;
+ opt_world = (ntime_t){ts.tv_sec, ts.tv_nsec};
+ opt_start = (ntime_t){0, 0};
+ opt_period = (ntime_t){1, 0};
+
+ // Long options
+ struct option long_options[] = {
+ {"device", required_argument },
+ {"world", required_argument },
+ {"start", required_argument },
+ {"period", required_argument },
+ {"relay", no_argument },
+ {"sync", no_argument },
+ {"pretend", no_argument },
+ {"verbose", no_argument },
+ {"help", no_argument },
+ {0, 0 },
+ };
+
+ // Run parser
+ while (1) {
+ int opt = getopt_long(argc, argv, "d:w:s:p:rynvh", long_options, 0);
+ if (opt == -1)
+ break;
+ switch (opt) {
+ case 'd': opt_device = atoi(optarg); break;
+ case 'w': opt_world = gettime(optarg); break;
+ case 's': opt_start = gettime(optarg); break;
+ case 'p': opt_period = gettime(optarg); break;
+ case 'r': opt_relay = 1; break;
+ case 'y': opt_sync = 1; break;
+ case 'n': opt_pretend = 1; break;
+ case 'v': opt_verbose++; break;
+ case 'h': usage(); exit(0); break;
+ default: usage(); exit(1); break;
+ }
+ }
+ if (optind < argc)
+ opt_tty = argv[optind];
+}
+
+// Main
+int main(int argc, char **argv)
+{
+ // Lookup current wall-clock time
+ parse(argc, argv);
+
+ // Debug output
+ if (opt_verbose) {
+ printf("options:\n");
+ printf(" tty = %s\n", opt_tty);
+ printf(" device = %d\n", opt_device);
+ printf(" world = %d.%09u\n", opt_world.seconds, opt_world.nanosec);
+ printf(" start = %d.%09u\n", opt_start.seconds, opt_start.nanosec);
+ printf(" period = %d.%09u\n", opt_period.seconds, opt_period.nanosec);
+ printf(" relay = %s\n", opt_relay ? "true" : "false");
+ printf(" sync = %s\n", opt_sync ? "true" : "false");
+ printf(" pretend = %s\n", opt_pretend ? "true" : "false");
+ printf(" verbose = %s\n", opt_verbose ? "true" : "false");
+ }
+
// Message buffers
header_t head = {};
init_msg_t body = {};
| MSG_CTL_VALID_START
| MSG_CTL_VALID_PERIOD
| MSG_CTL_VALID_WORLD
- | opt_relay
- | opt_sync;
-
- // 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 = 0; //ts.tv_nsec;
- body.period.seconds = 0;
- body.period.nanosec = 100000000;
- // [s][m][u][n]
+ | (opt_relay ? MSG_CTL_RELAY_MODE : 0)
+ | (opt_sync ? MSG_CTL_BEGIN_SYNC : 0);
+
+ body.device = opt_device;
+ body.world = opt_world;
+ body.start = opt_start;
+ body.period = opt_period;
// 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);
+ if (!opt_pretend) {
+ len += fwrite(&head, 1, sizeof(head), fd);
+ len += fwrite(&body, 1, sizeof(body), fd);
+ }
fclose(fd);
+ if (opt_verbose > 2)
+ printf("wrote %d bytes\n", len);
// Debug output
- dump("head", (uint8_t*)&head, sizeof(head));
- dump("body", (uint8_t*)&body, sizeof(body));
-
- printf("wrote %d bytes\n", len);
+ if (opt_verbose > 2) {
+ dump("head", (uint8_t*)&head, sizeof(head));
+ dump("body", (uint8_t*)&body, sizeof(body));
+ }
return 0;
}