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