Add PN532 toolkit firmware, web UI, and embedded SPIFFS assets

Includes ESP-IDF NFC stack (deep capture, 4K Classic geometry, UL write API,
open SoftAP), React dashboard with live tag diagnostics, and docs. README
updated for APIs and lab Wi-Fi defaults.

Made-with: Cursor
This commit is contained in:
drjones
2026-03-29 09:32:55 -07:00
parent d1068d965b
commit 8968560565
73 changed files with 8802 additions and 28 deletions

View File

@@ -0,0 +1,129 @@
#include "nfc_engine/session_capture.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include <string.h>
#define SESSION_CAPTURE_BYTES (48 * 1024)
static char s_buf[SESSION_CAPTURE_BYTES];
static size_t s_len;
static uint32_t s_lines;
static bool s_full;
static bool s_deep;
static SemaphoreHandle_t s_mu;
void session_capture_init(void)
{
s_mu = xSemaphoreCreateMutex();
session_capture_clear();
s_deep = false;
}
void session_capture_clear(void)
{
if (s_mu) {
xSemaphoreTake(s_mu, portMAX_DELAY);
}
s_len = 0;
s_lines = 0;
s_full = false;
s_buf[0] = 0;
if (s_mu) {
xSemaphoreGive(s_mu);
}
}
bool session_capture_is_full(void)
{
return s_full;
}
bool session_capture_deep_enabled(void) { return s_deep; }
void session_capture_set_deep(bool on) { s_deep = on; }
size_t session_capture_max(void) { return sizeof(s_buf) - 2; }
void session_capture_get_status(size_t *used_bytes, uint32_t *line_count, bool *full)
{
if (s_mu) {
xSemaphoreTake(s_mu, portMAX_DELAY);
}
if (used_bytes) {
*used_bytes = s_len;
}
if (line_count) {
*line_count = s_lines;
}
if (full) {
*full = s_full;
}
if (s_mu) {
xSemaphoreGive(s_mu);
}
}
bool session_capture_append_line(const char *line)
{
if (!line || s_full) {
return false;
}
size_t l = strlen(line);
size_t need = l + 1; /* newline */
if (s_mu) {
xSemaphoreTake(s_mu, portMAX_DELAY);
}
if (s_full || s_len + need >= sizeof(s_buf)) {
s_full = true;
if (s_mu) {
xSemaphoreGive(s_mu);
}
return false;
}
memcpy(s_buf + s_len, line, l);
s_len += l;
s_buf[s_len++] = '\n';
s_buf[s_len] = 0;
s_lines++;
if (s_len + 2 >= sizeof(s_buf)) {
s_full = true;
}
if (s_mu) {
xSemaphoreGive(s_mu);
}
return true;
}
size_t session_capture_export_size(void)
{
if (s_mu) {
xSemaphoreTake(s_mu, portMAX_DELAY);
}
size_t n = s_len;
if (s_mu) {
xSemaphoreGive(s_mu);
}
return n;
}
const char *session_capture_export_ptr(void) { return s_buf; }
void session_capture_copy_to(char *dst, size_t cap, size_t *out_len)
{
if (s_mu) {
xSemaphoreTake(s_mu, portMAX_DELAY);
}
size_t n = s_len;
if (n > cap) {
n = cap;
}
if (dst && n) {
memcpy(dst, s_buf, n);
}
if (out_len) {
*out_len = n;
}
if (s_mu) {
xSemaphoreGive(s_mu);
}
}