//********************************************************************************
// Project		:	Final Project(Remote Controller for digital thermometer)
// Start Date	:	11/04/2004
// Finish Date	:	11/13/2004
// Author		:	Xing Wang & Sunghwa Jung
// Company		:	Rose-Hulman Institute of Technology
// Purpose		:	1. Transmit IR data signal modulated with carrier by PWM.
//					2. IR receiver output is the same with toggled transmit data signal.
// Input		:	Nothing
// Outputs		:	Modulated data signal.	
// Chip type	:	PIC16F877
// Clock frequency		:	13.5 MHz
//********************************************************************************
#include <pic.h>
//***************************************************************************
// constant definitions
//***************************************************************************
#define	PORTC_DIRECTION	0B11111011	// RC1as input, RC2 as output
#define	PORTB_DIRECTION	0B10110000	// RB4 & RB5 as input
#define	PWM_Period			93			// write value to PR2 reg.
										// PWM period = [(PR2) + 1] * 4 * Tosc * (TM2 prescale value)
										// PR2 = 93, PWM fequency = 35.9 kHz
#define	PWM_Dutycycle		31			// write value to CCPR1L
										// Duty cycle = (CCPR1L:CCP1CON<5:4>) * Tosc * (TMR2 prescale value)
										// Duty cycle should be 1/3 of period to keep stable
										// CCPR1L:CCP1CON<5:4> = 125 ( 0b01111101)
										// CCPR1L = 47  ( 0b00011111)
//***************************************************************************
// variable definitions
//***************************************************************************
unsigned int		i;	// used for time delay loop
//***************************************************************************
// function definitions
//***************************************************************************
void	Initialize_Timer2();
void	Initialize_CCP1();				// work in PWM mode
void	Initialize_Ports();
void	interrupt Interrupt_Service();
void	Send_Head();
void	Send_One();
void	Send_Zero();
//***************************************************************************
// main program
//***************************************************************************
void main()
{
	Initialize_Ports();
	Initialize_Timer2();
	Initialize_CCP1();				// work in PWM mode
	for(;;);
}
//***************************************************************************
// Initialize_Ports()
//***************************************************************************
void Initialize_Ports()
{
	TRISB = PORTB_DIRECTION;
	TRISC = PORTC_DIRECTION;
	RC2 = 0;
	RBPU = 0;	// Enable internal resister of PORTB
	RBIF = 0;
	GIE  = 1;
	PEIE = 1;
	RBIE = 1;
}
//***************************************************************************
// Initialize_Timer2()
//***************************************************************************
void Initialize_Timer2()
{
	T2CKPS1 = 0;		// Timer2 prescale 1:1
	T2CKPS0 = 0;
	return;
}
//***************************************************************************
// Initialize_CCP1()
//***************************************************************************
void Initialize_CCP1()
{
	CCP1M3 = 1;	// PWM mode
	CCP1M2 = 1;
	PR2 = PWM_Period;
	CCPR1L = PWM_Dutycycle;
	CCP1X = 0;		// CCP1CON<5>
	CCP1Y = 1;		// CCP1CON<4>
	return;
}
//***************************************************************************
// Send_Head()
//***************************************************************************
void Send_Head()
{
		TMR2ON = 1;				// Timer1 enable, PWM starts
		// 4*24 = 96 pulses, delay 2673.778 us
		for(i=0;i<529;i++);			// actually delay 2669.926 us
		TMR2ON = 0;				// Timer1 disable, PWM stops
		TMR2 = 0;
}
//***************************************************************************
// Send_Zero()
//***************************************************************************
void Send_Zero()
{
		// delay about 24pulses, delay 668.444 us
		for(i=0;i<131;i++);			// actually delay 665.481 us
		TMR2ON = 1;				// Timer1 enable, PWM starts
		// 24 pulses, delay 668.444 us
		for(i=0;i<131;i++);			// actually delay 665.185 us
		TMR2ON = 0;				// Timer1 disable, PWM stops
		TMR2 = 0;
}
//***************************************************************************
// Send_One()
//***************************************************************************
void Send_One()
{
		// delay about 48 pulses, delay 1336.889us
		for(i=0;i<264;i++);			// actually delay 1337.778 us
		TMR2ON = 1;				// Timer1 enable, PWM starts
		// 24 pulses, delay 668.444 us
		for(i=0;i<131;i++);			// actually delay 665.185 us
		TMR2ON = 0;				// Timer1 disable, PWM stops
		TMR2 = 0;
}
//***************************************************************************
// interrupt Interrupt_Service()
//***************************************************************************
void interrupt Interrupt_Service()
{
	if (RBIF == 1)
	{
		for(i=0;i<300;i++);			// delay for debouncing
		if (RB4 == 0)				// increase button pressed, send out data: 1100
		{
			Send_Head();
			Send_One();
			Send_One();
			Send_Zero();
			Send_Zero();
			Send_Zero();			// send 4 bits: 0011 to check
			Send_Zero();	
			Send_One();
			Send_One();
			Send_Zero();			// stop bit
		}
		else if (RB5 == 0)			// decrease button pressed, send out data: 0011
		{
			Send_Head();
			Send_Zero();
			Send_Zero();
			Send_One();
			Send_One();
			Send_One();			// send 4 bits: 1100 to check
			Send_One();
			Send_Zero();
			Send_Zero();	
			Send_Zero();			// stop bit
		}
		RBIF = 0;
	}
}