#include <pic.h>

__CONFIG ( UNPROTECT & BORDIS & MCLRDIS & PWRTEN & WDTDIS & INTIO ) ;

/* 
This program outputs the Nikon D70 remote shutter release code by IR LED

You are free to use this code for anything you want but please send me
  (al@alanmacek.com) an email telling me what you are using it for and
  how it works out.  You are NOT ALLOWED to use this code until you send
  me an email.
    
This code comes with absolutely no warranty at all.  It works for me
  and hopefully will work for you as well

This is based on the well written and informative website by 'BigMike' who
  figured out the Nikon pulse code - http://www.bigmike.it/ir-control.html

-------------------------------
The NikonD70 pulse code is:
	2250us high
	27600us low
	650us high
	1375us low
	575us high
	3350us low
	650us high
	-- repeated a second time after 63ms

This program is designed to run on the 12F675's 4MHz internal clock which
  means each instruction is 1us long.  The IR output is modulated at 40kHz
  which is 25us per modulated cycle.
*/

#include "delay.h"

#define NOP4	asm("nop"); asm("nop"); asm("nop"); asm("nop");
#define NOP2	asm("nop"); asm("nop");

/* pin connections for the 12F675
1 - Power
2 - GP5(o) - 
3 - GP4(o) - 
4 - GP3(i) -
5 - GP2(i) -
6 - GP1(o) -
7 - GP0(o) - IR LED
8 - Ground
*/

//Declare the IO pins
static bit IRLED @ (unsigned)&GPIO*8+0; /* pin 7 */
static bank1 bit IRLED_DIR @ (unsigned)&TRISIO*8+0;

//Declare some nice constants
#define LED_ON 		1;
#define LED_OFF		0;
#define IO_INPUT 	1;
#define IO_OUTPUT 	0;

//predeclare this function - see below for details
void SendIRSequence();

//start of main execution
int main()
{
	//intialize IO
	GPIO = 0;
	CMCON = 0x07;
	ANSEL = 0;
	IRLED = LED_OFF;
	IRLED_DIR = IO_OUTPUT;

	//start pattern - do it twice
	SendIRSequence();	//first sequence
	DelayMs(62);		//actually 63ms
	SendIRSequence();	//second sequence

	asm("sleep; ");		//stop execution to save power
}

//sends out a pulse of IR modulated at 40khz
// - the parameter is the number of cycles to send
// - each cycle is 25us long - and 50% duty cycle
//the macro converts microseconds into cycles
#define SendIRPulse(x) SendIRPulseCycles(x/25);
void SendIRPulseCycles(char cycles)
{
	while (cycles--)		//this loop is exactly 25us - of approximately 50% dutycycle
	{
		IRLED = LED_ON;
		NOP4; NOP4; NOP2;
		IRLED = LED_OFF;
		NOP4; NOP4;
	}
}

//This is a delay loop that in theory delays an precise number of microseconds
//unfortunately it isn't particularly accurate
// - but it is easier to just trial/error the parameter value than to fix the function
#define waitExactUs(x) waitExactUsHex(x/256, (x%256)/5);
void waitExactUsHex(char hByte, char lByte)
{
	char i;
	while (lByte--) { continue; }	//delay for the extra bit
	while (hByte--) {				//delay loop for the bulk of the time
		i = 61;
		while (i--) { continue; }
		}
}

//This sends out the coded modulated IR pulses
// the sequence is courtesy of http://www.bigmike.it/ir-control.html
void SendIRSequence()
{
	SendIRPulse(2250);	//2250us of modulated IR
	waitExactUs(27900);	//delay 27600 us
	SendIRPulse(650);	//650us of modulated IR
	waitExactUs(1375);	//delay 1375 us
	SendIRPulse(575);	//575us of modulated IR
	waitExactUs(3373);	//delay 3350 us
	SendIRPulse(650);	//650us of modulated IR
}
