Skip to content

Commit 8d8eca3

Browse files
committed
Dump a range of a bank and size the write example from the tag
1 parent 1eeca47 commit 8d8eca3

4 files changed

Lines changed: 74 additions & 25 deletions

File tree

examples/UnitUnified/UHF/ReadWrite/main/ReadWrite.cpp

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <M5UnitUnifiedRFID.h>
1313
#include <M5Utility.h>
1414
#include <wiring/m5_unit_unified_wiring.hpp>
15+
#include <algorithm>
1516
#include <string>
1617
#include <vector>
1718

@@ -81,19 +82,12 @@ std::string to_hex(const std::vector<uint8_t>& data)
8182
//! @brief Words the short write test replaces and then puts back
8283
constexpr uint16_t WRITE_TEST_WORDS{2};
8384
/*!
84-
@brief Words the long write test replaces and then puts back
85-
@details The most a single Write command carries. The module programs the words into the tag
86-
one at a time and waits out the tag's write time for each, so this is the longest a single
87-
command legitimately takes. Monza 4QT holds exactly this much user memory
85+
@brief The most a single Write command carries
86+
@details The module programs the words into the tag one at a time and waits out the tag's
87+
write time for each, so a write of this many words is the longest a single command
88+
legitimately takes. Anything longer is split by writeBank into several
8889
*/
8990
constexpr uint16_t WRITE_TEST_MAX_WORDS{32};
90-
/*!
91-
@brief Words the whole-bank write test replaces and then puts back
92-
@details The full User bank of an Alien Higgs 9, 688 bits of it. More than a single Write
93-
command carries, so writeBank splits it, which is the thing worth exercising here. A tag with
94-
less user memory than this answers with a memory overrun and nothing is written
95-
*/
96-
constexpr uint16_t WRITE_TEST_BANK_WORDS{43};
9791

9892
/*!
9993
Write a stretch of User memory, read it back and put the original contents back.
@@ -128,7 +122,9 @@ void write_roundtrip(const m5::uhf::Tag& detected, const uint16_t words)
128122
const unsigned long read_began = m5::utility::millis();
129123
std::vector<uint8_t> original{};
130124
if (!uhf.readBank(original, m5::uhf::Bank::User, 0, words)) {
131-
M5_LOGE("write %u words: this tag has no User memory to write to, or not that much of it", words);
125+
// The caller sized this from what the tag holds, so a refusal here is not the bank being
126+
// too small; it is the read itself failing
127+
M5_LOGE("write %u words: could not read what is there now, so nothing is written", words);
132128
uhf.deselect();
133129
return;
134130
}
@@ -158,6 +154,7 @@ void write_roundtrip(const m5::uhf::Tag& detected, const uint16_t words)
158154
M5_LOGI("write %2u words: read %lums, write %lums, read back %s", words, read_took, took,
159155
readback == pattern ? "matches" : "MISMATCH");
160156
lcd.printf("%2u words %lums %s\n", words, took, readback == pattern ? "ok" : "NG");
157+
uhf.dump(m5::uhf::Bank::User, 0, words);
161158

162159
// Put it back the way it was, and say so loudly if that does not work: the tag is left
163160
// holding the pattern in that case
@@ -170,6 +167,7 @@ void write_roundtrip(const m5::uhf::Tag& detected, const uint16_t words)
170167
if (uhf.readBank(restored, m5::uhf::Bank::User, 0, words)) {
171168
M5_LOGI("write %2u words: restored %s", words, restored == original ? "matches" : "MISMATCH");
172169
}
170+
uhf.dump(m5::uhf::Bank::User, 0, words);
173171
uhf.deselect();
174172
}
175173
} // namespace
@@ -193,15 +191,48 @@ void loop()
193191
if (M5.BtnA.wasClicked()) {
194192
lcd.fillScreen(TFT_DARKGREEN);
195193
lcd.setCursor(0, 0);
194+
m5::uhf::Tag detected{};
195+
if (!detect_one(detected)) {
196+
return;
197+
}
198+
// How much user memory there is decides what is worth writing, and only the TID says
199+
// which chip this is
200+
if (!uhf.select(detected)) {
201+
M5_LOGE("Failed to select the tag");
202+
lcd.println("select: failed");
203+
return;
204+
}
196205
m5::uhf::Tag tag{};
197-
if (!detect_one(tag)) {
206+
const bool identified = uhf.identify(tag);
207+
uhf.deselect();
208+
if (!identified) {
209+
M5_LOGE("Failed to identify the tag");
210+
lcd.println("identify: failed");
198211
return;
199212
}
200-
// Two words to see it work, then the most a single command carries, then more than that
201-
// so writeBank has to split it across two
213+
214+
const uint16_t bank = static_cast<uint16_t>(tag.user_memory_bits / 16);
215+
M5_LOGI("%s: user memory %s", tag.chipAsString().c_str(),
216+
bank ? m5::utility::formatString("%u words", bank).c_str()
217+
: (m5::uhf::pcUserMemoryIndicator(tag.pc) ? "size not known" : "none"));
218+
lcd.printf("%s\n", tag.chipAsString().c_str());
219+
220+
if (bank == 0 && !m5::uhf::pcUserMemoryIndicator(tag.pc)) {
221+
M5_LOGI("Nothing to write to on this tag");
222+
lcd.println("no user memory");
223+
return;
224+
}
225+
226+
// Two words to see it work at all
202227
write_roundtrip(tag, WRITE_TEST_WORDS);
203-
write_roundtrip(tag, WRITE_TEST_MAX_WORDS);
204-
write_roundtrip(tag, WRITE_TEST_BANK_WORDS);
228+
// Then the most a single command carries, or the whole bank if that is smaller
229+
write_roundtrip(tag, bank ? std::min<uint16_t>(WRITE_TEST_MAX_WORDS, bank) : WRITE_TEST_MAX_WORDS);
230+
// Then the whole bank, which only tells us anything when it takes more than one command
231+
if (bank > WRITE_TEST_MAX_WORDS) {
232+
write_roundtrip(tag, bank);
233+
} else if (bank) {
234+
M5_LOGI("The whole bank fits in one command, so there is no split to exercise");
235+
}
205236
}
206237
}
207238

src/uhf/uhf_layer.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ uint16_t UHFLayer::bank_words(const Bank bank)
271271
}
272272
}
273273

274-
bool UHFLayer::dump_words(const char* what, const Bank bank, const uint16_t words)
274+
bool UHFLayer::dump_words(const char* what, const Bank bank, const uint16_t word_address, const uint16_t words)
275275
{
276276
printf("== %s ==\n", what);
277277
if (words == 0) {
@@ -282,8 +282,9 @@ bool UHFLayer::dump_words(const char* what, const Bank bank, const uint16_t word
282282

283283
// Eight words to a line, which is the sixteen bytes the sister NFC dump puts on one
284284
constexpr uint16_t PER_LINE{8};
285-
for (uint16_t at = 0; at < words; at += PER_LINE) {
286-
const uint16_t n = std::min<uint16_t>(PER_LINE, words - at);
285+
for (uint16_t off = 0; off < words; off += PER_LINE) {
286+
const uint16_t at = static_cast<uint16_t>(word_address + off);
287+
const uint16_t n = std::min<uint16_t>(PER_LINE, words - off);
287288
std::vector<uint8_t> data{};
288289
if (!readBank(data, bank, at, n)) {
289290
printf("[%03u/%03X] ERROR\n", at, at);
@@ -298,14 +299,19 @@ bool UHFLayer::dump_words(const char* what, const Bank bank, const uint16_t word
298299
return true;
299300
}
300301

301-
bool UHFLayer::dump(const Bank bank)
302+
bool UHFLayer::dump(const Bank bank, const uint16_t word_address, const uint16_t words)
302303
{
303304
if (!_has_selection) {
304305
M5_LIB_LOGE("dump needs a tag to have been selected");
305306
return false;
306307
}
307308
static const char* names[] = {"Reserved", "EPC", "TID", "User"};
308-
return dump_words(names[static_cast<uint8_t>(bank) & 0x03], bank, bank_words(bank));
309+
return dump_words(names[static_cast<uint8_t>(bank) & 0x03], bank, word_address, words);
310+
}
311+
312+
bool UHFLayer::dump(const Bank bank)
313+
{
314+
return dump(bank, 0, bank_words(bank));
309315
}
310316

311317
bool UHFLayer::dump()

src/uhf/uhf_layer.hpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ class UHFLayer {
131131
@pre A tag must have been selected
132132
*/
133133
bool dump(const Bank bank);
134+
/*!
135+
@brief Dump part of one memory bank
136+
@param bank Memory bank
137+
@param word_address Start address in 16-bit words
138+
@param words Number of 16-bit words
139+
@return True if successful
140+
@pre A tag must have been selected
141+
*/
142+
bool dump(const Bank bank, const uint16_t word_address, const uint16_t words);
134143
///@}
135144

136145
///@name Tag memory, addressed to the selected tag
@@ -186,8 +195,8 @@ class UHFLayer {
186195
bool verify_selection();
187196
//! @brief How many words of a bank there are to read, 0 when that is not known
188197
uint16_t bank_words(const Bank bank);
189-
//! @brief Print one bank's worth of words, sixteen bytes to a line
190-
bool dump_words(const char* what, const Bank bank, const uint16_t words);
198+
//! @brief Print a stretch of one bank, sixteen bytes to a line
199+
bool dump_words(const char* what, const Bank bank, const uint16_t word_address, const uint16_t words);
191200
/*!
192201
@brief Stop polling for as long as a tag is being addressed
193202
@details An inventory round leaves every tag it saw flagged as already counted, and a tag

src/unit/unit_JRD4035.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,10 @@ void UnitJRD4035::route_frame(const Frame& f)
353353
if (is_no_tag(code) && !awaiting_inventory) {
354354
return;
355355
}
356-
M5_LIB_LOGW("Error frame %02X", code);
356+
// Whether this matters is not known here: most of them are retried and succeed on the
357+
// next attempt. Saying so is left to succeeded(), which is reached only once the
358+
// operation has actually given up
359+
M5_LIB_LOGD("Error frame %02X", code);
357360
if (_response_pending) {
358361
_response = f;
359362
_response_pending = false;

0 commit comments

Comments
 (0)