/*
	5keylad.c

   PK21xx/Rugged Giant and PK22xx/Little Star Sample Program.
   
   Demonstrates 5key system and ladder C for control.
   Combines 5keycode.c and ladderc.c.
   Runs on Z-World's Demo Unit Two (robot arm).
*/

#use "default.h"
#use cplc.lib
#use 5key.lib
#use 5keyextd.lib
#use rtk.lib
#use gate_p.lib

#define NTASKS 7

#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

/***Begin Globals real_time_kernel  */
int task0(void), task1(void), task2(void), task3(void), 
    task4(void), task5(void), backgnd(void);
int (*Ftask[])() =
{
    task0, task1, task2, task3, task4, task5, backgnd
};

#define TASK0 0
#define TASK1 1
#define TASK2 2
#define TASK3 3
#define TASK4 4
#define TASK5 5

/***End Globals real_time_kernel */


#define RUNKERNEL 1
char time0[15];
char *time0_help[] =
     {
         "Set system time,",
         "use field, up &",
         "down key to chng"
     };
char date0[15];
char *date0_help[] =
     {
         "Set system date,",
         "use field, up &",
         "down key to chng"
     };


// Function Declaration
void input_output_menu(void);   // IO menuing with the 5key system
void time_date_menu(void);      // time date menu with the 5key system
void motor_pump(void);          // ladder C for motor/pump control
void sequence_lite(void);       // ladder C for sequencing of 3 lights (OUTS)
void heater(void);              // ladder C for heater control

extern int timer_menu(void);    // virtual timer menu for gate_p.lib
extern int uset_menu(void);     // universal input level menu from gate_p.lib
extern void reset_timers(void); // reset virtual timers
main()
{
    uplc_init();                // init background drivers
    reset_timers();             // reset the state of the virtual timers
    T1RLD = 40;                 // 1 count is 25 ms >> 40 x 25ms = 1 sec
    T2RLD = 40;
    T3RLD = 40;
    T4RLD = 40;
    T5RLD = 40;                 // load virtual timers

#if BOARD_TYPE==CPLC_BOARD
     upoint[0].ulow_set = 6950; // set limits for UIN1
     upoint[0].uhigh_set = 7000;
     U1HIGH = up_uncal(upoint[0].uhigh_set);
     U1LOW = up_uncal(upoint[0].ulow_set);
#endif
    backgnd();               // runs background task of the RTK
}


indirect task0(void)         // control loop is run every 25 ms
{
    motor_pump();
    sequence_lite();         // can actually run more than one ladderc blocks
                             // as long as the io's do no have any conflicts.
    heater();
}


indirect task1(void)
{
                             // task not used
}

indirect task2(void)
{
                             // task not used
}

indirect task3(void)
{
                             // task not used
}

indirect task4(void)
{
                             // task not used
}

// task server for 5 key system
indirect task5(void)
{
    while (1)
    {
        time_date_menu();
        input_output_menu();
        timer_menu();

#if BOARD_TYPE==CPLC_BOARD
        uset_menu();
#endif

    }
}

indirect backgnd(void)
{
    request(TASK5);          // request task for the 5key system
    run_every(TASK0, 1);     // run Ladder C control task every 25 ms
    while (1) 
        runwatch();          // do infinite loop; monitor with watch window
}

// 5key system for IO menu
void input_output_menu(void)
{
    lcd_server(3, 0L, "Input Output Set");
    while (1)
    {
#if BOARD_TYPE==CPLC_BOARD
        if (_5key_uinput() == MENU) 
            return;
        if (_5key_diginput() == MENU) 
            return;
        if (_5key_12out() == MENU) 
            return;
        if (_5key_dacout() == MENU) 
            return;
#elif BOARD_TYPE==L_STAR
        if (_5key_bank1dig() == MENU) 
            return;
        if (_5key_bank2dig() == MENU) 
            return;
        if (_5key_14out() == MENU) 
            return;
#endif
    }
}

// 5key system for time date menu
void time_date_menu(void)
{
    lcd_server(3, 0L, "Time Date Set");
    while (1)
    {
        if (_5key_time("time   ", time0, time0_help, 
        sizeof(time0_help), 1, 1, 10) == MENU) 
            return;
        if (_5key_date("date   ", date0, date0_help, 
        sizeof(date0_help), 1, 1, 10) == MENU) 
            return;
    }
}

/************************************************************************
ladderc.c
     -  sample program using ladderc concept.
     -  use the virtual drivers for the io's.
     -  use the virtual timers for the timing.
     -  timer reload values are set in softwares.
     - 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
         - 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.
**************************************************************************/

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

#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       // start timer1
#define T1_DONE    T1O       // timer1 is done
#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         // driver for light1
#define LITE2   OUT9         // driver for light2
#define LITE3   OUT10        // driver for light3

#define HEATER_ON_OFF  OUT3  // driver for a coil heater

#if BOARD_TYPE==CPLC_BOARD
#define THERMISTOR U1IN      // thermistor voltage read
#elif BOARD_TYPE==L_STAR
#define THERMISTOR DIGIN9    // use digital input 9 to mimic thermistor
#endif

// Ladder C for motor pump control
void motor_pump(void)
{
    OIL_PUMP = (OIL_PUMP OR START) AND MACHINE_ON AND NOT T2_DONE;

    START_T1 = OIL_PUMP AND MACHINE_ON AND NOT_STOP AND NOT T1_DONE;
    
    MOTOR = (T1_DONE OR MOTOR) AND NOT_STOP AND MACHINE_ON;

    START_T2 = (NOT NOT_STOP OR START_T2) AND MACHINE_ON AND NOT T2_DONE;
}

// Ladder C for Light Sequencing Control
void sequence_lite(void)
{
    LITE1 = (START OR T5_DONE OR LITE1) AND NOT_STOP AND MACHINE_ON
    AND NOT T3_DONE;

    START_T3 = LITE1;

    LITE2 = (T3_DONE OR LITE2) AND NOT_STOP AND MACHINE_ON AND NOT T4_DONE;

    START_T4 = LITE2;
    
    LITE3 = (T4_DONE OR LITE3) AND NOT_STOP AND MACHINE_ON AND NOT T5_DONE;
    
    START_T5 = LITE3;
}

// Ladder C for Heater Control
void heater(void)
{
    char start_heating;
#GLOBAL_INIT
    {
        start_heating = 0;
    }
    start_heating = (start_heating OR START) AND MACHINE_ON AND NOT_STOP;
    
    HEATER_ON_OFF = start_heating AND MACHINE_ON AND THERMISTOR;
}



