//***************************************************************************
//******
//****** PIC12F675. TCI ignition
//****** 
//****** SPORTDEVICES 3/3/2008
//******
//****** Tested on Kymco MXU250 ATV
//******
//****************************************************************************

#include <12F675.H>
#fuses HS,NOWDT,PUT,NOMCLR
#use fast_io(a)
#use delay(clock=10000000)

//setup values
#define prescaler        8     //2^8=256
#define silent_time      500  //silent time after spark to avoid false triggers

#define rpm_cte          (60*10000000/4/256)
#define cut_off          rpm_cte / 9000
#define ralenti          rpm_cte / 2000
#define max_period       rpm_cte / 200
#define dwell_constant   10000000/4/256 * 0.005 //5 ms

const byte ignition0[52]={
//9000 rpm
//20,21,22,23,24,25,26,27
5,5,5,6,6,6,6,6
//8000 rpm
//28,29,33,38,44,50,55,60,65,70
9,9,11,12,12,15,20,25,30,32
//7000 rpm
//69,74,77,80,81,82,83,84,85,86,87,89,91,93
34,37,38,40,50,61,83,84,85,86,87,89,91,93
//6000 rpm
97,100,103,107,113,119,124,131,137,140,145,150,157,160,165,170,175,176,177,178
//5000 rpm
};

#define pickup_hi  PIN_A3  //pin 4
#define pickup_lo  PIN_A2  //pin 5
#define coil       PIN_A1  //pin 6

#byte TMR0=0x01
#byte STATUS=0x03
#byte PORTB=0x06
#byte INTCON=0x0b
#byte OPTION_REG=0x81
#byte CMCON=0x19
#byte ANSEL=0x9f

int tmr0h=0,del;
int16 dwell,per;
boolean low_rpm=true,hi_rpm=false;

#byte W_TEMP=0x7f
int STATUS_TEMP;

#int_ext
void ext()
{
  //low pulse
  //if(low_rpm)
  output_low(coil); //fire or turn off the coil
}

#int_timer0
void timer0()
{
  tmr0h++;
  if(tmr0h>2) low_rpm=true;
  if(tmr0h>(max_period/256)) output_low(coil); //turn off the coil (residual spark will be made)
}


void wait_pulse()
{
int16 tmp;

  while (input(pickup_hi));   //wait line goes low

  //wait dwell
  if(!low_rpm && !hi_rpm)
  {
    do
      tmp=make16(tmr0h,TMR0);
    while((tmp<dwell) && !input(pickup_hi));
    output_high(coil); //start dwell time now
  }
  //**

  hi_rpm=false; low_rpm=false;
  while (!input(pickup_hi));  //wait line goes high
  per=make16(tmr0h,TMR0);
  TMR0=0; tmr0h=0;

  if (per<cut_off)
    hi_rpm=true;
  else
    output_high(coil); //start dwell time (if not started yet)

}

void main(){

   CMCON=0x07;
   ANSEL=0;
   INTCON=0b10110000; //T0IE=1,INTE=1
   OPTION_REG=0b01000000 | prescaler-1;  //PULLUP on, INTEDG=rising(1), 2^prescaler=128
   set_tris_a(0b11111101);

   while (true)
   {
      //first pulse is not processed because the period can not be calculated until the second pulse
      do
        wait_pulse();
      while(low_rpm);

      dwell=per;

      if (!hi_rpm)
      {
        if(per<(sizeof(ignition0)+cut_off))
        {
          del=(int8)per-cut_off;
          del=ignition0[del];
          #asm
bucle1:   nop
          nop
          nop
          nop
          nop
          decfsz &del,f
          goto bucle1
          #endasm
        }
        else
        {
          if(per>ralenti) per=per<<1;

          #asm
          incf &per+1,f
          incf &per,f
bucle2:   #endasm
          delay_cycles(9);
          #asm
          decfsz &per,f
          goto bucle2
          decfsz &per+1,f
          goto bucle2
          #endasm
        }

      }
      if(!low_rpm) output_low(coil); //fire or turn off the coil

      dwell-=dwell_constant;


   delay_us(silent_time); //time after spark to avoid false triggers
   }  //while
} //main
