M5Unit-RFID 0.2.0 git rev:79c1939
Loading...
Searching...
No Matches
unit_UHFRFID.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_RFID_UNIT_UNIT_UHFRFID_HPP
11#define M5_UNIT_RFID_UNIT_UNIT_UHFRFID_HPP
12
13#include <memory>
14#include <vector>
15
16#include <M5UnitComponent.hpp>
17#include <m5_utility/container/circular_buffer.hpp>
18#include <m5_utility/stl/expected.hpp>
19
20#include "uhf/uhf.hpp"
21
22namespace m5 {
23namespace uhf {
24class UHFLayer;
25} // namespace uhf
26
27namespace unit {
28
35using TagResult = m5::stl::expected<void, uint8_t>;
36
45constexpr uint8_t READER_SILENT{0xFF};
46constexpr uint8_t READER_BALKED{0xFE};
47constexpr uint8_t READER_GARBLED{0xFD};
48constexpr uint8_t NOT_SELECTED{0xFC};
49constexpr uint8_t BAD_ARGUMENT{0xFB};
50constexpr uint8_t READER_BUSY{0xFA};
52
64class UHFRFIDComponent : public Component {
65public:
70 struct config_t {
75 uint16_t polling_count{128};
77 m5::uhf::Region region{m5::uhf::Region::Unspecified};
79 uint16_t tag_queue_size{32};
86 uint32_t command_timeout_ms{1000};
95 };
96
97 virtual ~UHFRFIDComponent() = default;
98
102 inline config_t config() const
103 {
104 return _cfg;
105 }
107 inline void config(const config_t& cfg)
108 {
109 _cfg = cfg;
110 }
112
115
123 bool startPolling(const uint16_t count);
131 bool stopPolling();
133 inline bool inPolling() const
134 {
135 return _polling;
136 }
143 inline unsigned long lastFrameAt() const
144 {
145 return _last_frame_at;
146 }
148
152 inline size_t available() const
153 {
154 return _tags ? _tags->size() : 0U;
155 }
157 inline const m5::uhf::Tag& oldest() const
158 {
159 return (*_tags)[0];
160 }
162 inline void discard()
163 {
164 if (_tags && !_tags->empty()) {
165 _tags->pop_front();
166 }
167 }
169 inline void flush()
170 {
171 if (_tags) {
172 _tags->clear();
173 }
174 }
176 inline uint32_t dropped() const
177 {
178 return _dropped;
179 }
181 inline void clearDropped()
182 {
183 _dropped = 0;
184 }
186
192 virtual bool readTransmitPower(int16_t& dbm100) = 0;
194 virtual bool writeTransmitPower(const int16_t dbm100) = 0;
196 virtual bool readRegion(m5::uhf::Region& region) = 0;
198 virtual bool writeRegion(const m5::uhf::Region region) = 0;
206 virtual bool readChannel(uint8_t& index) = 0;
208 virtual bool writeChannel(const uint8_t index) = 0;
210 virtual bool writeAutomaticFrequencyHopping(const bool enable) = 0;
221 virtual bool writeContinuousCarrier(const bool enable) = 0;
236 virtual bool writeAutoSleepTime(const uint8_t minutes) = 0;
249 virtual bool writeIdle(const bool enter, const uint8_t minutes = 0) = 0;
261 virtual bool sleep() = 0;
279 virtual bool wake() = 0;
287 virtual bool writeOperatingChannels(const std::vector<uint8_t>& channels) = 0;
302 virtual bool readChannelRSSI(m5::uhf::ChannelLevels& levels) = 0;
312
315
326 virtual bool writeSelectParameter(const m5::uhf::Bank bank, const uint32_t pointer_bits, const uint8_t* mask,
327 const size_t mask_len) = 0;
335 virtual bool writeSelectEnabled(const bool enable) = 0;
346 virtual TagResult readTagMemory(std::vector<uint8_t>& out, const m5::uhf::Bank bank, const uint16_t word_address,
347 const uint16_t word_count, const uint32_t access_password) = 0;
360 virtual TagResult writeTagMemory(const m5::uhf::Bank bank, const uint16_t word_address, const uint8_t* data,
361 const size_t len, const uint32_t access_password) = 0;
371 virtual TagResult lockTagMemory(const uint32_t payload, const uint32_t access_password) = 0;
387 virtual TagResult killTag(const uint32_t kill_password) = 0;
404 virtual TagResult blockPermalock(std::vector<uint8_t>& out, const m5::uhf::Bank bank, const uint16_t block_pointer,
405 const uint8_t block_range, const uint8_t* mask, const size_t mask_len,
406 const uint32_t access_password, const bool allow_permanent) = 0;
418 virtual TagResult qtCommand(uint16_t& control, const bool write, const bool persistent,
419 const uint32_t access_password) = 0;
435 virtual TagResult nxpChangeConfig(uint16_t& config, const uint16_t toggle, const uint32_t access_password) = 0;
447 virtual TagResult nxpChangeEAS(const bool enable, const uint32_t access_password) = 0;
458 virtual bool nxpEASAlarm(std::vector<uint8_t>& alarm) = 0;
473 virtual TagResult nxpReadProtect(const bool protect, const uint32_t access_password) = 0;
481 virtual m5::uhf::Reason classify(const uint8_t error_code) const = 0;
483
484 virtual bool begin() override;
485 virtual void update(const bool force = false) override;
486
487protected:
488 explicit UHFRFIDComponent(const uint8_t addr = 0x00) : Component(addr)
489 {
490 }
491
492 // Pump the UART stream and route frames. Returns true if any frame was handled
493 virtual bool pump(const uint32_t timeout_ms) = 0;
494 // Issue the multiple polling command
495 virtual bool start_polling_command(const uint16_t count) = 0;
496 // Issue the stop polling command
497 virtual bool stop_polling_command() = 0;
498
499 /*
500 Refuse a reader setting while polling is running
501 @param what Name of the operation, used in the warning
502 @return True when the caller must give up
503 @details The module answers unreliably while it is running inventory rounds, so reader
504 settings are rejected outright instead of failing later with a timeout
505 */
506 bool reject_while_polling(const char* what) const;
507
508 /*
509 Refuse a tag operation while no mask is picking a tag out
510 @param what Name of the operation, used in the warning
511 @return True when the caller must give up
512 @details A mask of zero length matches every tag rather than none, so an operation sent
513 without one does not fail: it succeeds against whichever tag answers. A write lands on a
514 tag nobody chose and a kill cannot be taken back, so these are rejected outright
515 */
516 bool reject_without_selection(const char* what) const;
517
518 // Push a tag into the queue, counting a drop when it overflows
519 void push_tag(const m5::uhf::Tag& tag);
520 // Note that a frame arrived (exposed through lastFrameAt)
521 void note_frame_arrival();
522 // Reissue the polling command before its round count runs out
523 void reissue_polling_if_needed();
524
525 config_t _cfg{};
526 std::unique_ptr<m5::container::CircularBuffer<m5::uhf::Tag>> _tags{};
527 uint32_t _dropped{};
528 // Whether polling should be renewed. Cleared as soon as a stop is asked for
529 bool _polling{};
530 // Whether the module is believed to still be running rounds. Only a confirmed stop clears it
531 bool _rounds_running{};
532 // Whether a mask of some length has been stored in the module
533 bool _select_mask_stored{};
534 // Whether the stored mask is being applied to tag operations
535 bool _select_enabled{};
536 uint16_t _polling_count{};
537 unsigned long _last_frame_at{};
538 unsigned long _polling_issued_at{};
539
540 friend class m5::uhf::UHFLayer;
541};
542
543} // namespace unit
544} // namespace m5
545#endif
EPC Gen2 semantics layer for UHF-RFID reader units.
Definition uhf_layer.hpp:39
Non-instantiable base class for UHF-RFID reader units.
Definition unit_UHFRFID.hpp:64
virtual bool writeAutomaticFrequencyHopping(const bool enable)=0
Enable or disable automatic frequency hopping.
void flush()
Discard all queued tags.
Definition unit_UHFRFID.hpp:169
virtual TagResult readTagMemory(std::vector< uint8_t > &out, const m5::uhf::Bank bank, const uint16_t word_address, const uint16_t word_count, const uint32_t access_password)=0
Read word_count 16-bit words from bank, starting at word_address.
virtual bool readModuleInformation(m5::uhf::ModuleInformation &info)=0
Read the module information.
virtual bool readBlockingSignal(m5::uhf::ChannelLevels &levels)=0
Measure the blocking signal on every channel of the operating region.
virtual bool readChannel(uint8_t &index)=0
Read the operating channel index.
virtual bool nxpEASAlarm(std::vector< uint8_t > &alarm)=0
Ask the field whether any tag has its Product Status Flag asserted.
virtual bool readTransmitPower(int16_t &dbm100)=0
Read the transmit power in 1/100 dBm.
virtual TagResult nxpChangeEAS(const bool enable, const uint32_t access_password)=0
Set or clear the Product Status Flag of an NXP UCODE G2X.
virtual TagResult nxpReadProtect(const bool protect, const uint32_t access_password)=0
Turn the read protection of an NXP UCODE G2X on or off.
bool stopPolling()
Stop continuous polling.
Definition unit_UHFRFID.cpp:56
uint32_t dropped() const
Number of tag notifications dropped due to queue overflow.
Definition unit_UHFRFID.hpp:176
virtual bool sleep()=0
Put the module into low power sleep.
virtual TagResult writeTagMemory(const m5::uhf::Bank bank, const uint16_t word_address, const uint8_t *data, const size_t len, const uint32_t access_password)=0
Write len bytes to bank, starting at word_address.
virtual TagResult lockTagMemory(const uint32_t payload, const uint32_t access_password)=0
Apply a 20-bit Gen2 lock payload.
virtual bool writeTransmitPower(const int16_t dbm100)=0
Write the transmit power in 1/100 dBm.
virtual TagResult qtCommand(uint16_t &control, const bool write, const bool persistent, const uint32_t access_password)=0
Read or write the QT control word of the addressed tag.
size_t available() const
Number of queued tag notifications.
Definition unit_UHFRFID.hpp:152
void clearDropped()
Clear the dropped counter.
Definition unit_UHFRFID.hpp:181
virtual TagResult blockPermalock(std::vector< uint8_t > &out, const m5::uhf::Bank bank, const uint16_t block_pointer, const uint8_t block_range, const uint8_t *mask, const size_t mask_len, const uint32_t access_password, const bool allow_permanent)=0
Read or set which blocks of a bank are permanently locked.
virtual bool writeOperatingChannels(const std::vector< uint8_t > &channels)=0
Replace the channel list used for automatic frequency hopping.
virtual TagResult nxpChangeConfig(uint16_t &config, const uint16_t toggle, const uint32_t access_password)=0
Read the Config-Word of an NXP UCODE G2X, or invert bits of it.
virtual bool writeContinuousCarrier(const bool enable)=0
Turn the unmodulated carrier on or off.
virtual bool writeChannel(const uint8_t index)=0
Write the operating channel index.
virtual bool writeSelectParameter(const m5::uhf::Bank bank, const uint32_t pointer_bits, const uint8_t *mask, const size_t mask_len)=0
Store the mask that picks out one tag.
virtual bool writeIdle(const bool enter, const uint8_t minutes=0)=0
Put the module into IDLE, or bring it out.
const m5::uhf::Tag & oldest() const
Oldest queued tag.
Definition unit_UHFRFID.hpp:157
virtual bool readChannelRSSI(m5::uhf::ChannelLevels &levels)=0
Measure the RSSI on every channel of the operating region.
void discard()
Discard the oldest queued tag.
Definition unit_UHFRFID.hpp:162
virtual bool writeRegion(const m5::uhf::Region region)=0
Write the operating region.
void config(const config_t &cfg)
Sets the configuration.
Definition unit_UHFRFID.hpp:107
virtual bool writeAutoSleepTime(const uint8_t minutes)=0
Write the inactivity period after which the module sleeps automatically.
config_t config() const
Gets the configuration.
Definition unit_UHFRFID.hpp:102
virtual bool readSelectParameter(m5::uhf::SelectParameter &sp)=0
Read back the select mask the reader holds.
unsigned long lastFrameAt() const
Timestamp (m5::utility::millis()) of the most recently arrived frame.
Definition unit_UHFRFID.hpp:143
bool inPolling() const
In continuous polling?
Definition unit_UHFRFID.hpp:133
virtual bool writeSelectEnabled(const bool enable)=0
Apply the stored mask to tag operations, or stop applying it.
bool startPolling(const uint16_t count)
Start continuous polling.
Definition unit_UHFRFID.cpp:42
virtual bool wake()=0
Wake the module from low power sleep.
virtual bool readQueryParameters(m5::uhf::QueryParameters &qp)=0
Read the query parameters.
virtual bool readRegion(m5::uhf::Region &region)=0
Read the operating region.
virtual TagResult killTag(const uint32_t kill_password)=0
Kill the addressed tag permanently.
virtual m5::uhf::Reason classify(const uint8_t error_code) const =0
Say what one of this reader's error codes means in EPC Gen2 terms.
virtual bool writeQueryParameters(const m5::uhf::QueryParameters &qp)=0
Write the query parameters.
Top level namespace of M5Stack.
UHF-RFID (EPC Gen2) related namespace.
Unit-related namespace.
Signal level measured on each channel of the operating region.
Definition uhf.hpp:1454
Reader module information.
Definition uhf.hpp:1442
EPC Gen2 query parameters.
Definition uhf.hpp:1302
The mask the reader holds, and how it is matched.
Definition uhf.hpp:1424
A tag, as the EPC Gen2 standard calls it.
Definition uhf.hpp:366
Settings for begin.
Definition unit_UHFRFID.hpp:70
uint8_t auto_sleep_minutes
Definition unit_UHFRFID.hpp:94
uint32_t command_timeout_ms
Definition unit_UHFRFID.hpp:86
uint16_t polling_count
Definition unit_UHFRFID.hpp:75
m5::uhf::Region region
Operating region (Unspecified keeps the module's factory setting)
Definition unit_UHFRFID.hpp:77
uint16_t tag_queue_size
Capacity of the tag queue.
Definition unit_UHFRFID.hpp:79
Common vocabulary for UHF-RFID (EPCglobal UHF Class 1 Gen 2 / ISO 18000-6C)
Reason
Why an operation meant to change a tag did not change it.
Definition uhf.hpp:90
Bank
EPC Gen2 memory bank.
Definition uhf.hpp:32
Region
Operating region.
Definition uhf.hpp:44
constexpr uint8_t READER_BALKED
The reader answered, and said it had not done it.
Definition unit_UHFRFID.hpp:46
constexpr uint8_t READER_SILENT
Nothing came back at all.
Definition unit_UHFRFID.hpp:45
constexpr uint8_t READER_GARBLED
The answer came back and could not be read.
Definition unit_UHFRFID.hpp:47
constexpr uint8_t READER_BUSY
Polling held the reader, so nothing was sent.
Definition unit_UHFRFID.hpp:50
m5::stl::expected< void, uint8_t > TagResult
What became of an operation on a tag.
Definition unit_UHFRFID.hpp:35
constexpr uint8_t BAD_ARGUMENT
The request could not succeed, so nothing was sent.
Definition unit_UHFRFID.hpp:49
constexpr uint8_t NOT_SELECTED
No tag had been selected, so nothing was sent.
Definition unit_UHFRFID.hpp:48