diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index 6c6be7580..a4bddaf17 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -31,6 +31,7 @@ along with this program. If not, see .
#include "graphics/images.h"
#include "main.h"
#include "mesh-pb-constants.h"
+#include "mesh/generated/deviceonly.pb.h"
#include "mesh/Channels.h"
#include "modules/TextMessageModule.h"
#include "sleep.h"
@@ -44,6 +45,8 @@ along with this program. If not, see .
using namespace meshtastic; /** @todo remove */
+extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
+
namespace graphics
{
@@ -77,6 +80,10 @@ static char ourId[5];
// GeoCoord object for the screen
GeoCoord geoCoord;
+// OEM Config File
+static const char *oemConfigFile = "/prefs/oem.proto";
+OEMStore oemStore;
+
#ifdef SHOW_REDRAWS
static bool heartbeat = false;
#endif
@@ -148,6 +155,54 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1
drawIconScreen(region, display, state, x, y);
}
+static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
+{
+ // draw an xbm image.
+ // Please note that everything that should be transitioned
+ // needs to be drawn relative to x and y
+
+ // draw centered icon left to right and centered above the one line of app text
+ display->drawXbm(x + (SCREEN_WIDTH - oemStore.oem_icon_width) / 2, y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - oemStore.oem_icon_height) / 2 + 2,
+ oemStore.oem_icon_width, oemStore.oem_icon_height, (const uint8_t *)oemStore.oem_icon_bits.bytes);
+
+ switch(oemStore.oem_font){
+ case 0:
+ display->setFont(FONT_SMALL);
+ break;
+ case 2:
+ display->setFont(FONT_LARGE);
+ break;
+ default:
+ display->setFont(FONT_MEDIUM);
+ break;
+ }
+
+ display->setTextAlignment(TEXT_ALIGN_LEFT);
+ const char *title = oemStore.oem_text;
+ display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
+ display->setFont(FONT_SMALL);
+
+ // Draw region in upper left
+ if (upperMsg)
+ display->drawString(x + 0, y + 0, upperMsg);
+
+ // Draw version in upper right
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%s",
+ xstr(APP_VERSION_SHORT)); // Note: we don't bother printing region or now, it makes the string too long
+ display->drawString(x + SCREEN_WIDTH - display->getStringWidth(buf), y + 0, buf);
+ screen->forceDisplay();
+
+ // FIXME - draw serial # somewhere?
+}
+
+static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
+{
+ // Draw region in upper left
+ const char *region = myRegion ? myRegion->name : NULL;
+ drawOEMIconScreen(region, display, state, x, y);
+}
+
// Used on boot when a certificate is being created
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
@@ -813,8 +868,8 @@ void Screen::setup()
dispdev.setDetected(screen_model);
#endif
- // I think this is not needed - redundant with ui.init
- // dispdev.resetOrientation();
+ // Load OEM config from Proto file if existent
+ loadProto(oemConfigFile, OEMStore_size, sizeof(oemConfigFile), OEMStore_fields, &oemStore);
// Initialising the UI will init the display too.
ui.init();
@@ -867,6 +922,7 @@ void Screen::setup()
// twice initially.
ui.update();
ui.update();
+ serialSinceMsec = millis();
// Subscribe to status updates
powerStatusObserver.observe(&powerStatus->onNewStatus);
@@ -897,7 +953,7 @@ int32_t Screen::runOnce()
return RUN_SAME;
}
- // Show boot screen for first 3 seconds, then switch to normal operation.
+ // Show boot screen for first 5 seconds, then switch to normal operation.
// serialSinceMsec adjusts for additional serial wait time during nRF52 bootup
static bool showingBootScreen = true;
if (showingBootScreen && (millis() > (5000 + serialSinceMsec))) {
@@ -906,6 +962,21 @@ int32_t Screen::runOnce()
showingBootScreen = false;
}
+ // If we have an OEM Boot screen, toggle after 2,5 seconds
+ if(strlen(oemStore.oem_text) > 0){
+ static bool showingOEMBootScreen = true;
+ if (showingOEMBootScreen && (millis() > (2500 + serialSinceMsec))) {
+ DEBUG_MSG("Switch to OEM screen...\n");
+ // Change frames.
+ static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
+ static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
+ ui.setFrames(bootOEMFrames, bootOEMFrameCount);
+ ui.update();
+ ui.update();
+ showingOEMBootScreen = false;
+ }
+ }
+
#ifndef DISABLE_WELCOME_UNSET
if (showingNormalScreen && radioConfig.preferences.region == RegionCode_Unset) {
setWelcomeFrames();
diff --git a/src/mesh/generated/deviceonly.pb.c b/src/mesh/generated/deviceonly.pb.c
index a91649052..76aba1aef 100644
--- a/src/mesh/generated/deviceonly.pb.c
+++ b/src/mesh/generated/deviceonly.pb.c
@@ -12,4 +12,8 @@ PB_BIND(DeviceState, DeviceState, 4)
PB_BIND(ChannelFile, ChannelFile, 2)
+PB_BIND(OEMStore, OEMStore, 2)
+
+
+
diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h
index 8250cf568..a8df04eae 100644
--- a/src/mesh/generated/deviceonly.pb.h
+++ b/src/mesh/generated/deviceonly.pb.h
@@ -11,6 +11,17 @@
#error Regenerate this file with the current version of nanopb generator.
#endif
+/* Enum definitions */
+/* TODO: REPLACE */
+typedef enum _ScreenFonts {
+ /* TODO: REPLACE */
+ ScreenFonts_FONT_SMALL = 0,
+ /* TODO: REPLACE */
+ ScreenFonts_FONT_MEDIUM = 1,
+ /* TODO: REPLACE */
+ ScreenFonts_FONT_LARGE = 2
+} ScreenFonts;
+
/* Struct definitions */
/* The on-disk saved channels */
typedef struct _ChannelFile {
@@ -33,7 +44,7 @@ typedef struct _DeviceState {
User owner;
/* TODO: REPLACE */
pb_size_t node_db_count;
- NodeInfo node_db[80];
+ NodeInfo node_db[64];
/* Received packets saved for delivery to the phone */
pb_size_t receive_queue_count;
MeshPacket receive_queue[1];
@@ -53,16 +64,40 @@ typedef struct _DeviceState {
bool did_gps_reset;
} DeviceState;
+typedef PB_BYTES_ARRAY_T(2048) OEMStore_oem_icon_bits_t;
+/* This can be used for customizing the firmware distribution. If populated,
+ show a secondary bootup screen with cuatom logo and text for 2.5 seconds. */
+typedef struct _OEMStore {
+ /* The Logo width in Px */
+ uint32_t oem_icon_width;
+ /* The Logo height in Px */
+ uint32_t oem_icon_height;
+ /* The Logo in xbm bytechar format */
+ OEMStore_oem_icon_bits_t oem_icon_bits;
+ /* Use this font for the OEM text. */
+ ScreenFonts oem_font;
+ /* Use this font for the OEM text. */
+ char oem_text[40];
+} OEMStore;
+
+
+/* Helper constants for enums */
+#define _ScreenFonts_MIN ScreenFonts_FONT_SMALL
+#define _ScreenFonts_MAX ScreenFonts_FONT_LARGE
+#define _ScreenFonts_ARRAYSIZE ((ScreenFonts)(ScreenFonts_FONT_LARGE+1))
+
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
-#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
+#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
#define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}}
-#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
+#define OEMStore_init_default {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
+#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
#define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}}
+#define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
/* Field tags (for use in manual encoding/decoding) */
#define ChannelFile_channels_tag 1
@@ -74,6 +109,11 @@ extern "C" {
#define DeviceState_version_tag 8
#define DeviceState_no_save_tag 9
#define DeviceState_did_gps_reset_tag 11
+#define OEMStore_oem_icon_width_tag 1
+#define OEMStore_oem_icon_height_tag 2
+#define OEMStore_oem_icon_bits_tag 3
+#define OEMStore_oem_font_tag 4
+#define OEMStore_oem_text_tag 5
/* Struct field encoding specification for nanopb */
#define DeviceState_FIELDLIST(X, a) \
@@ -99,16 +139,28 @@ X(a, STATIC, REPEATED, MESSAGE, channels, 1)
#define ChannelFile_DEFAULT NULL
#define ChannelFile_channels_MSGTYPE Channel
+#define OEMStore_FIELDLIST(X, a) \
+X(a, STATIC, SINGULAR, UINT32, oem_icon_width, 1) \
+X(a, STATIC, SINGULAR, UINT32, oem_icon_height, 2) \
+X(a, STATIC, SINGULAR, BYTES, oem_icon_bits, 3) \
+X(a, STATIC, SINGULAR, UENUM, oem_font, 4) \
+X(a, STATIC, SINGULAR, STRING, oem_text, 5)
+#define OEMStore_CALLBACK NULL
+#define OEMStore_DEFAULT NULL
+
extern const pb_msgdesc_t DeviceState_msg;
extern const pb_msgdesc_t ChannelFile_msg;
+extern const pb_msgdesc_t OEMStore_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define DeviceState_fields &DeviceState_msg
#define ChannelFile_fields &ChannelFile_msg
+#define OEMStore_fields &OEMStore_msg
/* Maximum encoded size of messages (where known) */
#define ChannelFile_size 832
-#define DeviceState_size 23903
+#define DeviceState_size 19327
+#define OEMStore_size 2106
#ifdef __cplusplus
} /* extern "C" */