/*
 * zone_irene.c
 *
 *  Created on: Mar 14, 2025
 *      Author: Irene Hu
 */


#include "stdint.h"
#include "string.h"

#include "main.h"
#include "system.h"
#include "sleep.h"
#include "sample.h"
#include "serial.h"
#include "config.h"
#include "test.h"
#include "uart3.h"
#include "uartstdio.h"
#include "user_io.h"
#include "serial.h"
#include "board_util.h"
#include "apf.h"
#include "apf_util.h"
#include "apf_math.h"
#include "apf_numbr.h"
#include "mms_spec.h"
#include "mms_test.h"
#include "sample.h"
#include "ymodem.h"
#include "zmodem.h"
#include "i2c_fram.h"

// added on top of Thom's default includes
#include "i2c_pcal64xx.h"
#include "i2c_ina260.h"
#include "i2c_bme280.h"
#include "microsd.h"
#include "zone_irene.h"

#include <time.h>

//extern struct rxStateMach rx0;             // defd in serial.h
extern struct watchDog wdog;                // defd in board_util.h
extern struct apfCfgGlobals apf_eeprom;      //struct in apf_util.c, apf.h
//extern double **EcoefData, **EcoefFile;

#define ONTIMES_MS 5000
#define OFFTIME1_MS 80000
#define OFFTIME2_MS 10000
#define LOGINTERVAL_MS 100
#define LOGINTERVAL_SLOW_MS 1000

unsigned int tick_stateMachine;
unsigned int cycleNum;
unsigned int transitionFlag; // added 4/17/25 to flag measurements taken right after a transition
// these are often noisy, want to easily cut out of data


void log_current_voltage(char *filename, int bmeflag)
// IH 4/15/25 based on Thom's microsd_fatfs_hammer_test test0
// string manip for filename is from ec.c. any char limit on filename should be observed
// except we'll just reuse some of these isus write functions
// printout structure from sample.c
// 5/5/25 BMEflag to indicate if we'll use BME280 to measure temp/humidity/pressure or not
// this slows down measuring significnatly, need a different log interval
{
    uint32_t indx;

    char timestamp[TIMESTAMPLENGTH];
    uint32_t tickStart, tickLast;
    struct tm *time_struct;

    float fSysVolt, fSysAmp, fLampVolt, fLampAmp;
    int state;
    uint32_t uiHumidity = 0;
    float fBrdPressure = 0;
    float fBrdTempC = 0;

    unsigned long loginterval;

    if (bmeflag == 1) loginterval = LOGINTERVAL_SLOW_MS;
    else loginterval = LOGINTERVAL_MS;

    wdog_pet();

#if BOARD_MSC == 3
    // use the isus file write functions
    sprintf(apf_eeprom.logIsus, "//ISUS//%s.txt", filename);

    if (bmeflag == 1) {
        uprintf("Logging current, voltage, and environment");
    }
    else {
        uprintf("Logging current and voltage");
    }
    uprintf(" while turning ISUS things on and off. Logging interval is %lums. Hit any key to exit.", loginterval); prn_nl();
    uprintf("Filename = %s", apf_eeprom.logIsus); prn_nl();
#endif // BOARD_MSC == 3

    // print a header
    indx = 0;
    indx += sprintf((char*)&prnBuf[indx], "Timestamp\tTimeElapsed_ms\t");
    if (bmeflag == 1) {
        indx += sprintf((char *)&prnBuf[indx], "BrdT_C\tHumidity\tPressure\t");
    }
    indx += sprintf((char *)&prnBuf[indx], "CycleCt\tState\tTransFlag\tVin_V\tIin_A\tVlamp_V\tIlamp_A\t");
    indx += sprn_nl((char*)prnBuf, indx);
    //uprintf("%s", prnBuf);
#if BOARD_MSC == 3
    appendIsusProfileDataToSDCard((char*)prnBuf);      //exercise the fxn for writing ISUS log
#endif // #if BOARD_MSC == 3

    tickStart = Timer_1ms();
    tickLast = tickStart;

    state = ISUSpowerLog_stateMachine(0);
    cycleNum = 0;

    while(1) {

        if((Timer_1ms() - tickLast) >= loginterval) {
            tickLast = Timer_1ms();
            time_struct = get_RTC_time();
            strftime(timestamp, sizeof(timestamp), "%m/%d/%Y %H:%M:%S", time_struct);

            state = ISUSpowerLog_stateMachine(state);
            //wait_consoleTx();

            // INA260s are all set to do 1.1 ms x 1 avg
            ina260_system_voltageCurrent( &fSysVolt, &fSysAmp );        //system voltage and current
            ina260_lamp_voltageCurrent( &fLampVolt, &fLampAmp );        //Lamp voltage and current

            if (bmeflag == 1) {
                if(bme280_read_data() == 1) {
                    fBrdPressure = bme280_get_fPressure();
                    fBrdTempC = bme280_get_fTemperature();
                    uiHumidity = bme280_get_uiHumidity();
                } else {
                    fBrdPressure = NAN;
                    fBrdTempC = NAN;
                    uiHumidity = 0;
                }
            }

            indx = 0;
            // copied a bit from sample.c
            indx += sprintf((char *)&prnBuf[indx], "%s\t", timestamp);
            indx += sprintf((char *)&prnBuf[indx], "%u\t", tickLast - tickStart);
            if (bmeflag == 1) {
                indx += sprintf((char *)&prnBuf[indx], "%6.3f\t", fBrdTempC);
                indx += sprintf((char *)&prnBuf[indx], "%u\t", uiHumidity);
                indx += sprintf((char *)&prnBuf[indx], "%6.3f\t", fBrdPressure);
            }
            indx += sprintf((char *)&prnBuf[indx], "%u\t", cycleNum);
            indx += sprintf((char *)&prnBuf[indx], "%u\t", state);
            indx += sprintf((char *)&prnBuf[indx], "%u\t", transitionFlag);
            indx += sprintf((char *)&prnBuf[indx], "%6.3f\t", fSysVolt);
            indx += sprintf((char *)&prnBuf[indx], "%6.3f\t", fSysAmp);
            indx += sprintf((char *)&prnBuf[indx], "%6.3f\t", fLampVolt);
            indx += sprintf((char *)&prnBuf[indx], "%6.3f\t", fLampAmp);
            indx += sprn_nl((char*)prnBuf, indx);

            //uprintf("%s", prnBuf);
#if BOARD_MSC == 3
            appendIsusProfileDataToSDCard((char*)prnBuf);      //exercise the fxn for writing ISUS log
#endif

            wdog_pet();
        }

        if(kbhit())
        {
            uprintf("Received keyboard hit, exiting current/voltage log function."); prn_nl();
            state = ISUSpowerLog_stateMachine(0); // turns everything off
            led_red_off();
            led_green_off();
            //break;
            return;
        }

    }  // end the endless while loop
}


int ISUSpowerLog_stateMachine(int state)
// model for this is optode's state machine
{

    // example usage:
    // state = 0;
    // state = ISUSpowerLog_statemachine(state);     //pass in 0 to start the state machine, hereafter pass retVal
    // this one doesn't reach an end, just cycles through all the states endlessly as you keep calling
    // within each state is mostly waiting; actions happen on transitions

    // state 1: everything off
    // state 2: spectrometer on
    // state 3: spectrometer off, everything off
    // state 4: 12V to lamp on
    // state 5: tungston on
    // state 6: tungston off, 12V to lamp is still on
    // state 7: deuterium on
    // state 8: deuterium off, 12V to lamp is still on


    switch(state)
    {
        case 0:
            // set it going
            pcal6416_spec_pwr(0);
            pcal6416_lamp_pwr(0);
            pcal6416_deuterium(0);
            pcal6416_tungsten(0);

            tick_stateMachine = Timer_10ms();
            transitionFlag = 1;
            led_green_on();
            led_red_off();
            return(1);

        case 1:
            // resting off state. Next state is spectrometer on

            if((Timer_10ms() - tick_stateMachine) < OFFTIME1_MS/10) { // not yet ready to move on
                transitionFlag = 0;
                return(1);
            }

            // timer exceeded, ready to move on
            pcal6416_spec_pwr(1);
            tick_stateMachine = Timer_10ms();
            transitionFlag = 1;
            led_green_off();
            led_red_on();
            return(2);

        case 2:
            // spectrometer on. Next state is all off again

            if((Timer_10ms() - tick_stateMachine) < ONTIMES_MS/10) { // not yet ready to move on
                transitionFlag = 0;
                return(2);
            }

            // timer exceeded, ready to move on
            pcal6416_spec_pwr(0);
            tick_stateMachine = Timer_10ms();
            transitionFlag = 1;
            return(3);

        case 3:
            // resting off state.  Next state is 12V on

            if((Timer_10ms() - tick_stateMachine) < OFFTIME2_MS/10) { // not yet ready to move on
                transitionFlag = 0;
                return(3);
            }

            // timer exceeded, ready to move on
            pcal6416_lamp_pwr(1);
            tick_stateMachine = Timer_10ms();
            transitionFlag = 1;
            return(4);

        case 4:
            // 12V on.  Next state is turn on tungston lamp

            if((Timer_10ms() - tick_stateMachine) < ONTIMES_MS/10) { // not yet ready to move on
                transitionFlag = 0;
                return(4);
            }

            // timer exceeded, ready to move on
            pcal6416_tungsten(1);
            tick_stateMachine = Timer_10ms();
            transitionFlag = 1;
            return(5);

        case 5:
            // Tungston on, next state turns it off again

            if((Timer_10ms() - tick_stateMachine) < ONTIMES_MS/10) { // not yet ready to move on
                transitionFlag = 0;
                return(5);
            }

            // timer exceeded, ready to move on
            pcal6416_tungsten(0);
            tick_stateMachine = Timer_10ms();
            transitionFlag = 1;
            return(6);

        case 6:
            // 12V on, next state turns on deuterium

            if((Timer_10ms() - tick_stateMachine) < ONTIMES_MS/10) { // not yet ready to move on
                transitionFlag = 0;
                return(6);
            }

            // timer exceeded, ready to move on
            pcal6416_deuterium(1);
            tick_stateMachine = Timer_10ms();
            transitionFlag = 1;
            return(7);

        case 7:
            // Deuterium on, next state turns it off again

            if((Timer_10ms() - tick_stateMachine) < ONTIMES_MS/10) { // not yet ready to move on
                transitionFlag = 0;
                return(7);
            }

            // timer exceeded, ready to move on
            pcal6416_deuterium(0);
            tick_stateMachine = Timer_10ms();
            transitionFlag = 1;
            return(8);

        case 8:
            // 12V on, next state goes back to beginning

            if((Timer_10ms() - tick_stateMachine) < ONTIMES_MS/10) { // not yet ready to move on
                transitionFlag = 0;
                return(8);
            }

            // timer exceeded, ready to move on
            pcal6416_lamp_pwr(0);
            tick_stateMachine = Timer_10ms();
            cycleNum++;
            transitionFlag = 1;
            led_red_off();
            led_green_on();
            return(1);


        default:
            pcal6416_spec_pwr(0);
            pcal6416_lamp_pwr(0);
            pcal6416_deuterium(0);
            pcal6416_tungsten(0);

            tick_stateMachine = Timer_10ms();
            return(1);
            //break;
    }

}
