[\--tty \fItty-device\fP]
[\-D \fIaltos-device\fP]
[\--device \fIaltos-device\fP]
+[\-v] [\--verbose]
+[\-n] [\--nosave]
+[\-o \fIcal-value-output-file\fP]
+[\--output \fIcal-value-output-file\fP]
.SH DESCRIPTION
.I ao-cal-freq
drives the frequency calibration process and saves the result.
Leaving out the product name will cause the tool to select a suitable
product, leaving out the serial number will cause the tool to match
one of the available devices.
+.TP
+\-o cal-value-output-file | --output cal-value-output-file
+Writes the resulting calibration value to the specified file.
+.TP
+\-n | --nosave
+Inhibits saving the calibration value on the device. Necessary for
+devices which don't have on-board configuration storage.
+.TP
+\-v | --verbose
+Makes
+.I ao-cal-freq
+chatty about communication with the target device.
.SH USAGE
.I ao-cal-freq
opens the target device, interactively calibrates the frequency, then
-shows the resulting calibration values and saves them to configuration
-memory.
+shows the resulting calibration values and (optionally) saves them to
+configuration memory and/or a file.
.SH AUTHOR
Keith Packard
static const struct option options[] = {
{ .name = "tty", .has_arg = 1, .val = 'T' },
{ .name = "device", .has_arg = 1, .val = 'D' },
- { .name = "raw", .has_arg = 0, .val = 'r' },
{ .name = "verbose", .has_arg = 0, .val = 'v' },
+ { .name = "output", .has_arg = 1, .val = 'o' },
+ { .name = "nosave", .has_arg = 0, .val = 'n' },
{ 0, 0, 0, 0},
};
static void usage(char *program)
{
- fprintf(stderr, "usage: %s [--verbose] [--device=<device>] [-tty=<tty>]\n", program);
+ fprintf(stderr, "usage: %s [--verbose] [--nosave] [--device=<device>] [-tty=<tty>] [--output=<cal-value-file>]\n", program);
exit(1);
}
}
int
-do_cal(char *tty) {
+do_save(struct cc_usb *usb)
+{
+ int ret = 0;
+
+ printf("Saving calibration to device\n");
+ cc_usb_printf(usb, "c w\nv\n");
+ for (;;) {
+ char line[512];
+
+ cc_usb_getline(usb, line, sizeof (line));
+ if (strstr(line, "Nothing to save"))
+ ret = 1;
+ if (strstr(line, "Saved"))
+ ret = 1;
+ if (strstr(line, "software-version"))
+ break;
+ }
+ if (!ret) {
+ printf("Calibration save failed\n");
+ }
+ return ret;
+}
+
+int
+do_output(char *output, int cur_cal)
+{
+ printf ("Saving calibration value to file \"%s\"\n", output);
+
+ FILE *out = fopen(output, "w");
+ int ret = 1;
+
+ if (!out) {
+ perror(output);
+ return 0;
+ }
+
+ if (fprintf(out, "%d\n", cur_cal) < 0) {
+ perror("fprintf");
+ ret = 0;
+ }
+ if (fflush(out) != 0) {
+ perror("fflush");
+ ret = 0;
+ }
+ if (fclose(out) != 0) {
+ perror("fclose");
+ ret = 0;
+ }
+ return ret;
+}
+
+int
+do_cal(char *tty, int save, char *output)
+{
struct cc_usb *usb = NULL;
struct flash *b;
char line[1024];
int cur_cal;
int new_cal;
int ret = 1;
+ int changed = 0;
for(;;) {
usb = cc_usb_open(tty);
- if (!usb)
- exit(1);
+ if (!usb) {
+ fprintf(stderr, "failed to open device\n");
+ ret = 0;
+ break;
+ }
cc_usb_printf(usb, "E 0\n");
- cc_usb_sync(usb);
- cc_usb_printf(usb, "C 1\n");
- cc_usb_sync(usb);
-
- printf("Generating RF carrier. Please enter measured frequency [enter for done]: ");
- fflush(stdout);
- fgets(line, sizeof (line) - 1, stdin);
- cc_usb_printf(usb, "C 0\n");
- cc_usb_sync(usb);
-
- measured_freq = strtod(line, &line_end);
- if (line_end == line)
- break;
-
b = flash(usb);
cur_cal_words = find_flash(b, "Radio cal:");
cur_freq_words = find_flash(b, "Frequency:");
if (!cur_cal_words || !cur_freq_words) {
- printf("no response\n");
+ fprintf(stderr, "no response\n");
ret = 0;
break;
}
cur_freq = atoi(cur_freq_words[1]);
printf ("Current radio calibration %d\n", cur_cal);
- printf ("Current radio frequency: %d\n", cur_freq);
+ printf ("Current radio frequency: %7.3f\n", cur_freq / 1000.0);
+
+ cc_usb_sync(usb);
+ cc_usb_printf(usb, "C 1\n");
+ cc_usb_sync(usb);
+
+ printf("Generating RF carrier. Please enter measured frequency [enter for done]: ");
+ fflush(stdout);
+ fgets(line, sizeof (line) - 1, stdin);
+ cc_usb_printf(usb, "C 0\n");
+ cc_usb_sync(usb);
+ measured_freq = strtod(line, &line_end);
+ if (line_end == line)
+ break;
new_cal = floor ((((double) cur_freq / 1000.0) / measured_freq) * cur_cal + 0.5);
- printf ("Programming flash with cal value %d\n", new_cal);
+ if (new_cal == cur_cal) {
+ printf("Calibration value %d unchanged\n", cur_cal);
+ } else {
+ printf ("Setting cal value %d\n", new_cal);
- cc_usb_printf (usb, "c f %d\nc w\n", new_cal);
- cc_usb_sync(usb);
+ cc_usb_printf (usb, "c f %d\n", new_cal);
+ changed = 1;
+ cc_usb_sync(usb);
+ }
cc_usb_close(usb);
}
- if (usb)
+ if (usb) {
+ if (ret && save) {
+ if (changed) {
+ if (!do_save(usb))
+ ret = 0;
+ } else {
+ printf("Calibration unchanged, not saving\n");
+ }
+ }
+ if (ret && output) {
+ if (!do_output(output, cur_cal))
+ ret = 0;
+ }
cc_usb_close(usb);
+ }
return ret;
}
char *tty = NULL;
int success;
int verbose = 0;
+ int save = 1;
int ret = 0;
int expected_size;
+ char *output = NULL;
- while ((c = getopt_long(argc, argv, "vrT:D:c:s:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "vnT:D:o:", options, NULL)) != -1) {
switch (c) {
case 'T':
tty = optarg;
case 'v':
verbose++;
break;
+ case 'n':
+ save = 0;
+ break;
+ case 'o':
+ output = optarg;
+ break;
default:
usage(argv[0]);
break;
}
ao_verbose = verbose;
-
- if (verbose > 1)
+ if (verbose)
ccdbg_add_debug(CC_DEBUG_BITBANG);
if (!tty)
if (!tty)
tty="/dev/ttyACM0";
- if (!do_cal(tty))
+ if (!do_cal(tty, save, output))
ret = 1;
+ return ret;
}