/*
 * Sensors.h
 * Includes two INA260 objects and one BME280 for use with DiSCO m-spec board
 * Based on Paul Roberts' code, modifications by IH - April 2023
 *
 */

#include "Sensors.h"
#include "Config.h"
//#include <Arduino.h>
//#include <Adafruit_Sensor.h>

//******************************************************************************
//* Constructors
//******************************************************************************

Sensors::Sensors() 
// objects are all global, not much to do
{
    sensorsValid = false;
}

//******************************************************************************
//* Public Methods
//******************************************************************************

bool Sensors::begin() 
// initializes the sensors and sets a default averaging count for INA260
// default integration time for INA260 is 1.1 ms
// returns sensorsValid = true if all ok, false if not
{
    sensorsValid = true;
    
    if (!_ina260_pwrin.begin(INA260_PWRIN_ADDR)) {
        DEBUGPORT.println("Couldn't find INA260 pwrin chip");
        sensorsValid = false;
    }
    else {
        _ina260_pwrin.setAveragingCount(INA260_COUNT_1024);
    }

    if (!_ina260_LEDs.begin(INA260_LEDS_ADDR)) {
        DEBUGPORT.println("Couldn't find INA260 LEDs chip");
        sensorsValid = false;
    }
    else {
        _ina260_LEDs.setAveragingCount(INA260_COUNT_1024);
    }
    
    // default settings
    int status = _bme.begin(BME280_ADDR);  
    // You can also pass in a Wire library object like &Wire2
    // status = bme.begin(0x76, &Wire2)
    if (!status) {
        DEBUGPORT.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
        DEBUGPORT.print("SensorID was: 0x"); Serial.println(_bme.sensorID(),16);
        DEBUGPORT.print("        ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
        DEBUGPORT.print("   ID of 0x56-0x58 represents a BMP 280,\n");
        DEBUGPORT.print("        ID of 0x60 represents a BME 280.\n");
        DEBUGPORT.print("        ID of 0x61 represents a BME 680.\n");
        // while (1) delay(10);
        sensorsValid = false;
    }

    return sensorsValid;
}

void Sensors::update() 
// updates all three sensors and stores values in the variables/arrays
{
    if (!sensorsValid)
        return;

    temperature = _bme.readTemperature();
    pressure = _bme.readPressure();
    humidity = _bme.readHumidity();
    current[0] = _ina260_pwrin.readCurrent();
    voltage[0] = _ina260_pwrin.readBusVoltage();
    power[0] = _ina260_pwrin.readPower();
    current[1] = _ina260_LEDs.readCurrent();
    voltage[1] = _ina260_LEDs.readBusVoltage();
    power[1] = _ina260_LEDs.readPower();
}

void Sensors::printEnv(Stream * out) 
// reads and prints variables from BME to Stream out
// also updates the variables
{
    if (!sensorsValid)
        return;
    temperature = _bme.readTemperature();
    pressure = _bme.readPressure();
    humidity = _bme.readHumidity();
    String output = "$BME280," + String(temperature) + "," + String(pressure) + "," + String(humidity);
    out -> println(output);
}

void Sensors::printEnv() 
// reads and prints variables from BME to UT1 port specified by Config.h
// also updates the variables
{
    printEnv(&UI1);
}

void Sensors::printPower(Stream * out) 
// reads and prints variables from both INA260s to Stream out
// also updates arrays
{
    if (!sensorsValid)
        return;

    current[0] = _ina260_pwrin.readCurrent();
    voltage[0] = _ina260_pwrin.readBusVoltage();
    power[0] = _ina260_pwrin.readPower();

    String output = "$PWR_IN," + String(current[0]) + "," + String(voltage[0]) + "," + String(power[0]);
    out->println(output);

    current[1] = _ina260_LEDs.readCurrent();
    voltage[1] = _ina260_LEDs.readBusVoltage();
    power[1] = _ina260_LEDs.readPower();

    output = "$PWR_LED," + String(current[1]) + "," + String(voltage[1]) + "," + String(power[1]);
    out->println(output);         
}

void Sensors::printPower() 
// reads and prints variables from both INA260s to UI1 port specified by Config.h
// also updates arrays
{
    printPower(&UI1);     
}

void Sensors::printPwr1(Stream * out) 
// reads and prints variables from first INA260 to Stream out
// also updates arrays
{
    if (!sensorsValid)
        return;

    current[0] = _ina260_pwrin.readCurrent();
    voltage[0] = _ina260_pwrin.readBusVoltage();
    power[0] = _ina260_pwrin.readPower();

    String output = "PWR_IN," + String(current[0]) + "," + String(voltage[0]) + "," + String(power[0]);
    out->println(output);        
}

void Sensors::printPwr1() 
// reads and prints variables from first INA260 to UI1 port specified by Config.h
// also updates arrays
{
    printPwr1(&UI1);   
}

void Sensors::printPwr2(Stream * out) 
// reads and prints variables from second INA260 to Stream out
// also updates arrays
{
    if (!sensorsValid)
        return;

    current[1] = _ina260_LEDs.readCurrent();
    voltage[1] = _ina260_LEDs.readBusVoltage();
    power[1] = _ina260_LEDs.readPower();

    String output = "PWR_LED," + String(current[1]) + "," + String(voltage[1]) + "," + String(power[1]);
    out->println(output);        
}

void Sensors::printPwr2() 
// reads and prints variables from second INA260 to UI1 port specified by Config.h
// also updates arrays
{
    printPwr2(&UI1);      
}

void Sensors::shutdown_Power() 
// sends both INA260s into shutdown mode
// renamed from lowPower to avoid some confusion
{
    _ina260_LEDs.setMode(INA260_MODE_SHUTDOWN);
    _ina260_pwrin.setMode(INA260_MODE_SHUTDOWN);

}

void Sensors::resumeCont_Power()
// turns on both INA260s into continuous mode
// renamed from resumePower, as it can be used to return to continuous mode after single shot triggering
{
    _ina260_LEDs.setMode(INA260_MODE_CONTINUOUS);
    _ina260_pwrin.setMode(INA260_MODE_CONTINUOUS);
}

void Sensors::triggerPower()
// triggers a single shot power measurement for both INA260s
// note they will NOT be in continuous mode after this - use with caution
{
    _ina260_LEDs.setMode(INA260_MODE_TRIGGERED);
    _ina260_pwrin.setMode(INA260_MODE_TRIGGERED);
}

bool Sensors::convReady_Power()
// checks if conversion is ready for both INA260s
// returns FALSE if either one isn't ready
{
    return _ina260_LEDs.conversionReady() & _ina260_pwrin.conversionReady();
}

//******************************************************************************
//* INA260 wrappers
//* configure INA260s - all operate on both INAs in this board
//******************************************************************************

void Sensors::setCurrentConversionTime(INA260_ConversionTime time)
{
    _ina260_LEDs.setCurrentConversionTime(time);
    _ina260_pwrin.setCurrentConversionTime(time);
}

void Sensors::setVoltageConversionTime(INA260_ConversionTime time)
{
    _ina260_LEDs.setVoltageConversionTime(time);
    _ina260_pwrin.setVoltageConversionTime(time);
}

void Sensors::setCurrentVoltageAvging(INA260_AveragingCount count)
{
    _ina260_LEDs.setAveragingCount(count);
    _ina260_pwrin.setAveragingCount(count);
}


