The served pages of a device that runs on a logger: Margay’s and Okapi’s reading of themselves.

Classes

  Name
class NW_Pages
The register image a Schema 1 device keeps: Pages 0-1 from EEPROM, Pages 2-3 written per reading.

Source code


#ifndef NW_Pages_h
#define NW_Pages_h

#include <Arduino.h>
#include <EEPROM.h>
#include "NW_Report.h"

class NW_Pages {
  public:
    static const uint8_t SIZE = 128;      
    uint8_t page[SIZE];

    NW_Pages() { memset(page, 0, SIZE); }

    void loadStored(int base) { for (uint8_t i = 0; i < 64; i++) page[i] = EEPROM.read(base + i); }
    bool page0Valid() const { return page[0] == 0x01 && page[0x1D] == 0x4E && crc8(page, 0x1E) == page[0x1E]; }
    bool page1Blank() const { for (uint8_t i = 0x20; i < 0x40; i++) if (page[i] != 0xFF) return false; return true; }

    // --- Block 0 (0x40-0x47) ---
    void beginReading() { page[0x40] &= ~0x01; }
    void endReading(uint8_t chipFaults) {
      uint8_t status = 0x01 | (uint8_t)((chipFaults & 0x3F) << 1);
      if (status & 0x7E) status |= 0x80;
      uint16_t c = counter() + 1;
      page[0x42] = c & 0xFF; page[0x43] = c >> 8;
      page[0x40] = status;
    }
    uint16_t counter() const { return page[0x42] | (page[0x43] << 8); }
    void latchFault(uint8_t code) { page[0x47] = code; }
    void latchNotice(uint8_t code) { if (!isFaultCode(page[0x47])) page[0x47] = code; }
    void acknowledge() { page[0x47] = 0; }
    NW_Report report() const { NW_Report r; r.status = page[0x40]; r.code = page[0x47]; return r; }

    // --- Data helpers (little-endian, bus addresses) ---
    void put8(uint8_t at, uint8_t v)   { page[at] = v; }
    void put16(uint8_t at, uint16_t v) { page[at] = v & 0xFF; page[at + 1] = v >> 8; }
    void put32(uint8_t at, uint32_t v) { for (uint8_t i = 0; i < 4; i++) page[at + i] = (v >> (8 * i)) & 0xFF; }
    uint16_t get16(uint8_t at) const   { return page[at] | (page[at + 1] << 8); }
    float getFloat(uint8_t at) const   { float f; memcpy(&f, page + at, 4); return f; }

    size_t printSnapshot(Print& out, const char* const* chipNames, uint8_t nChips, const char* fw, const NW_Report* r = nullptr,
                         const char* const* kindWords = nullptr, uint8_t nKindWords = 0,
                         const char* fwCommit = "", const char* lib = "", const char* libCommit = "") const {
      NW_Report cur = report();
      if (!r) r = &cur;
      size_t n = 0;
      for (uint8_t i = 1; i <= 7 && page[i]; i++) n += out.print((char)page[i]);
      n += out.print(',');
      for (uint8_t i = 0; i < 4; i++) { if (i) n += out.print('-'); n += nwPrintHex(out, page + 0x10 + 2 * i, 2); }
      n += out.print(','); n += out.print(page[0x08]); n += out.print('.'); n += out.print(page[0x09]);
      n += out.print(','); n += out.print(fw);
      n += out.print(','); n += out.print(fwCommit);                                   // the logger's library commit: its firmware's
      n += out.print(','); n += out.print(lib); n += out.print(','); n += out.print(libCommit);   // for a logger: blank, and the sketch's commit
      n += out.print(F(",0x")); n += nwPrintHex(out, &r->code, 1);
      n += out.print(','); n += out.print(r->note(chipNames, nChips, kindWords, nKindWords));
      for (uint8_t p = 0; p < 0x60; p += 0x20) { n += out.print(','); n += nwPrintPage(out, page + p); }
      return n;
    }

    static uint8_t crc8(const uint8_t* d, uint8_t len) {
      uint8_t c = 0;
      for (uint8_t i = 0; i < len; i++) { c ^= d[i]; for (uint8_t b = 0; b < 8; b++) c = (c & 0x80) ? (uint8_t)((c << 1) ^ 0x07) : (uint8_t)(c << 1); }
      return c;
    }
    static bool isFaultCode(uint8_t code) { uint8_t k = code & 0x1F; return k >= 1 && k <= 8 && k != 6; }
};

#endif

Updated on 2026-09-29 at 05:58:59 +0000