23 uint64_t ipow(int i) {
32 printf("Error: %s\n", msg);
36 void dump(const char *label, uint8_t *data, int len)
39 printf("%s: ", label);
40 for (i = 0; i < len; i++)
41 printf("%02hhx ", data[i]);
45 ntime_t gettime(const char *str)
49 sscanf(str, "%u.%n%u%n", &time.seconds, &start, &time.nanosec, &end);
50 time.nanosec *= ipow(9-(end-start));
56 printf("usage: control [OPTIONS] [TTY]\n");
59 printf(" -d,--device=id mbed Device ID\n");
60 printf(" -w,--world=time initial world time\n");
61 printf(" -s,--start=time emit start time\n");
62 printf(" -p,--period=time emit period\n");
63 printf(" -r,--relay enable relay mode\n");
64 printf(" -y,--sync enable time sync\n");
65 printf(" -n,--pretend do not send message\n");
66 printf(" -v,--verbose print debug messages\n");
67 printf(" -h,--help print this usage\n");
71 void parse(int argc, char **argv)
75 clock_gettime(CLOCK_REALTIME, &ts);
78 opt_tty = "/dev/ttyACM0";
80 opt_world = (ntime_t){ts.tv_sec, ts.tv_nsec};
81 opt_start = (ntime_t){0, 0};
82 opt_period = (ntime_t){1, 0};
85 struct option long_options[] = {
86 {"device", required_argument },
87 {"world", required_argument },
88 {"start", required_argument },
89 {"period", required_argument },
90 {"relay", no_argument },
91 {"sync", no_argument },
92 {"pretend", no_argument },
93 {"verbose", no_argument },
94 {"help", no_argument },
100 int opt = getopt_long(argc, argv, "d:w:s:p:rynvh", long_options, 0);
104 case 'd': opt_device = atoi(optarg); break;
105 case 'w': opt_world = gettime(optarg); break;
106 case 's': opt_start = gettime(optarg); break;
107 case 'p': opt_period = gettime(optarg); break;
108 case 'r': opt_relay = 1; break;
109 case 'y': opt_sync = 1; break;
110 case 'n': opt_pretend = 1; break;
111 case 'v': opt_verbose++; break;
112 case 'h': usage(); exit(0); break;
113 default: usage(); exit(1); break;
117 opt_tty = argv[optind];
121 int main(int argc, char **argv)
123 // Lookup current wall-clock time
128 printf("options:\n");
129 printf(" tty = %s\n", opt_tty);
130 printf(" device = %d\n", opt_device);
131 printf(" world = %d.%09u\n", opt_world.seconds, opt_world.nanosec);
132 printf(" start = %d.%09u\n", opt_start.seconds, opt_start.nanosec);
133 printf(" period = %d.%09u\n", opt_period.seconds, opt_period.nanosec);
134 printf(" relay = %s\n", opt_relay ? "true" : "false");
135 printf(" sync = %s\n", opt_sync ? "true" : "false");
136 printf(" pretend = %s\n", opt_pretend ? "true" : "false");
137 printf(" verbose = %s\n", opt_verbose ? "true" : "false");
142 init_msg_t body = {};
144 // Set message header
145 head.header = MSG_HEADER;
146 head.msgid = MSG_ID_INIT;
147 head.length = sizeof(init_msg_t);
148 head.cksum = 0; // todo
151 body.control = MSG_CTL_VALID_DEVICE
152 | MSG_CTL_VALID_START
153 | MSG_CTL_VALID_PERIOD
154 | MSG_CTL_VALID_WORLD
155 | (opt_relay ? MSG_CTL_RELAY_MODE : 0)
156 | (opt_sync ? MSG_CTL_BEGIN_SYNC : 0);
158 body.device = opt_device;
159 body.world = opt_world;
160 body.start = opt_start;
161 body.period = opt_period;
164 FILE *fd = fopen(opt_tty, "a+");
165 if (!fd) error("opening device");
168 len += fwrite(&head, 1, sizeof(head), fd);
169 len += fwrite(&body, 1, sizeof(body), fd);
173 printf("wrote %d bytes\n", len);
176 if (opt_verbose > 2) {
177 dump("head", (uint8_t*)&head, sizeof(head));
178 dump("body", (uint8_t*)&body, sizeof(body));