// BODE.C - draws bode plots for RC filter circuits //

#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <string.h>
#include "n:/course/elec/include/gfxlib1.h"

void draw_axes(void)
{
	int x;
	char label[5];
	cleardevice(); // clear the screen
	moveto(0,0);
	setcolor(GREEN);
	// vertical gridlines
	for(x=120; x<=600; x+=120)
	{
	line(20+x,450,20+x,40);
	}

	// horizontal gridlines
	for (x=0; x<=400; x+=80)
	{
	line(15,40+x,620,40+x);
	}

	setcolor(YELLOW);
	line(15,40,620,40); // x-axis
	line(20,40,20,450); // y-axis

	for (x=0; x>=-50; x-=10)
	{
		sprintf(label,"%d",x);
		outtextxy(0,(x*-8)+42,label);
	}

	outtextxy(20,455,"10");
	outtextxy(140,455,"100");
	outtextxy(260,455,"1k");
	outtextxy(380,455,"10k");
	outtextxy(500,455,"100k");
	outtextxy(620,455,"1M");

	outtextxy(10,10,"Transfer Function dBV");
	outtextxy(280,470,"Frequency Hz");
	setcolor(WHITE);

}

double calculate_value(double r, double c, double freq)
{
	double output; // raw value for transfer function
	double output_dB; //20 log10 of output

	output=sqrt(1/(1+pow(2*M_PI*freq,2)*pow(c,2)*pow(r,2)));
	output_dB=20*log10(output);
	//printf("Frequency=%lf o/p=%lf dB=%lf\n", freq, output, output_dB);

	return output_dB;
}

void plot_value(double logfreq, double output_dB)
{
	int xpoint, ypoint;
	static int oldx=-1, oldy=-1;
	if (logfreq==-1 && output_dB==-1) // special case to reset old variables...
	{
		oldx=-1;
		oldy=-1;
		logfreq=1;
      output_dB=0;
	}
	xpoint=20+((logfreq-1)*120); // scale frequency value to axis
	setcolor(WHITE);
	if (output_dB>0)   // constrain top end of dB axis
	{
		output_dB=0;
		setcolor(YELLOW);
	}
	if (output_dB<-50)
	{
		output_dB=-50; // constrain bottom end of dB axis
		setcolor(GREEN);
	}
	ypoint=(output_dB*-8)+40; // scale dB value to axis

	if (oldx!=-1 && oldy!=-1)
	{
		line(oldx,oldy,xpoint,ypoint);
	}

	oldx=xpoint;
	oldy=ypoint;

}

void get_values(char *r_str, char*c_str)
{
	printf("Welcome to the RC Bode Plotter\n\n");
	printf("Please enter component values. You may use engineering\n");
	printf("(M, k, m, u, n, p) suffixes to your values.\n\n");
	printf("For example, 100pF may be entered as 100p\n\n");
	printf("Please enter a value for the resistance ");
	scanf("%s" ,r_str);
	printf("\nPlease enter a value for the capacitance ");
	scanf("%s", c_str);

	return;
}

double eng_to_float(char *input)
{
	int length;
	char number[20];
	double output=0;
	double multiplier=1;

	length=strlen(input);
	switch (input[length-1])
	{
		case 'M' : multiplier=1E6; break;
		case 'k' : multiplier=1E3; break;
		case 'm' : multiplier=1E-3; break;
		case 'u' : multiplier=1E-6; break;
		case 'n' : multiplier=1E-9; break;
		case 'p' : multiplier=1E-12; break;

	}
	if (multiplier!=1)
	{
		strncpy(number,input,length-1);
		number[length-1]=0;
	}
	else strcpy(number,input);
  //	printf("Number=%s, Multiplier=%lf",number, multiplier);
	output=atof(number)*multiplier;
	return output;
}


int main(void)
{
	// declare variables

	double freq; // frequency
	double logfreq; // logarithm of frequency (to base 10)
	double r; // resistance
	double c; // capacitance
	double breakfreq; // break frequency
	double output; // raw value for transfer function
	double output_dB; //20 log10 of output
	char r_str[20]; //string value of R
	char c_str[20]; //string value of C
	char labels[80];
	char quit;

	// endprogram = FALSE
	int endprogram = 0;

	// while (endprogram is FALSE)
	while (endprogram==0)
	{
		// initialise variables
		logfreq=0;

		// read in component values
		get_values(r_str, c_str);
		//printf("R=%s C=%s", r_str, c_str);

		// Process component values
		r=eng_to_float(r_str);
		c=eng_to_float(c_str);
		//printf("r=%lf c=%lf", r,c);
		//while(!(kbhit()));
		//r=1E4;
		//c=1E-7;
		// Go to graphics mode & draw axes
		graphics_on();
		draw_axes();


		breakfreq=1/(2*M_PI*r*c); // calculate break frequency

		// put some labels on!
		sprintf(labels, "R=%s, C=%sF, Break frequency=%.0lf Hz",r_str, c_str,breakfreq);
		outtextxy(200,10,labels);

		// reset the plot...
		plot_value(-1,-1);
		// for (increasing values of frequency until we reach 1MHz)
		for(logfreq=1; logfreq<=6; logfreq+=0.1)
		{
				// calculate the value at this point
				freq=pow(10,logfreq);
				output_dB=calculate_value(r,c,freq);
				// draw the line
				plot_value(logfreq,output_dB);

				// end of the above loop

		}
		// ask user if they want to do it again
		outtextxy(150,25,"Draw another plot ? Press y for yes or any other key to exit.");
		quit=getch();
		// if no, endprogram = TRUE
		if(quit=='y' || quit=='Y') endprogram=0; else endprogram=1; // quit!

		// graphics off
		graphics_off();
		// end of main while loop
	}
	// deinitialise variables & clear up


	// that's all, folks!
	return 0;
}