//	cpf-logger-lite-pic.c
//	serial port adc for cpf-logger
//	ver. 0.84
//	djpark@astsb.info
//	osccal calibration (0x3ff -> 0x90) is done by the compiler default code

//	a0	an0
//	a1	an1
//	a2	an2
//	a3	gpio mode sw
//	a4	an3	ti-opt101
//	a5	gpio serial-tx


#include <12F675.h>
#device  adc=10
#fuses   NOWDT, INTRC_IO, NOCPD, NOPROTECT, NOMCLR, PUT, NOBROWNOUT
#use     delay(clock=4000000)

#include <STDLIB.H>


// id & ver in data flash

#rom 0x2100 = { 0 }		// compensate (faster)
#rom 0x2101 = { 0 }		// compensate (slower)
#rom 0x2110 = { "CPF-LOGGER-LITE Ver. 0.84" }
#rom 0x2130 = { "(C) djpark@astsb.info 2004,2005" }
#rom 0x2150 = { "To be used freely by CPF members" }


// RTC timer0

#define CLOCK_CYCLE      8
#define CLOCK_PRELOAD    (65536 - 15625)	// 1000000 / 8 / 8 = 15625
// chip specific clock compensation
#define CLOCK_COMPENSATE (16)	//

int8  clock_compensate_positive = 0;
int8  clock_compensate_negative = 0;
int16 clock_preload_val = (CLOCK_PRELOAD + 33+2 + 4+2);	// 35=irq overhead 6=t1 overhead

int8 days = 0, hours = 0, minutes = 0, seconds = 0;
int8 sec_updated = 0, clock_updated = 0;

#define SWITCH_PIN   PIN_A3
#define DEBOUNCE_MAX 1

int8 logging_mode;

#int_TIMER1
TIMER1_isr()
{
	static int8 clock_count = 0;

	static signed int8 debounce_counter = 0;
	static int8 previous_mode = 255;

	set_timer1(clock_preload_val);

	if (input(SWITCH_PIN))
	{
		if (++debounce_counter > DEBOUNCE_MAX)
		{
			debounce_counter = DEBOUNCE_MAX;
			logging_mode = 1;
			if (previous_mode != 1)
			{
				previous_mode = 1;
				clock_count = 0;
				days = 0;
				hours = 0;
				minutes = 0;
				seconds = 0;
				sec_updated = 1;
			}
		}
	}
	else
	{
		if (--debounce_counter < -DEBOUNCE_MAX)
		{
			debounce_counter = -DEBOUNCE_MAX;
			logging_mode = 0;
			previous_mode = 0;
		}
	}

	if (++clock_count >= CLOCK_CYCLE)
	{
		seconds++;
		sec_updated = 1;
		if (seconds >= 60)
		{
			seconds = 0;
			minutes++;
			if (minutes >= 60)
			{
				minutes = 0;
				hours++;
				if (hours >= 24)
				{
					hours= 0;
					days++;
				}
			}
		}
		clock_count = 0;
	}
	clock_updated = 1;
}


// get adc value

int16 adc0, adc1, adc2, adc3;

#define ADC_SAMPLES 128
#define ADC_LFP     8

#separate
int16 adc_one(int adc)
{
	int32 adc_val = 0;
	int8  i;

	set_adc_channel(adc);
	delay_us(10);

	for (i=0; ; i++)
	{
		//delay_us(1);
		adc_val += (read_adc(ADC_START_AND_READ) << 2);
		if (i >= ADC_SAMPLES)
			break;
	}
	adc_val /= ADC_SAMPLES;

	return adc_val;
}

void adc_all(void)
{
	adc0 = adc_one(0);
	adc1 = adc_one(1);
	adc2 = adc_one(2);
	adc3 = adc_one(3);
}

int16 lpf_one(int16 old, int16 new)
{
	return (new + old * (ADC_LFP-1) ) / ADC_LFP ;
}

void lpf_all(void)
{
	adc0 = lpf_one(adc0, adc_one(0));
	adc1 = lpf_one(adc1, adc_one(1));
	adc2 = lpf_one(adc2, adc_one(2));
	adc3 = lpf_one(adc3, adc_one(3));
}


// print

#use rs232(baud=9600, xmit=PIN_A5, INVERT)

#inline
void print_continuous(void)
{
	printf("----------,");
	printf("%04lu,%04lu,%04lu,%04lu\r\n", adc0, adc1, adc2, adc3);
}

void print_logging(void)
{
	printf("%u.%02u:%02u:%02u,", days, hours, minutes, seconds);
	printf("%04lu,%04lu,%04lu,%04lu\r\n", adc0, adc1, adc2, adc3);
}


// main & init

void main()
{
	// setup
	setup_comparator(NC_NC_NC_NC);
	setup_vref(FALSE);

	setup_adc_ports(ALL_ANALOG);
	setup_adc(ADC_CLOCK_INTERNAL);
	set_tris_a(0b00011111);		// 0x1f
	delay_cycles(5);

	setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
	set_timer1(CLOCK_PRELOAD);
	enable_interrupts(INT_TIMER1);

	// initial value
	delay_ms(8);

	clock_compensate_positive = read_eeprom(0);
	clock_compensate_negative = read_eeprom(1);
	clock_preload_val += clock_compensate_positive;
	clock_preload_val -= clock_compensate_negative;

	adc_all();
	logging_mode = input(SWITCH_PIN);

	// start int
	enable_interrupts(GLOBAL);

	while (TRUE)
	{
		if (clock_updated)
		{
			adc_all();
			//lpf_all();		// nable for low pass filter

			if (logging_mode == 0)
			{
				print_continuous();
			}
			else
			{
				if (sec_updated)
				{
					print_logging();
					sec_updated = 0;
				}
			}
			clock_updated = 0;
		}
	}
}
