/******************************************************************************
  ZE_SineConverter.c   mains-locked 50Hz to 60Hz converting sinewave Inverter
  Open-source  -  9th Dec 2009  -  www.RomanBlack.com/one_sec.htm

  PIC 12F675, 8MHz xtal (see below).
  This generates dual push-pull sinewave outputs at 60Hz, which is
  freq locked to a 50Hz mains input. It acts as a 50Hz to 60Hz converter
  that can drive a transformer to make a mains freq converter.

  GP0 - this is 60Hz push-pull outputA (hi = FET on)
  GP1 - this is 60Hz push-pull outputB (hi = FET on)
  GP2 - is the \ edge detect for 50Hz mains input
  
_BODEN_OFF _MCLRE_OFF _PWRTE_ON _WDT_OFF _HSOSC
******************************************************************************/

// edit PERIOD to give the freq; PERIOD = (xtal / 4 / (freq*24))
// Note! we need 24 period events per mains cycle, so use (freq * 24)
#define PERIOD 1667   // 8Mhz xtal (don't edit this)
#define PERHI (PERIOD / 256)          // don't edit this!
#define PERLO (PERIOD - (PERHI*256))  // don't edit this!

unsigned char vpulse;   // to sequence the 24 virtual pulses
unsigned char step;     // sequences each of the 20 PWM steps

#define PHASEA 0b00000001;  // push-pull outputA on
#define PHASEB 0b00000010;  // push-pull outputB on

//=============================================================================
void interrupt()
{
  //-----------------------------------------------------
  // This is a TMR1 overflow interrupt for 23 of 24 cases.
  // on 1 of 24 cases it acts as a GP2 interrupt on \ edge.
  // This is used to generate exactly 24 virtual pulses,
  // synchronised to the 50Hz mains input (GP2 \ edge).
  //-----------------------------------------------------
  if(!vpulse)  // if it is last vpulse0
  {
    // just leave TMR1 free running, this allows easy first sync!
    vpulse = 23;
  }
  else      // else is vpulse1-23
  {
    TMR1L = (256 - (PERLO - 3 - 16));   // load TMR1 for 1 vpulse period
    TMR1H = (256 - (PERHI + 1));
    vpulse--;         // sequence the next virtual pulse
    INTCON.INTF = 0;  // clear GP2 \ edge int flag
  }
  step++;             // sequence the next 60Hz PWM step
  PIR1.TMR1IF = 0;
}

//=============================================================================
void Delay10(void)
{
  // gives a total delay of 10 PIC instructions
  asm goto $+1;   // 2 insts each
  asm goto $+1;
  asm goto $+1;
}
//=============================================================================
void Delay20(void)
{
  // gives a total delay of 20 PIC instructions
  asm goto $+1;   // 2 insts each
  asm goto $+1;
  asm goto $+1;
  asm goto $+1;
  asm goto $+1;
  asm goto $+1;
  asm goto $+1;
  asm goto $+1;
}

//=============================================================================
void main ()
{
  //-----------------------------------------------------
  // PIC 12F675  setup ports
  ANSEL = 0;            // ADC off
  CMCON = 0x07;         // comparators off
  GPIO =   0b00000000;  // clear GPIO
  TRISIO = 0b00000100;  // GP2 input, rest outputs
  //-----------------------------------------------------
  // timer setup etc
  OPTION_REG = 0b00001000;  // GP2 \ int edge 
  T1CON  = 0b00000001;  // TMR1 on, 1:1 prescale
  INTCON = 0b11000000;  // GIE on, PEIE on 
  PIE1 =   0b00000001;  // TMR1 int ON
  INTCON.INTE = 1;      // GP2 \ edge int ON
  //-----------------------------------------------------
  // main run loop here
  while(1)
  {
    //---------------------------------
    // 50% PWM
    sinestep0:
      step = 0;
    sinestep0b:
      GPIO = PHASEA;
      if(step == 1) goto sinestep1;
      Delay20();
      GPIO = PHASEB;
      Delay20();
      asm goto $+1;
      asm goto $+1;
      goto sinestep0b;

    //---------------------------------
    // 64% PWM
    sinestep1:
      GPIO = PHASEA;
      if(step == 2) goto sinestep2;
      Delay20();
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm nop;
      GPIO = PHASEB;
      Delay20();
      goto sinestep1;

    //---------------------------------
    // 78% PWM
    sinestep2:
      GPIO = PHASEA;
      if(step == 3) goto sinestep3;
      Delay20();
      Delay10();
      asm goto $+1;
      asm goto $+1;
      asm nop;
      GPIO = PHASEB;
      Delay10();
      goto sinestep2;

    //---------------------------------
    // 89% PWM
    sinestep3:
      GPIO = PHASEA;
      if(step == 4) goto sinestep4;
      Delay20();
      Delay20();
      asm goto $+1;
      asm goto $+1;
      GPIO = PHASEB;
      asm goto $+1;
      asm goto $+1;
      goto sinestep3;

    //---------------------------------
    // 96% PWM
    sinestep4:
      GPIO = PHASEA;
      if(step == 5) goto sinestep5;
      Delay20();
      Delay20();
      Delay20();
      Delay20();
      asm goto $+1;
      asm goto $+1;
      GPIO = PHASEB;
      asm goto $+1;
      goto sinestep4;

    //---------------------------------
    // 100% PWM
    sinestep5:
      GPIO = PHASEA;
      if(step == 6) goto sinestep6;
      goto sinestep5;

    //---------------------------------
    // 96% PWM
    sinestep6:
      GPIO = PHASEA;
      if(step == 7) goto sinestep7;
      Delay20();
      Delay20();
      Delay20();
      Delay20();
      asm goto $+1;
      asm goto $+1;
      GPIO = PHASEB;
      asm goto $+1;
      goto sinestep6;

    //---------------------------------
    // 89% PWM
    sinestep7:
      GPIO = PHASEA;
      if(step == 8) goto sinestep8;
      Delay20();
      Delay20();
      asm goto $+1;
      asm goto $+1;
      GPIO = PHASEB;
      asm goto $+1;
      asm goto $+1;
      goto sinestep7;

    //---------------------------------
    // 78% PWM
    sinestep8:
      GPIO = PHASEA;
      if(step == 9) goto sinestep9;
      Delay20();
      Delay10();
      asm goto $+1;
      asm goto $+1;
      asm nop;
      GPIO = PHASEB;
      Delay10();
      goto sinestep8;

    //---------------------------------
    // 64% PWM
    sinestep9:
      GPIO = PHASEA;
      if(step == 10) goto sinestep10;
      Delay20();
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm nop;
      GPIO = PHASEB;
      Delay20();
      goto sinestep9;

    //---------------------------------
    // 50% PWM
    sinestep10:
      GPIO = PHASEA;
      if(step == 11) goto sinestep11;
      Delay20();
      GPIO = PHASEB;
      Delay20();
      asm goto $+1;
      asm goto $+1;
      goto sinestep10;

    //---------------------------------
    // 64% PWM inv
    sinestep11:
      GPIO = PHASEB;
      if(step == 12) goto sinestep12;
      Delay20();
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm nop;
      GPIO = PHASEA;
      Delay20();
      goto sinestep11;

    //---------------------------------
    // 78% PWM inv
    sinestep12:
      GPIO = PHASEB;
      if(step == 13) goto sinestep13;
      Delay20();
      Delay10();
      asm goto $+1;
      asm goto $+1;
      asm nop;
      GPIO = PHASEA;
      Delay10();
      goto sinestep12;

    //---------------------------------
    // 89% PWM inv
    sinestep13:
      GPIO = PHASEB;
      if(step == 14) goto sinestep14;
      Delay20();
      Delay20();
      asm goto $+1;
      asm goto $+1;
      GPIO = PHASEA;
      asm goto $+1;
      asm goto $+1;
      goto sinestep13;

    //---------------------------------
    // 96% PWM inv
    sinestep14:
      GPIO = PHASEB;
      if(step == 15) goto sinestep15;
      Delay20();
      Delay20();
      Delay20();
      Delay20();
      asm goto $+1;
      asm goto $+1;
      GPIO = PHASEA;
      asm goto $+1;
      goto sinestep14;

    //---------------------------------
    // 100% PWM inv
    sinestep15:
      GPIO = PHASEB;
      if(step == 16) goto sinestep16;
      goto sinestep15;

    //---------------------------------
    // 96% PWM inv
    sinestep16:
      GPIO = PHASEB;
      if(step == 17) goto sinestep17;
      Delay20();
      Delay20();
      Delay20();
      Delay20();
      asm goto $+1;
      asm goto $+1;
      GPIO = PHASEA;
      asm goto $+1;
      goto sinestep16;

    //---------------------------------
    // 89% PWM inv
    sinestep17:
      GPIO = PHASEB;
      if(step == 18) goto sinestep18;
      Delay20();
      Delay20();
      asm goto $+1;
      asm goto $+1;
      GPIO = PHASEA;
      asm goto $+1;
      asm goto $+1;
      goto sinestep17;

    //---------------------------------
    // 78% PWM inv
    sinestep18:
      GPIO = PHASEB;
      if(step == 19) goto sinestep19;
      Delay20();
      Delay10();
      asm goto $+1;
      asm goto $+1;
      asm nop;
      GPIO = PHASEA;
      Delay10();
      goto sinestep18;

    //---------------------------------
    // 64% PWM inv
    sinestep19:
      GPIO = PHASEB;
      if(step == 20) goto sinestep0;
      Delay20();
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm goto $+1;
      asm nop;
      GPIO = PHASEA;
      Delay20();
      goto sinestep19;
  }
}
//-----------------------------------------------------------------------------