#if defined __RC51__
  #define CODE code
#elif defined SDCC
  #define CODE __code
#else
  #error "Unknown compiler"
#endif


#include <c8051F040.h>

// #include "ports.h"
// #include "smoker_iopoints.h"
// #include "nib.h"
// #include "LCD.h"
// #include "time.h"
// #include "recipes.h"

// #include <stdlib.h> // not needed while NULL is commented out

#define NUM_OF_RULES_PER_RECIPE     10


//this file handles the saving / restoring and control of the recipes for the smoker.
//in short we have only a few variables that we are able to control we can load these in a struct and save the whole struct to flash.


#define RULE_ACTION_ON          1
#define RULE_ACTION_OFF         2
#define RULE_ACTION_REGULATE    3
#define RULE_ACTION_PULSE       4

#define RULE_START_COND_ABSOLUTE       1
#define RULE_START_COND_PRIOR_RULE     2
#define RULE_START_COND_ANY_RULE       3


#define RULE_FEEDBACK_EXTERNAL_IO       1
#define RULE_FEEDBACK_TIME_OFF          2
#define RULE_FEEDBACK_TIME_ON           3

#define RULE_NOT_STARTED                0
#define RULE_IN_PROGRESS                1
#define RULE_COMPLETED                  2




struct strct_rules{
    unsigned char out_point;
    unsigned char action;
    unsigned char start_condition;
    unsigned char start_time;
    unsigned char stop_time;
    unsigned char feedback_rule;
    unsigned char feedback_point;
};





struct recipe{
    char    title[16];                   // RECIPE TITLE
    unsigned int run_time;
    struct strct_rules rules[NUM_OF_RULES_PER_RECIPE];       //each recipe has 10 rules that it can have.

};


#define HEAT_OUTPUT 0
#define SMOKE_OUTPUT 1
#define PUMP_OUTPUT 2
#define THERMOSTAT_INPUT 3

CODE struct recipe salmon = {
    "SALMON",       //nice title
    20,             //run for 20mins
    {
        {HEAT_OUTPUT,   RULE_ACTION_REGULATE,   RULE_START_COND_ABSOLUTE,   0, 0, RULE_FEEDBACK_EXTERNAL_IO, THERMOSTAT_INPUT},           //turn on the element
        {SMOKE_OUTPUT,  RULE_ACTION_ON,         RULE_START_COND_ABSOLUTE,   0, 5, RULE_FEEDBACK_TIME_OFF,   0},                           //turn on the smoke for 5mins
        {PUMP_OUTPUT,   RULE_ACTION_PULSE,      RULE_START_COND_PRIOR_RULE, 0, 1, RULE_FEEDBACK_TIME_OFF,   0},                           //start the pump pulsing for 1 min on / off after smoke has been on for 5mins
        {SMOKE_OUTPUT,  RULE_ACTION_PULSE,      RULE_START_COND_PRIOR_RULE, 0, 1, RULE_FEEDBACK_TIME_OFF,   0}                           //start the smoke pulsing for 1 min on / off after pump has been on for 1mins
    }
};



struct strct_running_recipe {
    CODE struct recipe *recipe_in_flash;
    unsigned int recipe_elapsed_time;
    unsigned int rule_elapsed_time[NUM_OF_RULES_PER_RECIPE];    //hold variable for the elapsed time in a rule
    unsigned char rule_holding_var[NUM_OF_RULES_PER_RECIPE];
    unsigned char rule_active[NUM_OF_RULES_PER_RECIPE];
};

//load a few defaults for us
//bacon
//salmon
//kahawai
//snapper
//chicken
//cheese
//sausages
//salami
//cold smoke
//hot smoke


struct strct_running_recipe current_recipe;


void funInitRecipe(void){
    unsigned char i;
    static unsigned char j;
    current_recipe.recipe_in_flash = &salmon;
    current_recipe.recipe_elapsed_time = 0;

    for (i = 0; i< NUM_OF_RULES_PER_RECIPE; i++){
        current_recipe.rule_elapsed_time[i] = 0;
        current_recipe.rule_holding_var[i] = 0; // NULL;
        current_recipe.rule_active[i] = RULE_NOT_STARTED;
    }

    i = current_recipe.recipe_in_flash->rules[1].stop_time;
    j = i;
}



void funExecuteRecipe(void){
//this function assumes that current_recipe is loaded with a recipe and is
//available, we could have had it accept a recipe pointer but that seems kind of redunant
//as we can only run one recipe at a time.
    static unsigned long start_time = 0;
    unsigned char rule_index = 0;

    if (start_time == 0){
//        start_time = sysTime;
    }

    //whip through all the rules and look for the inactive rules.
    for (rule_index = 0 ; rule_index < NUM_OF_RULES_PER_RECIPE; rule_index++){

        if (current_recipe.rule_active[rule_index]== RULE_NOT_STARTED){ //rule is not active
            if (current_recipe.recipe_in_flash->rules[rule_index].start_condition == RULE_START_COND_ABSOLUTE){ //se if we are supposed to start on a time stamp.
                //obviously more to do in here.
            }
        }
    }
}
