ESPHome  2024.5.0
ade7880_i2c.cpp
Go to the documentation of this file.
1 // This component was developed using knowledge gathered by a number
2 // of people who reverse-engineered the Shelly 3EM:
3 //
4 // @AndreKR on GitHub
5 // Axel (@Axel830 on GitHub)
6 // Marko (@goodkiller on GitHub)
7 // Michaël Piron (@michaelpiron on GitHub)
8 // Theo Arends (@arendst on GitHub)
9 
10 #include "ade7880.h"
11 
12 namespace esphome {
13 namespace ade7880 {
14 
15 // adapted from https://stackoverflow.com/a/55912127/1886371
16 template<size_t Bits, typename T> inline T sign_extend(const T &v) noexcept {
17  using S = struct { signed Val : Bits; };
18  return reinterpret_cast<const S *>(&v)->Val;
19 }
20 
21 // Register types
22 // unsigned 8-bit (uint8_t)
23 // signed 10-bit - 16-bit ZP on wire (int16_t, needs sign extension)
24 // unsigned 16-bit (uint16_t)
25 // unsigned 20-bit - 32-bit ZP on wire (uint32_t)
26 // signed 24-bit - 32-bit ZPSE on wire (int32_t, needs sign extension)
27 // signed 24-bit - 32-bit ZP on wire (int32_t, needs sign extension)
28 // signed 24-bit - 32-bit SE on wire (int32_t)
29 // signed 28-bit - 32-bit ZP on wire (int32_t, needs sign extension)
30 // unsigned 32-bit (uint32_t)
31 // signed 32-bit (int32_t)
32 
33 uint8_t ADE7880::read_u8_register16_(uint16_t a_register) {
34  uint8_t in;
35  this->read_register16(a_register, &in, sizeof(in));
36  return in;
37 }
38 
39 int16_t ADE7880::read_s16_register16_(uint16_t a_register) {
40  int16_t in;
41  this->read_register16(a_register, reinterpret_cast<uint8_t *>(&in), sizeof(in));
42  return convert_big_endian(in);
43 }
44 
45 uint16_t ADE7880::read_u16_register16_(uint16_t a_register) {
46  uint16_t in;
47  this->read_register16(a_register, reinterpret_cast<uint8_t *>(&in), sizeof(in));
48  return convert_big_endian(in);
49 }
50 
51 int32_t ADE7880::read_s24zp_register16_(uint16_t a_register) {
52  // s24zp means 24 bit signed value in the lower 24 bits of a 32-bit register
53  int32_t in;
54  this->read_register16(a_register, reinterpret_cast<uint8_t *>(&in), sizeof(in));
55  return sign_extend<24>(convert_big_endian(in));
56 }
57 
58 int32_t ADE7880::read_s32_register16_(uint16_t a_register) {
59  int32_t in;
60  this->read_register16(a_register, reinterpret_cast<uint8_t *>(&in), sizeof(in));
61  return convert_big_endian(in);
62 }
63 
64 uint32_t ADE7880::read_u32_register16_(uint16_t a_register) {
65  uint32_t in;
66  this->read_register16(a_register, reinterpret_cast<uint8_t *>(&in), sizeof(in));
67  return convert_big_endian(in);
68 }
69 
70 void ADE7880::write_u8_register16_(uint16_t a_register, uint8_t value) {
71  this->write_register16(a_register, &value, sizeof(value));
72 }
73 
74 void ADE7880::write_s10zp_register16_(uint16_t a_register, int16_t value) {
75  int16_t out = convert_big_endian(value & 0x03FF);
76  this->write_register16(a_register, reinterpret_cast<uint8_t *>(&out), sizeof(out));
77 }
78 
79 void ADE7880::write_u16_register16_(uint16_t a_register, uint16_t value) {
80  uint16_t out = convert_big_endian(value);
81  this->write_register16(a_register, reinterpret_cast<uint8_t *>(&out), sizeof(out));
82 }
83 
84 void ADE7880::write_s24zpse_register16_(uint16_t a_register, int32_t value) {
85  // s24zpse means a 24-bit signed value, sign-extended to 28 bits, in the lower 28 bits of a 32-bit register
86  int32_t out = convert_big_endian(value & 0x0FFFFFFF);
87  this->write_register16(a_register, reinterpret_cast<uint8_t *>(&out), sizeof(out));
88 }
89 
90 void ADE7880::write_s32_register16_(uint16_t a_register, int32_t value) {
91  int32_t out = convert_big_endian(value);
92  this->write_register16(a_register, reinterpret_cast<uint8_t *>(&out), sizeof(out));
93 }
94 
95 void ADE7880::write_u32_register16_(uint16_t a_register, uint32_t value) {
96  uint32_t out = convert_big_endian(value);
97  this->write_register16(a_register, reinterpret_cast<uint8_t *>(&out), sizeof(out));
98 }
99 
100 } // namespace ade7880
101 } // namespace esphome
T sign_extend(const T &v) noexcept
Definition: ade7880_i2c.cpp:16
void write_s32_register16_(uint16_t a_register, int32_t value)
Definition: ade7880_i2c.cpp:90
void write_u32_register16_(uint16_t a_register, uint32_t value)
Definition: ade7880_i2c.cpp:95
int16_t read_s16_register16_(uint16_t a_register)
Definition: ade7880_i2c.cpp:39
void write_u8_register16_(uint16_t a_register, uint8_t value)
Definition: ade7880_i2c.cpp:70
void write_s10zp_register16_(uint16_t a_register, int16_t value)
Definition: ade7880_i2c.cpp:74
void write_s24zpse_register16_(uint16_t a_register, int32_t value)
Definition: ade7880_i2c.cpp:84
uint32_t read_u32_register16_(uint16_t a_register)
Definition: ade7880_i2c.cpp:64
constexpr14 T convert_big_endian(T val)
Convert a value between host byte order and big endian (most significant byte first) order...
Definition: helpers.h:239
ErrorCode write_register16(uint16_t a_register, const uint8_t *data, size_t len, bool stop=true)
write an array of bytes to a specific register in the I²C device
Definition: i2c.cpp:34
int32_t read_s32_register16_(uint16_t a_register)
Definition: ade7880_i2c.cpp:58
void write_u16_register16_(uint16_t a_register, uint16_t value)
Definition: ade7880_i2c.cpp:79
uint8_t read_u8_register16_(uint16_t a_register)
Definition: ade7880_i2c.cpp:33
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
ErrorCode read_register16(uint16_t a_register, uint8_t *data, size_t len, bool stop=true)
reads an array of bytes from a specific register in the I²C device
Definition: i2c.cpp:17
uint16_t read_u16_register16_(uint16_t a_register)
Definition: ade7880_i2c.cpp:45
int32_t read_s24zp_register16_(uint16_t a_register)
Definition: ade7880_i2c.cpp:51