Browse Source

Merge branch 'You69Man-feature/display_84x48_symbolic_PR' into development03

pull/1163/head
lumapu 2 years ago
parent
commit
c8f5f29fe9
  1. BIN
      pics/PXL_20230824_204200660.jpg
  2. BIN
      pics/PXL_20230901_061927908.jpg
  3. 2
      src/app.cpp
  4. 4
      src/app.h
  5. 4
      src/hm/hmRadio.h
  6. 10
      src/hm/miPayload.h
  7. 52
      src/plugins/Display/Display.h
  8. 96
      src/plugins/Display/Display_Mono.h
  9. 63
      src/plugins/Display/Display_Mono_128X32.h
  10. 63
      src/plugins/Display/Display_Mono_128X64.h
  11. 61
      src/plugins/Display/Display_Mono_64X48.h
  12. 151
      src/plugins/Display/Display_Mono_84X48.h
  13. 22
      src/plugins/Display/Display_data.h
  14. 8
      src/plugins/Display/Display_ePaper.cpp
  15. 4
      src/plugins/Display/Display_ePaper.h
  16. 6
      tools/fonts/fontconv.bat
  17. 11
      tools/fonts/u8g2 font-sources.txt
  18. 1328
      tools/fonts/u8g2_font_5x8_symbols_ahoy.bdf
  19. 40
      tools/fonts/u8g2_font_5x8_symbols_ahoy.c_
  20. BIN
      tools/fonts/u8g2_font_5x8_symbols_ahoy.fon
  21. 166
      tools/fonts/u8g2_font_ncenB08_symbols8_ahoy.bdf
  22. 13
      tools/fonts/u8g2_font_ncenB08_symbols8_ahoy.c_
  23. BIN
      tools/fonts/u8g2_font_ncenB08_symbols8_ahoy.fon
  24. 188
      tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.bdf
  25. 14
      tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.c_
  26. BIN
      tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.fon
  27. 16
      tools/fonts/used_fonts.txt

BIN
pics/PXL_20230824_204200660.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
pics/PXL_20230901_061927908.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

2
src/app.cpp

@ -115,7 +115,7 @@ void app::setup() {
// Plugins
if (mConfig->plugin.display.type != 0)
mDisplay.setup(&mConfig->plugin.display, &mSys, &mTimestamp, mVersion);
mDisplay.setup(this, &mConfig->plugin.display, &mSys, &mNrfRadio, &mTimestamp);
mPubSerial.setup(mConfig, &mSys, &mTimestamp);

4
src/app.h

@ -55,7 +55,8 @@ typedef PubSerial<HmSystemType> PubSerialType;
// PLUGINS
#include "plugins/Display/Display.h"
typedef Display<HmSystemType> DisplayType;
#include "plugins/Display/Display_data.h"
typedef Display<HmSystemType, HmRadio<>> DisplayType;
class app : public IApp, public ah::Scheduler {
public:
@ -362,6 +363,7 @@ class app : public IApp, public ah::Scheduler {
// plugins
DisplayType mDisplay;
DisplayData mDispData;
};
#endif /*__APP_H__*/

4
src/hm/hmRadio.h

@ -272,8 +272,8 @@ class HmRadio {
isLastPackage = true; // response from dev control command
}
}
yield();
}
yield();
}
return isLastPackage;
}

10
src/hm/miPayload.h

@ -96,16 +96,16 @@ class MiPayload {
} else {
mStat->rxFail++; // got "fragments" (part of the required messages)
// but no complete set of responses
if (mSerialDebug) {
if (mSerialDebug) {
DBGPRINT(F("no complete Payload received! (retransmits: "));
DBGPRINT(String(mPayload[iv->id].retransmits));
DBGPRINTLN(F(")"));
DBGPRINT(String(mPayload[iv->id].retransmits));
DBGPRINTLN(F(")"));
}
}
}
iv->setQueuedCmdFinished(); // command failed
}
}
}
}
reset(iv->id);
mPayload[iv->id].requested = true;

52
src/plugins/Display/Display.h

@ -5,6 +5,7 @@
#include <U8g2lib.h>
#include "../../hm/hmSystem.h"
#include "../../hm/hmRadio.h"
#include "../../utils/helper.h"
#include "Display_Mono.h"
#include "Display_Mono_128X32.h"
@ -12,21 +13,25 @@
#include "Display_Mono_84X48.h"
#include "Display_Mono_64X48.h"
#include "Display_ePaper.h"
#include "Display_data.h"
template <class HMSYSTEM>
template <class HMSYSTEM, class HMRADIO>
class Display {
public:
Display() {
mMono = NULL;
}
void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs, const char *version) {
void setup(IApp *app, display_t *cfg, HMSYSTEM *sys, HMRADIO *radio, uint32_t *utcTs) {
mApp = app;
mHmRadio = radio;
mCfg = cfg;
mSys = sys;
mUtcTs = utcTs;
mNewPayload = false;
mLoopCnt = 0;
mVersion = version;
mDisplayData.version = app->getVersion(); // version never changes, so only set once
switch (mCfg->type) {
case 0: mMono = NULL; break;
@ -41,7 +46,7 @@ class Display {
mMono = NULL; // ePaper does not use this
mRefreshCycle = 0;
mEpaper.config(mCfg->rot, mCfg->pwrSaveAtIvOffline);
mEpaper.init(mCfg->type, mCfg->disp_cs, mCfg->disp_dc, mCfg->disp_reset, mCfg->disp_busy, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion);
mEpaper.init(mCfg->type, mCfg->disp_cs, mCfg->disp_dc, mCfg->disp_reset, mCfg->disp_busy, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mDisplayData.version);
break;
#endif
@ -49,7 +54,7 @@ class Display {
}
if(mMono) {
mMono->config(mCfg->pwrSaveAtIvOffline, mCfg->pxShift, mCfg->contrast);
mMono->init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, 0xff, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion);
mMono->init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, 0xff, mCfg->disp_clk, mCfg->disp_data, &mDisplayData);
}
}
@ -61,7 +66,7 @@ class Display {
if (mMono != NULL)
mMono->loop(mCfg->contrast);
if (mNewPayload || (((++mLoopCnt) % 30) == 0)) {
if (mNewPayload || (((++mLoopCnt) % 10) == 0)) {
mNewPayload = false;
mLoopCnt = 0;
DataScreen();
@ -75,14 +80,13 @@ class Display {
void DataScreen() {
if (mCfg->type == 0)
return;
if (*mUtcTs == 0)
return;
float totalPower = 0;
float totalYieldDay = 0;
float totalYieldTotal = 0;
uint8_t isprod = 0;
uint8_t nrprod = 0;
uint8_t nrsleep = 0;
Inverter<> *iv;
record_t<> *rec;
@ -93,19 +97,39 @@ class Display {
continue;
if (iv->isProducing())
isprod++;
nrprod++;
else
nrsleep++;
totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec);
totalYieldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec);
totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec);
}
// prepare display data
mDisplayData.nrProducing = nrprod;
mDisplayData.nrSleeping = nrsleep;
mDisplayData.totalPower = totalPower;
mDisplayData.totalYieldDay = totalYieldDay;
mDisplayData.totalYieldTotal = totalYieldTotal;
mDisplayData.RadioSymbol = mHmRadio->isChipConnected();
mDisplayData.WifiSymbol = (WiFi.status() == WL_CONNECTED);
mDisplayData.MQTTSymbol = mApp->getMqttIsConnected();
mDisplayData.RadioRSSI = (0 < mDisplayData.nrProducing) ? 0 : SCHAR_MIN; // Workaround as NRF24 has no RSSI. Could be approximated by transmisson error heuristic in the future
mDisplayData.WifiRSSI = (WiFi.status() == WL_CONNECTED) ? WiFi.RSSI() : SCHAR_MIN;
mDisplayData.ipAddress = WiFi.localIP();
time_t utc= mApp->getTimestamp();
if (year(utc) > 2020)
mDisplayData.utcTs = utc;
else
mDisplayData.utcTs = 0;
if (mMono ) {
mMono->disp(totalPower, totalYieldDay, totalYieldTotal, isprod);
mMono->disp();
}
#if defined(ESP32)
else if (mCfg->type == 10) {
mEpaper.loop(totalPower, totalYieldDay, totalYieldTotal, isprod);
mEpaper.loop(totalPower, totalYieldDay, totalYieldTotal, nrprod);
mRefreshCycle++;
}
@ -117,12 +141,14 @@ class Display {
}
// private member variables
IApp *mApp;
DisplayData mDisplayData;
bool mNewPayload;
uint8_t mLoopCnt;
uint32_t *mUtcTs;
const char *mVersion;
display_t *mCfg;
HMSYSTEM *mSys;
HMRADIO *mHmRadio;
uint16_t mRefreshCycle;
#if defined(ESP32)

96
src/plugins/Display/Display_Mono.h

@ -9,6 +9,7 @@
#define DISP_FMT_TEXT_LEN 32
#define BOTTOM_MARGIN 5
#include "defines.h"
#ifdef ESP8266
#include <ESP8266WiFi.h>
@ -16,25 +17,29 @@
#include <WiFi.h>
#endif
#include "../../utils/helper.h"
#include "Display_data.h"
class DisplayMono {
public:
DisplayMono() {};
virtual void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t* utcTs, const char* version) = 0;
virtual void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) = 0;
virtual void init(uint8_t type, uint8_t rot, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, DisplayData *displayData) = 0;
virtual void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) = 0;
virtual void loop(uint8_t lum) = 0;
virtual void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) = 0;
virtual void disp(void) = 0;
protected:
U8G2* mDisplay;
DisplayData *mDisplayData;
uint8_t mType;
bool mEnPowerSafe, mEnScreenSaver;
uint16_t mDispWidth;
uint16_t mDispHeight;
bool mEnPowerSave, mEnScreenSaver;
uint8_t mLuminance;
uint8_t mLoopCnt;
uint32_t* mUtcTs;
uint8_t mLineXOffsets[5] = {};
uint8_t mLineYOffsets[5] = {};
@ -42,4 +47,83 @@ class DisplayMono {
uint8_t mExtra;
uint16_t mTimeout;
char mFmtText[DISP_FMT_TEXT_LEN];};
char mFmtText[DISP_FMT_TEXT_LEN];
// Common initialization function to be called by subclasses
void monoInit(U8G2* display, uint8_t type, DisplayData *displayData) {
mDisplay = display;
mType = type;
mDisplayData = displayData;
mDisplay->begin();
mDisplay->setContrast(mLuminance);
mDisplay->clearBuffer();
mDispWidth = mDisplay->getDisplayWidth();
mDispHeight = mDisplay->getDisplayHeight();
}
};
/* adapted 5x8 Font for low-res displays with symbols
Symbols:
\x80 ... antenna
\x81 ... WiFi
\x82 ... suncurve
\x83 ... sum/sigma
\x84 ... antenna crossed
\x85 ... WiFi crossed
\x86 ... sun
\x87 ... moon
\x88 ... calendar/day
\x89 ... MQTT */
const uint8_t u8g2_font_5x8_symbols_ahoy[1052] U8G2_FONT_SECTION("u8g2_font_5x8_symbols_ahoy") =
"j\0\3\2\4\4\3\4\5\10\10\0\377\6\377\6\0\1\61\2b\4\3 \5\0\304\11!\7a\306"
"\212!\11\42\7\63\335\212\304\22#\16u\304\232R\222\14JePJI\2$\14u\304\252l\251m"
"I\262E\0%\10S\315\212(\351\24&\13t\304\232(i\252\64%\1'\6\61\336\212\1(\7b"
"\305\32\245))\11b\305\212(\251(\0*\13T\304\212(Q\206D\211\2+\12U\304\252\60\32\244"
"\60\2,\7\63\275\32\245\4-\6\24\324\212!.\6\42\305\212!/\10d\304\272R[\6\60\14d"
"\304\32%R\206DJ\24\0\61\10c\305\232Dj\31\62\13d\304\32%\312\22%\33\2\63\13d\304"
"\212!\212D)Q\0\64\13d\304\252H\251\14Q\226\0\65\12d\304\212A\33\245D\1\66\13d\304"
"\32%[\42)Q\0\67\13d\304\212!\213\262(\213\0\70\14d\304\32%J\224HJ\24\0\71\13"
"d\304\32%\222\222-Q\0:\10R\305\212!\32\2;\10c\275\32\243R\2<\10c\305\252\244\224"
"\25=\10\64\314\212!\34\2>\11c\305\212\254\224\224\0?\11c\305\232\246$M\0@\15\205\274*"
")\222\226DI\244\252\2A\12d\304\32%\222\206I\12B\14d\304\212%\32\222H\32\22\0C\12"
"d\304\32%\322J\211\2D\12d\304\212%r\32\22\0E\12d\304\212A[\262l\10F\12d\304"
"\212A[\262\32\0G\13d\304\32%\322\222)Q\0H\12d\304\212H\32&S\0I\10c\305\212"
"%j\31J\12d\304\232)\253\224\42\0K\13d\304\212HI\244\244S\0L\10d\304\212\254\333\20"
"M\12d\304\212h\70D\246\0N\12d\304\212h\31\226I\12O\12d\304\32%rJ\24\0P\13"
"d\304\212%\222\206$\313\0Q\12t\274\32%\222\26\307\0R\13d\304\212%\222\206$\222\2S\14"
"d\304\32%J\302$J\24\0T\11e\304\212A\12;\1U\11d\304\212\310S\242\0V\12d\304"
"\212\310)\221\24\0W\12d\304\212\310\64\34\242\0X\13d\304\212HJ$%\222\2Y\12e\304\212"
"LKja\11Z\12d\304\212!\213\332\206\0[\10c\305\212!j\32\134\10d\304\212,l\13]"
"\10c\305\212\251i\10^\6#\345\232\6_\6\24\274\212!`\6\42\345\212(a\11D\304\232!\222"
"\222\1b\13d\304\212,[\42iH\0c\7C\305\232)\23d\12d\304\272\312\20I\311\0e\11"
"D\304\32%\31\262\1f\12d\304\252Ji\312\42\0g\12T\274\32%J\266D\1h\12d\304\212"
",[\42S\0i\10c\305\232P\252\14j\12s\275\252\64\212\224\12\0k\12d\304\212\254\64$\221"
"\24l\10c\305\12\251\313\0m\12E\304\12\245EI\224\2n\10D\304\212%\62\5o\11D\304\32"
"%\222\22\5p\12T\274\212%\32\222,\3q\11T\274\232!J\266\2r\11D\304\212$\261e\0"
"s\10C\305\232![\0t\13d\304\232,\232\262$J\0u\10D\304\212\310\224\14v\10C\305\212"
"\304R\1w\12E\304\212LI\224.\0x\11D\304\212(\221\224(y\13T\274\212HJ\206(Q"
"\0z\11D\304\212!*\15\1{\12t\304*%L\304(\24|\6a\306\212\3}\13t\304\12\61"
"\12\225\60\221\0~\10$\344\232DI\0\5\0\304\12\200\13u\274\212K\242T\266\260\4\201\14f"
"D\233!\11#-\312!\11\202\15hD<\65\12\243,\214\302$\16\203\15w<\214C\22F\71\220"
"\26\207A\204\16\205\274\212,)%Y\230%QR\13\205\17\206<\213\60\31\22\311\66D\245!\11\3"
"\206\20\210<\254\342\20]\302(L\246C\30E\0\207\15wD\334X\25\267\341\20\15\21\0\210\16w"
"<\214\203RQ\25I\212\324a\20\211\15f\304\213)\213\244,\222\222\245\0\0\0\0";
const uint8_t u8g2_font_ncenB08_symbols8_ahoy[173] U8G2_FONT_SECTION("u8g2_font_ncenB08_symbols8_ahoy") =
"\13\0\3\2\4\4\1\2\5\10\11\0\0\10\0\10\0\0\0\0\0\0\224A\14\207\305\70H\321\222H"
"k\334\6B\20\230\305\32\262\60\211\244\266\60T\243\34\326\0C\20\210\305S\243\60\312\302(\214\302("
"L\342\0D\16\210\315\70(i\224#\71\20W\207\3E\15\207\305xI\206\323\232nIS\1F\25"
"\230\305H\206\244\230$C\22\15Y\242\204j\224\205I$\5G\17\210\305*\16\321%\214\302d:\204"
"Q\4H\14w\307\215Uq\33\16\321\20\1I\21\227\305\311\222aP\245H\221\244H\212\324a\20J"
"\5\0\275\0K\5\0\315\0\0\0\0";
const uint8_t u8g2_font_ncenB10_symbols10_ahoy[207] U8G2_FONT_SECTION("u8g2_font_ncenB10_symbols10_ahoy") =
"\13\0\3\2\4\4\2\2\5\13\13\0\0\13\0\13\0\0\0\0\0\0\266A\15\267\212q\220\42\251\322"
"\266\306\275\1B\20\230\236\65da\22Ima\250F\71\254\1C\23\272\272\251\3Q\32\366Q\212\243"
"\70\212\243\70\311\221\0D\20\271\252\361\242F:\242#: {\36\16\1E\22\267\212\361\222\14I\242"
"\14\332\232\216[RJ\232\12F\25\250\233\221\14I\61I\206$\252%J\250Fa\224%J\71G\30"
"\273\312W\316r`T\262DJ\303\64L#%K\304\35\310\342,\3H\27\272\272\217\344P\16\351\210"
"\16\354\300<\244C\70,\303 \16!\0I\24\271\252\241\34\336\1-\223\64-\323\62-\323\62\35x"
"\10J\5\0\232\1K\5\0\232\1\0\0\0";

63
src/plugins/Display/Display_Mono_128X32.h

@ -9,45 +9,32 @@
class DisplayMono128X32 : public DisplayMono {
public:
DisplayMono128X32() : DisplayMono() {
mEnPowerSafe = true;
mEnPowerSave = true;
mEnScreenSaver = true;
mLuminance = 60;
mExtra = 0;
mDispY = 0;
mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds)
mUtcTs = NULL;
mType = 0;
}
void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) {
mEnPowerSave = enPowerSave;
mEnScreenSaver = enScreenSaver;
mLuminance = lum;
}
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) {
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, DisplayData *displayData) {
u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0);
mType = type;
mDisplay = new U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C(rot, reset, clock, data);
mUtcTs = utcTs;
mDisplay->begin();
monoInit(new U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C(rot, reset, clock, data), type, displayData);
calcLinePositions();
mDisplay->clearBuffer();
mDisplay->setContrast(mLuminance);
printText("AHOY!", 0);
printText("Ahoy!", 0);
printText("ahoydtu.de", 2);
printText(version, 3);
printText(mDisplayData->version, 3);
mDisplay->sendBuffer();
}
void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) {
mEnPowerSafe = enPowerSafe;
mEnScreenSaver = enScreenSaver;
mLuminance = lum;
}
void loop(uint8_t lum) {
if (mEnPowerSafe) {
if (mEnPowerSave) {
if (mTimeout != 0)
mTimeout--;
}
@ -58,43 +45,43 @@ class DisplayMono128X32 : public DisplayMono {
}
}
void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) {
void disp(void) {
mDisplay->clearBuffer();
// set Contrast of the Display to raise the lifetime
if (3 != mType)
mDisplay->setContrast(mLuminance);
if ((totalPower > 0) && (isprod > 0)) {
if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000));
if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (mDisplayData->totalPower / 1000));
else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", mDisplayData->totalPower);
printText(mFmtText, 0);
} else {
printText("offline", 0);
// check if it's time to enter power saving mode
if (mTimeout == 0)
mDisplay->setPowerSave(mEnPowerSafe);
mDisplay->setPowerSave(mEnPowerSave);
}
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, 1);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", mDisplayData->totalYieldTotal);
printText(mFmtText, 2);
IPAddress ip = WiFi.localIP();
if (!(mExtra % 10) && (ip))
printText(ip.toString().c_str(), 3);
else if (!(mExtra % 5)) {
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", mDisplayData->nrProducing);
printText(mFmtText, 3);
} else if (NULL != mUtcTs)
printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3);
} else if (0 != mDisplayData->utcTs)
printText(ah::getTimeStr(gTimezone.toLocal(mDisplayData->utcTs)).c_str(), 3);
mDisplay->sendBuffer();
@ -119,13 +106,13 @@ class DisplayMono128X32 : public DisplayMono {
inline void setFont(uint8_t line) {
switch (line) {
case 0:
mDisplay->setFont(u8g2_font_9x15_tf);
mDisplay->setFont(u8g2_font_9x15_tr);
break;
case 3:
mDisplay->setFont(u8g2_font_tom_thumb_4x6_tf);
mDisplay->setFont(u8g2_font_tom_thumb_4x6_tr);
break;
default:
mDisplay->setFont(u8g2_font_tom_thumb_4x6_tf);
mDisplay->setFont(u8g2_font_tom_thumb_4x6_tr);
break;
}
}

63
src/plugins/Display/Display_Mono_128X64.h

@ -9,53 +9,42 @@
class DisplayMono128X64 : public DisplayMono {
public:
DisplayMono128X64() : DisplayMono() {
mEnPowerSafe = true;
mEnPowerSave = true;
mEnScreenSaver = true;
mLuminance = 60;
mDispY = 0;
mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds)
mUtcTs = NULL;
mType = 0;
}
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) {
void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) {
mEnPowerSave = enPowerSave;
mEnScreenSaver = enScreenSaver;
mLuminance = lum;
}
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, DisplayData *displayData) {
u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0);
mType = type;
switch (type) {
case 1:
mDisplay = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(rot, reset, clock, data);
monoInit(new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(rot, reset, clock, data), type, displayData);
break;
case 2:
mDisplay = new U8G2_SH1106_128X64_NONAME_F_HW_I2C(rot, reset, clock, data);
monoInit(new U8G2_SH1106_128X64_NONAME_F_HW_I2C(rot, reset, clock, data), type, displayData);
break;
case 6:
mDisplay = new U8G2_SSD1309_128X64_NONAME0_F_HW_I2C(rot, reset, clock, data);
default:
monoInit(new U8G2_SSD1309_128X64_NONAME0_F_HW_I2C(rot, reset, clock, data), type, displayData);
break;
}
mUtcTs = utcTs;
mDisplay->begin();
calcLinePositions();
mDisplay->clearBuffer();
mDisplay->setContrast(mLuminance);
printText("AHOY!", 0, 35);
printText("Ahoy!", 0, 35);
printText("ahoydtu.de", 2, 20);
printText(version, 3, 46);
printText(mDisplayData->version, 3, 46);
mDisplay->sendBuffer();
}
void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) {
mEnPowerSafe = enPowerSafe;
mEnScreenSaver = enScreenSaver;
mLuminance = lum;
}
void loop(uint8_t lum) {
if (mEnPowerSafe) {
if (mEnPowerSave) {
if (mTimeout != 0)
mTimeout--;
}
@ -66,43 +55,43 @@ class DisplayMono128X64 : public DisplayMono {
}
}
void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) {
void disp(void) {
mDisplay->clearBuffer();
// set Contrast of the Display to raise the lifetime
mDisplay->setContrast(mLuminance);
if ((totalPower > 0) && (isprod > 0)) {
if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000));
if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (mDisplayData->totalPower / 1000));
else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", mDisplayData->totalPower);
printText(mFmtText, 0);
} else {
printText("offline", 0, 25);
// check if it's time to enter power saving mode
if (mTimeout == 0)
mDisplay->setPowerSave(mEnPowerSafe);
mDisplay->setPowerSave(mEnPowerSave);
}
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, 1);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", mDisplayData->totalYieldTotal);
printText(mFmtText, 2);
IPAddress ip = WiFi.localIP();
if (!(mExtra % 10) && (ip))
printText(ip.toString().c_str(), 3);
else if (!(mExtra % 5)) {
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", mDisplayData->nrProducing);
printText(mFmtText, 3);
} else if (NULL != mUtcTs)
printText(ah::getDateTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3);
} else if (0 != mDisplayData->utcTs)
printText(ah::getDateTimeStr(gTimezone.toLocal(mDisplayData->utcTs)).c_str(), 3);
mDisplay->sendBuffer();
@ -126,7 +115,7 @@ class DisplayMono128X64 : public DisplayMono {
mDisplay->setFont(u8g2_font_ncenB14_tr);
break;
case 3:
mDisplay->setFont(u8g2_font_5x8_tr);
mDisplay->setFont(u8g2_font_5x8_symbols_ahoy);
break;
default:
mDisplay->setFont(u8g2_font_ncenB10_tr);

61
src/plugins/Display/Display_Mono_64X48.h

@ -9,46 +9,33 @@
class DisplayMono64X48 : public DisplayMono {
public:
DisplayMono64X48() : DisplayMono() {
mEnPowerSafe = true;
mEnPowerSave = true;
mEnScreenSaver = false;
mLuminance = 20;
mExtra = 0;
mDispY = 0;
mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds)
mUtcTs = NULL;
mType = 0;
}
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) {
void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) {
mEnPowerSave = enPowerSave;
mEnScreenSaver = enScreenSaver;
mLuminance = lum;
}
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, DisplayData *displayData) {
u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0);
mType = type;
// Wemos OLed Shield is not defined in u8 lib -> use nearest compatible
mDisplay = new U8G2_SSD1306_64X48_ER_F_HW_I2C(rot, reset, clock, data);
mUtcTs = utcTs;
mDisplay->begin();
monoInit(new U8G2_SSD1306_64X48_ER_F_HW_I2C(rot, reset, clock, data), type, displayData);
calcLinePositions();
mDisplay->clearBuffer();
mDisplay->setContrast(mLuminance);
printText("AHOY!", 0);
printText("Ahoy!", 0);
printText("ahoydtu.de", 1);
printText(version, 2);
printText(mDisplayData->version, 2);
mDisplay->sendBuffer();
}
void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) {
mEnPowerSafe = enPowerSafe;
mEnScreenSaver = enScreenSaver;
mLuminance = lum;
}
void loop(uint8_t lum) {
if (mEnPowerSafe) {
if (mEnPowerSave) {
if (mTimeout != 0)
mTimeout--;
}
@ -59,43 +46,43 @@ class DisplayMono64X48 : public DisplayMono {
}
}
void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) {
void disp(void) {
mDisplay->clearBuffer();
// set Contrast of the Display to raise the lifetime
mDisplay->setContrast(mLuminance);
if ((totalPower > 0) && (isprod > 0)) {
if ((mDisplayData->totalPower > 0) && (mDisplayData->nrProducing > 0)) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000));
if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (mDisplayData->totalPower / 1000));
else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", mDisplayData->totalPower);
printText(mFmtText, 0);
} else {
printText("offline", 0);
// check if it's time to enter power saving mode
if (mTimeout == 0)
mDisplay->setPowerSave(mEnPowerSafe);
mDisplay->setPowerSave(mEnPowerSave);
}
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "D: %4.0f Wh", totalYieldDay);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "D: %4.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, 1);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "T: %4.0f kWh", totalYieldTotal);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "T: %4.0f kWh", mDisplayData->totalYieldTotal);
printText(mFmtText, 2);
IPAddress ip = WiFi.localIP();
if (!(mExtra % 10) && (ip))
printText(ip.toString().c_str(), 3);
else if (!(mExtra % 5)) {
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "active Inv: %d", isprod);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "active Inv: %d", mDisplayData->nrProducing);
printText(mFmtText, 3);
} else if (NULL != mUtcTs)
printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3);
} else if (0 != mDisplayData->utcTs)
printText(ah::getTimeStr(gTimezone.toLocal(mDisplayData->utcTs)).c_str(), 3);
mDisplay->sendBuffer();
@ -115,11 +102,11 @@ class DisplayMono64X48 : public DisplayMono {
inline void setFont(uint8_t line) {
switch (line) {
case 0:
mDisplay->setFont(u8g2_font_fur11_tf);
mDisplay->setFont(u8g2_font_fur11_tr);
break;
case 1:
case 2:
mDisplay->setFont(u8g2_font_6x10_tf);
mDisplay->setFont(u8g2_font_6x10_tr);
break;
case 3:
mDisplay->setFont(u8g2_font_4x6_tr);

151
src/plugins/Display/Display_Mono_84X48.h

@ -5,50 +5,37 @@
#pragma once
#include "Display_Mono.h"
#include "../../utils/dbg.h"
class DisplayMono84X48 : public DisplayMono {
public:
DisplayMono84X48() : DisplayMono() {
mEnPowerSafe = true;
mEnPowerSave = true;
mEnScreenSaver = true;
mLuminance = 60;
mLuminance = 140;
mExtra = 0;
mDispY = 0;
mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds)
mUtcTs = NULL;
mType = 0;
mDispWidth = 0;
}
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) {
void config(bool enPowerSave, bool enScreenSaver, uint8_t lum) {
mEnPowerSave = enPowerSave;
mEnScreenSaver = enScreenSaver;
mLuminance = lum;
}
void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, DisplayData *displayData) {
u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0);
mType = type;
mDisplay = new U8G2_PCD8544_84X48_F_4W_SW_SPI(rot, clock, data, cs, dc, reset);
mUtcTs = utcTs;
mDisplay->begin();
mDispWidth = mDisplay->getDisplayWidth();
monoInit(new U8G2_PCD8544_84X48_F_4W_SW_SPI(rot, clock, data, cs, dc, reset), type, displayData);
calcLinePositions();
mDisplay->clearBuffer();
mDisplay->setContrast(mLuminance);
printText("AHOY!", l_Ahoy);
printText("ahoydtu.de", l_Website);
printText(version, l_Version);
printText("Ahoy!", l_Ahoy, 0xff);
printText("ahoydtu.de", l_Website, 0xff);
printText(mDisplayData->version, l_Version, 0xff);
mDisplay->sendBuffer();
}
void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) {
mEnPowerSafe = enPowerSafe;
mEnScreenSaver = enScreenSaver;
mLuminance = lum;
}
void loop(uint8_t lum) {
if (mEnPowerSafe) {
if (mEnPowerSave) {
if (mTimeout != 0)
mTimeout--;
}
@ -59,44 +46,88 @@ class DisplayMono84X48 : public DisplayMono {
}
}
void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) {
mDisplay->clearBuffer();
void disp(void) {
// Test
/*
mDisplayData->nrSleeping = 10;
mDisplayData->nrProducing = 10;
mDisplayData->totalPower = 12345.67;
mDisplayData->totalYieldDay = 12345.67;
mDisplayData->totalYieldTotal = 1234;
mDisplayData->utcTs += 1000000;
*/
// set Contrast of the Display to raise the lifetime
mDisplay->setContrast(mLuminance);
mDisplay->clearBuffer();
if ((totalPower > 0) && (isprod > 0)) {
// print total power
if (mDisplayData->nrProducing > 0) {
mTimeout = DISP_DEFAULT_TIMEOUT;
mDisplay->setPowerSave(false);
if (totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f kW", (totalPower / 1000));
if (mDisplayData->totalPower > 9999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2fkW", (mDisplayData->totalPower / 1000)); // forgo spacing between value and SI unit in favor of second position after decimal point
else if (mDisplayData->totalPower > 999)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.2f kW", (mDisplayData->totalPower / 1000));
else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.0f W", totalPower);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%.1f W", mDisplayData->totalPower);
printText(mFmtText, l_TotalPower);
printText(mFmtText, l_TotalPower, 0xff);
} else {
printText("offline", l_TotalPower);
printText("offline", l_TotalPower, 0xff);
// check if it's time to enter power saving mode
if (mTimeout == 0)
mDisplay->setPowerSave(mEnPowerSafe);
mDisplay->setPowerSave(mEnPowerSave);
}
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "Today: %4.0f Wh", totalYieldDay);
printText(mFmtText, l_YieldDay);
// print Date and time
if (0 != mDisplayData->utcTs)
printText(ah::getDateTimeStrShort(gTimezone.toLocal(mDisplayData->utcTs)).c_str(), l_Time, 0xff);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "Total: %.1f kWh", totalYieldTotal);
printText(mFmtText, l_YieldTotal);
// alternatively:
// print ip address
if (!(mExtra % 5) && (mDisplayData->ipAddress)) {
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%s", (mDisplayData->ipAddress).toString().c_str());
printText(mFmtText, l_Status, 0xff);
}
// print status of inverters
else {
if (0 == mDisplayData->nrSleeping)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "\x86");
else if (0 == mDisplayData->nrProducing)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "\x87");
else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d\x86 %d\x87", mDisplayData->nrProducing, mDisplayData->nrSleeping);
setLineFont(l_Status);
printText(mFmtText, l_Status, (mDispWidth - mDisplay->getStrWidth(mFmtText)) / 2);
}
if (NULL != mUtcTs)
printText(ah::getDateTimeStrShort(gTimezone.toLocal(*mUtcTs)).c_str(), l_Time);
// print yields
printText("\x88", l_YieldDay, 11); // day symbol
printText("\x83", l_YieldTotal, 11); // total symbol
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.0f Wh", mDisplayData->totalYieldDay);
printText(mFmtText, l_YieldDay, 18);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%7.1f kWh", mDisplayData->totalYieldTotal);
printText(mFmtText, l_YieldTotal, 18);
// draw dynamic Nokia RSSI bars
int rssi_bar_height = 7;
for (int i=0; i<4;i++) {
int radio_rssi_threshold = -60 - i*10; // radio rssi not yet tested in reality!
int wifi_rssi_threshold = -60 - i*10;
if (mDisplayData->RadioRSSI > radio_rssi_threshold)
mDisplay->drawBox(0, 8+(rssi_bar_height+1)*i, 4-i,rssi_bar_height);
if (mDisplayData->WifiRSSI > wifi_rssi_threshold)
mDisplay->drawBox(mDispWidth-4+i, 8+(rssi_bar_height+1)*i, 4-i,rssi_bar_height);
}
IPAddress ip = WiFi.localIP();
if (!(mExtra % 5) && (ip))
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%s", ip.toString().c_str());
// draw dynamic antenna and WiFi symbols
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%c", mDisplayData->RadioSymbol?'\x80':'\x84'); // NRF
printText(mFmtText, l_RSSI);
if (mDisplayData->MQTTSymbol)
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "\x89"); // MQTT
else
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "Inv.On: %d", isprod);
printText(mFmtText, l_Status);
snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%c", mDisplayData->WifiSymbol?'\x81':'\x85'); // Wifi connected
printText(mFmtText, l_RSSI, mDispWidth - 6);
mDisplay->sendBuffer();
@ -104,7 +135,6 @@ class DisplayMono84X48 : public DisplayMono {
}
private:
uint16_t mDispWidth;
enum _dispLine {
// start page
l_Website = 0,
@ -116,6 +146,8 @@ class DisplayMono84X48 : public DisplayMono {
l_TotalPower = 2,
l_YieldDay = 3,
l_YieldTotal = 4,
// run page - rssi bar symbols
l_RSSI = 4,
// End
l_MAX_LINES = 5,
};
@ -126,7 +158,7 @@ class DisplayMono84X48 : public DisplayMono {
uint8_t asc, dsc;
do {
setFont(i);
setLineFont(i);
asc = mDisplay->getAscent();
yOff += asc;
mLineYOffsets[i] = yOff;
@ -138,18 +170,23 @@ class DisplayMono84X48 : public DisplayMono {
} while(l_MAX_LINES>i);
}
inline void setFont(uint8_t line) {
inline void setLineFont(uint8_t line) {
if ((line == l_TotalPower) || (line == l_Ahoy))
mDisplay->setFont(u8g2_font_logisoso16_tr);
else
mDisplay->setFont(u8g2_font_5x8_tr);
mDisplay->setFont(u8g2_font_5x8_symbols_ahoy);
}
void printText(const char *text, uint8_t line) {
void printText(const char *text, uint8_t line, uint8_t col=0) {
uint8_t dispX;
setFont(line);
dispX = (mDispWidth - mDisplay->getStrWidth(text)) / 2; // center text
dispX += (mEnScreenSaver) ? (mExtra % 7) : 0;
setLineFont(line);
if (0xff == col)
dispX = (mDispWidth - mDisplay->getStrWidth(text)) / 2; // center text
else
dispX = col;
mDisplay->drawStr(dispX, mLineYOffsets[line], text);
}
};

22
src/plugins/Display/Display_data.h

@ -0,0 +1,22 @@
#include "../../utils/helper.h"
#ifndef __DISPLAY_DATA__
#define __DISPLAY_DATA__
struct DisplayData {
const char *version=nullptr;
float totalPower=0.0f; // indicate current power (W)
float totalYieldDay=0.0f; // indicate day yield (W)
float totalYieldTotal=0.0f; // indicate total yield (W)
uint32_t utcTs=0; // indicate absolute timestamp (utc unix time). 0 = time is not synchonized
uint8_t nrProducing=0; // indicate number of producing inverters
uint8_t nrSleeping=0; // indicate number of sleeping inverters
bool WifiSymbol = false; // indicate if WiFi is connected
bool RadioSymbol = false; // indicate if radio module is connecting and working
bool MQTTSymbol = false; // indicate if MQTT is connected
int8_t WifiRSSI=SCHAR_MIN; // indicate RSSI value for WiFi
int8_t RadioRSSI=SCHAR_MIN; // indicate RSSI value for radio
IPAddress ipAddress; // indicate ip adress of ahoy
};
#endif /*__DISPLAY_DATA__*/

8
src/plugins/Display/Display_ePaper.cpp

@ -46,9 +46,9 @@ void DisplayEPaper::init(uint8_t type, uint8_t _CS, uint8_t _DC, uint8_t _RST, u
}
}
void DisplayEPaper::config(uint8_t rotation, bool enPowerSafe) {
void DisplayEPaper::config(uint8_t rotation, bool enPowerSave) {
mDisplayRotation = rotation;
mEnPowerSafe = enPowerSafe;
mEnPowerSave = enPowerSave;
}
//***************************************************************************
@ -209,7 +209,7 @@ void DisplayEPaper::actualPowerPaged(float totalPower, float totalYieldDay, floa
} else
snprintf(_fmtText, sizeof(_fmtText), "offline");
if ((totalPower == 0) && (mEnPowerSafe)) {
if ((totalPower == 0) && (mEnPowerSave)) {
_display->fillRect(0, mHeadFootPadding, 200, 200, GxEPD_BLACK);
_display->drawBitmap(0, 0, logo, 200, 200, GxEPD_WHITE);
} else {
@ -291,7 +291,7 @@ void DisplayEPaper::loop(float totalPower, float totalYieldDay, float totalYield
if ((isprod > 0) && (_changed)) {
_changed = false;
lastUpdatePaged();
} else if ((0 == totalPower) && (mEnPowerSafe))
} else if ((0 == totalPower) && (mEnPowerSave))
offlineFooter();
_display->powerOff();

4
src/plugins/Display/Display_ePaper.h

@ -28,7 +28,7 @@ class DisplayEPaper {
DisplayEPaper();
void fullRefresh();
void init(uint8_t type, uint8_t _CS, uint8_t _DC, uint8_t _RST, uint8_t _BUSY, uint8_t _SCK, uint8_t _MOSI, uint32_t* utcTs, const char* version);
void config(uint8_t rotation, bool enPowerSafe);
void config(uint8_t rotation, bool enPowerSave);
void loop(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod);
void refreshLoop();
void tickerSecond();
@ -56,7 +56,7 @@ class DisplayEPaper {
uint8_t mHeadFootPadding;
GxEPD2_GFX* _display;
uint32_t* mUtcTs;
bool mEnPowerSafe;
bool mEnPowerSave;
const char* _version;
RefreshStatus mRefreshState, mNextRefreshState;
uint8_t mSecondCnt;

6
tools/fonts/fontconv.bat

@ -0,0 +1,6 @@
.\bdfconv\bdfconv_2_22.exe -v -f 1 -m "32-137" u8g2_font_5x8_symbols_ahoy.bdf -o u8g2_font_5x8_symbols_ahoy.c_ -n u8g2_font_5x8_symbols_ahoy
.\bdfconv\bdfconv_2_22.exe -v -f 1 -m "65-75" u8g2_font_ncenB10_symbols10_ahoy.bdf -o u8g2_font_ncenB10_symbols10_ahoy.c_ -n u8g2_font_ncenB10_symbols10_ahoy
.\bdfconv\bdfconv_2_22.exe -v -f 1 -m "65-75" u8g2_font_ncenB08_symbols8_ahoy.bdf -o u8g2_font_ncenB08_symbols8_ahoy.c_ -n u8g2_font_ncenB08_symbols8_ahoy
pause

11
tools/fonts/u8g2 font-sources.txt

@ -0,0 +1,11 @@
Useful sources to edit u8g2 fonts:
bdf font files for u8g2 font library:
https://github.com/olikraus/u8g2/tree/master/tools/font/bdf
Tool to edit bdf files:
https://github.com/olikraus/u8g2/tree/master/tools/font/fony
Tool to convert bdf font files to u8g2 source code:
https://github.com/olikraus/u8g2/tree/master/tools/font/bdfconv

1328
tools/fonts/u8g2_font_5x8_symbols_ahoy.bdf

File diff suppressed because it is too large

40
tools/fonts/u8g2_font_5x8_symbols_ahoy.c_

@ -0,0 +1,40 @@
/*
Fontname: u8g2_font_5x8_symbols_ahoy
Copyright: Public domain font. Share and enjoy.
Glyphs: 106/106
BBX Build Mode: 0
*/
const uint8_t u8g2_font_5x8_symbols_ahoy[1052] U8G2_FONT_SECTION("u8g2_font_5x8_symbols_ahoy") =
"j\0\3\2\4\4\3\4\5\10\10\0\377\6\377\6\0\1\61\2b\4\3 \5\0\304\11!\7a\306"
"\212!\11\42\7\63\335\212\304\22#\16u\304\232R\222\14JePJI\2$\14u\304\252l\251m"
"I\262E\0%\10S\315\212(\351\24&\13t\304\232(i\252\64%\1'\6\61\336\212\1(\7b"
"\305\32\245))\11b\305\212(\251(\0*\13T\304\212(Q\206D\211\2+\12U\304\252\60\32\244"
"\60\2,\7\63\275\32\245\4-\6\24\324\212!.\6\42\305\212!/\10d\304\272R[\6\60\14d"
"\304\32%R\206DJ\24\0\61\10c\305\232Dj\31\62\13d\304\32%\312\22%\33\2\63\13d\304"
"\212!\212D)Q\0\64\13d\304\252H\251\14Q\226\0\65\12d\304\212A\33\245D\1\66\13d\304"
"\32%[\42)Q\0\67\13d\304\212!\213\262(\213\0\70\14d\304\32%J\224HJ\24\0\71\13"
"d\304\32%\222\222-Q\0:\10R\305\212!\32\2;\10c\275\32\243R\2<\10c\305\252\244\224"
"\25=\10\64\314\212!\34\2>\11c\305\212\254\224\224\0?\11c\305\232\246$M\0@\15\205\274*"
")\222\226DI\244\252\2A\12d\304\32%\222\206I\12B\14d\304\212%\32\222H\32\22\0C\12"
"d\304\32%\322J\211\2D\12d\304\212%r\32\22\0E\12d\304\212A[\262l\10F\12d\304"
"\212A[\262\32\0G\13d\304\32%\322\222)Q\0H\12d\304\212H\32&S\0I\10c\305\212"
"%j\31J\12d\304\232)\253\224\42\0K\13d\304\212HI\244\244S\0L\10d\304\212\254\333\20"
"M\12d\304\212h\70D\246\0N\12d\304\212h\31\226I\12O\12d\304\32%rJ\24\0P\13"
"d\304\212%\222\206$\313\0Q\12t\274\32%\222\26\307\0R\13d\304\212%\222\206$\222\2S\14"
"d\304\32%J\302$J\24\0T\11e\304\212A\12;\1U\11d\304\212\310S\242\0V\12d\304"
"\212\310)\221\24\0W\12d\304\212\310\64\34\242\0X\13d\304\212HJ$%\222\2Y\12e\304\212"
"LKja\11Z\12d\304\212!\213\332\206\0[\10c\305\212!j\32\134\10d\304\212,l\13]"
"\10c\305\212\251i\10^\6#\345\232\6_\6\24\274\212!`\6\42\345\212(a\11D\304\232!\222"
"\222\1b\13d\304\212,[\42iH\0c\7C\305\232)\23d\12d\304\272\312\20I\311\0e\11"
"D\304\32%\31\262\1f\12d\304\252Ji\312\42\0g\12T\274\32%J\266D\1h\12d\304\212"
",[\42S\0i\10c\305\232P\252\14j\12s\275\252\64\212\224\12\0k\12d\304\212\254\64$\221"
"\24l\10c\305\12\251\313\0m\12E\304\12\245EI\224\2n\10D\304\212%\62\5o\11D\304\32"
"%\222\22\5p\12T\274\212%\32\222,\3q\11T\274\232!J\266\2r\11D\304\212$\261e\0"
"s\10C\305\232![\0t\13d\304\232,\232\262$J\0u\10D\304\212\310\224\14v\10C\305\212"
"\304R\1w\12E\304\212LI\224.\0x\11D\304\212(\221\224(y\13T\274\212HJ\206(Q"
"\0z\11D\304\212!*\15\1{\12t\304*%L\304(\24|\6a\306\212\3}\13t\304\12\61"
"\12\225\60\221\0~\10$\344\232DI\0\5\0\304\12\200\13u\274\212K\242T\266\260\4\201\14f"
"D\233!\11#-\312!\11\202\15hD<\65\12\243,\214\302$\16\203\15w<\214C\22F\71\220"
"\26\207A\204\16\205\274\212,)%Y\230%QR\13\205\17\206<\213\60\31\22\311\66D\245!\11\3"
"\206\20\210<\254\342\20]\302(L\246C\30E\0\207\15wD\334X\25\267\341\20\15\21\0\210\16w"
"<\214\203RQ\25I\212\324a\20\211\15f\304\213)\213\244,\222\222\245\0\0\0\0";

BIN
tools/fonts/u8g2_font_5x8_symbols_ahoy.fon

Binary file not shown.

166
tools/fonts/u8g2_font_ncenB08_symbols8_ahoy.bdf

@ -0,0 +1,166 @@
STARTFONT 2.1
COMMENT Exported by Fony v1.4.7
FONT u8g2_font_ncenB08_symbols8_ahoy
SIZE 12 100 100
FONTBOUNDINGBOX 9 11 0 -2
STARTPROPERTIES 6
COPYRIGHT ""
RESOLUTION_X 100
RESOLUTION_Y 100
FONT_ASCENT 10
FONT_DESCENT 2
DEFAULT_CHAR 0
ENDPROPERTIES
CHARS 11
STARTCHAR 065
ENCODING 65
SWIDTH 576 0
DWIDTH 8 0
BBX 7 8 0 0
BITMAP
FE
92
D6
38
10
10
10
10
ENDCHAR
STARTCHAR 066
ENCODING 66
SWIDTH 648 0
DWIDTH 9 0
BBX 8 9 1 0
BITMAP
3C
42
99
24
42
18
24
00
18
ENDCHAR
STARTCHAR 067
ENCODING 67
SWIDTH 576 0
DWIDTH 8 0
BBX 8 8 0 0
BITMAP
18
24
24
42
42
42
42
81
ENDCHAR
STARTCHAR 068
ENCODING 68
SWIDTH 648 0
DWIDTH 9 0
BBX 8 8 0 0
BITMAP
FF
41
20
10
10
20
41
FF
ENDCHAR
STARTCHAR 069
ENCODING 69
SWIDTH 576 0
DWIDTH 8 0
BBX 7 8 0 0
BITMAP
FE
D6
FE
38
10
38
54
92
ENDCHAR
STARTCHAR 070
ENCODING 70
SWIDTH 648 0
DWIDTH 9 0
BBX 8 9 1 0
BITMAP
BD
42
BD
3C
5A
18
24
42
99
ENDCHAR
STARTCHAR 071
ENCODING 71
SWIDTH 648 0
DWIDTH 9 0
BBX 8 8 0 0
BITMAP
24
3C
E7
42
42
E7
3C
24
ENDCHAR
STARTCHAR 072
ENCODING 72
SWIDTH 576 0
DWIDTH 8 0
BBX 7 7 0 1
BITMAP
04
06
06
0E
1E
FC
78
ENDCHAR
STARTCHAR 073
ENCODING 73
SWIDTH 576 0
DWIDTH 8 0
BBX 7 9 0 0
BITMAP
44
FE
82
92
B2
92
92
82
FE
ENDCHAR
STARTCHAR 074
ENCODING 74
SWIDTH 504 0
DWIDTH 7 0
BBX 0 0 0 0
BITMAP
ENDCHAR
STARTCHAR 075
ENCODING 75
SWIDTH 648 0
DWIDTH 9 0
BBX 0 0 0 0
BITMAP
ENDCHAR
ENDFONT

13
tools/fonts/u8g2_font_ncenB08_symbols8_ahoy.c_

@ -0,0 +1,13 @@
/*
Fontname: u8g2_font_ncenB08_symbols8_ahoy
Copyright:
Glyphs: 11/11
BBX Build Mode: 0
*/
const uint8_t u8g2_font_ncenB08_symbols8_ahoy[173] U8G2_FONT_SECTION("u8g2_font_ncenB08_symbols8_ahoy") =
"\13\0\3\2\4\4\2\2\5\11\11\0\0\10\0\10\0\0\0\0\0\0\224A\14\207\212q\220\242%\221"
"\326\270\15B\20\230\233\65da\22Ima\250F\71\254\1C\20\210\212\247Fa\224\205Q\30\205Q"
"\230\304\1D\16\210\232qP\322(Gr \256\16\7E\15\207\212\361\222\14\247\65\335\222\246\2F\25"
"\230\233\221\14I\61I\206$\32\262D\11\325(\13\223H\12G\17\210\232U\34\242K\30\205\311t\10"
"\243\10H\14w\216\33\253\342\66\34\242!\2I\21\227\212\223%\303\240J\221\42I\221\24\251\303 J"
"\5\0z\1K\5\0\232\1\0\0\0";

BIN
tools/fonts/u8g2_font_ncenB08_symbols8_ahoy.fon

Binary file not shown.

188
tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.bdf

@ -0,0 +1,188 @@
STARTFONT 2.1
COMMENT Exported by Fony v1.4.7
FONT u8g2_font_symbols10_ahoy
SIZE 16 100 100
FONTBOUNDINGBOX 12 15 0 -3
STARTPROPERTIES 6
COPYRIGHT ""
RESOLUTION_X 100
RESOLUTION_Y 100
FONT_ASCENT 13
FONT_DESCENT 3
DEFAULT_CHAR 0
ENDPROPERTIES
CHARS 11
STARTCHAR 065
ENCODING 65
SWIDTH 576 0
DWIDTH 8 0
BBX 7 11 0 0
BITMAP
FE
92
92
54
38
10
10
10
10
10
10
ENDCHAR
STARTCHAR 066
ENCODING 66
SWIDTH 648 0
DWIDTH 9 0
BBX 8 9 0 1
BITMAP
3C
42
99
24
42
18
24
00
18
ENDCHAR
STARTCHAR 067
ENCODING 67
SWIDTH 792 0
DWIDTH 11 0
BBX 10 11 0 0
BITMAP
0C00
1200
2100
2100
2100
2180
4080
4080
4080
4080
8040
ENDCHAR
STARTCHAR 068
ENCODING 68
SWIDTH 720 0
DWIDTH 10 0
BBX 9 11 0 0
BITMAP
FF80
6080
3000
1800
0C00
0C00
1800
3000
6000
C080
FF80
ENDCHAR
STARTCHAR 069
ENCODING 69
SWIDTH 576 0
DWIDTH 8 0
BBX 7 11 0 0
BITMAP
FE
D6
D6
7C
38
10
38
38
54
54
92
ENDCHAR
STARTCHAR 070
ENCODING 70
SWIDTH 648 0
DWIDTH 9 0
BBX 8 10 1 0
BITMAP
BD
42
BD
24
5A
18
24
24
5A
81
ENDCHAR
STARTCHAR 071
ENCODING 71
SWIDTH 864 0
DWIDTH 12 0
BBX 11 11 0 0
BITMAP
1100
1100
0E00
D160
2080
2080
2080
D160
0E00
1100
1100
ENDCHAR
STARTCHAR 072
ENCODING 72
SWIDTH 792 0
DWIDTH 11 0
BBX 10 11 0 0
BITMAP
0080
0080
00C0
00C0
01C0
01C0
03C0
0780
1F80
FF00
3C00
ENDCHAR
STARTCHAR 073
ENCODING 73
SWIDTH 720 0
DWIDTH 10 0
BBX 9 11 0 0
BITMAP
DD80
FF80
8080
8880
9880
8880
8880
8880
8880
8080
FF80
ENDCHAR
STARTCHAR 074
ENCODING 74
SWIDTH 648 0
DWIDTH 9 0
BBX 0 0 0 0
BITMAP
ENDCHAR
STARTCHAR 075
ENCODING 75
SWIDTH 648 0
DWIDTH 9 0
BBX 0 0 0 0
BITMAP
ENDCHAR
ENDFONT

14
tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.c_

@ -0,0 +1,14 @@
/*
Fontname: u8g2_font_symbols10_ahoy
Copyright:
Glyphs: 11/11
BBX Build Mode: 0
*/
const uint8_t u8g2_font_ncenB10_symbols10_ahoy[207] U8G2_FONT_SECTION("u8g2_font_ncenB10_symbols10_ahoy") =
"\13\0\3\2\4\4\2\2\5\13\13\0\0\13\0\13\0\0\0\0\0\0\266A\15\267\212q\220\42\251\322"
"\266\306\275\1B\20\230\236\65da\22Ima\250F\71\254\1C\23\272\272\251\3Q\32\366Q\212\243"
"\70\212\243\70\311\221\0D\20\271\252\361\242F:\242#: {\36\16\1E\22\267\212\361\222\14I\242"
"\14\332\232\216[RJ\232\12F\25\250\233\221\14I\61I\206$\252%J\250Fa\224%J\71G\30"
"\273\312W\316r`T\262DJ\303\64L#%K\304\35\310\342,\3H\27\272\272\217\344P\16\351\210"
"\16\354\300<\244C\70,\303 \16!\0I\24\271\252\241\34\336\1-\223\64-\323\62-\323\62\35x"
"\10J\5\0\232\1K\5\0\232\1\0\0\0";

BIN
tools/fonts/u8g2_font_ncenB10_symbols10_ahoy.fon

Binary file not shown.

16
tools/fonts/used_fonts.txt

@ -0,0 +1,16 @@
Display_Mono_64x48:
u8g2_font_fur11_tr
u8g2_font_6x10_tf
u8g2_font_4x6_tr
Display_Mono_128x32:
u8g2_font_9x15_tr
u8g2_font_tom_thumb_4x6_tr
Display_Mono_84x48:
u8g2_font_5x8_symbols_ahoy
u8g2_font_logisoso16_tr
Display_Mono_128x64:
u8g2_font_ncenB08_symbols8_ahoy
u8g2_font_ncenB10_symbols10_ahoy
Loading…
Cancel
Save