#include <p18f2510.h>        // Register defions
#include <stdlib.h>
#include <timers.h>         // Timer library functions
#include <delays.h>         // Time delay functions
#include <capture.h>        // CCP library functions
#include <portb.h>
#include <usart.h>
#include <i2c.h>
#include <spi.h>
#include <math.h>

#pragma config OSC = XT
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = ON
#pragma config BOREN = NOSLP
#pragma config BORV = 2
#pragma config WDT = ON
//#pragma config WDT = OFF
#pragma config WDTPS = 512
//#pragma config WDTPS = 32768
#pragma config MCLRE = ON
#pragma config PBADEN = OFF
#pragma config LVP = OFF
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CP2 = OFF
#pragma config CP3 = OFF
#pragma config CPB = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRT2 = OFF
#pragma config WRT3 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTR2 = OFF
#pragma config EBTR3 = OFF
#pragma config EBTRB = OFF

#define WIRELESS_RX PORTCbits.RC2

#define LED1 LATCbits.LATC0
#define LED2 LATCbits.LATC1
#define LED3 LATCbits.LATC3

#define word unsigned int
#define byte unsigned char
// function prototypes

void timer_isr(void);
void SendTemp(void);
void ReadWirelessTemp(void);
void phex16(word data);
void SendMoisture(void);


int		Global_Temp, Global_Temp_Raw, Global_Moisture_Raw;
byte	Global_Power_On = 1;
byte	Carrier_Detect;
byte	Signal_Level;
word	GPoint;
byte	rx_data[16];

#pragma code isrcode=0x0008

void isrhandler(void)        // This function directs execution to the
{                            //   actual interrupt code
_asm
goto timer_isr
_endasm
}

#pragma code

#pragma interrupt timer_isr save=W

//---------------------------------------------------------------------
// timer_isr()
// Performs the capture interupt
//---------------------------------------------------------------------
void timer_isr(void)
{
static word	this_point,
			this_abs, last_abs;
static word	Carrier_lost_timer=0;
static word	Carrier_found_timer=0;

/*
#define low_min		0x64
#define low_max		0x6e
#define high_min	0x55
#define high_max	0x5f
*/
#define low_min		0x90
#define low_max		0x9f
#define high_min	0x80
#define high_max	0x86

// CCP interupt (RX Demodulator)
	if ((PIR1bits.CCP1IF==1)&&(PIE1bits.CCP1IE==1))
	{	
		this_abs=CCPR1;							// get the capture value
		this_point= this_abs - last_abs;		// compute the delta
		last_abs=this_abs;						// save current absolute reading for next pass
		GPoint = this_point;
//LATCbits.LATC3 = 0;
		if((this_point <= low_max) && (this_point >= low_min))
			{
				Signal_Level = 0;
				//LED2 = 0;
				if((Carrier_Detect==0)&&(Carrier_found_timer==0))Carrier_found_timer = 20;
				if(Carrier_Detect==1)Carrier_lost_timer = 20;
			}
		else if((this_point <= high_max) && (this_point >= high_min))
			{
				Signal_Level = 1;
				//LED2 = 1;
				if((Carrier_Detect==0)&&(Carrier_found_timer==0))Carrier_found_timer = 20;
				if(Carrier_Detect==1)Carrier_lost_timer = 20;
			}
		else if(Carrier_Detect==0)
			{
				Carrier_found_timer = 0;
			}
		PIR1bits.CCP1IF=0;						// reset interupt
	}


// Timer interupt - used for carrier detect timeout
	if ((INTCONbits.TMR0IE==1)&&(INTCONbits.TMR0IF==1))
	{
LATBbits.LATB4=!LATBbits.LATB4;
		INTCONbits.TMR0IF=0;							// reset interupt
		if((Carrier_Detect==1)&&(Carrier_lost_timer>0))
			if(--Carrier_lost_timer==0) Carrier_Detect=0;	// carrier is lost;
		if((Carrier_Detect==0)&&(Carrier_found_timer>0))
			if(--Carrier_found_timer==0) Carrier_Detect=1;	// carrier is found;
			
			
	if(Carrier_Detect == 1)LED3 = 0; else LED3 = 1;
	if(Carrier_Detect == 1)LED2 = 0;
	}


}

void main (void)
{
int	  loc_x,
	  loc_y,
	TRISA = 0x20;
	TRISB = 0x0;
	TRISC = 0x84;

	OpenUSART(  USART_TX_INT_OFF &
				USART_RX_INT_OFF &
				USART_ASYNCH_MODE &
				USART_EIGHT_BIT &
				USART_CONT_RX &
				BAUD_16_BIT_RATE,
				2976 );
				BAUDCON=0x08;
				loc_x=2976;
				SPBRG = (loc_x&0xff);
				SPBRGH = (loc_x >> 8);

	OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_16);
//	OpenTimer3(TIMER_INT_OFF & 	T3_16BIT_RW & T3_SOURCE_INT & T3_PS_1_8 & T3_OSC1EN_OFF & T3_SYNC_EXT_OFF & T3_SOURCE_CCP);
//	OpenTimer3(0xf9);
	T3CON=0xf9;
 	CCP1CON=0x00;			// reset ccp module
 	CCP1CON=0x04;			// set for every 4th edge, 0x06 = every 4th edge - 0x04 = every edge

	PIR1bits.CCP1IF=0;												// Reset the interupt
	PIE1bits.CCP1IE=1;
	INTCONbits.PEIE=1;
	INTCONbits.GIE=1;
	Carrier_Detect = 0;
	Signal_Level = 1;
	loc_x = 0x30;
	Global_Temp = 0x5533;
	LED1 = 1;
	LED2 = 1;
	LED3 = 1;
	while(1)
		{
LATBbits.LATB7=!LATBbits.LATB7;

			if(Carrier_Detect == 1)ReadWirelessTemp();
			if(DataRdyUSART())
				{
					loc_x=getcUSART();
					if(loc_x == '?') SendTemp();
					if(loc_x == 'M') SendMoisture();
//					phex16(GPoint);
				}
			if((RCSTAbits.OERR == 1)||(RCSTAbits.FERR == 1))
				{
					loc_x = RCREG;
					RCSTAbits.CREN = 0;
					Nop();
					RCSTAbits.CREN = 1;
				}
			ClrWdt();
		}

}

void SendTemp(void)
{
			while(BusyUSART())ClrWdt();
			WriteUSART(Global_Temp_Raw >> 8);
			while(BusyUSART())ClrWdt();
			WriteUSART(Global_Temp_Raw & 0xff);
			LED1 = 1;
			LED2 = 1;
}

void SendMoisture(void)
{
			while(BusyUSART())ClrWdt();
			WriteUSART(Global_Moisture_Raw >> 8);
			while(BusyUSART())ClrWdt();
			WriteUSART(Global_Moisture_Raw & 0xff);
			while(BusyUSART())ClrWdt();
			WriteUSART((Global_Power_On & 0xff)+0x30);
			LED1 = 1;
			LED2 = 1;
}

void ReadWirelessTemp(void)
{
// do a bit banged serial rx
// first byte can be anything
// second byte is 0x55
// third byte is 0xaa
// fourth byte is 'T'
// fifth and sixth bytes are temp
// seventh byte is checksum
word	shift_reg;
//byte	rx_data[16];
byte	rx_ptr,
		bit_ctr;
word	bit_timer;
int		temp_val;
long	templ;

#define half_cell 350
#define full_cell 615

	for(rx_ptr=0; rx_ptr<15; rx_ptr++)rx_data[rx_ptr]=0xff;
//	for(rx_ptr=0; rx_ptr<7; rx_ptr++)
	for(rx_ptr=0; rx_ptr<10; rx_ptr++)	// changed for moisture - changed again for power fail
		{
			while((Carrier_Detect == 1) && (Signal_Level == 1)) ClrWdt();	// wait for start bit
			if(Carrier_Detect == 0) return;									// lost carrier waiting for start bit
			for(bit_timer = 0; bit_timer < half_cell; bit_timer++)ClrWdt();
			if(Signal_Level == 1)return;									// if false start then exit
			shift_reg = 0;
			for(bit_ctr=0; bit_ctr<9; bit_ctr++)
				{
					shift_reg >>= 1;
					if(Signal_Level & 1)shift_reg |= 0x80;
					for(bit_timer = 0; bit_timer < full_cell; bit_timer++)ClrWdt();
				}
			if((Carrier_Detect == 0)  || (Signal_Level == 0))return;			// if carrier lost or overrun exit
			rx_data[rx_ptr]=shift_reg;				
		}
	if(rx_data[1] != 0xaa) return;									// bad sync byte 1
	if(rx_data[2] != 0x55) return;									// bad sync byte 2
	if(rx_data[3] != 'T') return;									// bad ID byte
//	if(rx_data[6] != (rx_data[4]+rx_data[5])) return;					// bad checksum
	if(rx_data[9] != (rx_data[4]+rx_data[5]+rx_data[6]+rx_data[7]+rx_data[8])) return; // bad checksum with moisture
	LED1 = 0;
	temp_val = rx_data[4];
	temp_val <<= 8;
	temp_val |= rx_data[5];											// temp val is signed .0625 degree c units
	Global_Temp_Raw = temp_val;
	templ = temp_val;
// convert the .0625 degree units to degrees
	templ *= 625;
	templ /= 10000;
// Convert C to F using (C*1.8)+32 = F	
	templ *= 18L;
	templ /= 10L;
	templ += 32;													// convert C to F
	Global_Temp = templ;											// and save the new temp

	temp_val = rx_data[6];
	temp_val <<= 8;
	temp_val |= rx_data[7];											// Save the raw 0-1023 valur for moisture
	Global_Moisture_Raw = temp_val;
	
	Global_Power_On = rx_data[8];
}


void phex16(word data)
{
word	tempw;
	tempw = data;
	tempw >>= 12;
	tempw &= 0x0f;
	if(tempw > 9)tempw+=7;
	tempw+=0x30;
	while(BusyUSART())ClrWdt();
	WriteUSART(tempw);
	
	tempw = data;
	tempw >>= 8;
	tempw &= 0x0f;
	if(tempw > 9)tempw+=7;
	tempw+=0x30;
	while(BusyUSART())ClrWdt();
	WriteUSART(tempw);
	
	tempw = data;
	tempw >>= 4;
	tempw &= 0x0f;
	if(tempw > 9)tempw+=7;
	tempw+=0x30;
	while(BusyUSART())ClrWdt();
	WriteUSART(tempw);
	
	tempw = data;
	tempw &= 0x0f;
	if(tempw > 9)tempw+=7;
	tempw+=0x30;
	while(BusyUSART())ClrWdt();
	WriteUSART(tempw);
	
	while(BusyUSART())ClrWdt();
	WriteUSART(' ');
	
	
	
}
