ESPHome 2025.9.0-dev
Loading...
Searching...
No Matches
pn532_spi.cpp
Go to the documentation of this file.
1#include "pn532_spi.h"
2#include "esphome/core/log.h"
3
4// Based on:
5// - https://cdn-shop.adafruit.com/datasheets/PN532C106_Application+Note_v1.2.pdf
6// - https://www.nxp.com/docs/en/nxp/application-notes/AN133910.pdf
7// - https://www.nxp.com/docs/en/nxp/application-notes/153710.pdf
8
9namespace esphome {
10namespace pn532_spi {
11
12static const char *const TAG = "pn532_spi";
13
15 this->spi_setup();
16
17 this->cs_->digital_write(false);
18 delay(10);
19 PN532::setup();
20}
21
23 this->enable();
24 this->write_byte(0x02);
25 bool ready = this->read_byte() == 0x01;
26 this->disable();
27 return ready;
28}
29
30bool PN532Spi::write_data(const std::vector<uint8_t> &data) {
31 this->enable();
32 delay(2);
33 // First byte, communication mode: Write data
34 this->write_byte(0x01);
35 ESP_LOGV(TAG, "Writing data: %s", format_hex_pretty(data).c_str());
36 this->write_array(data.data(), data.size());
37 this->disable();
38
39 return true;
40}
41
42bool PN532Spi::read_data(std::vector<uint8_t> &data, uint8_t len) {
43 if (this->read_ready_(true) != pn532::PN532ReadReady::READY) {
44 return false;
45 }
46
47 // Read data (transmission from the PN532 to the host)
48 this->enable();
49 delay(2);
50 this->write_byte(0x03);
51
52 ESP_LOGV(TAG, "Reading data");
53
54 data.resize(len);
55 this->read_array(data.data(), len);
56 this->disable();
57 data.insert(data.begin(), 0x01);
58 ESP_LOGV(TAG, "Read data: %s", format_hex_pretty(data).c_str());
59 return true;
60}
61
62bool PN532Spi::read_response(uint8_t command, std::vector<uint8_t> &data) {
63 ESP_LOGV(TAG, "Reading response");
64
65 if (this->read_ready_(true) != pn532::PN532ReadReady::READY) {
66 return false;
67 }
68
69 this->enable();
70 delay(2);
71 this->write_byte(0x03);
72
73 std::vector<uint8_t> header(7);
74 this->read_array(header.data(), 7);
75
76 ESP_LOGV(TAG, "Header data: %s", format_hex_pretty(header).c_str());
77
78 if (header[0] != 0x00 && header[1] != 0x00 && header[2] != 0xFF) {
79 // invalid packet
80 ESP_LOGV(TAG, "read data invalid preamble!");
81 return false;
82 }
83
84 bool valid_header = (static_cast<uint8_t>(header[3] + header[4]) == 0 && // LCS, len + lcs = 0
85 header[5] == 0xD5 && // TFI - frame from PN532 to system controller
86 header[6] == command + 1); // Correct command response
87
88 if (!valid_header) {
89 ESP_LOGV(TAG, "read data invalid header!");
90 return false;
91 }
92
93 // full length of message, including command response
94 uint8_t full_len = header[3];
95 // length of data, excluding command response
96 uint8_t len = full_len - 1;
97 if (full_len == 0)
98 len = 0;
99
100 ESP_LOGV(TAG, "Reading response of length %d", len);
101
102 data.resize(len + 1);
103 this->read_array(data.data(), len + 1);
104 this->disable();
105
106 ESP_LOGV(TAG, "Response data: %s", format_hex_pretty(data).c_str());
107
108 uint8_t checksum = header[5] + header[6]; // TFI + Command response code
109 for (int i = 0; i < len - 1; i++) {
110 uint8_t dat = data[i];
111 checksum += dat;
112 }
113 checksum = ~checksum + 1;
114
115 if (data[len - 1] != checksum) {
116 ESP_LOGV(TAG, "read data invalid checksum! %02X != %02X", data[len - 1], checksum);
117 return false;
118 }
119
120 if (data[len] != 0x00) {
121 ESP_LOGV(TAG, "read data invalid postamble!");
122 return false;
123 }
124
125 data.erase(data.end() - 2, data.end()); // Remove checksum and postamble
126
127 return true;
128}
129
131 PN532::dump_config();
132 LOG_PIN(" CS Pin: ", this->cs_);
133}
134
135} // namespace pn532_spi
136} // namespace esphome
uint8_t checksum
Definition bl0906.h:3
virtual void digital_write(bool value)=0
enum PN532ReadReady read_ready_(bool block)
Definition pn532.cpp:308
bool write_data(const std::vector< uint8_t > &data) override
Definition pn532_spi.cpp:30
bool read_data(std::vector< uint8_t > &data, uint8_t len) override
Definition pn532_spi.cpp:42
bool is_read_ready() override
Definition pn532_spi.cpp:22
bool read_response(uint8_t command, std::vector< uint8_t > &data) override
Definition pn532_spi.cpp:62
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:279
std::string format_hex_pretty(const uint8_t *data, size_t length, char separator, bool show_length)
Format a byte array in pretty-printed, human-readable hex format.
Definition helpers.cpp:280
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:29