1313#include < M5Utility.h>
1414#include < wiring/m5_unit_unified_wiring.hpp>
1515#include < vector>
16+ #include < algorithm>
17+ #include < cstring>
1618
1719// *************************************************************
1820// Choose ONE define symbol to match the unit you are using
@@ -143,6 +145,38 @@ uint8_t bcc8(const uint8_t* p, const uint8_t len, const uint8_t init = 0)
143145}
144146
145147// Correctly embed the Ultralight and NTAG UIDs into memory
148+ // The emulated memory as it stood at the last hold, so a hold shows only what the reader has
149+ // written since. A click prints everything and leaves this alone, so the two never interfere
150+ uint8_t picc_memory_seen[sizeof (picc_memory)]{};
151+
152+ void dump_emulated_memory (const bool only_changed)
153+ {
154+ constexpr uint16_t BLOCK_SIZE {4 };
155+ const uint16_t blocks = (sizeof (picc_memory) + BLOCK_SIZE - 1 ) / BLOCK_SIZE ;
156+ uint16_t shown{};
157+
158+ M5 .Log .printf (" ==== Emulated memory (%s) ====\n " , only_changed ? " changed since the last hold" : " all" );
159+ for (uint16_t blk = 0 ; blk < blocks; ++blk) {
160+ const uint16_t offset = blk * BLOCK_SIZE ;
161+ const uint16_t len = std::min<uint16_t >(BLOCK_SIZE , sizeof (picc_memory) - offset);
162+ if (only_changed && memcmp (picc_memory + offset, picc_memory_seen + offset, len) == 0 ) {
163+ continue ;
164+ }
165+ M5 .Log .printf (" [%03X]:" , offset);
166+ for (uint16_t i = 0 ; i < len; ++i) {
167+ M5 .Log .printf (" %02X " , picc_memory[offset + i]);
168+ }
169+ M5 .Log .printf (" \n " );
170+ ++shown;
171+ }
172+ if (only_changed) {
173+ if (!shown) {
174+ M5 .Log .printf (" No block has changed\n " );
175+ }
176+ memcpy (picc_memory_seen, picc_memory, sizeof (picc_memory));
177+ }
178+ }
179+
146180void embed_uid (uint8_t mem[9 ], const uint8_t uid[7 ])
147181{
148182 memcpy (mem, uid, 3 );
@@ -196,6 +230,7 @@ void setup()
196230 lcd.fillScreen (TFT_RED );
197231 if (picc.emulate (type, uid, sizeof (uid))) {
198232 embed_uid (picc_memory, uid);
233+ memcpy (picc_memory_seen, picc_memory, sizeof (picc_memory));
199234 if (emu_a.begin (picc, picc_memory, sizeof (picc_memory))) {
200235 lcd.fillScreen (TFT_DARKGREEN );
201236 lcd.setCursor (0 , 16 );
@@ -217,6 +252,14 @@ void loop()
217252 Units.update ();
218253 emu_a.update (); // Need call in loop
219254
255+ // Take the phone away before asking, since printing stops the emulation answering for as long
256+ // as it runs
257+ if (M5 .BtnA .wasClicked ()) {
258+ dump_emulated_memory (false );
259+ } else if (M5 .BtnA .wasHold ()) {
260+ dump_emulated_memory (true );
261+ }
262+
220263 static EmulationLayerA::State latest{};
221264 auto state = emu_a.state ();
222265 if (latest != state) {
0 commit comments