view ffstools/newcomp/compile-fc-chg.c @ 497:74610c4f10f7

target-utils: added 10 ms delay at the end of abb_power_off() The deosmification of the ABB access code (replacement of osmo_delay_ms() bogus delays with correctly-timed ones, which are significantly shorter) had one annoying side effect: when executing the poweroff command from any of the programs, one last '=' prompt character was being sent (and received by the x86 host) as the Calypso board powers off. With delays being shorter now, the abb_power_off() function was returning and the standalone program's main loop was printing its prompt before the Iota chip fully executed the switch-off sequence! I thought about inserting an endless tight loop at the end of the abb_power_off() function, but the implemented solution of a 10 ms delay is a little nicer IMO because if the DEVOFF operation doesn't happen for some reason in a manual hacking scenario, there won't be an artificial blocker in the form of a tight loop keeping us from further poking around.
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 25 May 2019 20:44:05 +0000
parents 0937521ec2f4
children
line wrap: on
line source

/*
 * This utility compiles a FreeCalypso battery charging configuration file
 * from ASCII source into the binary form suitable for uploading into
 * /etc/charging on a FreeCalypso device.
 */

#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include "../../rvinterf/include/exitcodes.h"

char *infname;
FILE *inf;
char linebuf[256];
int lineno;

struct setting {
	char		*kw;
	int		allow_always;
	int		allow_never;
	int		mandatory;
	unsigned	default_value;
	unsigned	set_value;
	int		is_set;
} settings[] = {
	{"start-delay",               0, 0, 0, 0,      0, 0},
	{"start-threshold",           1, 1, 1, 0,      0, 0},
	{"restart-threshold",         0, 1, 1, 0,      0, 0},
	{"ci2cv-threshold",           0, 0, 1, 0,      0, 0},
	{"cv-initial-setpoint",       0, 0, 1, 0,      0, 0},
	{"cv-ctrl-loop-high",         0, 0, 1, 0,      0, 0},
	{"cv-ctrl-loop-low",          0, 0, 1, 0,      0, 0},
	{"cv-dac-max-incr",           0, 0, 1, 0,      0, 0},
	{"cv-dac-max-decr",           0, 0, 1, 0,      0, 0},
	{"cv-ctrl-loop-sample-count", 0, 0, 1, 0,      0, 0},
	{"overvoltage",               0, 0, 0, 0xFFFF, 0, 0},
	{"ci-current",                0, 0, 1, 0,      0, 0},
	{"end-current",               0, 0, 1, 0,      0, 0},
	{"ichg-max-spike",            0, 0, 0, 0x400,  0, 0},
	{"ichg-low-samples-needed",   0, 0, 1, 0,      0, 0},
	{"charging-time-limit",       0, 0, 0, 0xFFFF, 0, 0},
	{"restart-delay",             0, 0, 0, 0,      0, 0},
	{"i2v-offset",                0, 0, 0, 0,      0, 0},
	{0,                           0, 0, 0, 0,      0, 0}
};

static void
do_setting(tp, arg)
	struct setting *tp;
	char *arg;
{
	char *endp;

	if (tp->allow_always && !strcmp(arg, "always")) {
		tp->set_value = 0xFFFF;
		return;
	}
	if (tp->allow_never && !strcmp(arg, "never")) {
		tp->set_value = 0;
		return;
	}
	tp->set_value = strtoul(arg, &endp, 0);
	if (*endp || tp->set_value > 0xFFFF) {
		fprintf(stderr, "%s line %d: invalid argument to %s\n",
			infname, lineno, tp->kw);
		exit(ERROR_USAGE);
	}
}

process_line()
{
	char *cp, *kw, *arg;
	struct setting *tp;

	for (cp = linebuf; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#')
		return(0);
	kw = cp;
	while (*cp && !isspace(*cp))
		cp++;
	if (!*cp) {
inv:		fprintf(stderr, "%s line %d: invalid syntax\n", infname,
			lineno);
		exit(ERROR_USAGE);
	}
	*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp == '\0' || *cp == '#')
		goto inv;
	arg = cp;
	while (*cp && !isspace(*cp))
		cp++;
	if (*cp)
		*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp != '\0' && *cp != '#')
		goto inv;
	for (tp = settings; tp->kw; tp++)
		if (!strcmp(tp->kw, kw))
			break;
	if (!tp->kw) {
		fprintf(stderr, "%s line %d: setting \"%s\" not known\n",
			infname, lineno, kw);
		exit(ERROR_USAGE);
	}
	if (tp->is_set) {
		fprintf(stderr, "%s line %d: %s set more than once\n", infname,
			lineno, kw);
		exit(ERROR_USAGE);
	}
	do_setting(tp, arg);
	tp->is_set = 1;
	return(1);
}

set_defaults()
{
	struct setting *tp;

	for (tp = settings; tp->kw; tp++) {
		if (tp->is_set)
			continue;
		if (tp->mandatory) {
			fprintf(stderr,
				"error: required setting %s is not set\n",
				tp->kw);
			exit(ERROR_USAGE);
		}
		tp->set_value = tp->default_value;
	}
}

write_output(filename)
	char *filename;
{
	FILE *of;
	struct setting *tp;

	of = fopen(filename, "w");
	if (!of) {
		perror(filename);
		exit(ERROR_UNIX);
	}
	for (tp = settings; tp->kw; tp++) {
		putc(tp->set_value, of);
		putc(tp->set_value >> 8, of);
	}
	fclose(of);
}

main(argc, argv)
	char **argv;
{
	if (argc != 3) {
		fprintf(stderr, "usage: %s srcfile output-binfile\n", argv[0]);
		exit(ERROR_USAGE);
	}
	infname = argv[1];
	inf = fopen(infname, "r");
	if (!inf) {
		perror(infname);
		exit(ERROR_UNIX);
	}
	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++)
		process_line();
	fclose(inf);
	set_defaults();
	write_output(argv[2]);
	exit(0);
}