// SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012-2024 Scott Penrose and WII5 Buoy contributors // // This file is part of WII5 Buoy firmware. // See LICENSE for full terms. /** * @file WII5Display.cpp * @brief Status display helpers: SD-block view, formatted metadata dumps. */ /* WII5Display */ #include #include // TODO Move to utils (could also be pinMode by different inputs) uint8_t bit; uint8_t port; volatile uint8_t *reg; volatile uint8_t *out; int wii5_getPinMode(uint8_t pin) { if (pin >= NUM_PINS) return (-1); // TODO analog? bit = digitalPinToBitMask(pin); port = digitalPinToPort(pin); reg = portModeRegister(port); if (*reg & bit) return (OUTPUT); out = portOutputRegister(port); return ((*out & bit) ? INPUT_PULLUP : INPUT); } uint32_t minutes; uint32_t used; uint32_t WII5Display::minutesUntilNext(uint32_t period) { minutes = (hour() * 60) + minute(); used = minutes % period; return period - used; } // SD / Storage Display Helpers void WII5Display::sdBlockView(uint32_t block_in, bool show_results, bool show_raw) { // Read block #ifdef WII5_DEBUG_DISPLAY Serial.print(F("# BLOCK=")); Serial.println(block_in); #endif if (!sdBlock.read(block_in)) { console.log(LOG_ERROR, F("Unable to view block - %lu"), block_in); return; } uint32_t dataBlockStart = sdBlock.metadata->dataBlockStart; uint32_t dataBlocks = sdBlock.metadata->dataBlocks; uint32_t resultsBlockStart = sdBlock.metadata->resultsBlockStart; uint32_t resultsBlocks = sdBlock.metadata->resultsBlocks; console.printf(F("@Block,metadata,address=%lu,deviceId=%lu,recordId=%lu\r\n"), block_in, sdBlock.metadata->deviceId, sdBlock.metadata->recordId ); console.printf(F("@Block,metadata,dataBlockStart=%lu,dataBlocks=%lu"), dataBlockStart, dataBlocks ); console.printf(F("@Block,metadata,resultsBlockStart=%lu,resultsBlocks=%lu"), resultsBlockStart, resultsBlocks ); printMetadataBlock((WII5MetaDataObject*)&sdBlock.metadata->data); if (show_results) { console.printf(F("# Loading results block\r\n")); if (!sdBlock.read(resultsBlockStart)) { console.log(LOG_ERROR, F("Unable to view resultsBlock - %lu"), resultsBlockStart); return; } WII5Processed* processed = (WII5Processed*)sdBlock.block->data; #ifdef WII5_DEBUG_DISPLAY void* a = &processed->processed1; void* b = &processed->processed1.part1float; void* c = &processed->processed2.part2float; void* d = &processed->processed2.part2int; Serial.println(int(processed)); Serial.println(int(a)); Serial.println(int(b)); Serial.println(int(c)); Serial.println(int(d)); Serial.println(int(sizeof(WII5Processed))); Serial.println(int(sizeof(WII5Processed1))); Serial.println(int(sizeof(WII5Processed2))); for (uint8_t i = 0; i < 73; i++) { Serial.println(processed->processed1.part1float[i]); } for (uint8_t i = 0; i < 20; i++) { Serial.println(processed->processed2.part2float[i]); } for (uint8_t i = 0; i < 62; i++) { Serial.println(processed->processed2.part2int[i]); } #else (void)processed; #endif console.print("# END out/processed.out"); console.printNewLine(); } if (show_raw) { console.log(LOG_ERROR, F("Raw view not yet implemented")); } } void WII5Display::printMetadataBlock(WII5MetaDataObject* metadata) { // TODO MAke this use metadtat abvoe but look the same console.printf(F("@Metadata,start,print block\r\n")); console.printf(F("@Metadata,deviceId=%ld,recordId=%ld\r\n"), metadata->deviceId, metadata->recordCount ); console.printf(F("@Metadata,time=%ld,uptime=%ld\r\n"), metadata->last, metadata->uptime ); console.printf(F("@Metadata,temperature=%ld,battery=%ld\r\n"), metadata->temperatureValue, metadata->batteryValue ); console.printf(F("@Metadata,lat=%ld,lon=%ld,alt=%ld,sats=%ld,hdop=%ld\r\n"), long(wii5Gps.gps->location.lat() * GPS_POS_MULT), long(wii5Gps.gps->location.lng() * GPS_POS_MULT), long(wii5Gps.gps->altitude.meters() * GPS_POS_MULT), metadata->gpsLat, metadata->gpsLon, metadata->gpsHdop ); /* console.printf(F("@Metadata,capture,timeError=%ld,sizeError=-%ld,writeMin=%ld,writeMax=%ld,writeOver=%ld\r\n"), wii5Sparton.captureWriteMax, wii5Sparton.captureWriteMin, wii5Sparton.captureWriteOver, wii5Sparton.statsTimeError, wii5Sparton.serialSizeError ); */ console.printf(F("@Metadata,end,print block\r\n")); } uint8_t a_start; uint8_t a_end; uint8_t p; void WII5Display::dumpPins() { a_start = analogInputToDigitalPin(0); a_end = a_start + NUM_ANALOG_INPUTS - 1; console.printf(F("# Pins:\r\n")); for (p = 0; p < NUM_PINS; p++) { console.printf(F("# D%02d "), int(p)); console.printf(F("%s "), wii5Strings.strPinMode(wii5_getPinMode(p))); console.printf(F(" ")); // Long term - if analog - analogRead too or instead if ((p >= a_start) && (p <= a_end)) { console.printf(F("%04d"), analogRead(p)); } else { console.printf(F("%s"), wii5Strings.strState(digitalRead(p))); } console.printf(F(" ")); console.printf(F("%s"), wii5Strings.strPinArduinoName(p)); console.printf(F(" ")); console.printf(F("%s"), wii5Strings.strPinWII5Name(p)); console.printf(F(" | ")); // TODO - Arduino name, D3, A4, MOSI, etc // TODO - WII5 name - e.g. GPS Power Switch // 4 per line? if ( ((p+1) % 3) == 0) { console.printNewLine(); } } console.printNewLine(); } void WII5Display::atMathsSend(const __FlashStringHelper *area, const __FlashStringHelper *out, ... ){ console.printf(F("@Maths,")); console.printf(area); console.printf(F(",")); va_list argptr; va_start(argptr, out); VSNPRINTF(wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT, (const char *)out, argptr); va_end(argptr); console.print(wii5BufferConsolePrint); // console.printf(F(",%lu/%lu,"), wii5Config.getDeviceId(), wii5Config.getRecordCount()); // console.printDateTime(), console.printNewLine(); } void WII5Display::atStatsSend(const __FlashStringHelper *area, const __FlashStringHelper *out, ... ){ console.printf(F("@Stats,")); console.printf(area); console.printf(F(",%lu/%lu,"), wii5Config.getDeviceId(), wii5Config.getRecordCount()); console.printDateTime(), console.printf(F(",")); va_list argptr; va_start(argptr, out); VSNPRINTF(wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT, (const char *)out, argptr); va_end(argptr); console.print(wii5BufferConsolePrint); console.printNewLine(); } void WII5Display::atDataSend(const __FlashStringHelper *area, const __FlashStringHelper *out, ... ){ console.printf(F("@Data,")); console.printf(area); console.printf(F(",%lu/%lu,"), wii5Config.getDeviceId(), wii5Config.getRecordCount()); console.printDateTime(), console.printf(F(",")); va_list argptr; va_start(argptr, out); VSNPRINTF(wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT, (const char *)out, argptr); va_end(argptr); console.print(wii5BufferConsolePrint); console.printNewLine(); } // NOTE ! This is the StatusSerial - not the console void WII5Display::statusSend(const __FlashStringHelper *area, const __FlashStringHelper *out, ... ){ #ifdef WII5_STATUS_SERIAL SerialStatus.print(area); SerialStatus.print(","); // Low level - assume we know device id - see if we can send it // SerialStatus.print(wii5Config.getDeviceId()); // SerialStatus.print("/"); SerialStatus.print(wii5Config.getRecordCount()); // SerialStatus.printDateTime(), SerialStatus.print(F(",")); va_list argptr; va_start(argptr, out); VSNPRINTF(wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT, (const char *)out, argptr); va_end(argptr); SerialStatus.print(wii5BufferConsolePrint); SerialStatus.println(); #endif } void WII5Display::atCommandSend(const __FlashStringHelper *area, const __FlashStringHelper *out, ... ){ console.printf(F("@WII5,")); console.printf(area); // TODO @WII5 commands do not normally have device and date details console.printf(F(",%lu/%lu,"), wii5Config.getDeviceId(), wii5Config.getRecordCount()); console.printDateTime(), console.printf(F(",")); va_list argptr; va_start(argptr, out); VSNPRINTF(wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT, (const char *)out, argptr); va_end(argptr); console.print(wii5BufferConsolePrint); console.printNewLine(); } void WII5Display::atCommsSend(const __FlashStringHelper *area, const __FlashStringHelper *out, ... ){ console.printf(F("@Comms,")); console.printf(area); console.printf(F(",%lu/%lu,"), wii5Config.getDeviceId(), wii5Config.getRecordCount()); console.printDateTime(), console.printf(F(",")); va_list argptr; va_start(argptr, out); VSNPRINTF(wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT, (const char *)out, argptr); va_end(argptr); console.print(wii5BufferConsolePrint); console.printNewLine(); } void WII5Display::printMetadata() { console.printf(F("@Metadata,deviceId=%ld,recordId=%ld\r\n"), wii5Config.getDeviceId(), wii5Config.getRecordCount() ); console.printf(F("@Metadata,time=%ld,uptime=%ld\r\n"), now(), wii5Controller.uptime ); console.printf(F("@Metadata,temperature=%ld,battery=%ld\r\n"), wii5Weather_18B20.value, wii5Battery.value ); #ifdef WII5_GPS console.printf(F("@Metadata,lat=%ld,lon=%ld,alt=%ld,sats=%ld,hdop=%ld\r\n"), long(wii5Gps.gps->location.lat() * GPS_POS_MULT), long(wii5Gps.gps->location.lng() * GPS_POS_MULT), long(wii5Gps.gps->altitude.meters() * GPS_POS_MULT), wii5Gps.gps->satellites.value(), wii5Gps.gps->hdop.value() ); #endif console.printf(F("@Metadata,capture,timeError=%ld,sizeError=-%ld,writeMin=%ld,writeMax=%ld,writeOver=%ld\r\n"), wii5Sparton.captureWriteMax, wii5Sparton.captureWriteMin, wii5Sparton.captureWriteOver, wii5Sparton.statsTimeError, wii5Sparton.serialSizeError ); } void WII5Display::updateMetadata(void* ref = NULL) { if (ref) { metadata = (WII5MetaDataObject*)ref; } if (metadata) { memset(metadata, 0, sizeof(WII5MetaDataObject)); metadata->deviceId = wii5Config.getDeviceId(); metadata->recordCount = wii5Config.getRecordCount(); // TODO last is now? What about start of capture time? metadata->last = now(); metadata->age = 0; metadata->uptime = wii5Controller.uptime; metadata->temperatureValue = wii5Weather_18B20.value; metadata->temperatureAge = wii5Weather_18B20.age; metadata->batteryValue = wii5Battery.value; metadata->batteryAge = wii5Battery.age; #ifdef WII5_GPS // TODO move to float metadata->gpsLat = wii5Gps.gps->location.lat(); metadata->gpsLon = wii5Gps.gps->location.lng(); metadata->gpsAlt = wii5Gps.gps->altitude.meters(); metadata->gpsSat = wii5Gps.gps->satellites.value(); metadata->gpsHdop = wii5Gps.gps->hdop.value(); // fixtime // age metadata->gpsAge = wii5Gps.gps->time.age(); #endif metadata->captureWriteMax = wii5Sparton.captureWriteMax; metadata->captureWriteMin = wii5Sparton.captureWriteMin; metadata->captureWriteOver = wii5Sparton.captureWriteOver; metadata->captureTimeError = wii5Sparton.statsTimeError; metadata->captureSizeError = wii5Sparton.serialSizeError; metadata->captureStartTime = wii5ModeCapture.startTime; metadata->mode = (uint8_t)wii5Controller.getMode(); } } WII5Display wii5Display;