#include <stdio.h>
#include <stdint.h>
 
#define UINT16_MAX (65535)
#define VREF (3.3)
/* Current gain of the AD8210 plus effect of resistor divider */
#define GALVO_CUR_GAIN (20.0)
#define GALVO_R_SENSE (0.008)
 
#ifndef M_PI
// Stolen from /usr/include/math.h
#define M_PI 3.14159265358979323846f
#endif
#define POSITION_SCALE_FACTOR (1)
#define DEGREES_TO_RADIANS(d) ((d) * (M_PI / 180.0f))
#define RADIANS_TO_DEGREES(r) ((r) * (180.0f / M_PI))
 
/*                      VREF  RANGE === V_AT_8210 ===  GAIN      SENSE_R */
#define ADC2AMP_FACTOR (VREF/(UINT16_MAX + 1) / GALVO_CUR_GAIN / GALVO_R_SENSE)
 
enum stop_type
{
    STOP_TYPE_BOTTOM,
    STOP_TYPE_TOP,
    STOP_TYPE_NUM_STOPS,
};
struct stop_data
{
    int32_t stop_position;
    float stop_det_cur;
    int32_t current_sum;
    int32_t voltage_sum;
    uint32_t sum_count;
};
struct stop_data stops[STOP_TYPE_NUM_STOPS];
int main(void) {
	// your code goes here
	stops[STOP_TYPE_BOTTOM].stop_position = -93174;
	stops[STOP_TYPE_TOP].stop_position = 93511;
	stops[STOP_TYPE_BOTTOM].stop_det_cur = 0.000276;
	stops[STOP_TYPE_TOP].stop_det_cur = 0.000279;
	stops[STOP_TYPE_BOTTOM].current_sum = -258999;
	stops[STOP_TYPE_TOP].current_sum = 22135;
	stops[STOP_TYPE_BOTTOM].voltage_sum = -589489;
	stops[STOP_TYPE_TOP].voltage_sum = 55361;
	stops[STOP_TYPE_BOTTOM].sum_count = 1063;
	stops[STOP_TYPE_TOP].sum_count = 100;
	float const voltage_top = stops[STOP_TYPE_TOP].voltage_sum * 5.04f / 5000 / stops[STOP_TYPE_TOP].sum_count;
	float const voltage_bottom = stops[STOP_TYPE_BOTTOM].voltage_sum * 5.04f / 5000 / stops[STOP_TYPE_BOTTOM].sum_count;
	float const current_top = stops[STOP_TYPE_TOP].current_sum * ADC2AMP_FACTOR / stops[STOP_TYPE_TOP].sum_count;
	float const current_bottom = stops[STOP_TYPE_BOTTOM].current_sum * ADC2AMP_FACTOR / stops[STOP_TYPE_BOTTOM].sum_count;
	float const resistance = (voltage_top - voltage_bottom) / (current_top - current_bottom);
	printf("Resistance = %.3f\n", resistance
); 	float const pwm_offset = voltage_top - (resistance * current_top);
	printf("PWM Offset = %.3f\n", pwm_offset
); 	float const pwm_offset2 = voltage_bottom - (resistance * current_bottom);
	printf("PWM Offset 2 = %.3f\n", pwm_offset2
); 	int32_t const adjusted_bottom_pos = (stops[STOP_TYPE_BOTTOM].stop_det_cur / 0.000250) * stops[STOP_TYPE_BOTTOM].stop_position;
	int32_t const adjusted_top_pos = (stops[STOP_TYPE_TOP].stop_det_cur / 0.000250) * stops[STOP_TYPE_TOP].stop_position;
	int32_t const pos_delta = adjusted_top_pos - adjusted_bottom_pos;
	int32_t const expected_delta = (100000 / 30.f) * 60.0f;
	float const scale = (float)pos_delta / (float)expected_delta;
	printf("Adjusted top pos = %d\n", adjusted_top_pos
); 	printf("Adjusted bottom pos = %d\n", adjusted_bottom_pos
); 	printf("Pos Delta = %d\n", pos_delta
); 	printf("Expected Delta = %d\n", expected_delta
); 	printf("Scale = %.3f\n", scale
); 	float const scale_adjusted = scale * 1.5f;
	printf("Scale Adjusted = %.3f\n", scale_adjusted
); 	float const top_deg = adjusted_top_pos * (30.f / 100000) * scale_adjusted;
	float const deg_offset = (30 * scale_adjusted) - top_deg;
	float const bottom_deg = adjusted_bottom_pos * (30.f / 100000) * scale_adjusted;
	float const deg_offset2 = (-30 * scale_adjusted) - bottom_deg;
	printf("Top Deg = %.3f\n", top_deg
); 	printf("Bottom Deg = %.3f\n", bottom_deg
); 	printf("Deg Offset = %.3f\n", deg_offset
); 	printf("Deg Offset 2 = %.3f\n", deg_offset2
); 	return 0;
}