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

const float fs = 4000000/.2;
const float dt = 1/fs;
const float T = 1./125000;
const float schmitt_min = 2;
const float schmitt_max = 3;
const float Vcc = 5.;

const float tau_smooth = .05 * T; // determined based on what looks good (seems to smooth it without lagging much)
const float tau_delay = .05 * T; // also what looks good
const float tau_thresh = 8 * T; // delay for averaging, should result in a constant-ish value
const float tau_envelope_up = 1.0 * T; // determined this constant as ~maximum to follow normal peak rise rates
const float tau_envelope_down = T / (-log(.995));
const float tau_smooth_phase = 8 * T;

const float smooth_mult = exp(-dt/tau_smooth);
const float delay_mult = exp(-dt/tau_delay);
const float thresh_mult = exp(-dt/tau_thresh);
const float envelope_up_mult_oneminus = 1-exp(-dt/tau_envelope_up);
const float envelope_down_mult = exp(-dt/tau_envelope_down);
const float smooth_phase_mult_oneminus = 1-exp(-dt/tau_smooth_phase);

const int start_cycle_count = 20;
const int cycle_wrap_count = 32;
const float f = 125000;
const float bitrate = f/cycle_wrap_count;
const float bits_per_sample = bitrate/fs;


void fprint_bits(FILE* f, bool *bits, int len) {
	fprintf(f, "[");
	if (len != 0) {
		fprintf(f, "%d", bits[0]);
	}
	for (int i = 1; i < len; ++i) {
		fprintf(f, ", %d", bits[i]);
	}
	fprintf(f, "]\n");
}

int main(int argc, char** argv) {
	if (argc != 2) {
		return 1;
	}

	FILE *oscfile = fopen(argv[1],"rb");  // r for read, b for binary
	if (!oscfile) {
		return 2;
	}

	if (fseek(oscfile, 0L, SEEK_END) == -1) {
		return 3;
	}

	int sz = ftell(oscfile);
	if (sz < 164) {
		return 4;
	}

	if (fseek(oscfile, 164L, SEEK_SET) == -1) {
		return 5;
	}

	float *oscdata = (float*)malloc(sz - 164);
	if (!oscdata) {
		return 6;
	}

	if (fread(oscdata, sz-164, 1, oscfile) != 1) {
		return 7;
	}

	int n = (sz-164)/4;

	int bits_cap = 1+n*bits_per_sample;
	bool *bits = (bool*)malloc(bits_cap * sizeof(bool));
	if (!bits) {
		return 8;
	}
	bits[0] = 0;
	int bits_len = 1;

	float max_voltage = -1e60;
	for (int i=0; i<n; ++i) {
		if (oscdata[i] > max_voltage) {
			max_voltage = oscdata[i];
		}
	}
	for (int i=0; i<n; ++i) {
		oscdata[i] = max_voltage - oscdata[i];
	}

	float smooth_voltage = 0.0;
	float delay_voltage = 0.0;
	float thresh = 0.0;
	float phase_a_peak = 0.0;
	float phase_b_peak = 0.0;
	float raw_phase = 0.0;
	float smooth_phase = 0.0;
	bool binary_voltage = false;
	bool binary_delay = false;
	bool phase_a = false;
	bool next_phase_a = false;
	bool phase = false;

	int cycle_count = 0;
	int cycle_middle = -1;
	int next_count = 0;
	bool prev_cycle_phase = false;
	bool prev_bit_phase = false;

	for (int i=0; i<n; ++i) {
		float voltage = oscdata[i];
		smooth_phase += (raw_phase-smooth_phase)*smooth_phase_mult_oneminus;
		raw_phase = (phase_a_peak > phase_b_peak) ? Vcc : 0;
		if (smooth_phase > schmitt_max) {
			phase = true;
		} else if (smooth_phase < schmitt_min) {
			phase = false;
		}

		thresh = phase_a_peak*.25 + (thresh  - phase_a_peak*.25)*thresh_mult;

		phase_a_peak = (phase_a_peak*envelope_down_mult +
			(( phase_a) && (smooth_voltage > phase_a_peak) ? (Vcc-phase_a_peak) * envelope_up_mult_oneminus : 0));
		phase_b_peak = (phase_b_peak*envelope_down_mult +
			((!phase_a) && (smooth_voltage > phase_b_peak) ? (Vcc-phase_b_peak) * envelope_up_mult_oneminus : 0));

		if (binary_voltage && binary_delay) {
			phase_a = next_phase_a;
		}
		if (!binary_voltage && !binary_delay) {
			next_phase_a = !phase_a;
		}

		binary_voltage = smooth_voltage > thresh;
		binary_delay = delay_voltage > thresh;

		delay_voltage = smooth_voltage + (delay_voltage - smooth_voltage)*delay_mult;
		smooth_voltage = voltage + (smooth_voltage - voltage)*smooth_mult;

		if (binary_voltage && !binary_delay) {
			next_count = cycle_count + 1;
		}
		if (!binary_voltage && binary_delay) {
			if (cycle_count != next_count) {
				if (cycle_middle == -1 && cycle_count > start_cycle_count && prev_cycle_phase != phase) {
					cycle_middle = (cycle_count + cycle_wrap_count/2) % cycle_wrap_count;
					prev_bit_phase = phase;
				} else if (cycle_count % cycle_wrap_count == cycle_middle) {
					if (bits_len < bits_cap) {
						bits[bits_len++] = prev_bit_phase ^ phase;
					} else {
						return 9;
					}
				}
			}
			cycle_count = next_count;
			prev_cycle_phase = phase;
		}

		// printf("%f ", smooth_voltage);
		// printf("%f ", delay_voltage);
		// printf("%f ", next_phase_a*Vcc);
		// printf("%f ", phase_a*Vcc);
		// printf("%f ", phase_a_peak);
		// printf("%f ", thresh);
		// printf("%f ", phase_b_peak);
		// printf("%f ", raw_phase);
		// printf("%f\n", smooth_phase);
	}

	printf("bits = ");
	fprint_bits(stdout, bits, bits_len);

	int start_same = 0;
	for (int i=0; i<bits_len; ++i) {
		if (bits[i] != bits[start_same]) {
			start_same = i;
		}
		if (i-start_same+1 == 30) { // FIXME: magic numbers 30 and 224
			if (start_same + 224 <= bits_len) {
				fprint_bits(stdout, &bits[start_same], 224);
			} else {
				fprint_bits(stdout, &bits[start_same], bits_len-start_same);
			}
		}
	}

	free(bits);
	free(oscdata);
	return 0;
}
