/******************************************************************************
  ZJ_SineInverter.c   xtal-locked push-pull sinewave Inverter driver
  Open-source  -  8th Dec 2009  -  www.RomanBlack.com/one_sec.htm

  PIC 12F675, xtal (see below).
  This manually generates dual inverted sinewave PWM outputs.
  PWM frequency varies from 25kHz to 47kHz depending on the step.
  It will drive push-pull FETs to make a mains inverter;
    10MHz xtal; 50Hz output (same code is used for both)
    12MHz xtal; 60Hz output  
  GP0 - this is push-pull outputA (hi = FET on)
  GP1 - this is push-pull outputB (hi = FET on)
  
_BODEN_OFF _MCLRE_OFF _PWRTE_ON _WDT_OFF _HSOSC
******************************************************************************/

// edit PERIOD to give the freq; PERIOD = (xtal / 4 / (freq*20))
// Note! we need 20 period events per mains cycle, so use (freq * 20)
#define PERIOD 2500   // 10Mhz xtal = 50Hz, 12MHz xtal = 60Hz. (don't edit)
#define PERHI (PERIOD / 256)          // don't edit this!
#define PERLO (PERIOD - (PERHI*256))  // don't edit this!

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()
{
  // TMR1 interrupt. This is a very simple zero-error TMR1 correction.
  // It generates an interrupt every 2500 PIC instructions.
  // (this code was hardware tested to exact cycle accuracy)
  TMR1L -= (PERLO - 2);   // fix TMR1, retain error for next period
  TMR1H -= (PERHI + 1);
  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 = 0b00000000;  // All outputs
  //-----------------------------------------------------
  // timer setup etc
  OPTION_REG = 0b00001000;  // TMR0 on, 1:1 prescale
  T1CON  = 0b00000001;  // TMR1 on, 1:1 prescale
  INTCON = 0b11000000;  // GIE on, PEIE on 
  PIE1 =   0b00000001;  // TMR1 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;
  }
}
//-----------------------------------------------------------------------------