/*
 * diot_util - diagnostic tool for DIOT system board
 * 
 * Author: Greg Daniluk
 * Copyright CERN 2021
 * 
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include "diot_util_pts.h"
#include "diot_util_sensors.h"
#include "diot_util_clk.h"
#include "diot_util_gpio.h"

#define DECLARE_PTS_SENSOR(_short_name, _allowed_min, _allowed_max) \
	{ .short_name = _short_name, \
		.allowed_min = _allowed_min, \
		.allowed_max = _allowed_max }

struct pts_sensor pts_sensors_list[] = {
	DECLARE_PTS_SENSOR("FPGA" , 21, 61),
	DECLARE_PTS_SENSOR("FMC"  , 22, 62),
	DECLARE_PTS_SENSOR("DDR"  , 23, 63),
	DECLARE_PTS_SENSOR("Pow M", 24, 64),
	DECLARE_PTS_SENSOR("IRPS1", 25, 65),
	DECLARE_PTS_SENSOR("IRPS2", 26, 66),
	DECLARE_PTS_SENSOR("IRPS1 Input Voltage", 11.0, 12.5),
	DECLARE_PTS_SENSOR("IRPS1 Input Current", 0.01, 0.25),
	DECLARE_PTS_SENSOR("IRPS1 P0V85 Voltage", 0.84, 0.86),
	DECLARE_PTS_SENSOR("IRPS1 P1V8_AUX Voltage", 1.79, 1.81),
	DECLARE_PTS_SENSOR("IRPS1 P1V2 Voltage", 1.19, 1.21),
	DECLARE_PTS_SENSOR("IRPS1 P1V8 Voltage", 1.79, 1.81),
	DECLARE_PTS_SENSOR("IRPS1 P1V2_PSPLL LDO Voltage", 1.18, 1.21),
	DECLARE_PTS_SENSOR("IRPS2 Input Voltage", 11.0, 12.5),
	DECLARE_PTS_SENSOR("IRPS2 Input Current", 0.01, 0.2),
	DECLARE_PTS_SENSOR("IRPS2 P3V3 Voltage", 3.2, 3.4),
	DECLARE_PTS_SENSOR("IRPS2 MGT_1V8 Voltage", 1.79, 1.81),
	DECLARE_PTS_SENSOR("IRPS2 MGT_0V9 Voltage", 0.89, 0.91),
	DECLARE_PTS_SENSOR("IRPS2 MGT_1V2 Voltage", 1.19, 1.21),
	DECLARE_PTS_SENSOR("PLL Input Present", 1, 1),
	DECLARE_PTS_SENSOR("PLL Locked", 1, 1),
	DECLARE_PTS_SENSOR("PLL Input", 0, 0),
	DECLARE_PTS_SENSOR("PLL Out0", 124.9, 125.1),
	DECLARE_PTS_SENSOR("PLL Out1", 156.24, 156.26),
	DECLARE_PTS_SENSOR("PLL Out2", 124.9, 125.1),
	DECLARE_PTS_SENSOR("PLL Out3", 124.9, 125.1),
	DECLARE_PTS_SENSOR("PLL Out4", 124.9, 125.1),
	DECLARE_PTS_SENSOR("PLL Out5", 124.9, 125.1),
	DECLARE_PTS_SENSOR("PLL Out6", 62.4, 62.6),
	DECLARE_PTS_SENSOR("PLL Out7", 124.9, 125.1),
	DECLARE_PTS_SENSOR("PLL Out8", 124.9, 125.1),
	DECLARE_PTS_SENSOR("PLL Out9", 24.9, 25.1),
	DECLARE_PTS_SENSOR(NULL, 0, 0)
};

struct pts_sensor * find_pts_sensor(char *sensor_name)
{
	struct pts_sensor *sensor_p = pts_sensors_list;

	for (; sensor_p->short_name; sensor_p++) {
		if (!strcmp(sensor_name, sensor_p->short_name)) {
			return sensor_p;
		}
	}

	return NULL;
}

int pts_sensor_inrange(double val, struct pts_sensor *sens)
{
	if (sens && val >= sens->allowed_min && val <= sens->allowed_max) {
		return 1;
	}

	return 0;
}

int cmd_pts(char *params)
{
	int errors = 0;
	int val;

	printf("Testing HW rev....");
	val = read_pcb_ver();
	if (val == PTS_HWVER) {
		printf("\rOK     HW rev         \n");
	} else {
		printf("\rFAIL   HW rev(%d vs %d)\n", val, PTS_HWVER);
		errors++;
	}

	errors += pts_sensors();
	errors += pts_clocks();

	if (errors == 0) {
		printf("All seems fine\n");
	} else {
		printf("Board has %d errors.\n", errors);
	}

	return 0;
}
