#include <stdlib.h>
#include <stdio.h>
#include <math.h>

/*
#define RANKS 4
#define VDD 1.42
#define PROCODT 60

struct rank_attr{
	double drive_strength;
	double rtt_nom;
	double rtt_wr;
	double rtt_park;
};
*/

/*
write to cs0
read from cs 0

4 reads
4 writes
no active cs


struct Odt_State {
	bool rtt_nom;
	bool rtt_wr;
	bool rtt_park;
};
*/

#define RTT_PARK 0
#define RTT_WR 1
#define RTT_NOM 2
#define RTT_OFF 3



const char Odt_State[9][4] = {
	//no active cs
	{RTT_PARK, RTT_PARK, RTT_PARK, RTT_PARK},
	//writes
	{RTT_WR, RTT_NOM, RTT_PARK, RTT_PARK},
	{RTT_PARK, RTT_WR, RTT_NOM, RTT_PARK},
	{RTT_PARK, RTT_PARK, RTT_WR, RTT_NOM},
	{RTT_PARK, RTT_PARK, RTT_PARK, RTT_WR},
	//reads
	{RTT_OFF, RTT_NOM, RTT_PARK, RTT_PARK},
	{RTT_PARK, RTT_OFF, RTT_NOM, RTT_PARK},
	{RTT_PARK, RTT_PARK, RTT_OFF, RTT_NOM},
	{RTT_PARK, RTT_PARK, RTT_PARK, RTT_OFF}
};




int main(int argc, char **argv){
	//struct rank_attr Ranks[RANKS];
	const int ranks = 4;
	const int max_odt_states = 9;

	double voltage = 1.35;
	double procodt = 34.3;

	const double dram_drive = 40;
	const double proc_drive = 34;

	double rtt_nom = 80;
	double rtt_wr = 120;
	double rtt_park = 120;

	const double rtt_off = 0;
	const double estimated_line_z = 40;
	double tmp1 = 0;
	double tmp2 = 0;
	double tmp3 = 0;
	double zero = 0;
	int cs = 0;
	int state = 0;
	double Cur_Termination = 0;
	double Total_Resistance = 0;
	const char *description[9] = {"No active cs", "Write to cs3", "Write to cs2", "Write to cs1", "Write to cs0", "Read from cs3", "Read from cs2", "Read from cs1", "Read from cs0"};

//∞
//	struct Odt_State odt_state[];

	voltage = atof(argv[1]);
	procodt = atof(argv[2]);
	rtt_nom = atof(argv[3]);
	rtt_wr = atof(argv[4]);
	rtt_park = atof(argv[5]);
	if(rtt_nom != 0)
		rtt_nom = 240/rtt_nom;
	else
		rtt_nom = 0;
	if(rtt_wr != 0)
		rtt_wr = 240/rtt_wr;
	else
		rtt_wr = 0;
	if(rtt_park != 0)
		rtt_park = 240/rtt_park;
	else
		rtt_park = 0;


	printf("dram drive strength(Read): %.02lfohms\n", dram_drive);
	printf("proc drive strength(Write): %.02lfohms (est. not user selectable)\n", proc_drive);

	printf("dram drive current(Read): %.04lfamps\n", voltage/dram_drive);
	printf("proc drive current(Write): %.04lfamps (est. not user selectable)\n", voltage/proc_drive);

	printf("ProctODT\t\tCS3\tCS2\tCS1\tCS0\t\tI to VDD\tOhms\t\tDescription\n");
	for(state = 0; state<max_odt_states; state++){
		Total_Resistance = 1/procodt;
		printf("%.02lf\t\t\t", procodt);
		for(cs = 0; cs<ranks; cs++){
			if(Odt_State[state][cs] == RTT_PARK){
				Cur_Termination = rtt_park;
			}else if(Odt_State[state][cs] == RTT_WR){
				Cur_Termination = rtt_wr;
			}else if(Odt_State[state][cs] == RTT_NOM){
				Cur_Termination = rtt_nom;
			}else{
				Cur_Termination = rtt_off;
			}
			if(Cur_Termination == zero){
				printf("∞\t");
			}else{
				printf("%.02lf\t", Cur_Termination);
			}
			if(Cur_Termination != zero){
				tmp1 = 1;
				tmp1 /= Cur_Termination;
				Total_Resistance += tmp1;
			}
		}
		tmp1 = 1;
		tmp1 /= Total_Resistance;
		printf("\t%.04lf\t", voltage/tmp1);
		printf("\t%.04lf\t", tmp1);
		printf("\t%s\n", description[state]);

	}


	//calculate estimated drive current at dram reciever to each rank
	//write

/*
	//drive current at source
	tmp1 = voltage/proc_drive;
	//current loss to destination
	tmp2 = voltage/estimated_line_z;
	tmp3 = tmp1 - tmp2;

	printf("write to dram:\n");
	printf("\tdrive current at source: %lfA\n", tmp1);
	printf("\tmax current at destination: %lfA\n", tmp3);

	//read

	tmp1 = voltage/dram_drive;
	tmp2 = voltage/estimated_line_z;
	//tmp3 = tmp2 - voltage/procodt;
	tmp3 = tmp1 - tmp2;

	printf("read from dram:\n");
	printf("\tdrive current at source: %lfA\n", tmp1);
	printf("\tmax current at destination: %lfA\n", tmp3);
*/

	//calculate estamated drive current at proc reciever from each rank
	//write
	//read

	return 0;
}
