/*
   Copyright (c) 2015, Digi International Inc.

   Permission to use, copy, modify, and/or distribute this software for any
   purpose with or without fee is hereby granted, provided that the above
   copyright notice and this permission notice appear in all copies.

   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/********************************************************************
	triac_phase_flash.c

	Description
	-----------
   This program demonstrates phase-angle triac control with
   writing to application code flash (Does not apply to serial
   flashes).


   PowerCoreFLEX Prototyping Board Setup:
   --------------------------------
   1. Solder-in incandescent lamps provided in your kit into
      DS1 and DS2 (This step not needed if you're going to
      monitor with oscilloscope or you're using some other
      load circuit).


	Instructions:
	-------------
   1. Compile and run this program.
 	2. Then you can monitor the triac control pin with an
      oscilloscope to see the control pin going active at
      phase-angles 0 - 180. Control pins are located on
      connector J4 of the prototyping board as follows:

      J4 Pin#   Signal name
      -------	 -----------
        41      PF2_SCR-0
        40      PF3_SCR-1

   3. If incandescent lamps are installed, visually monitor
   	the lamps, you should see lamps go from being full ON
      to dimming down to being OFF.

   4. Select menu option 1 to observe (via steps 2 and/or 3
      listed above) the triac control being disabled when
      writing to application code flash.

*********************************************************************/
//  Set a default of declaring all local variables "auto" (on stack)
#class auto

// Sample library for PowerCoreFLEX series core modules
#use "PowerCoreFLEX.lib"

// Define phase-angle triac control method for proper
// library compilation.
#define PHASECONTROL

// Set the max number of triacs for application control
#define MAX_TRIACS 2

// Define the triac custom function ON/OFF function names
// for proper library compilation.
#define TRIAC_GATE_ON 	triac_gate_on
#define TRIAC_GATE_OFF 	triac_gate_off

// Function proptypes for the custom I/O routines.
void triac_gate_on(int triac);
void triac_gate_off(int triac);

// Use the common ISR library for the triac and the ADC
// ramp circuit.
#use "adctriac_isr.lib"

// Use the triac library
#use "triac.lib"

nodebug
void msDelay(unsigned int delay)
{
	auto unsigned long done_time;

	done_time = MS_TIMER + delay;
   while( (long) (MS_TIMER - done_time) < 0 );
}

// set the STDIO cursor location and display a string
void DispStr(int x, int y, char *s)
{
   x += 0x20;
   y += 0x20;
   printf ("\x1B=%c%c%s", x, y, s);
}

void  blankScreen(int start, int end)
{
	auto char buffer[256];
   auto int i;

   memset(buffer, 0x00, sizeof(buffer));
 	memset(buffer, ' ', sizeof(buffer));
   buffer[sizeof(buffer)-1] = '\0';
   for(i=start; i < end; i++)
   {
   	DispStr(start, i, buffer);
   }
}

main()
{
 	auto int key, i, j;
   auto int triac0_cntrl, triac1_cntrl;
   auto char s[256];
   auto int userblock_flashwrite;

   // The brdInit function is only used to configure the I/O
   // on the prototyping board and is not required for the triac
   // library which will configure everything required for triac
   // control.
   brdInit();

 	triac_PhaseInit(1, 3);
   triac_PhaseCntrlPin(0, PFDR, 2, 0);
	triac_PhaseCntrlPin(1, PFDR, 3, 0);
   triac_PhaseInitPWM(0, 0, 300, 0, 10000ul);

   triac0_cntrl = 0;
   triac1_cntrl = 50;

   DispStr(1, 1,  "Triac Status");
   DispStr(1, 2,  "------------");
   sprintf(s,"Triac 0 ON, phase angle = %d   ", triac0_cntrl);
   DispStr(1, 3, s);
   sprintf(s,"Triac 1 ON, phase angle = %d   ", triac1_cntrl);
   DispStr(1, 4, s);


   DispStr(1, 6,  "Option Menu");
	DispStr(1, 7,  "-----------");
   DispStr(1, 8, "1. Write to flash");
   DispStr(1, 9, "2. Exit program");

  	userblock_flashwrite = FALSE;
   while (1)
	{
		costate
		{
         // Do asynchronous control of triac's
         if(!userblock_flashwrite)
         {
         	triac_PhaseCntrl(0, 1, triac0_cntrl, 0);
         	triac_PhaseCntrl(1, 1, triac1_cntrl, 0);
 			}
         else
         {
         	sprintf(s,"Triac 0 OFF, phase angle = 0  ");
   		  	DispStr(1, 3, s);
           	sprintf(s,"Triac 1 OFF, phase angle = 0  ");
   			DispStr(1, 4, s);

            // Disable triac driver...Its a non-blocking function which
            // takes approx. 50 ms to execute.
            waitfor(triac_PhaseDisable());

            // Write to application code flash
            writeUserBlock(0, "test", 4);

            // Re-enable triac driver...Its a non-blocking function which
            // takes approx. 750 ms to execute.
            waitfor(triac_PhaseEnable());

            // Delay so you can see STDIO display being updated
            waitfor(DelayMs(1000));
            DispStr(1, 10, "Select Option 1 - 2 >     ");
            userblock_flashwrite = FALSE;
            triac0_cntrl = 0;
   			triac1_cntrl = 50;
         }
      }

      costate
   	{
   		if(!userblock_flashwrite)
      	{
      		for(i=0; i < 180; i++)
      		{
            	if(triac0_cntrl > 180 || userblock_flashwrite)
               {
               	triac0_cntrl = 180;
               	break;
               }
            	sprintf(s,"Triac 0 ON, phase angle = %d  ", triac0_cntrl);
   				DispStr(1, 3, s);
               triac0_cntrl++;
        			yield;
      		}
      		for(i=0; i < 180; i++)
      		{
            	if(triac0_cntrl <= 0 || userblock_flashwrite)
        			{
        				triac0_cntrl = 0;
           			break;
          		}
            	sprintf(s,"Triac 0 ON, phase angle = %d  ", triac0_cntrl);
   				DispStr(1, 3, s);
        			triac0_cntrl--;\
        			yield;
         	}
      	}
   	}
   	costate
   	{
     		if(!userblock_flashwrite)
      	{
      		for(j=0; j < 180; j++)
      		{
            	if(triac1_cntrl > 180 || userblock_flashwrite)
               {
                 	triac1_cntrl = 180;
                	break;
               }
            	sprintf(s,"Triac 1 ON, phase angle = %d  ", triac1_cntrl);
   				DispStr(1, 4, s);
               triac1_cntrl++;
        			yield;
      		}
      		for(j=0; j < 180; j++)
      		{
            	if(triac1_cntrl <= 0 || userblock_flashwrite)
        			{
        				triac1_cntrl = 0;
           			break;
          		}
            	sprintf(s,"Triac 1 ON, phase angle = %d  ", triac1_cntrl);
   				DispStr(1, 4, s);
        			triac1_cntrl--;
        			yield;
      		}
      	}
   	}


      costate
		{
         if(kbhit())
			{
				key = getchar();
            while(kbhit()) getchar();

            if( key >= '1' && key <='2')
				{
            	sprintf(s, "Select Option 1 - 2 > %c  ", key);
            	DispStr(1, 10, s);
            }
            switch(key)
            {
               case '1':
               	userblock_flashwrite = TRUE;
                 	break;
               case '2':
               	// Disable triac control driver before exiting
                 	waitfor(triac_PhaseDisable());
               	exit(0);
            }
         }
   	}
	}
}


//----------------------------------------------------------------------
// Custom triac control routines, triac_gate_on() and triac_gate_off().
// These routines are already set up for the PowerCoreFLEX series core module
// prototyping board. If you have a custom design you will need to change
// the routines to match the I/O port pins that you're using.
//
// The following registers are available for use by this routine:
// Registers...af, bc, de, hl, ix, and iy.
//------------------------------------------------------------------------
#asm root nodebug
triac_gate_on::
   ld		a,l
   ld 	de,PFDR
	ld 	hl,PFDRShadow
   or		a,(hl)
   ld    (hl),a
	ioi 	ldd
   ret
#endasm


#asm root nodebug
triac_gate_off::
   ld		a,l
   cpl
   ld 	de,PFDR 	; Port address
	ld 	hl,PFDRShadow
   and	a,(hl)
   ld    (hl),a
	ioi 	ldd   	; [io](de) <- (hl)  copy shadow to port
   ret
#endasm



