/*
  xnrg_07_ade7953.ino - ADE7953 energy sensor support for Tasmota

  Copyright (C) 2021  Theo Arends

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#if defined(ESP32) && defined(USE_SPI)
#define USE_ESP32_SPI
#endif
#if defined(USE_I2C) || defined(USE_ESP32_SPI)
#ifdef USE_ENERGY_SENSOR
#ifdef USE_ADE7953
/*********************************************************************************************\
 * ADE7953 - Energy used in Shelly 2.5 (model 1), EM (model 2), Plus 2PM (model 3), Pro 1PM (model 4), Pro 2PM (model 5) and Pro 4PM (model 6)
 *
 * {"NAME":"Shelly 2.5","GPIO":[320,0,32,0,224,193,0,0,640,192,608,225,3456,4736],"FLAG":0,"BASE":18}
 * {"NAME":"Shelly EM","GPIO":[0,0,0,0,0,0,0,0,640,3457,608,224,8832,1],"FLAG":0,"BASE":18}
 * {"NAME":"Shelly Plus 2PM PCB v0.1.5","GPIO":[320,0,192,0,0,0,1,1,225,224,0,0,0,0,193,0,0,0,0,0,0,608,3840,32,0,0,0,0,0,640,0,0,3458,4736,0,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,32000,40000,3350"}
 * {"NAME":"Shelly Plus 2PM PCB v0.1.9","GPIO":[320,0,0,0,32,192,0,0,225,224,0,0,0,0,193,0,0,0,0,0,0,608,640,3458,0,0,0,0,0,9472,0,4736,0,0,0,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350"}
 * {"NAME":"Shelly Pro 1PM","GPIO":[9568,1,9472,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,3459,0,0,32,4736,0,160,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350"}
 * {"NAME":"Shelly Pro 2PM","GPIO":[9568,1,9472,1,768,0,0,0,672,704,736,9569,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,3460,0,0,32,4736,4737,160,161],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350;AdcParam2 2,5600,4700,3350"}
 * {"NAME":"Shelly Pro 4PM","GPIO":[0,6210,0,6214,9568,0,0,0,0,0,9569,0,768,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,736,704,3461,0,4736,0,0,672],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350"}
 *
 * Based on datasheet from https://www.analog.com/en/products/ade7953.html
 *
 * Model differences:
 * Function                        Model1   Model2   Model3   Model4  Model5  Model6  Remark
 * ------------------------------  -------  -------  -------  ------  ------  ------  -------------------------------------------------
 * Shelly                          2.5      EM       Plus2PM  Pro1PM  Pro2PM  Pro4PM
 * Processor                       ESP8266  ESP8266  ESP32    ESP32   ESP32   ESP32
 * Interface                       I2C      I2C      I2C      SPI     SPI     SPI     Interface type used
 * Number of inputs                2        2        2        1       2       4       Count of ADE9753 inputs used
 * Number of ADE9753 chips         1        1        1        1       2       2       Count of ADE9753 chips
 * ADE9753 IRQ                     1        2        3        4       5       6       Index defines model number
 * Current measurement device      shunt    CT       shunt    shunt   shunt   shunt   CT = Current Transformer
 * Common voltage                  Yes      Yes      Yes      No      No      Yes     Show common voltage in GUI/JSON
 * Common frequency                Yes      Yes      Yes      No      No      Yes     Show common frequency in GUI/JSON
 * Swapped channel A/B             Yes      No       No       No      No      No      Defined by hardware design - Fixed by Tasmota
 * Support Export Active           No       Yes      No       No      No      No      Only EM supports correct negative value detection
 * Show negative (reactive) power  No       Yes      No       No      No      No      Only EM supports correct negative value detection
 * Default phase calibration       0        200      0        0       0       0       CT needs different phase calibration than shunts
 * Default reset pin on ESP8266    -        16       -        -       -       -       Legacy support. Replaced by GPIO ADE7953RST
 *
 * I2C Address: 0x38
 *********************************************************************************************
 * Optionally allowing users to tweak calibration registers:
 * - In addition to possible rules add a rule containing the calib.dat string like:
 *   - rule3 on file#calib.dat do {"angles":{"angle0":180,"angle1":176}} endon
 *   - rule3 on file#calib.dat do {"rms":{"current_a":4194303,"current_b":4194303,"voltage":1613194},"angles":{"angle0":200,"angle1":200},"powers":{"totactive":{"a":2723574,"b":2723574},"apparent":{"a":2723574,"b":2723574},"reactive":{"a":2723574,"b":2723574}}} endon
 * - Restart Tasmota and obeserve that the results seem calibrated as Tasmota now uses the information from calib.dat
 * To restore standard calibration using commands like VoltSet remove above entry from rule3
\*********************************************************************************************/

#define XNRG_07                   7
#define XI2C_07                   7  // See I2CDEVICES.md

#define ADE7953_ADDR              0x38

/*********************************************************************************************/

#define ADE7953_ACCU_ENERGY                  // Use accumulating energy instead of instant power

//#define ADE7953_DUMP_REGS

#define ADE7953_PREF              1540       // 4194304 / (1540 / 1000) = 2723574 (= WGAIN, VAGAIN and VARGAIN)
#define ADE7953_UREF              26000      // 4194304 / (26000 / 10000) = 1613194 (= VGAIN)
#define ADE7953_IREF              10000      // 4194304 / (10000 / 10000) = 4194303 (= IGAIN, needs to be different than 4194304 in order to use calib.dat)
#define ADE7953_NO_LOAD_THRESHOLD 29196      // According to ADE7953 datasheet the default threshold for no load detection is 58,393 use half this value to measure lower (5w) powers.
#define ADE7953_NO_LOAD_ENABLE    0          // Set DISNOLOAD register to 0 to enable No-load detection
#define ADE7953_NO_LOAD_DISABLE   7          // Set DISNOLOAD register to 7 to disable No-load detection

// Default calibration parameters can be overridden by a rule as documented above.
#define ADE7953_GAIN_DEFAULT      4194304    // = 0x400000 range 2097152 (min) to 6291456 (max)
#define ADE7953_PHCAL_DEFAULT     0          // = range -383 to 383 - Default phase calibration for Shunts
#define ADE7953_PHCAL_DEFAULT_CT  200        // = range -383 to 383 - Default phase calibration for Current Transformers (Shelly EM)

#define ADE7953_MAX_CHANNEL       4

enum Ade7953Models { ADE7953_SHELLY_25, ADE7953_SHELLY_EM, ADE7953_SHELLY_PLUS_2PM, ADE7953_SHELLY_PRO_1PM, ADE7953_SHELLY_PRO_2PM, ADE7953_SHELLY_PRO_4PM };

enum Ade7953_8BitRegisters {
  // Register Name                    Addres  R/W  Bt  Ty  Default     Description
  // ----------------------------     ------  ---  --  --  ----------  --------------------------------------------------------------------
  ADE7953_SAGCYC = 0x000,          // 0x000   R/W  8   U   0x00        Sag line cycles
  ADE7953_DISNOLOAD,               // 0x001   R/W  8   U   0x00        No-load detection disable (see Table 16)
  ADE7953_RESERVED_0X002,          // 0x002
  ADE7953_RESERVED_0X003,          // 0x003
  ADE7953_LCYCMODE,                // 0x004   R/W  8   U   0x40        Line cycle accumulation mode configuration (see Table 17)
  ADE7953_RESERVED_0X005,          // 0x005
  ADE7953_RESERVED_0X006,          // 0x006
  ADE7953_PGA_V,                   // 0x007   R/W  8   U   0x00        Voltage channel gain configuration (Bits[2:0])
  ADE7953_PGA_IA,                  // 0x008   R/W  8   U   0x00        Current Channel A gain configuration (Bits[2:0])
  ADE7953_PGA_IB                   // 0x009   R/W  8   U   0x00        Current Channel B gain configuration (Bits[2:0])
};

enum Ade7953_16BitRegisters {
  // Register Name                    Addres  R/W  Bt  Ty  Default     Description
  // ----------------------------     ------  ---  --  --  ----------  --------------------------------------------------------------------
  ADE7953_ZXTOUT = 0x100,          // 0x100   R/W  16  U   0xFFFF      Zero-crossing timeout
  ADE7953_LINECYC,                 // 0x101   R/W  16  U   0x0000      Number of half line cycles for line cycle energy accumulation mode
  ADE7953_CONFIG,                  // 0x102   R/W  16  U   0x8004      Configuration register (see Table 18)
  ADE7953_CF1DEN,                  // 0x103   R/W  16  U   0x003F      CF1 frequency divider denominator. When modifying this register, two sequential write operations must be performed to ensure that the write is successful.
  ADE7953_CF2DEN,                  // 0x104   R/W  16  U   0x003F      CF2 frequency divider denominator. When modifying this register, two sequential write operations must be performed to ensure that the write is successful.
  ADE7953_RESERVED_0X105,          // 0x105
  ADE7953_RESERVED_0X106,          // 0x106
  ADE7953_CFMODE,                  // 0x107   R/W  16  U   0x0300      CF output selection (see Table 19)
  ADE7943_PHCALA,                  // 0x108   R/W  16  S   0x0000      Phase calibration register (Current Channel A). This register is in sign magnitude format.
  ADE7943_PHCALB,                  // 0x109   R/W  16  S   0x0000      Phase calibration register (Current Channel B). This register is in sign magnitude format.
  ADE7943_PFA,                     // 0x10A   R    16  S   0x0000      Power factor (Current Channel A)
  ADE7943_PFB,                     // 0x10B   R    16  S   0x0000      Power factor (Current Channel B)
  ADE7943_ANGLE_A,                 // 0x10C   R    16  S   0x0000      Angle between the voltage input and the Current Channel A input
  ADE7943_ANGLE_B,                 // 0x10D   R    16  S   0x0000      Angle between the voltage input and the Current Channel B input
  ADE7943_Period,                  // 0x10E   R    16  U   0x0000      Period register

  ADE7953_RESERVED_0X120 = 0x120   // 0x120                            This register should be set to 30h to meet the performance specified in Table 1. To modify this register, it must be unlocked by setting Register Address 0xFE to 0xAD immediately prior.
};

enum Ade7953_32BitRegisters {
  // Register Name                    Addres  R/W  Bt  Ty  Default     Description
  // ----------------------------     ------  ---  --  --  ----------  --------------------------------------------------------------------
  ADE7953_ACCMODE = 0x301,         // 0x301   R/W  24  U   0x000000    Accumulation mode (see Table 21)

  ADE7953_AP_NOLOAD = 0x303,       // 0x303   R/W  24  U   0x00E419    No load threshold for actual power
  ADE7953_VAR_NOLOAD,              // 0x304   R/W  24  U   0x00E419    No load threshold for reactive power
  ADE7953_VA_NOLOAD,               // 0x305   R/W  24  U   0x000000    No load threshold for appearant power

  ADE7953_AVA = 0x310,             // 0x310   R    24  S   0x000000    Instantaneous apparent power (Current Channel A)
  ADE7953_BVA,                     // 0x311   R    24  S   0x000000    Instantaneous apparent power (Current Channel B)
  ADE7953_AWATT,                   // 0x312   R    24  S   0x000000    Instantaneous active power (Current Channel A)
  ADE7953_BWATT,                   // 0x313   R    24  S   0x000000    Instantaneous active power (Current Channel B)
  ADE7953_AVAR,                    // 0x314   R    24  S   0x000000    Instantaneous reactive power (Current Channel A)
  ADE7953_BVAR,                    // 0x315   R    24  S   0x000000    Instantaneous reactive power (Current Channel B)
  ADE7953_IA,                      // 0x316   R    24  S   0x000000    Instantaneous current (Current Channel A)
  ADE7953_IB,                      // 0x317   R    24  S   0x000000    Instantaneous current (Current Channel B)
  ADE7953_V,                       // 0x318   R    24  S   0x000000    Instantaneous voltage (voltage channel)
  ADE7953_RESERVED_0X319,          // 0x319
  ADE7953_IRMSA,                   // 0x31A   R    24  U   0x000000    IRMS register (Current Channel A)
  ADE7953_IRMSB,                   // 0x31B   R    24  U   0x000000    IRMS register (Current Channel B)
  ADE7953_VRMS,                    // 0x31C   R    24  U   0x000000    VRMS register
  ADE7953_RESERVED_0X31D,          // 0x31D
  ADE7953_AENERGYA,                // 0x31E   R    24  S   0x000000    Active energy (Current Channel A)
  ADE7953_AENERGYB,                // 0x31F   R    24  S   0x000000    Active energy (Current Channel B)
  ADE7953_RENERGYA,                // 0x320   R    24  S   0x000000    Reactive energy (Current Channel A)
  ADE7953_RENERGYB,                // 0x321   R    24  S   0x000000    Reactive energy (Current Channel B)
  ADE7953_APENERGYA,               // 0x322   R    24  S   0x000000    Apparent energy (Current Channel A)
  ADE7953_APENERGYB,               // 0x323   R    24  S   0x000000    Apparent energy (Current Channel B)
  ADE7953_OVLVL,                   // 0x324   R/W  24  U   0xFFFFFF    Overvoltage level
  ADE7953_OILVL,                   // 0x325   R/W  24  U   0xFFFFFF    Overcurrent level
  ADE7953_VPEAK,                   // 0x326   R    24  U   0x000000    Voltage channel peak
  ADE7953_RSTVPEAK,                // 0x327   R    24  U   0x000000    Read voltage peak with reset
  ADE7953_IAPEAK,                  // 0x328   R    24  U   0x000000    Current Channel A peak
  ADE7953_RSTIAPEAK,               // 0x329   R    24  U   0x000000    Read Current Channel A peak with reset
  ADE7953_IBPEAK,                  // 0x32A   R    24  U   0x000000    Current Channel B peak
  ADE7953_RSTIBPEAK,               // 0x32B   R    24  U   0x000000    Read Current Channel B peak with reset
  ADE7953_IRQENA,                  // 0x32C   R/W  24  U   0x100000    Interrupt enable (Current Channel A, see Table 22)
  ADE7953_IRQSTATA,                // 0x32D   R    24  U   0x000000    Interrupt status (Current Channel A, see Table 23)
  ADE7953_RSTIRQSTATA,             // 0x32E   R    24  U   0x000000    Reset interrupt status (Current Channel A)
  ADE7953_IRQENB,                  // 0x32F   R/W  24  U   0x000000    Interrupt enable (Current Channel B, see Table 24)
  ADE7953_IRQSTATB,                // 0x330   R    24  U   0x000000    Interrupt status (Current Channel B, see Table 25)
  ADE7953_RSTIRQSTATB,             // 0x331   R    24  U   0x000000    Reset interrupt status (Current Channel B)

  ADE7953_CRC = 0x37F,             // 0x37F   R    32  U   0xFFFFFFFF  Checksum
  ADE7953_AIGAIN,                  // 0x380   R/W  24  U   0x400000    Current channel gain (Current Channel A)
  ADE7953_AVGAIN,                  // 0x381   R/W  24  U   0x400000    Voltage channel gain
  ADE7953_AWGAIN,                  // 0x382   R/W  24  U   0x400000    Active power gain (Current Channel A)
  ADE7953_AVARGAIN,                // 0x383   R/W  24  U   0x400000    Reactive power gain (Current Channel A)
  ADE7953_AVAGAIN,                 // 0x384   R/W  24  U   0x400000    Apparent power gain (Current Channel A)
  ADE7953_RESERVED_0X385,          // 0x385
  ADE7953_AIRMSOS,                 // 0x386   R/W  24  S   0x000000    IRMS offset (Current Channel A)
  ADE7953_RESERVED_0X387,          // 0x387
  ADE7953_VRMSOS,                  // 0x388   R/W  24  S   0x000000    VRMS offset
  ADE7953_AWATTOS,                 // 0x389   R/W  24  S   0x000000    Active power offset correction (Current Channel A)
  ADE7953_AVAROS,                  // 0x38A   R/W  24  S   0x000000    Reactive power offset correction (Current Channel A)
  ADE7953_AVAOS,                   // 0x38B   R/W  24  S   0x000000    Apparent power offset correction (Current Channel A)
  ADE7953_BIGAIN,                  // 0x38C   R/W  24  U   0x400000    Current channel gain (Current Channel B)
  ADE7953_BVGAIN,                  // 0x38D   R/W  24  U   0x400000    This register should not be modified.
  ADE7953_BWGAIN,                  // 0x38E   R/W  24  U   0x400000    Active power gain (Current Channel B)
  ADE7953_BVARGAIN,                // 0x38F   R/W  24  U   0x400000    Reactive power gain (Current Channel B)
  ADE7953_BVAGAIN,                 // 0x390   R/W  24  U   0x400000    Apparent power gain (Current Channel B)
  ADE7953_RESERVED_0X391,          // 0x391
  ADE7953_BIRMSOS,                 // 0x392   R/W  24  S   0x000000    IRMS offset (Current Channel B)
  ADE7953_RESERVED_0X393,          // 0x393
  ADE7953_RESERVED_0X394,          // 0x394
  ADE7953_BWATTOS,                 // 0x395   R/W  24  S   0x000000    Active power offset correction (Current Channel B)
  ADE7953_BVAROS,                  // 0x396   R/W  24  S   0x000000    Reactive power offset correction (Current Channel B)
  ADE7953_BVAOS                    // 0x397   R/W  24  S   0x000000    Apparent power offset correction (Current Channel B)
};

enum Ade7953CalibrationRegisters {
  ADE7953_CAL_VGAIN,
  ADE7953_CAL_IGAIN,
  ADE7953_CAL_WGAIN,
  ADE7953_CAL_VAGAIN,
  ADE7953_CAL_VARGAIN,
  ADE7943_CAL_PHCAL
};

const uint8_t  ADE7953_CALIBREGS = 6;
const uint16_t Ade7953CalibRegs[2][ADE7953_CALIBREGS] {
  { ADE7953_AVGAIN, ADE7953_AIGAIN, ADE7953_AWGAIN, ADE7953_AVAGAIN, ADE7953_AVARGAIN, ADE7943_PHCALA },
  { ADE7953_BVGAIN, ADE7953_BIGAIN, ADE7953_BWGAIN, ADE7953_BVAGAIN, ADE7953_BVARGAIN, ADE7943_PHCALB }
};

const uint8_t  ADE7953_REGISTERS = 6;
const uint16_t Ade7953Registers[2][ADE7953_REGISTERS] {
#ifdef ADE7953_ACCU_ENERGY
  { ADE7953_IRMSA, ADE7953_AENERGYA, ADE7953_APENERGYA, ADE7953_RENERGYA, ADE7953_VRMS, ADE7943_Period },
  { ADE7953_IRMSB, ADE7953_AENERGYB, ADE7953_APENERGYB, ADE7953_RENERGYB, ADE7953_VRMS, ADE7943_Period }
#else   // No ADE7953_ACCU_ENERGY
  { ADE7953_IRMSA, ADE7953_AWATT, ADE7953_AVA, ADE7953_AVAR, ADE7953_VRMS, ADE7943_Period },
  { ADE7953_IRMSB, ADE7953_BWATT, ADE7953_BVA, ADE7953_BVAR, ADE7953_VRMS, ADE7943_Period }
#endif  // ADE7953_ACCU_ENERGY
};

#ifdef ADE7953_ACCU_ENERGY
const float ADE7953_LSB_PER_WATTSECOND = 2.5;
const float ADE7953_POWER_CORRECTION = 23.41494;  // See https://github.com/arendst/Tasmota/pull/16941
#else   // No ADE7953_ACCU_ENERGY
const float ADE7953_LSB_PER_WATTSECOND = 44;
#endif  // ADE7953_ACCU_ENERGY

typedef struct {
  uint32_t voltage_rms;
  uint32_t current_rms;
  uint32_t active_power;
  int32_t calib_data[ADE7953_CALIBREGS];
} tAde7953Channel;

struct Ade7953 {
  uint32_t last_update;
  uint32_t voltage_rms[ADE7953_MAX_CHANNEL] = { 0, 0 };
  uint32_t current_rms[ADE7953_MAX_CHANNEL] = { 0, 0 };
  uint32_t active_power[ADE7953_MAX_CHANNEL] = { 0, 0 };
  int32_t calib_data[ADE7953_MAX_CHANNEL][ADE7953_CALIBREGS];
  uint8_t init_step = 0;
  uint8_t model = 0;             // 0 = Shelly 2.5, 1 = Shelly EM, 2 = Shelly Plus 2PM, 3 = Shelly Pro 1PM, 4 = Shelly Pro 2PM, 5 = Shelly Pro 4PM
  uint8_t cs_index;
#ifdef USE_ESP32_SPI
  int8_t pin_cs[ADE7953_MAX_CHANNEL / 2];
#endif  // USE_ESP32_SPI
  bool use_spi;
} Ade7953;

/*********************************************************************************************/

int Ade7953RegSize(uint16_t reg) {
  int size = 0;
  switch ((reg >> 8) & 0x0F) {
    case 0x03:  // 32-bit
      size++;
    case 0x02:  // 24-bit
      size++;
    case 0x01:  // 16-bit
      size++;
    case 0x00:  // 8-bit
    case 0x07:
    case 0x08:
      size++;
  }
  return size;
}

#ifdef USE_ESP32_SPI
void Ade7953SpiEnable(void) {
  digitalWrite(Ade7953.pin_cs[Ade7953.cs_index], 0);
  delayMicroseconds(1);                              // CS 1uS to SCLK edge
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));  // Set up SPI at 1MHz, MSB first, Capture at rising edge
}

void Ade7953SpiDisable(void) {
  SPI.endTransaction();
  delayMicroseconds(2);                              // CS high 1.2uS after SCLK edge (when writing to COMM_LOCK bit)
  digitalWrite(Ade7953.pin_cs[Ade7953.cs_index], 1);
}
#endif  // USE_ESP32_SPI

void Ade7953Write(uint16_t reg, uint32_t val) {
  int size = Ade7953RegSize(reg);
  if (size) {

//      AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: Write %08X"), val);

#ifdef USE_ESP32_SPI
    if (Ade7953.use_spi) {
      Ade7953SpiEnable();
      SPI.transfer16(reg);
      SPI.transfer(0x00);                            // Write
      while (size--) {
        SPI.transfer((val >> (8 * size)) & 0xFF);    // Write data, MSB first
      }
      Ade7953SpiDisable();
    } else {
#endif  // USE_ESP32_SPI
      Wire.beginTransmission(ADE7953_ADDR);
      Wire.write((reg >> 8) & 0xFF);
      Wire.write(reg & 0xFF);
      while (size--) {
        Wire.write((val >> (8 * size)) & 0xFF);      // Write data, MSB first
      }
      Wire.endTransmission();
      delayMicroseconds(5);                          // Bus-free time minimum 4.7us
#ifdef USE_ESP32_SPI
    }
#endif  // USE_ESP32_SPI
  }
}

int32_t Ade7953Read(uint16_t reg) {
  uint32_t response = 0;

  int size = Ade7953RegSize(reg);
  if (size) {
#ifdef USE_ESP32_SPI
    if (Ade7953.use_spi) {
      Ade7953SpiEnable();
      SPI.transfer16(reg);
      SPI.transfer(0x80);                            // Read
      while (size--) {
        response = response << 8 | SPI.transfer(0xFF);  // receive DATA (MSB first)
      }
      Ade7953SpiDisable();
    } else {
#endif  // USE_ESP32_SPI
      Wire.beginTransmission(ADE7953_ADDR);
      Wire.write((reg >> 8) & 0xFF);
      Wire.write(reg & 0xFF);
      Wire.endTransmission(0);
      Wire.requestFrom(ADE7953_ADDR, size);
      if (size <= Wire.available()) {
        for (uint32_t i = 0; i < size; i++) {
          response = response << 8 | Wire.read();    // receive DATA (MSB first)
        }
      }
#ifdef USE_ESP32_SPI
    }
#endif  // USE_ESP32_SPI
  }
  return response;
}

#ifdef ADE7953_DUMP_REGS
void Ade7953DumpRegs(uint32_t chip) {
  AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: *** Chip%d ****  SAGCYC DISNOLD  Resrvd  Resrvd LCYCMOD  Resrvd  Resrvd    PGAV   PGAIA   PGAIB"), chip +1);
  char data[200] = { 0 };
  for (uint32_t i = 0; i < 10; i++) {
    int32_t value = Ade7953Read(ADE7953_SAGCYC + i);
    snprintf_P(data, sizeof(data), PSTR("%s      %02X"), data, value);  // 8-bit regs
  }
  AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: *** 0x000..009%s"), data);
  AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: ***             ZXTOUT LINECYC  CONFIG  CF1DEN  CF2DEN  Resrvd  Resrvd  CFMODE  PHCALA  PHCALB     PFA     PFB  ANGLEA  ANGLEB  Period"));
  data[0] = '\0';
  for (uint32_t i = 0; i < 15; i++) {
    int32_t value = Ade7953Read(ADE7953_ZXTOUT + i);
    snprintf_P(data, sizeof(data), PSTR("%s    %04X"), data, value);  // 16-bit regs
  }
  AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: *** 0x100..10E%s"), data);
  AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: ***              IGAIN   VGAIN   WGAIN VARGAIN  VAGAIN  Resrvd  IRMSOS  Resrvd  VRMSOS  WATTOS   VAROS    VAOS"));
  data[0] = '\0';
  for (uint32_t i = 0; i < 12; i++) {
    int32_t value = Ade7953Read(ADE7953_AIGAIN + i);
    snprintf_P(data, sizeof(data), PSTR("%s  %06X"), data, value);  // 24-bit regs
  }
  AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: *** 0x380..38B%s"), data);
  data[0] = '\0';
  for (uint32_t i = 0; i < 12; i++) {
    int32_t value = Ade7953Read(ADE7953_BIGAIN + i);
    snprintf_P(data, sizeof(data), PSTR("%s  %06X"), data, value);  // 24-bit regs
  }
  AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: *** 0x38C..397%s"), data);
}
#endif  // ADE7953_DUMP_REGS

void Ade7953SetCalibration(uint32_t regset, uint32_t calibset) {
  for (uint32_t i = 0; i < ADE7953_CALIBREGS; i++) {
    int32_t value = Ade7953.calib_data[calibset][i];
    if (ADE7943_CAL_PHCAL == i) {
//      if (ADE7953_PHCAL_DEFAULT == value) { continue; }  // ADE7953 reset does NOT always reset all registers
      if (value < 0) {
        value = abs(value) + 0x200;                  // Add sign magnitude
      }
    }
//    if (ADE7953_GAIN_DEFAULT == value) { continue; }  // ADE7953 reset does NOT always reset all registers
    Ade7953Write(Ade7953CalibRegs[regset][i], value);
  }
}

void Ade7953Init(void) {
  uint32_t chips = 1;
#ifdef USE_ESP32_SPI
  chips = (Ade7953.pin_cs[1] >= 0) ? 2 : 1;
#endif  // USE_ESP32_SPI

  // Init ADE7953 with calibration settings
  for (uint32_t chip = 0; chip < chips; chip++) {
    Ade7953.cs_index = chip;

#ifdef ADE7953_DUMP_REGS
    Ade7953DumpRegs(chip);
#endif  // ADE7953_DUMP_REGS

    Ade7953Write(ADE7953_CONFIG, 0x0004);                        // Locking the communication interface (Clear bit COMM_LOCK), Enable HPF
    Ade7953Write(0x0FE, 0x00AD);                                 // Unlock register 0x120
    Ade7953Write(ADE7953_RESERVED_0X120, 0x0030);                // Configure optimum setting
    Ade7953Write(ADE7953_DISNOLOAD, 0x07);                       // Disable no load detection, required before setting thresholds
    Ade7953Write(ADE7953_AP_NOLOAD, ADE7953_NO_LOAD_THRESHOLD);  // Set no load treshold for active power
    Ade7953Write(ADE7953_VAR_NOLOAD, ADE7953_NO_LOAD_THRESHOLD); // Set no load treshold for reactive power
    Ade7953Write(ADE7953_DISNOLOAD, 0x00);                       // Enable no load detection

#ifdef USE_ESP32_SPI
//    int32_t value = Ade7953Read(0x702);              // Silicon version
//    AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: Chip%d version %d"), chip +1, value);
    if (1 == chip) {
      switch (Ade7953.model) {
        case ADE7953_SHELLY_PRO_2PM:
          Ade7953SetCalibration(0, 1);               // Second ADE7953 A registers set with calibration set 1
          break;
        case ADE7953_SHELLY_PRO_4PM:
          Ade7953SetCalibration(0, 2);               // Second ADE7953 A registers set with calibration set 2
          Ade7953SetCalibration(1, 3);               // Second ADE7953 B registers set with calibration set 3
      }
    } else {
#endif  // USE_ESP32_SPI
      Ade7953SetCalibration(0, 0);                   // First ADE7953 A registers set with calibration set 0
      switch (Ade7953.model) {
        case ADE7953_SHELLY_25:
        case ADE7953_SHELLY_EM:
        case ADE7953_SHELLY_PLUS_2PM:
//        case ADE7953_SHELLY_PRO_1PM:               // Uses defaults for B registers
        case ADE7953_SHELLY_PRO_4PM:
          Ade7953SetCalibration(1, 1);               // First ADE7953 B registers set with calibration set 1
      }
#ifdef USE_ESP32_SPI
    }
#endif  // USE_ESP32_SPI
  }

  // Report set calibration settings
  int32_t regs[ADE7953_CALIBREGS];
  for (uint32_t chip = 0; chip < chips; chip++) {
    Ade7953.cs_index = chip;
    for (uint32_t channel = 0; channel < 2; channel++) {
      for (uint32_t i = 0; i < ADE7953_CALIBREGS; i++) {
        regs[i] = Ade7953Read(Ade7953CalibRegs[channel][i]);
        if (ADE7943_CAL_PHCAL == i) {
          if (regs[i] >= 0x0200) {
            regs[i] &= 0x01FF;                       // Clear sign magnitude
            regs[i] *= -1;                           // Make negative
          }
        }
      }
#ifdef USE_ESP32_SPI
      AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: Chip%d CalibRegs%c V %d, I %d, W %d, VA %d, VAr %d, Ph %d"),
        chip +1, 'A'+channel, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]);
#else
      AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: CalibRegs%c V %d, I %d, W %d, VA %d, VAr %d, Ph %d"),
        'A'+channel, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5]);
#endif  // USE_ESP32_SPI
    }

#ifdef ADE7953_DUMP_REGS
    Ade7953DumpRegs(chip);
#endif  // ADE7953_DUMP_REGS
  }
}

void Ade7953GetData(void) {
  uint32_t acc_mode = 0;
  int32_t reg[ADE7953_MAX_CHANNEL][ADE7953_REGISTERS];

#ifdef USE_ESP32_SPI
  if (Ade7953.use_spi) {
    uint32_t channel = 0;
    for (uint32_t chip = 0; chip < ADE7953_MAX_CHANNEL / 2; chip++) {
      if (Ade7953.pin_cs[chip] < 0) { continue; }
      Ade7953.cs_index = chip;
      for (uint32_t i = 0; i < ADE7953_REGISTERS; i++) {
        reg[channel][i] = Ade7953Read(Ade7953Registers[0][i]);    // IRMSa, WATTa, VAa, VARa, VRMS, Period
      }
      channel++;
      if (4 == Energy->phase_count) {
        for (uint32_t i = 0; i < ADE7953_REGISTERS; i++) {
          reg[channel][i] = Ade7953Read(Ade7953Registers[1][i]);  // IRMSb, WATTb, VAb, VARb, VRMS, Period
        }
        channel++;
      }
    }
  } else {
#endif  // USE_ESP32_SPI
    for (uint32_t channel = 0; channel < 2; channel++) {
      uint32_t channel_swap = (ADE7953_SHELLY_25 == Ade7953.model) ? !channel : channel;
      for (uint32_t i = 0; i < ADE7953_REGISTERS; i++) {
        reg[channel_swap][i] = Ade7953Read(Ade7953Registers[channel][i]);
      }
    }
    acc_mode = Ade7953Read(ADE7953_ACCMODE);         // Accumulation mode
#ifdef USE_ESP32_SPI
  }
#endif  // USE_ESP32_SPI

  for (uint32_t i = 0; i < Energy->phase_count; i++) {
    AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: Channel%d ACCMODE 0x%06X, VRMS %d, Period %d, IRMS %d, WATT %d, VA %d, VAR %d"),
      i+1, acc_mode, reg[i][4], reg[i][5], reg[i][0], reg[i][1], reg[i][2], reg[i][3]);
  }

  // If the device is initializing, we read the energy registers to reset them, but don't report the values as the first read may be inaccurate
  if (Ade7953.init_step) { return; }

  uint32_t apparent_power[ADE7953_MAX_CHANNEL] = { 0, 0 };
  uint32_t reactive_power[ADE7953_MAX_CHANNEL] = { 0, 0 };

  for (uint32_t channel = 0; channel < Energy->phase_count; channel++) {
    Ade7953.voltage_rms[channel] = reg[channel][4];
    Ade7953.current_rms[channel] = reg[channel][0];
    Ade7953.active_power[channel] = abs(reg[channel][1]);
    apparent_power[channel] = abs(reg[channel][2]);
    reactive_power[channel] = abs(reg[channel][3]);
    if ((ADE7953_SHELLY_EM == Ade7953.model) && (bitRead(acc_mode, 18 +(channel * 3)))) {  // VARNLOAD
      reactive_power[channel] = 0;
    }
  }

  if (Energy->power_on) {                              // Powered on

#ifdef USE_ESP32_SPI
    float correction = 1.0f;
    if (Ade7953.use_spi) {        // SPI
      uint32_t time = millis();
      if (Ade7953.last_update) {
        uint32_t difference = time - Ade7953.last_update;
        correction = (float)difference / 1000;    // Correction to 1 second

//        AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: Correction %4_f"), &correction);
      }
      Ade7953.last_update = time;
    }
#endif  // USE_ESP32_SPI

    float divider;
    for (uint32_t channel = 0; channel < Energy->phase_count; channel++) {
      Energy->data_valid[channel] = 0;

      float power_calibration = (float)EnergyGetCalibration(ENERGY_POWER_CALIBRATION, channel) / 10;
#ifdef ADE7953_ACCU_ENERGY
      power_calibration /= ADE7953_POWER_CORRECTION;
#endif  // ADE7953_ACCU_ENERGY
      float voltage_calibration = (float)EnergyGetCalibration(ENERGY_VOLTAGE_CALIBRATION, channel);
      float current_calibration = (float)EnergyGetCalibration(ENERGY_CURRENT_CALIBRATION, channel) * 10;

      Energy->frequency[channel] = 223750.0f / ((float)reg[channel][5] + 1);

      divider = (Ade7953.calib_data[channel][ADE7953_CAL_VGAIN] != ADE7953_GAIN_DEFAULT) ? 10000 : voltage_calibration;
      Energy->voltage[channel] = (float)Ade7953.voltage_rms[channel] / divider;

      divider = (Ade7953.calib_data[channel][ADE7953_CAL_WGAIN] != ADE7953_GAIN_DEFAULT) ? ADE7953_LSB_PER_WATTSECOND : power_calibration;
      Energy->active_power[channel] = (float)Ade7953.active_power[channel] / divider;

      divider = (Ade7953.calib_data[channel][ADE7953_CAL_VARGAIN] != ADE7953_GAIN_DEFAULT) ? ADE7953_LSB_PER_WATTSECOND : power_calibration;
      Energy->reactive_power[channel] = (float)reactive_power[channel] / divider;

      if (ADE7953_SHELLY_EM == Ade7953.model) {
        if (bitRead(acc_mode, 10 +channel)) {        // APSIGN
          Energy->active_power[channel] *= -1;
        }
        if (bitRead(acc_mode, 12 +channel)) {        // VARSIGN
          Energy->reactive_power[channel] *= -1;
        }
      }

      divider = (Ade7953.calib_data[channel][ADE7953_CAL_VAGAIN] != ADE7953_GAIN_DEFAULT) ? ADE7953_LSB_PER_WATTSECOND : power_calibration;
      Energy->apparent_power[channel] = (float)apparent_power[channel] / divider;

#ifdef USE_ESP32_SPI
      if (Ade7953.use_spi) {        // SPI
        Energy->active_power[channel] /= correction;
        Energy->reactive_power[channel] /= correction;
        Energy->apparent_power[channel] /= correction;
      }
#endif  // USE_ESP32_SPI

      if (0 == Energy->active_power[channel]) {
        Energy->current[channel] = 0;
      } else {
        divider = (Ade7953.calib_data[channel][ADE7953_CAL_IGAIN] != ADE7953_GAIN_DEFAULT) ? 100000 : current_calibration;
        Energy->current[channel] = (float)Ade7953.current_rms[channel] / divider;
        Energy->kWhtoday_delta[channel] += Energy->active_power[channel] * 1000 / 36;
      }
    }
    EnergyUpdateToday();
  }
}

void Ade7953EnergyEverySecond(void) {
  if (Ade7953.init_step) {
    if (2 == Ade7953.init_step) { Ade7953Init(); }
    if (1 == Ade7953.init_step) { Ade7953GetData(); }  // Read registers but do not display yet
    Ade7953.init_step--;
  } else {
    Ade7953GetData();
  }
}

/*********************************************************************************************/

bool Ade7953SetDefaults(const char* json) {
  // {"angles":{"angle0":180,"angle1":176}}
  // {"rms":{"current_a":4194303,"current_b":4194303,"voltage":1613194},"angles":{"angle0":0,"angle1":0},"powers":{"totactive":{"a":2723574,"b":2723574},"apparent":{"a":2723574,"b":2723574},"reactive":{"a":2723574,"b":2723574}}}
  // {"rms":{"current_a":21865738,"current_b":1558533,"voltage_a":1599149,"voltage_b":1597289},"angles":{"angle0":0,"angle1":0},"powers":{"totactive":{"a":106692616,"b":3540894}}}
  uint32_t len = strlen(json) +1;
  if (len < 7) { return false; }                     // Too short

  char json_buffer[len];
  memcpy(json_buffer, json, len);                    // Keep original safe
  JsonParser parser(json_buffer);
  JsonParserObject root = parser.getRootObject();
  if (!root) {
    AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: Invalid JSON"));
    return false;
  }

  // All parameters are optional allowing for partial changes
  JsonParserToken val;
  char field[20];
  for (uint32_t i = 0; i < ADE7953_MAX_CHANNEL; i++) {
    JsonParserObject rms = root[PSTR("rms")].getObject();
    if (rms) {
      val = rms[PSTR("voltage")];
      if (val) {
        Ade7953.calib_data[i][ADE7953_CAL_VGAIN] = val.getInt();
      }
  #ifdef USE_ESP32_SPI
      snprintf_P(field, sizeof(field), PSTR("voltage_%c"), 'a'+i);
      val = rms[field];                              // "voltage_a" .. "voltage_d"
      if (val) { Ade7953.calib_data[i][ADE7953_CAL_VGAIN] = val.getInt(); }
  #endif  // USE_ESP32_SPI
      snprintf_P(field, sizeof(field), PSTR("current_%c"), 'a'+i);
      val = rms[field];                              // "current_a" .. "current_d"
      if (val) { Ade7953.calib_data[i][ADE7953_CAL_IGAIN] = val.getInt(); }
    }
    JsonParserObject angles = root[PSTR("angles")].getObject();
    if (angles) {
      snprintf_P(field, sizeof(field), PSTR("angle%c"), '0'+i);
      val = angles[field];                           // "angle0" .. "angle3"
      if (val) { Ade7953.calib_data[i][ADE7943_CAL_PHCAL] = val.getInt(); }
    }
    JsonParserObject powers = root[PSTR("powers")].getObject();
    if (powers) {
      snprintf_P(field, sizeof(field), PSTR("%c"), 'a'+i);
      JsonParserObject totactive = powers[PSTR("totactive")].getObject();
      if (totactive) {
        val = totactive[field];                      // "a" .. "d"
        if (val) { Ade7953.calib_data[i][ADE7953_CAL_WGAIN] = val.getInt(); }
      }
      JsonParserObject apparent = powers[PSTR("apparent")].getObject();
      if (apparent) {
        val = apparent[field];                       // "a" .. "d"
        if (val) { Ade7953.calib_data[i][ADE7953_CAL_VAGAIN] = val.getInt(); }
      }
      JsonParserObject reactive = powers[PSTR("reactive")].getObject();
      if (reactive) {
        val = reactive[field];                       // "a" .. "d"
        if (val) { Ade7953.calib_data[i][ADE7953_CAL_VARGAIN] = val.getInt(); }
      }
    }
  }
  return true;
}

void Ade7953Defaults(void) {
  for (uint32_t channel = 0; channel < ADE7953_MAX_CHANNEL; channel++) {
    for (uint32_t i = 0; i < ADE7953_CALIBREGS; i++) {
      if (ADE7943_CAL_PHCAL == i) {
        Ade7953.calib_data[channel][i] = (ADE7953_SHELLY_EM == Ade7953.model) ? ADE7953_PHCAL_DEFAULT_CT : ADE7953_PHCAL_DEFAULT;
      } else {
        Ade7953.calib_data[channel][i] = ADE7953_GAIN_DEFAULT;
      }
    }
  }

  String calib = "";
#ifdef USE_UFILESYS
  calib = TfsLoadString("/calib.dat");
#endif  // USE_UFILESYS
#ifdef USE_RULES
  // rule3 on file#calib.dat do {"angles":{"angle0":180,"angle1":176}} endon
  if (!calib.length()) {
    calib = RuleLoadFile("CALIB.DAT");
  }
#endif  // USE_RULES
  if (calib.length()) {
//    AddLog(LOG_LEVEL_DEBUG, PSTR("ADE: File '%s'"), calib.c_str());
    Ade7953SetDefaults(calib.c_str());
  }
}

void Ade7953DrvInit(void) {
  if (PinUsed(GPIO_ADE7953_IRQ, GPIO_ANY)) {         // Irq is not supported...
    uint32_t pin_irq = Pin(GPIO_ADE7953_IRQ, GPIO_ANY);
    pinMode(pin_irq, INPUT);                         // Related to resetPins() - Must be set to input
    // 0 (1 = Shelly 2.5), 1 (2 = Shelly EM), 2 (3 = Shelly Plus 2PM), 3 (4 = Shelly Pro 1PM), 4 (5 = Shelly Pro 2PM), 5 (6 = Shelly Pro 4PM)
    Ade7953.model = GetPin(pin_irq) - AGPIO(GPIO_ADE7953_IRQ);

    int pin_reset = Pin(GPIO_ADE7953_RST);           // -1 if not defined
#ifdef ESP8266
    if (ADE7953_SHELLY_EM == Ade7953.model) {
      if (-1 == pin_reset) {
        pin_reset = 16;
      }
    }
#endif
    if (pin_reset >= 0) {
      digitalWrite(pin_reset, 0);
      pinMode(pin_reset, OUTPUT);                    // Reset pin ADE7953
      delay(1);                                      // To initiate a hardware reset, this pin must be brought low for a minimum of 10 μs.
      digitalWrite(pin_reset, 1);
      if (Ade7953.model < ADE7953_SHELLY_PRO_1PM) {
        pinMode(pin_reset, INPUT);
      }
    }
#ifdef USE_ESP32_SPI
#if (defined(USE_SHELLY_PRO) && defined(USE_MCP23XXX_DRV)) || defined(USE_SHELLY_PRO_V2)
    if (Ade7953.model == ADE7953_SHELLY_PRO_4PM) {
      ShellyPro4Reset();
    }
#endif  // USE_SHELLY_PRO
#endif  // USE_ESP32_SPI
    delay(100);                                      // Need 100mS to init ADE7953

#ifdef USE_ESP32_SPI
    Ade7953.pin_cs[0] = -1;
    Ade7953.pin_cs[1] = -1;
    if (Ade7953.model >= ADE7953_SHELLY_PRO_1PM) {   // SPI
      if (PinUsed(GPIO_ADE7953_CS)) {                // ADE7953 CS1 enabled (Pro 1PM/2PM)
        Ade7953.pin_cs[0] = Pin(GPIO_ADE7953_CS);
        digitalWrite(Ade7953.pin_cs[0], 1);          // ADE7953 CS1 enabled (Pro 2PM)
        pinMode(Ade7953.pin_cs[0], OUTPUT);
        Ade7953.pin_cs[1] = Pin(GPIO_ADE7953_CS, 1);
        if (Ade7953.pin_cs[1] > -1) {                // ADE7953 CS2 enabled (Pro 2PM)
          digitalWrite(Ade7953.pin_cs[1], 1);
          pinMode(Ade7953.pin_cs[1], OUTPUT);
        } else {
          Ade7953.model = ADE7953_SHELLY_PRO_1PM;
        }
        Ade7953.cs_index = 0;
        Ade7953.use_spi = true;
        SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1);
        AddLog(LOG_LEVEL_INFO, PSTR("SPI: ADE7953 found"));
      } else {
        return;                                       // No CS pin defined
      }
    } else {
#endif  // USE_ESP32_SPI
      if (!I2cSetDevice(ADE7953_ADDR)) {
        return;
      }
      I2cSetActiveFound(ADE7953_ADDR, "ADE7953");
#ifdef USE_ESP32_SPI
    }
#endif  // USE_ESP32_SPI
    if (EnergyGetCalibration(ENERGY_POWER_CALIBRATION) == HLW_PREF_PULSE) {
      for (uint32_t i = 0; i < ADE7953_MAX_CHANNEL; i++) {
        EnergySetCalibration(ENERGY_POWER_CALIBRATION, ADE7953_PREF, i);
        EnergySetCalibration(ENERGY_VOLTAGE_CALIBRATION, ADE7953_UREF, i);
        EnergySetCalibration(ENERGY_CURRENT_CALIBRATION, ADE7953_IREF, i);
      }
    }

    Ade7953Defaults();

    Ade7953.init_step = 3;

//    Energy->phase_count = 1;
//    Energy->voltage_common = false;
//    Energy->frequency_common = false;
//    Energy->use_overtemp = false;
    if (ADE7953_SHELLY_PRO_1PM == Ade7953.model) {
    } else {
      Energy->phase_count = 2;                        // Handle two channels as two phases
      if (ADE7953_SHELLY_PRO_2PM == Ade7953.model) {
      } else {
        Energy->voltage_common = true;                // Use common voltage
        Energy->frequency_common = true;              // Use common frequency
        if (ADE7953_SHELLY_PRO_4PM == Ade7953.model) {
          Energy->phase_count = 4;
        }
      }
    }
    Energy->use_overtemp = true;                      // Use global temperature for overtemp detection
    if (ADE7953_SHELLY_EM == Ade7953.model) {
      Energy->local_energy_active_export = true;
    }
    TasmotaGlobal.energy_driver = XNRG_07;
  }
}

bool Ade7953Command(void) {
  bool serviced = true;

  if (XdrvMailbox.index > ADE7953_MAX_CHANNEL) { return false; };
  uint32_t channel = XdrvMailbox.index -1;
  if (ADE7953_SHELLY_PRO_4PM != Ade7953.model) {
    channel = (2 == XdrvMailbox.index) ? 1 : 0;
  }
  uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100);  // 1.23 = 123

  if (CMND_POWERCAL == Energy->command_code) {
    if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; }
    // Service in xdrv_03_energy.ino
  }
  else if (CMND_VOLTAGECAL == Energy->command_code) {
    if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_UREF; }
    // Service in xdrv_03_energy.ino
  }
  else if (CMND_CURRENTCAL == Energy->command_code) {
    if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_IREF; }
    // Service in xdrv_03_energy.ino
  }
  else if (CMND_POWERSET == Energy->command_code) {
    if (XdrvMailbox.data_len && Ade7953.active_power[channel]) {
      if ((value > 100) && (value < 200000)) {       // Between 1W and 2000W
#ifdef ADE7953_ACCU_ENERGY
        float power_calibration = (float)(Ade7953.active_power[channel] * 1000) / value;  // 0.00 W
        power_calibration *= ADE7953_POWER_CORRECTION;
        XdrvMailbox.payload = (uint32_t)power_calibration;  // 0.00 W
#else   // No ADE7953_ACCU_ENERGY
        XdrvMailbox.payload = (Ade7953.active_power[channel] * 1000) / value;  // 0.00 W
#endif  // ADE7953_ACCU_ENERGY
      }
    }
  }
  else if (CMND_VOLTAGESET == Energy->command_code) {
    if (XdrvMailbox.data_len && Ade7953.voltage_rms[channel]) {
      if ((value > 10000) && (value < 26000)) {      // Between 100V and 260V
        XdrvMailbox.payload = (Ade7953.voltage_rms[channel] * 100) / value;  // 0.00 V
      }
    }
  }
  else if (CMND_CURRENTSET == Energy->command_code) {
    if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) {
      if ((value > 2000) && (value < 1000000)) {     // Between 20mA and 10A
        XdrvMailbox.payload = ((Ade7953.current_rms[channel] * 100) / value) * 100;  // 0.00 mA
      }
    }
  }
  else serviced = false;                             // Unknown command

  return serviced;
}

/*********************************************************************************************\
 * Interface
\*********************************************************************************************/

bool Xnrg07(uint32_t function) {
  if (!I2cEnabled(XI2C_07) && (SPI_MOSI_MISO != TasmotaGlobal.spi_enabled)) { return false; }

  bool result = false;

  switch (function) {
#ifdef USE_ESP32_SPI
    case FUNC_ENERGY_EVERY_SECOND:  // Use energy interrupt timer (fails on SPI)
      if (!Ade7953.use_spi) {       // No SPI
        Ade7953EnergyEverySecond();
      }
      break;
    case FUNC_EVERY_SECOND:         // Use loop timer (without interrupt)
      if (Ade7953.use_spi) {        // SPI
        Ade7953EnergyEverySecond();
      }
      break;
#else   // ESP8266
    case FUNC_ENERGY_EVERY_SECOND:  // Use energy interrupt timer
      Ade7953EnergyEverySecond();
      break;
#endif  // USE_ESP32_SPI
    case FUNC_COMMAND:
      result = Ade7953Command();
      break;
    case FUNC_PRE_INIT:
      Ade7953DrvInit();
      break;
  }
  return result;
}

#endif  // USE_ADE7953
#endif  // USE_ENERGY_SENSOR
#endif  // USE_I2C or USE_ESP_SPI
