ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
pn532_i2c.cpp
Go to the documentation of this file.
1#include "pn532_i2c.h"
2#include "esphome/core/log.h"
3#include "esphome/core/hal.h"
4
5// Based on:
6// - https://cdn-shop.adafruit.com/datasheets/PN532C106_Application+Note_v1.2.pdf
7// - https://www.nxp.com/docs/en/nxp/application-notes/AN133910.pdf
8// - https://www.nxp.com/docs/en/nxp/application-notes/153710.pdf
9
11
12static const char *const TAG = "pn532_i2c";
13
15 uint8_t ready;
16 if (!this->read_bytes_raw(&ready, 1)) {
17 return false;
18 }
19 return ready == 0x01;
20}
21
22bool PN532I2C::write_data(const std::vector<uint8_t> &data) {
23 return this->write(data.data(), data.size()) == i2c::ERROR_OK;
24}
25
26bool PN532I2C::read_data(std::vector<uint8_t> &data, uint8_t len) {
27 delay(1);
28
29 if (this->read_ready_(true) != pn532::PN532ReadReady::READY) {
30 return false;
31 }
32
33 data.resize(len + 1);
34 this->read_bytes_raw(data.data(), len + 1);
35 return true;
36}
37
38bool PN532I2C::read_response(uint8_t command, std::vector<uint8_t> &data) {
39 ESP_LOGV(TAG, "Reading response");
40 uint8_t len = this->read_response_length_();
41 if (len == 0) {
42 return false;
43 }
44
45 ESP_LOGV(TAG, "Reading response of length %d", len);
46 if (!this->read_data(data, 6 + len + 2)) {
47 ESP_LOGD(TAG, "No response data");
48 return false;
49 }
50
51 if (data[1] != 0x00 || data[2] != 0x00 || data[3] != 0xFF) {
52 // invalid packet
53 ESP_LOGV(TAG, "read data invalid preamble!");
54 return false;
55 }
56
57 bool valid_header = (static_cast<uint8_t>(data[4] + data[5]) == 0 && // LCS, len + lcs = 0
58 data[6] == 0xD5 && // TFI - frame from PN532 to system controller
59 data[7] == command + 1); // Correct command response
60
61 if (!valid_header) {
62 ESP_LOGV(TAG, "read data invalid header!");
63 return false;
64 }
65
66 data.erase(data.begin(), data.begin() + 6); // Remove headers
67
68 uint8_t checksum = 0;
69 for (int i = 0; i < len + 1; i++) {
70 uint8_t dat = data[i];
71 checksum += dat;
72 }
73 checksum = ~checksum + 1;
74
75 if (data[len + 1] != checksum) {
76 ESP_LOGV(TAG, "read data invalid checksum! %02X != %02X", data[len], checksum);
77 return false;
78 }
79
80 if (data[len + 2] != 0x00) {
81 ESP_LOGV(TAG, "read data invalid postamble!");
82 return false;
83 }
84
85 data.erase(data.begin(), data.begin() + 2); // Remove TFI and command code
86 data.erase(data.end() - 2, data.end()); // Remove checksum and postamble
87
88 return true;
89}
90
92 std::vector<uint8_t> data;
93 if (!this->read_data(data, 6)) {
94 return 0;
95 }
96
97 if (data[1] != 0x00 || data[2] != 0x00 || data[3] != 0xFF) {
98 // invalid packet
99 ESP_LOGV(TAG, "read data invalid preamble!");
100 return 0;
101 }
102
103 bool valid_header = (static_cast<uint8_t>(data[4] + data[5]) == 0 && // LCS, len + lcs = 0
104 data[6] == 0xD5); // TFI - frame from PN532 to system controller
105
106 if (!valid_header) {
107 ESP_LOGV(TAG, "read data invalid header!");
108 return 0;
109 }
110
111 this->send_nack_();
112
113 // full length of message, including TFI
114 uint8_t full_len = data[4];
115 // length of data, excluding TFI
116 uint8_t len = full_len - 1;
117 if (full_len == 0)
118 len = 0;
119 return len;
120}
121
123 PN532::dump_config();
124 LOG_I2C_DEVICE(this);
125}
126
127} // namespace esphome::pn532_i2c
uint8_t checksum
Definition bl0906.h:3
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
Definition i2c.h:183
optional< std::array< uint8_t, N > > read_bytes_raw()
Definition i2c.h:230
enum PN532ReadReady read_ready_(bool block)
Definition pn532.cpp:307
bool write_data(const std::vector< uint8_t > &data) override
Definition pn532_i2c.cpp:22
bool read_response(uint8_t command, std::vector< uint8_t > &data) override
Definition pn532_i2c.cpp:38
bool is_read_ready() override
Definition pn532_i2c.cpp:14
bool read_data(std::vector< uint8_t > &data, uint8_t len) override
Definition pn532_i2c.cpp:26
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:14
const void size_t len
Definition hal.h:64
void HOT delay(uint32_t ms)
Definition hal.cpp:85