/*
	SCANBLK.C

   	This sample illustrates the use of the Dynamic C funcblk construct (i.e.
   "costatements"). It also illustrates the use of the virtual drivers for i/o
   and the virtual timers for timing. The timer reload values are set in
   software.

	Following are actions performed by this sample.
	
     - motor_pump()
         - when started, the pump comes on first
         - the motor comes on after the specified delay
         - when stop, the motor stops right away.
         - the pump stops after a specified delay.
         - a machine off shuts down everything.

     - sequence_lite()
         - when started, lite 1 comes on
         - after some delay, lite1 is off, lite2 comes on
         - after some delay, lite2 is off, lite3 comes on
         - after some delay, lite3 is off, lite1 comes on
         - a stop or a machine_off shuts down everything.

      - heater()
         - universal input U1IN is connected across a thermistor
         - U1IN is replaced by DIGIN9 for the Little Star.
         - when the voltage read is high ( thermistor is cool)
            the heater is turn on with OUT3.
         - when the voltage read is low ( thermistor is hot)
            the heater is turn off with OUT3.

      - Runs on Z-World's Demo Unit Two

	See the file ladderc.c for a Ladder C version of this program.
*/

#use "default.h"
#use cplc.lib

#if !(BOARD_TYPE==CPLC_BOARD || BOARD_TYPE==L_STAR)
#fatal "This program only runs on a PK21xx/Rugged Giant or a PK22xx/Little Star"
#endif

#define AND &&
#define OR  ||
#define NOT !

#define ON 1
#define OFF 0

#define START      DIGIN3    // DIGIN3 is a NC switch
#define NOT_STOP   DIGIN2    // DIGIN2 is a NO switch
#define MACHINE_ON DIGIN1    // DIGIN1 is a toggle switch
#define MOTOR      OUT1      // OUT1 drives a MOTOR
#define OIL_PUMP   OUT2      // OUT2 drives a PUMP

#define START_T1  T1I
#define T1_DONE   T1O
#define START_T2  T2I
#define T2_DONE   T2O

#define START_T3 T3I
#define START_T4 T4I
#define START_T5 T5I
#define T3_DONE  T3O
#define T4_DONE  T4O
#define T5_DONE  T5O

#define LITE1   OUT8
#define LITE2   OUT9
#define LITE3   OUT10

#define HEATER_ON_OFF  OUT3

#if BOARD_TYPE==CPLC_BOARD
#define THERMISTOR U1IN
#elif BOARD_TYPE==L_STAR
#define THERMISTOR DIGIN9    // use digin 9 to mimic themistor
#endif

extern FuncBlk motor_pump;
extern FuncBlk sequence_lite;
extern FuncBlk heater;

main()
{
    char on_flag;
    uplc_init();

#if BOARD_TYPE==CPLC_BOARD
    U1HIGH = up_uncal(8000); // high threshold is 8 volts
    U1LOW  = up_uncal(6000); // low threshold is 5 volts
#endif

    while (1)                // do an infinite loop
    {
        runwatch();          // monitor with the watch window
        funcblk monitor_start_stop always_on
        {
            waitfor(START AND MACHINE_ON);
            CoBegin(&motor_pump); // start motor_pump block
            CoBegin(&sequence_lite); // start sequence_lite block
            CoBegin(&heater); // start heater block
        }
        funcblk motor_pump
        {
            OIL_PUMP = ON;
            waitfor(DelaySec(2L) OR NOT NOT_STOP OR NOT MACHINE_ON);
            if (NOT NOT_STOP OR NOT MACHINE_ON)
            {
                OIL_PUMP = OFF; // Didn't have chance to turn motor on
            }
            else
            {
                MOTOR = ON;
                waitfor(NOT NOT_STOP OR NOT MACHINE_ON);
                MOTOR = OFF;
                if (NOT MACHINE_ON) 
                    OIL_PUMP = OFF; // Machine is off, turn off pump now! 
                else
                {
                    waitfor(DelaySec(2L) OR NOT MACHINE_ON);
                    OIL_PUMP = OFF;
                }
            }
        }                    // end of motor_pump block

        funcblk sequence_lite
        {
            do
            {
                LITE1 = ON;
                waitfor(DelaySec(1L) OR NOT NOT_STOP OR NOT MACHINE_ON);
                if (NOT NOT_STOP OR NOT MACHINE_ON) 
                    break;
                LITE1 = OFF;
                LITE2 = ON;
                waitfor(DelaySec(1L) OR NOT NOT_STOP OR NOT MACHINE_ON);
                if (NOT NOT_STOP OR NOT MACHINE_ON) 
                    break;
                LITE2 = OFF;
                LITE3 = ON;
                waitfor(DelaySec(1L) OR NOT NOT_STOP OR NOT MACHINE_ON);
                if (NOT NOT_STOP OR NOT MACHINE_ON) 
                    break;
                LITE3 = OFF;
            } while (1);
            LITE1 = LITE2 = LITE3 = OFF;
        }                    // end of sequence_lite block

        funcblk heater
        {
            do
            {
                waitfor(THERMISTOR OR NOT NOT_STOP OR NOT MACHINE_ON);
                             // when cool, turn on heater
                if (NOT NOT_STOP OR NOT MACHINE_ON) 
                    break;
                HEATER_ON_OFF = ON;
                waitfor(NOT THERMISTOR OR NOT NOT_STOP OR NOT MACHINE_ON);
                             // when hot, turn off heater
                if (NOT NOT_STOP OR NOT MACHINE_ON) 
                    break;
                HEATER_ON_OFF = OFF;
            } while (1);
            HEATER_ON_OFF = OFF;
        }                    // end of heater block
    }
}

