ESPHome  2024.7.1
at581x.cpp
Go to the documentation of this file.
1 #include "at581x.h"
2 #include "esphome/core/log.h"
3 
4 /* Select gain for AT581X (3dB per step for level1, 6dB per step for level 2), high value = small gain. (p12) */
5 const uint8_t GAIN_ADDR_TABLE[] = {0x5c, 0x63};
6 const uint8_t GAIN5C_TABLE[] = {0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xa8, 0xb8, 0xc8};
7 const uint8_t GAIN63_TABLE[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
8 const uint8_t GAIN61_VALUE = 0xCA; // 0xC0 | 0x02 (freq present) | 0x08 (gain present)
9 
11 const uint8_t POWER_TABLE[] = {48, 56, 63, 70, 77, 91, 105, 115, 40, 44, 47, 51, 54, 61, 68, 78};
12 const uint8_t POWER67_TABLE[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
13 const uint8_t POWER68_TABLE[] = {0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
14  24, 24, 24, 24, 24, 24, 24, 24}; // See Page 12, shift by 3 bits
15 
17 const uint8_t FREQ_ADDR = 0x61;
18 const uint16_t FREQ_TABLE[] = {5696, 5715, 5730, 5748, 5765, 5784, 5800, 5819, 5836, 5851, 5869, 5888};
19 const uint8_t FREQ5F_TABLE[] = {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x40, 0x41, 0x42, 0x43};
20 const uint8_t FREQ60_TABLE[] = {0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e};
21 
23 const uint8_t RF_OFF_TABLE[] = {0x46, 0xaa, 0x50};
24 const uint8_t RF_ON_TABLE[] = {0x45, 0x55, 0xA0};
25 const uint8_t RF_REG_ADDR[] = {0x5d, 0x62, 0x51};
26 
28 const uint8_t HIGH_LEVEL_DELAY_CONTROL_ADDR = 0x41;
29 const uint8_t HIGH_LEVEL_DELAY_VALUE_ADDR = 0x42;
31 const uint8_t RESET_ADDR = 0x00;
32 
36 
38 const uint8_t POWER_THRESHOLD_ADDR_HI = 0x68;
39 const uint8_t POWER_THRESHOLD_ADDR_LO = 0x67;
40 const uint8_t PWR_WORK_TIME_EN = 8; // Reg 0x67
41 const uint8_t PWR_BURST_TIME_EN = 32; // Reg 0x68
42 const uint8_t PWR_THRESH_EN = 64; // Reg 0x68
43 const uint8_t PWR_THRESH_VAL_EN = 128; // Reg 0x67
44 
46 const uint8_t TRIGGER_BASE_TIME_ADDR = 0x3D; // 4 bytes, so up to 0x40
47 const uint8_t PROTECT_TIME_ADDR = 0x4E; // 2 bytes, up to 0x4F
48 const uint8_t TRIGGER_KEEP_TIME_ADDR = 0x42; // 4 bytes, so up to 0x45
49 const uint8_t TIME41_VALUE = 1;
50 const uint8_t SELF_CHECK_TIME_ADDR = 0x38; // 2 bytes, up to 0x39
51 
52 namespace esphome {
53 namespace at581x {
54 
55 static const char *const TAG = "at581x";
56 
57 bool AT581XComponent::i2c_write_reg(uint8_t addr, uint8_t data) {
58  return this->write_register(addr, &data, 1) == esphome::i2c::NO_ERROR;
59 }
60 bool AT581XComponent::i2c_write_reg(uint8_t addr, uint32_t data) {
61  return this->i2c_write_reg(addr + 0, uint8_t(data & 0xFF)) &&
62  this->i2c_write_reg(addr + 1, uint8_t((data >> 8) & 0xFF)) &&
63  this->i2c_write_reg(addr + 2, uint8_t((data >> 16) & 0xFF)) &&
64  this->i2c_write_reg(addr + 3, uint8_t((data >> 24) & 0xFF));
65 }
66 bool AT581XComponent::i2c_write_reg(uint8_t addr, uint16_t data) {
67  return this->i2c_write_reg(addr, uint8_t(data & 0xFF)) && this->i2c_write_reg(addr + 1, uint8_t((data >> 8) & 0xFF));
68 }
69 
70 bool AT581XComponent::i2c_read_reg(uint8_t addr, uint8_t &data) {
71  return this->read_register(addr, &data, 1) == esphome::i2c::NO_ERROR;
72 }
73 
74 void AT581XComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up AT581X..."); }
75 void AT581XComponent::dump_config() { LOG_I2C_DEVICE(this); }
76 #define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
78  ESP_LOGCONFIG(TAG, "Writing new config for AT581X...");
79  ESP_LOGCONFIG(TAG, "Frequency: %dMHz", this->freq_);
80  ESP_LOGCONFIG(TAG, "Sensing distance: %d", this->delta_);
81  ESP_LOGCONFIG(TAG, "Power: %dµA", this->power_);
82  ESP_LOGCONFIG(TAG, "Gain: %d", this->gain_);
83  ESP_LOGCONFIG(TAG, "Trigger base time: %dms", this->trigger_base_time_ms_);
84  ESP_LOGCONFIG(TAG, "Trigger keep time: %dms", this->trigger_keep_time_ms_);
85  ESP_LOGCONFIG(TAG, "Protect time: %dms", this->protect_time_ms_);
86  ESP_LOGCONFIG(TAG, "Self check time: %dms", this->self_check_time_ms_);
87 
88  // Set frequency point
89  if (!this->i2c_write_reg(FREQ_ADDR, GAIN61_VALUE)) {
90  ESP_LOGE(TAG, "Failed to write AT581X Freq mode");
91  return false;
92  }
93  // Find the current frequency from the table to know what value to write
94  for (size_t i = 0; i < ARRAY_SIZE(FREQ_TABLE) + 1; i++) {
95  if (i == ARRAY_SIZE(FREQ_TABLE)) {
96  ESP_LOGE(TAG, "Set frequency not found");
97  return false;
98  }
99  if (FREQ_TABLE[i] == this->freq_) {
100  if (!this->i2c_write_reg(0x5F, FREQ5F_TABLE[i]) || !this->i2c_write_reg(0x60, FREQ60_TABLE[i])) {
101  ESP_LOGE(TAG, "Failed to write AT581X Freq value");
102  return false;
103  }
104  break;
105  }
106  }
107 
108  // Set distance
109  if (!this->i2c_write_reg(SIGNAL_DETECTION_THRESHOLD_ADDR_LO, (uint8_t) (this->delta_ & 0xFF)) ||
110  !this->i2c_write_reg(SIGNAL_DETECTION_THRESHOLD_ADDR_HI, (uint8_t) (this->delta_ >> 8))) {
111  ESP_LOGE(TAG, "Failed to write AT581X sensing distance low");
112  return false;
113  }
114 
115  // Set power setting
117  for (size_t i = 0; i < ARRAY_SIZE(POWER_TABLE) + 1; i++) {
118  if (i == ARRAY_SIZE(POWER_TABLE)) {
119  ESP_LOGE(TAG, "Set power not found");
120  return false;
121  }
122  if (POWER_TABLE[i] == this->power_) {
123  pwr67 |= POWER67_TABLE[i];
124  pwr68 |= POWER68_TABLE[i]; // See Page 12
125  break;
126  }
127  }
128 
129  if (!this->i2c_write_reg(POWER_THRESHOLD_ADDR_LO, pwr67) || !this->i2c_write_reg(POWER_THRESHOLD_ADDR_HI, pwr68)) {
130  ESP_LOGE(TAG, "Failed to write AT581X power registers");
131  return false;
132  }
133 
134  // Set gain
135  if (!this->i2c_write_reg(GAIN_ADDR_TABLE[0], GAIN5C_TABLE[this->gain_]) ||
136  !this->i2c_write_reg(GAIN_ADDR_TABLE[1], GAIN63_TABLE[this->gain_ >> 1])) {
137  ESP_LOGE(TAG, "Failed to write AT581X gain registers");
138  return false;
139  }
140 
141  // Set times
142  if (!this->i2c_write_reg(TRIGGER_BASE_TIME_ADDR, (uint32_t) this->trigger_base_time_ms_)) {
143  ESP_LOGE(TAG, "Failed to write AT581X trigger base time registers");
144  return false;
145  }
146  if (!this->i2c_write_reg(TRIGGER_KEEP_TIME_ADDR, (uint32_t) this->trigger_keep_time_ms_)) {
147  ESP_LOGE(TAG, "Failed to write AT581X trigger keep time registers");
148  return false;
149  }
150 
151  if (!this->i2c_write_reg(PROTECT_TIME_ADDR, (uint16_t) this->protect_time_ms_)) {
152  ESP_LOGE(TAG, "Failed to write AT581X protect time registers");
153  return false;
154  }
155  if (!this->i2c_write_reg(SELF_CHECK_TIME_ADDR, (uint16_t) this->self_check_time_ms_)) {
156  ESP_LOGE(TAG, "Failed to write AT581X self check time registers");
157  return false;
158  }
159 
160  if (!this->i2c_write_reg(0x41, TIME41_VALUE)) {
161  ESP_LOGE(TAG, "Failed to enable AT581X time registers");
162  return false;
163  }
164 
165  // Don't know why it's required in other code, it's not in datasheet
166  if (!this->i2c_write_reg(0x55, (uint8_t) 0x04)) {
167  ESP_LOGE(TAG, "Failed to enable AT581X");
168  return false;
169  }
170 
171  // Ok, config is written, let's reset the chip so it's using the new config
172  return this->reset_hardware_frontend();
173 }
174 
175 // float AT581XComponent::get_setup_priority() const { return 0; }
177  if (!this->i2c_write_reg(RESET_ADDR, (uint8_t) 0) || !this->i2c_write_reg(RESET_ADDR, (uint8_t) 1)) {
178  ESP_LOGE(TAG, "Failed to reset AT581X hardware frontend");
179  return false;
180  }
181  return true;
182 }
183 
184 void AT581XComponent::set_rf_mode(bool enable) {
185  const uint8_t *p = enable ? &RF_ON_TABLE[0] : &RF_OFF_TABLE[0];
186  for (size_t i = 0; i < ARRAY_SIZE(RF_REG_ADDR); i++) {
187  if (!this->i2c_write_reg(RF_REG_ADDR[i], p[i])) {
188  ESP_LOGE(TAG, "Failed to write AT581X RF mode");
189  return;
190  }
191  }
192 }
193 
194 } // namespace at581x
195 } // namespace esphome
bool i2c_read_reg(uint8_t addr, uint8_t &data)
Definition: at581x.cpp:70
void dump_config() override
Definition: at581x.cpp:75
const uint8_t RF_OFF_TABLE[]
Definition: at581x.cpp:23
ErrorCode read_register(uint8_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:10
bool i2c_write_reg(uint8_t addr, uint8_t data)
Definition: at581x.cpp:57
const uint8_t HIGH_LEVEL_DELAY_VALUE_ADDR
Definition: at581x.cpp:29
void set_rf_mode(bool enabled)
Definition: at581x.cpp:184
const uint8_t FREQ_ADDR
Definition: at581x.cpp:17
const uint8_t POWER67_TABLE[]
Definition: at581x.cpp:12
const uint8_t GAIN_ADDR_TABLE[]
Definition: at581x.cpp:5
const uint8_t RF_REG_ADDR[]
Definition: at581x.cpp:25
const uint8_t GAIN61_VALUE
Definition: at581x.cpp:8
const uint8_t GAIN63_TABLE[]
Definition: at581x.cpp:7
const uint8_t SIGNAL_DETECTION_THRESHOLD_ADDR_HI
Definition: at581x.cpp:35
const uint8_t PWR_THRESH_VAL_EN
Definition: at581x.cpp:43
const uint8_t PWR_WORK_TIME_EN
Definition: at581x.cpp:40
No error found during execution of method.
Definition: i2c_bus.h:12
const uint8_t POWER_THRESHOLD_ADDR_HI
Definition: at581x.cpp:38
const uint8_t FREQ60_TABLE[]
Definition: at581x.cpp:20
const uint8_t POWER68_TABLE[]
Definition: at581x.cpp:13
const uint8_t PWR_BURST_TIME_EN
Definition: at581x.cpp:41
const uint8_t GAIN5C_TABLE[]
Definition: at581x.cpp:6
const uint8_t TRIGGER_KEEP_TIME_ADDR
Definition: at581x.cpp:48
const uint8_t PWR_THRESH_EN
Definition: at581x.cpp:42
const uint8_t SIGNAL_DETECTION_THRESHOLD_ADDR_LO
Definition: at581x.cpp:34
const uint16_t FREQ_TABLE[]
Definition: at581x.cpp:18
const uint8_t RESET_ADDR
Definition: at581x.cpp:31
const uint8_t HIGH_LEVEL_DELAY_CONTROL_ADDR
Definition: at581x.cpp:28
const uint8_t TRIGGER_BASE_TIME_ADDR
Definition: at581x.cpp:46
const uint8_t TIME41_VALUE
Definition: at581x.cpp:49
const uint8_t SELF_CHECK_TIME_ADDR
Definition: at581x.cpp:50
const uint8_t RF_ON_TABLE[]
Definition: at581x.cpp:24
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len, bool stop=true)
writes an array of bytes to a specific register in the I²C device
Definition: i2c.cpp:25
const uint8_t FREQ5F_TABLE[]
Definition: at581x.cpp:19
const uint8_t POWER_TABLE[]
Definition: at581x.cpp:11
const uint8_t POWER_THRESHOLD_ADDR_LO
Definition: at581x.cpp:39
const uint8_t PROTECT_TIME_ADDR
Definition: at581x.cpp:47