From 660e534963e8d4dfe21acec6b655d5d3d91bf433 Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Tue, 15 Jan 2019 18:04:16 -0800 Subject: [PATCH] C++ interface for U8G2 --- components/sx127x_driver/sx127x_driver.h | 8 + components/sx127x_driver/sx127x_pb.h | 8 + components/sx127x_driver/sx127x_registers.h | 8 + main/CMakeLists.txt | 3 +- main/Print.cpp | 269 +++++++++++++++ main/Print.h | 100 ++++++ main/U8g2lib.hh | 363 ++++++++++++++++++++ main/u8g2_esp32_hal.c | 96 +++--- main/u8g2_esp32_hal.h | 31 +- main/ugv_comms.h | 8 + main/{ugv_main.c => ugv_main.cc} | 44 +-- 11 files changed, 847 insertions(+), 91 deletions(-) create mode 100644 main/Print.cpp create mode 100644 main/Print.h create mode 100644 main/U8g2lib.hh rename main/{ugv_main.c => ugv_main.cc} (81%) diff --git a/components/sx127x_driver/sx127x_driver.h b/components/sx127x_driver/sx127x_driver.h index 203652d..b3de351 100644 --- a/components/sx127x_driver/sx127x_driver.h +++ b/components/sx127x_driver/sx127x_driver.h @@ -4,6 +4,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define SX127_MAX_PACKET_LEN 255 // carrier frequency type @@ -101,4 +105,8 @@ QueueHandle_t sx127x_get_recv_queue(sx127x_hndl hndl); void sx127x_packet_rx_free(sx127x_rx_packet_t *packet); +#ifdef __cplusplus +} +#endif + #include "sx127x_pb.h" diff --git a/components/sx127x_driver/sx127x_pb.h b/components/sx127x_driver/sx127x_pb.h index f323944..84bb256 100644 --- a/components/sx127x_driver/sx127x_pb.h +++ b/components/sx127x_driver/sx127x_pb.h @@ -2,6 +2,10 @@ #include "sdkconfig.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifdef CONFIG_SX127X_USE_NANOPB #include "sx127x_driver.h" @@ -12,3 +16,7 @@ esp_err_t sx127x_send_packet_pb(sx127x_hndl hndl, const pb_field_t fields[], void *src_struct, TickType_t ticks_to_wait); #endif + +#ifdef __cplusplus +} +#endif diff --git a/components/sx127x_driver/sx127x_registers.h b/components/sx127x_driver/sx127x_registers.h index e0e7f32..633430b 100644 --- a/components/sx127x_driver/sx127x_registers.h +++ b/components/sx127x_driver/sx127x_registers.h @@ -1,5 +1,9 @@ #include "sx127x_driver.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef enum sx127x_reg { SX127X_REG_FIFO = 0x00, SX127X_REG_OP_MODE = 0x01, @@ -98,3 +102,7 @@ esp_err_t sx127x_read_lna_gain(sx127x_hndl hdnl, uint8_t *lna_gain); esp_err_t sx127x_write_fifo(sx127x_hndl hdnl, const char *data, size_t data_len); esp_err_t sx127x_read_fifo(sx127x_hndl hdnl, char *data_out, size_t data_len); + +#ifdef __cplusplus +} +#endif diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 0b398c5..d7f1e81 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -5,10 +5,11 @@ set(PB_OUT ${CMAKE_CURRENT_SOURCE_DIR}/pb_out) make_directory(${PB_OUT}) nanopb_generate(messages.proto ${PB_OUT} PROTO_HDRS PROTO_SRCS) -list(APPEND COMPONENT_SRCS "ugv_main.c" +list(APPEND COMPONENT_SRCS "ugv_main.cc" "ugv_comms.c" "ugv_io.c" "u8g2_esp32_hal.c" + "Print.cpp" ${PROTO_SRCS}) set(COMPONENT_PRIV_INCLUDEDIRS "." ${PB_OUT}) set(COMPONENT_REQUIRES "u8g2" "sx127x_driver" "nanopb" "mpu_driver") diff --git a/main/Print.cpp b/main/Print.cpp new file mode 100644 index 0000000..3e9e59c --- /dev/null +++ b/main/Print.cpp @@ -0,0 +1,269 @@ +/* + Print.cpp - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Modified 23 November 2006 by David A. Mellis + Modified December 2014 by Ivan Grokhotkov + Modified May 2015 by Michael C. Miller - ESP31B progmem support + */ + +#include +#include +#include +#include +#include + +#include "Print.h" + +extern "C" { +#include "time.h" +} + +// Public Methods ////////////////////////////////////////////////////////////// + +/* default implementation: may be overridden */ +size_t Print::write(const uint8_t *buffer, size_t size) { + size_t n = 0; + while (size--) { + n += write(*buffer++); + } + return n; +} + +size_t Print::printf(const char *format, ...) { + char loc_buf[64]; + char * temp = loc_buf; + va_list arg; + va_list copy; + va_start(arg, format); + va_copy(copy, arg); + size_t len = vsnprintf(NULL, 0, format, arg); + va_end(copy); + if (len >= sizeof(loc_buf)) { + temp = new char[len + 1]; + if (temp == NULL) { + return 0; + } + } + len = vsnprintf(temp, len + 1, format, arg); + write((uint8_t *)temp, len); + va_end(arg); + if (len >= sizeof(loc_buf)) { + delete[] temp; + } + return len; +} + +// size_t Print::print(const String &s) { return write(s.c_str(), s.length()); } + +size_t Print::print(const std::string &s) { return write(s.c_str(), s.length()); } + +size_t Print::print(const char str[]) { return write(str); } + +size_t Print::print(char c) { return write(c); } + +size_t Print::print(unsigned char b, int base) { + return print((unsigned long)b, base); +} + +size_t Print::print(int n, int base) { return print((long)n, base); } + +size_t Print::print(unsigned int n, int base) { + return print((unsigned long)n, base); +} + +size_t Print::print(long n, int base) { + if (base == 0) { + return write(n); + } else if (base == 10) { + if (n < 0) { + int t = print('-'); + n = -n; + return printNumber(n, 10) + t; + } + return printNumber(n, 10); + } else { + return printNumber(n, base); + } +} + +size_t Print::print(unsigned long n, int base) { + if (base == 0) { + return write(n); + } else { + return printNumber(n, base); + } +} + +size_t Print::print(double n, int digits) { return printFloat(n, digits); } + +// size_t Print::print(const Printable &x) { return x.printTo(*this); } + +size_t Print::print(struct tm *timeinfo, const char *format) { + const char *f = format; + if (!f) { + f = "%c"; + } + char buf[64]; + size_t written = strftime(buf, 64, f, timeinfo); + print(buf); + return written; +} + +size_t Print::println(void) { return print("\r\n"); } + +// size_t Print::println(const String &s) { +// size_t n = print(s); +// n += println(); +// return n; +// } + +size_t Print::println(const std::string &s) { + size_t n = print(s); + n += println(); + return n; +} + +size_t Print::println(const char c[]) { + size_t n = print(c); + n += println(); + return n; +} + +size_t Print::println(char c) { + size_t n = print(c); + n += println(); + return n; +} + +size_t Print::println(unsigned char b, int base) { + size_t n = print(b, base); + n += println(); + return n; +} + +size_t Print::println(int num, int base) { + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(unsigned int num, int base) { + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(long num, int base) { + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(unsigned long num, int base) { + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(double num, int digits) { + size_t n = print(num, digits); + n += println(); + return n; +} + +// size_t Print::println(const Printable &x) { +// size_t n = print(x); +// n += println(); +// return n; +// } + +size_t Print::println(struct tm *timeinfo, const char *format) { + size_t n = print(timeinfo, format); + n += println(); + return n; +} + +// Private Methods ///////////////////////////////////////////////////////////// + +size_t Print::printNumber(unsigned long n, uint8_t base) { + char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. + char *str = &buf[sizeof(buf) - 1]; + + *str = '\0'; + + // prevent crash if called with base == 1 + if (base < 2) { + base = 10; + } + + do { + unsigned long m = n; + n /= base; + char c = m - base * n; + *--str = c < 10 ? c + '0' : c + 'A' - 10; + } while (n); + + return write(str); +} + +size_t Print::printFloat(double number, uint8_t digits) { + size_t n = 0; + + if (std::isnan(number)) { + return print("nan"); + } + if (std::isinf(number)) { + return print("inf"); + } + if (number > 4294967040.0) { + return print("ovf"); // constant determined empirically + } + if (number < -4294967040.0) { + return print("ovf"); // constant determined empirically + } + + // Handle negative numbers + if (number < 0.0) { + n += print('-'); + number = -number; + } + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + for (uint8_t i = 0; i < digits; ++i) { + rounding /= 10.0; + } + + number += rounding; + + // Extract the integer part of the number and print it + unsigned long int_part = (unsigned long)number; + double remainder = number - (double)int_part; + n += print(int_part); + + // Print the decimal point, but only if there are digits beyond + if (digits > 0) { + n += print("."); + } + + // Extract digits from the remainder one at a time + while (digits-- > 0) { + remainder *= 10.0; + int toPrint = int(remainder); + n += print(toPrint); + remainder -= toPrint; + } + + return n; +} diff --git a/main/Print.h b/main/Print.h new file mode 100644 index 0000000..f741e13 --- /dev/null +++ b/main/Print.h @@ -0,0 +1,100 @@ +/* + Print.h - Base class that provides print() and println() + Copyright (c) 2008 David A. Mellis. All right reserved. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef Print_h +#define Print_h + +#include +#include +#include + +// #include "Printable.h" + +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 + +class Print +{ +private: + int write_error; + size_t printNumber(unsigned long, uint8_t); + size_t printFloat(double, uint8_t); +protected: + void setWriteError(int err = 1) + { + write_error = err; + } +public: + Print() : + write_error(0) + { + } + virtual ~Print() {} + int getWriteError() + { + return write_error; + } + void clearWriteError() + { + setWriteError(0); + } + + virtual size_t write(uint8_t) = 0; + size_t write(const char *str) + { + if(str == NULL) { + return 0; + } + return write((const uint8_t *) str, strlen(str)); + } + virtual size_t write(const uint8_t *buffer, size_t size); + size_t write(const char *buffer, size_t size) + { + return write((const uint8_t *) buffer, size); + } + + size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3))); + // size_t print(const String &); + size_t print(const std::string &); + size_t print(const char[]); + size_t print(char); + size_t print(unsigned char, int = DEC); + size_t print(int, int = DEC); + size_t print(unsigned int, int = DEC); + size_t print(long, int = DEC); + size_t print(unsigned long, int = DEC); + size_t print(double, int = 2); + // size_t print(const Printable&); + size_t print(struct tm * timeinfo, const char * format = NULL); + + // size_t println(const String &s); + size_t println(const std::string &s); + size_t println(const char[]); + size_t println(char); + size_t println(unsigned char, int = DEC); + size_t println(int, int = DEC); + size_t println(unsigned int, int = DEC); + size_t println(long, int = DEC); + size_t println(unsigned long, int = DEC); + size_t println(double, int = 2); + // size_t println(const Printable&); + size_t println(struct tm * timeinfo, const char * format = NULL); + size_t println(void); +}; + +#endif \ No newline at end of file diff --git a/main/U8g2lib.hh b/main/U8g2lib.hh new file mode 100644 index 0000000..6fdbd48 --- /dev/null +++ b/main/U8g2lib.hh @@ -0,0 +1,363 @@ +#pragma once + +#include "Print.h" +#include "u8g2.h" +#include "u8g2_esp32_hal.h" + +class U8G2 : public Print { + protected: + u8g2_t u8g2; + u8x8_char_cb cpp_next_cb; /* the cpp interface has its own decoding function + for the Arduino print command */ + public: + u8g2_uint_t tx, ty; + + U8G2(void) { + cpp_next_cb = u8x8_ascii_next; + home(); + } + u8x8_t *getU8x8(void) { return u8g2_GetU8x8(&u8g2); } + u8g2_t *getU8g2(void) { return &u8g2; } + + uint32_t getBusClock(void) { return u8g2_GetU8x8(&u8g2)->bus_clock; } + void setBusClock(uint32_t clock_speed) { + u8g2_GetU8x8(&u8g2)->bus_clock = clock_speed; + } + + void setI2CAddress(uint8_t adr) { u8g2_SetI2CAddress(&u8g2, adr); } + + void enableUTF8Print(void) { cpp_next_cb = u8x8_utf8_next; } + void disableUTF8Print(void) { cpp_next_cb = u8x8_ascii_next; } + + /* u8x8 interface */ + uint8_t getCols(void) { return u8x8_GetCols(u8g2_GetU8x8(&u8g2)); } + uint8_t getRows(void) { return u8x8_GetRows(u8g2_GetU8x8(&u8g2)); } + void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) { + u8x8_DrawTile(u8g2_GetU8x8(&u8g2), x, y, cnt, tile_ptr); + } + +#ifdef U8X8_WITH_USER_PTR + void *getUserPtr() { return u8g2_GetUserPtr(&u8g2); } + void setUserPtr(void *p) { u8g2_SetUserPtr(&u8g2, p); } +#endif + +#ifdef U8X8_USE_PINS + /* set the menu pins before calling begin() or initDisplay() */ + void setMenuSelectPin(uint8_t val) { u8g2_SetMenuSelectPin(&u8g2, val); } + void setMenuPrevPin(uint8_t val) { u8g2_SetMenuPrevPin(&u8g2, val); } + void setMenuNextPin(uint8_t val) { u8g2_SetMenuNextPin(&u8g2, val); } + void setMenuUpPin(uint8_t val) { u8g2_SetMenuUpPin(&u8g2, val); } + void setMenuDownPin(uint8_t val) { u8g2_SetMenuDownPin(&u8g2, val); } + void setMenuHomePin(uint8_t val) { u8g2_SetMenuHomePin(&u8g2, val); } +#endif + + /* return 0 for no event or U8X8_MSG_GPIO_MENU_SELECT, */ + /* U8X8_MSG_GPIO_MENU_NEXT, U8X8_MSG_GPIO_MENU_PREV, */ + /* U8X8_MSG_GPIO_MENU_HOME */ + uint8_t getMenuEvent(void) { return u8x8_GetMenuEvent(u8g2_GetU8x8(&u8g2)); } + + void initDisplay(void) { u8g2_InitDisplay(&u8g2); } + + void clearDisplay(void) { u8g2_ClearDisplay(&u8g2); } + + void setPowerSave(uint8_t is_enable) { u8g2_SetPowerSave(&u8g2, is_enable); } + + void setFlipMode(uint8_t mode) { u8g2_SetFlipMode(&u8g2, mode); } + + void setContrast(uint8_t value) { u8g2_SetContrast(&u8g2, value); } + + void setDisplayRotation(const u8g2_cb_t *u8g2_cb) { + u8g2_SetDisplayRotation(&u8g2, u8g2_cb); + } + + bool begin(void) { + /* note: call to u8x8_utf8_init is not required here, this is done in the + * setup procedures before */ + initDisplay(); + clearDisplay(); + setPowerSave(0); + return 1; + } + + void beginSimple(void) { + /* does not clear the display and does not wake up the display */ + /* user is responsible for calling clearDisplay() and setPowerSave(0) */ + initDisplay(); + } + +#ifdef U8X8_USE_PINS + /* use U8X8_PIN_NONE if a pin is not required */ + bool begin(uint8_t menu_select_pin, uint8_t menu_next_pin, + uint8_t menu_prev_pin, uint8_t menu_up_pin = U8X8_PIN_NONE, + uint8_t menu_down_pin = U8X8_PIN_NONE, + uint8_t menu_home_pin = U8X8_PIN_NONE) { + setMenuSelectPin(menu_select_pin); + setMenuNextPin(menu_next_pin); + setMenuPrevPin(menu_prev_pin); + setMenuUpPin(menu_up_pin); + setMenuDownPin(menu_down_pin); + setMenuHomePin(menu_home_pin); + return begin(); + } +#endif + + /* u8g2 */ + +#ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT + void setMaxClipWindow(void) { u8g2_SetMaxClipWindow(&u8g2); } + void setClipWindow(u8g2_uint_t clip_x0, u8g2_uint_t clip_y0, + u8g2_uint_t clip_x1, u8g2_uint_t clip_y1) { + u8g2_SetClipWindow(&u8g2, clip_x0, clip_y0, clip_x1, clip_y1); + } +#endif /* U8G2_WITH_CLIP_WINDOW_SUPPORT */ + + u8g2_uint_t getDisplayHeight(void) { return u8g2_GetDisplayHeight(&u8g2); } + u8g2_uint_t getDisplayWidth(void) { return u8g2_GetDisplayWidth(&u8g2); } + + /* u8g2_buffer.c */ + void sendBuffer(void) { u8g2_SendBuffer(&u8g2); } + void clearBuffer(void) { u8g2_ClearBuffer(&u8g2); } + + void firstPage(void) { u8g2_FirstPage(&u8g2); } + uint8_t nextPage(void) { return u8g2_NextPage(&u8g2); } + + uint8_t *getBufferPtr(void) { return u8g2_GetBufferPtr(&u8g2); } + uint8_t getBufferTileHeight(void) { return u8g2_GetBufferTileHeight(&u8g2); } + uint8_t getBufferTileWidth(void) { return u8g2_GetBufferTileWidth(&u8g2); } + uint8_t getPageCurrTileRow(void) { + return u8g2_GetBufferCurrTileRow(&u8g2); + } // obsolete + void setPageCurrTileRow(uint8_t row) { + u8g2_SetBufferCurrTileRow(&u8g2, row); + } // obsolete + uint8_t getBufferCurrTileRow(void) { + return u8g2_GetBufferCurrTileRow(&u8g2); + } + void setBufferCurrTileRow(uint8_t row) { + u8g2_SetBufferCurrTileRow(&u8g2, row); + } + + // this should be renamed to setBufferAutoClear + void setAutoPageClear(uint8_t mode) { u8g2_SetAutoPageClear(&u8g2, mode); } + + /* u8g2_hvline.c */ + void setDrawColor(uint8_t color_index) { + u8g2_SetDrawColor(&u8g2, color_index); + } + uint8_t getDrawColor(void) { return u8g2_GetDrawColor(&u8g2); } + void drawPixel(u8g2_uint_t x, u8g2_uint_t y) { u8g2_DrawPixel(&u8g2, x, y); } + void drawHLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w) { + u8g2_DrawHLine(&u8g2, x, y, w); + } + void drawVLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t h) { + u8g2_DrawVLine(&u8g2, x, y, h); + } + void drawHVLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir) { + u8g2_DrawHVLine(&u8g2, x, y, len, dir); + } + + /* u8g2_box.c */ + void drawFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h) { + u8g2_DrawFrame(&u8g2, x, y, w, h); + } + void drawRFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, + u8g2_uint_t r) { + u8g2_DrawRFrame(&u8g2, x, y, w, h, r); + } + void drawBox(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h) { + u8g2_DrawBox(&u8g2, x, y, w, h); + } + void drawRBox(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, + u8g2_uint_t r) { + u8g2_DrawRBox(&u8g2, x, y, w, h, r); + } + + /* u8g2_circle.c */ + void drawCircle(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, + uint8_t opt = U8G2_DRAW_ALL) { + u8g2_DrawCircle(&u8g2, x0, y0, rad, opt); + } + void drawDisc(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, + uint8_t opt = U8G2_DRAW_ALL) { + u8g2_DrawDisc(&u8g2, x0, y0, rad, opt); + } + void drawEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, + u8g2_uint_t ry, uint8_t opt = U8G2_DRAW_ALL) { + u8g2_DrawEllipse(&u8g2, x0, y0, rx, ry, opt); + } + void drawFilledEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, + u8g2_uint_t ry, uint8_t opt = U8G2_DRAW_ALL) { + u8g2_DrawFilledEllipse(&u8g2, x0, y0, rx, ry, opt); + } + + /* u8g2_line.c */ + void drawLine(u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, + u8g2_uint_t y2) { + u8g2_DrawLine(&u8g2, x1, y1, x2, y2); + } + + /* u8g2_bitmap.c */ + void setBitmapMode(uint8_t is_transparent) { + u8g2_SetBitmapMode(&u8g2, is_transparent); + } + void drawBitmap(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t cnt, u8g2_uint_t h, + const uint8_t *bitmap) { + u8g2_DrawBitmap(&u8g2, x, y, cnt, h, bitmap); + } + void drawXBM(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, + const uint8_t *bitmap) { + u8g2_DrawXBM(&u8g2, x, y, w, h, bitmap); + } + void drawXBMP(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, + const uint8_t *bitmap) { + u8g2_DrawXBMP(&u8g2, x, y, w, h, bitmap); + } + + /* u8g2_polygon.c */ + void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, + int16_t y2) { + u8g2_DrawTriangle(&u8g2, x0, y0, x1, y1, x2, y2); + } + + /* u8log_u8g2.c */ + void drawLog(u8g2_uint_t x, u8g2_uint_t y, class U8G2LOG &u8g2log); + + /* u8g2_font.c */ + + void setFont(const uint8_t *font) { u8g2_SetFont(&u8g2, font); } + void setFontMode(uint8_t is_transparent) { + u8g2_SetFontMode(&u8g2, is_transparent); + } + void setFontDirection(uint8_t dir) { u8g2_SetFontDirection(&u8g2, dir); } + + int8_t getAscent(void) { return u8g2_GetAscent(&u8g2); } + int8_t getDescent(void) { return u8g2_GetDescent(&u8g2); } + + void setFontPosBaseline(void) { u8g2_SetFontPosBaseline(&u8g2); } + void setFontPosBottom(void) { u8g2_SetFontPosBottom(&u8g2); } + void setFontPosTop(void) { u8g2_SetFontPosTop(&u8g2); } + void setFontPosCenter(void) { u8g2_SetFontPosCenter(&u8g2); } + + void setFontRefHeightText(void) { u8g2_SetFontRefHeightText(&u8g2); } + void setFontRefHeightExtendedText(void) { + u8g2_SetFontRefHeightExtendedText(&u8g2); + } + void setFontRefHeightAll(void) { u8g2_SetFontRefHeightAll(&u8g2); } + + /* + uint8_t u8g2_IsGlyph(u8g2_t *u8g2, uint16_t requested_encoding); + int8_t u8g2_GetGlyphWidth(u8g2_t *u8g2, uint16_t requested_encoding); + u8g2_uint_t u8g2_GetStrWidth(u8g2_t *u8g2, const char *s); + u8g2_uint_t u8g2_GetUTF8Width(u8g2_t *u8g2, const char *str); + */ + + u8g2_uint_t drawGlyph(u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding) { + return u8g2_DrawGlyph(&u8g2, x, y, encoding); + } + u8g2_uint_t drawStr(u8g2_uint_t x, u8g2_uint_t y, const char *s) { + return u8g2_DrawStr(&u8g2, x, y, s); + } + u8g2_uint_t drawUTF8(u8g2_uint_t x, u8g2_uint_t y, const char *s) { + return u8g2_DrawUTF8(&u8g2, x, y, s); + } + u8g2_uint_t drawExtUTF8(u8g2_uint_t x, u8g2_uint_t y, uint8_t to_left, + const uint16_t *kerning_table, const char *s) { + return u8g2_DrawExtUTF8(&u8g2, x, y, to_left, kerning_table, s); + } + + u8g2_uint_t getStrWidth(const char *s) { return u8g2_GetStrWidth(&u8g2, s); } + u8g2_uint_t getUTF8Width(const char *s) { + return u8g2_GetUTF8Width(&u8g2, s); + } + + // not required any more, enable UTF8 for print + // void printUTF8(const char *s) { tx += u8g2_DrawUTF8(&u8g2, tx, ty, s); } + + /* virtual function for print base class */ + size_t write(uint8_t v) { + uint16_t e = cpp_next_cb(&(u8g2.u8x8), v); + + if (e < 0x0fffe) tx += u8g2_DrawGlyph(&u8g2, tx, ty, e); + return 1; + } + + size_t write(const uint8_t *buffer, size_t size) { + size_t cnt = 0; + while (size > 0) { + cnt += write(*buffer++); + size--; + } + return cnt; + } + + /* user interface */ + /* + uint8_t u8g2_UserInterfaceSelectionList(u8g2_t *u8g2, const char *title, + uint8_t start_pos, const char *sl); uint8_t u8g2_UserInterfaceMessage(u8g2_t + *u8g2, const char *title1, const char *title2, const char *title3, const char + *buttons); uint8_t u8g2_UserInterfaceInputValue(u8g2_t *u8g2, const char + *title, const char *pre, uint8_t *value, uint8_t lo, uint8_t hi, uint8_t + digits, const char *post); + */ + + uint8_t userInterfaceSelectionList(const char *title, uint8_t start_pos, + const char *sl) { + return u8g2_UserInterfaceSelectionList(&u8g2, title, start_pos, sl); + } + uint8_t userInterfaceMessage(const char *title1, const char *title2, + const char *title3, const char *buttons) { + return u8g2_UserInterfaceMessage(&u8g2, title1, title2, title3, buttons); + } + uint8_t userInterfaceInputValue(const char *title, const char *pre, + uint8_t *value, uint8_t lo, uint8_t hi, + uint8_t digits, const char *post) { + return u8g2_UserInterfaceInputValue(&u8g2, title, pre, value, lo, hi, + digits, post); + } + + /* LiquidCrystal compatible functions */ + void home(void) { + tx = 0; + ty = 0; + u8x8_utf8_init(u8g2_GetU8x8(&u8g2)); + } + void clear(void) { + home(); + clearDisplay(); + clearBuffer(); + } + void noDisplay(void) { u8g2_SetPowerSave(&u8g2, 1); } + void display(void) { u8g2_SetPowerSave(&u8g2, 0); } + void setCursor(u8g2_uint_t x, u8g2_uint_t y) { + tx = x; + ty = y; + } + + /* u8glib compatible functions */ + void sleepOn(void) { u8g2_SetPowerSave(&u8g2, 1); } + void sleepOff(void) { u8g2_SetPowerSave(&u8g2, 0); } + void setColorIndex(uint8_t color_index) { + u8g2_SetDrawColor(&u8g2, color_index); + } + uint8_t getColorIndex(void) { return u8g2_GetDrawColor(&u8g2); } + int8_t getFontAscent(void) { return u8g2_GetAscent(&u8g2); } + int8_t getFontDescent(void) { return u8g2_GetDescent(&u8g2); } + int8_t getMaxCharHeight(void) { return u8g2_GetMaxCharHeight(&u8g2); } + int8_t getMaxCharWidth(void) { return u8g2_GetMaxCharWidth(&u8g2); } + u8g2_uint_t getHeight() { return u8g2_GetDisplayHeight(&u8g2); } + u8g2_uint_t getWidth() { return u8g2_GetDisplayWidth(&u8g2); } +}; + +void u8x8_SetPin_HW_I2C(u8x8_t *u8x8, uint8_t reset, uint8_t clock, uint8_t data) +{ + u8x8_SetPin(u8x8, U8X8_PIN_RESET, reset); + u8x8_SetPin(u8x8, U8X8_PIN_I2C_CLOCK, clock); + u8x8_SetPin(u8x8, U8X8_PIN_I2C_DATA, data); +} + +class U8G2_SSD1306_128X64_NONAME_F_HW_I2C : public U8G2 { + public: U8G2_SSD1306_128X64_NONAME_F_HW_I2C(const u8g2_cb_t *rotation, uint8_t reset = U8X8_PIN_NONE, uint8_t clock = U8X8_PIN_NONE, uint8_t data = U8X8_PIN_NONE) : U8G2() { + u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, rotation, u8g2_esp32_i2c_byte_cb, u8g2_esp32_gpio_and_delay_cb); + u8x8_SetPin_HW_I2C(getU8x8(), reset, clock, data); + } +}; diff --git a/main/u8g2_esp32_hal.c b/main/u8g2_esp32_hal.c index e5111f8..52f7020 100644 --- a/main/u8g2_esp32_hal.c +++ b/main/u8g2_esp32_hal.c @@ -12,9 +12,8 @@ static const char * TAG = "u8g2_hal"; static const unsigned int I2C_TIMEOUT_MS = 100; -static spi_device_handle_t handle_spi; // SPI handle. -static i2c_cmd_handle_t handle_i2c; // I2C handle. -static u8g2_esp32_hal_t u8g2_esp32_hal; // HAL state data. +static spi_device_handle_t handle_spi; // SPI handle. +static i2c_cmd_handle_t handle_i2c; // I2C handle. #undef ESP_ERROR_CHECK #define ESP_ERROR_CHECK(x) \ @@ -27,13 +26,6 @@ static u8g2_esp32_hal_t u8g2_esp32_hal; // HAL state data. } \ } while (0); -/* - * Initialze the ESP32 HAL. - */ -void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param) { - u8g2_esp32_hal = u8g2_esp32_hal_param; -} // u8g2_esp32_hal_init - /* * HAL callback function as prescribed by the U8G2 library. This callback is * invoked to handle SPI communications. @@ -44,25 +36,25 @@ uint8_t u8g2_esp32_spi_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, msg, arg_int, arg_ptr); switch (msg) { case U8X8_MSG_BYTE_SET_DC: - if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { - gpio_set_level(u8g2_esp32_hal.dc, arg_int); + if (u8x8->pins[U8X8_PIN_DC] != U8X8_PIN_NONE) { + gpio_set_level(u8x8->pins[U8X8_PIN_DC], arg_int); } break; case U8X8_MSG_BYTE_INIT: { - if (u8g2_esp32_hal.clk == U8G2_ESP32_HAL_UNDEFINED || - u8g2_esp32_hal.mosi == U8G2_ESP32_HAL_UNDEFINED || - u8g2_esp32_hal.cs == U8G2_ESP32_HAL_UNDEFINED) { + if (u8x8->pins[U8X8_PIN_SPI_CLOCK] == U8X8_PIN_NONE || + u8x8->pins[U8X8_PIN_SPI_DATA] == U8X8_PIN_NONE || + u8x8->pins[U8X8_PIN_CS] == U8X8_PIN_NONE) { break; } spi_bus_config_t bus_config; memset(&bus_config, 0, sizeof(spi_bus_config_t)); - bus_config.sclk_io_num = u8g2_esp32_hal.clk; // CLK - bus_config.mosi_io_num = u8g2_esp32_hal.mosi; // MOSI - bus_config.miso_io_num = -1; // MISO - bus_config.quadwp_io_num = -1; // Not used - bus_config.quadhd_io_num = -1; // Not used + bus_config.sclk_io_num = u8x8->pins[U8X8_PIN_SPI_CLOCK]; // CLK + bus_config.mosi_io_num = u8x8->pins[U8X8_PIN_SPI_DATA]; // MOSI + bus_config.miso_io_num = -1; // MISO + bus_config.quadwp_io_num = -1; // Not used + bus_config.quadhd_io_num = -1; // Not used // ESP_LOGI(TAG, "... Initializing bus."); ESP_ERROR_CHECK(spi_bus_initialize(HSPI_HOST, &bus_config, 1)); @@ -75,7 +67,7 @@ uint8_t u8g2_esp32_spi_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, dev_config.cs_ena_posttrans = 0; dev_config.cs_ena_pretrans = 0; dev_config.clock_speed_hz = 10000; - dev_config.spics_io_num = u8g2_esp32_hal.cs; + dev_config.spics_io_num = u8x8->pins[U8X8_PIN_CS]; dev_config.flags = 0; dev_config.queue_size = 200; dev_config.pre_cb = NULL; @@ -117,23 +109,24 @@ uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, // arg_int, arg_ptr); switch (msg) { case U8X8_MSG_BYTE_SET_DC: { - if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { - gpio_set_level(u8g2_esp32_hal.dc, arg_int); + if (u8x8->pins[U8X8_PIN_DC] != U8X8_PIN_NONE) { + gpio_set_level(u8x8->pins[U8X8_PIN_DC], arg_int); } break; } case U8X8_MSG_BYTE_INIT: { - if (u8g2_esp32_hal.sda == U8G2_ESP32_HAL_UNDEFINED || - u8g2_esp32_hal.scl == U8G2_ESP32_HAL_UNDEFINED) { + if (u8x8->pins[U8X8_PIN_I2C_DATA] == U8X8_PIN_NONE || + u8x8->pins[U8X8_PIN_I2C_CLOCK] == U8X8_PIN_NONE) { + ESP_LOGE(TAG, "i2c_byte_cb: missing pins"); break; } i2c_config_t conf; conf.mode = I2C_MODE_MASTER; - conf.sda_io_num = u8g2_esp32_hal.sda; + conf.sda_io_num = u8x8->pins[U8X8_PIN_I2C_DATA]; conf.sda_pullup_en = GPIO_PULLUP_ENABLE; - conf.scl_io_num = u8g2_esp32_hal.scl; + conf.scl_io_num = u8x8->pins[U8X8_PIN_I2C_CLOCK]; conf.scl_pullup_en = GPIO_PULLUP_ENABLE; ESP_LOGV(TAG, "clk_speed %d", I2C_MASTER_FREQ_HZ); conf.master.clk_speed = I2C_MASTER_FREQ_HZ; @@ -142,6 +135,8 @@ uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, I2C_MASTER_NUM, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1)); + ESP_LOGI(TAG, "i2c_byte_cb: BYTE_INIT sda_io_num: %d, scl_io_num: %d", + conf.sda_io_num, conf.scl_io_num); break; } @@ -182,7 +177,12 @@ uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, i2c_cmd_link_delete(handle_i2c); break; } - default: return 0; + default: + ESP_LOGW(TAG, + "i2c_byte_cb: Received an unimplemented msg: %d, arg_int: " + "%d, arg_ptr: %p", + msg, arg_int, arg_ptr); + return 0; } return 1; } // u8g2_esp32_i2c_byte_cb @@ -202,15 +202,20 @@ uint8_t u8g2_esp32_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, // RESET have been specified then we define those pins as GPIO outputs. case U8X8_MSG_GPIO_AND_DELAY_INIT: { uint64_t bitmask = 0; - if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { - bitmask = bitmask | (1ull << u8g2_esp32_hal.dc); + uint8_t dc = u8x8->pins[U8X8_PIN_DC]; + uint8_t reset = u8x8->pins[U8X8_PIN_RESET]; + uint8_t cs = u8x8->pins[U8X8_PIN_CS]; + if (dc != U8X8_PIN_NONE) { + bitmask = bitmask | (1ull << dc); } - if (u8g2_esp32_hal.reset != U8G2_ESP32_HAL_UNDEFINED) { - bitmask = bitmask | (1ull << u8g2_esp32_hal.reset); + if (reset != U8X8_PIN_NONE) { + bitmask = bitmask | (1ull << reset); } - if (u8g2_esp32_hal.cs != U8G2_ESP32_HAL_UNDEFINED) { - bitmask = bitmask | (1ull << u8g2_esp32_hal.cs); + if (cs != U8X8_PIN_NONE) { + bitmask = bitmask | (1ull << cs); } + ESP_LOGI(TAG, "GPIO_AND_DELAY_INIT: dc=%d, reset=%d, cs=%d", dc, reset, + cs); if (bitmask == 0) { break; @@ -227,34 +232,39 @@ uint8_t u8g2_esp32_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, // Set the GPIO reset pin to the value passed in through arg_int. case U8X8_MSG_GPIO_RESET: - if (u8g2_esp32_hal.reset != U8G2_ESP32_HAL_UNDEFINED) { - gpio_set_level(u8g2_esp32_hal.reset, arg_int); + if (u8x8->pins[U8X8_PIN_RESET] != U8X8_PIN_NONE) { + gpio_set_level(u8x8->pins[U8X8_PIN_RESET], arg_int); } break; // Set the GPIO client select pin to the value passed in through arg_int. case U8X8_MSG_GPIO_CS: - if (u8g2_esp32_hal.cs != U8G2_ESP32_HAL_UNDEFINED) { - gpio_set_level(u8g2_esp32_hal.cs, arg_int); + if (u8x8->pins[U8X8_PIN_CS] != U8X8_PIN_NONE) { + gpio_set_level(u8x8->pins[U8X8_PIN_CS], arg_int); } break; // Set the Software I²C pin to the value passed in through arg_int. case U8X8_MSG_GPIO_I2C_CLOCK: - if (u8g2_esp32_hal.scl != U8G2_ESP32_HAL_UNDEFINED) { - gpio_set_level(u8g2_esp32_hal.scl, arg_int); + if (u8x8->pins[U8X8_PIN_I2C_CLOCK] != U8X8_PIN_NONE) { + gpio_set_level(u8x8->pins[U8X8_PIN_I2C_CLOCK], arg_int); // printf("%c",(arg_int==1?'C':'c')); } break; // Set the Software I²C pin to the value passed in through arg_int. case U8X8_MSG_GPIO_I2C_DATA: - if (u8g2_esp32_hal.sda != U8G2_ESP32_HAL_UNDEFINED) { - gpio_set_level(u8g2_esp32_hal.sda, arg_int); + if (u8x8->pins[U8X8_PIN_I2C_DATA] != U8X8_PIN_NONE) { + gpio_set_level(u8x8->pins[U8X8_PIN_I2C_DATA], arg_int); // printf("%c",(arg_int==1?'D':'d')); } break; // Delay for the number of milliseconds passed in through arg_int. case U8X8_MSG_DELAY_MILLI: vTaskDelay(arg_int / portTICK_PERIOD_MS); break; - default: return 0; + default: + ESP_LOGW(TAG, + "gpio_and_delay_cb: Received an unimplemented msg: %d, arg_int: " + "%d, arg_ptr: %p", + msg, arg_int, arg_ptr); + return 0; } return 1; } // u8g2_esp32_gpio_and_delay_cb \ No newline at end of file diff --git a/main/u8g2_esp32_hal.h b/main/u8g2_esp32_hal.h index 77dea40..dc23eaf 100644 --- a/main/u8g2_esp32_hal.h +++ b/main/u8g2_esp32_hal.h @@ -7,14 +7,17 @@ #ifndef U8G2_ESP32_HAL_H_ #define U8G2_ESP32_HAL_H_ + +#if __cplusplus +extern "C" { +#endif + #include "u8g2.h" #include "driver/gpio.h" #include "driver/i2c.h" #include "driver/spi_master.h" -#define U8G2_ESP32_HAL_UNDEFINED (-1) - #define I2C_MASTER_NUM I2C_NUM_1 // I2C port number for master dev #define I2C_MASTER_TX_BUF_DISABLE 0 // I2C master do not need buffer #define I2C_MASTER_RX_BUF_DISABLE 0 // I2C master do not need buffer @@ -22,29 +25,15 @@ #define ACK_CHECK_EN 0x1 // I2C master will check ack from slave #define ACK_CHECK_DIS 0x0 // I2C master will not check ack from slave -typedef struct { - gpio_num_t clk; - gpio_num_t mosi; - gpio_num_t sda; // data for I²C - gpio_num_t scl; // clock for I²C - gpio_num_t cs; - gpio_num_t reset; - gpio_num_t dc; -} u8g2_esp32_hal_t; - -#define U8G2_ESP32_HAL_DEFAULT \ - { \ - U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, \ - U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, \ - U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, \ - U8G2_ESP32_HAL_UNDEFINED \ - } - -void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param); uint8_t u8g2_esp32_spi_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8g2_esp32_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); + +#if __cplusplus +} +#endif + #endif /* U8G2_ESP32_HAL_H_ */ \ No newline at end of file diff --git a/main/ugv_comms.h b/main/ugv_comms.h index 940d434..7a68294 100644 --- a/main/ugv_comms.h +++ b/main/ugv_comms.h @@ -7,6 +7,10 @@ #include "messages.pb.h" #include "sx127x_driver.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct ugv_comms_state_s { sx127x_hndl lora; TaskHandle_t task_handle; @@ -22,3 +26,7 @@ typedef struct ugv_comms_state_s { ugv_comms_state_t ugv_comms_state; void ugv_comms_init(); + +#ifdef __cplusplus +} +#endif diff --git a/main/ugv_main.c b/main/ugv_main.cc similarity index 81% rename from main/ugv_main.c rename to main/ugv_main.cc index f185324..4a53ef0 100644 --- a/main/ugv_main.c +++ b/main/ugv_main.cc @@ -1,4 +1,3 @@ -#define U8X8_USE_PINS #include #include #include @@ -9,24 +8,17 @@ #include "u8g2_esp32_hal.h" #include "ugv_comms.h" #include "ugv_config.h" +#include "U8g2lib.hh" static const char *TAG = "ugv_main"; -u8g2_t u8g2; +U8G2 *oled; void setup_oled(void) { - u8g2_esp32_hal_t u8g2_hal_config = { - .scl = 15, - .sda = 4, - .reset = 16, - }; - u8g2_esp32_hal_init(u8g2_hal_config); - - u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb, - u8g2_esp32_gpio_and_delay_cb); - u8g2_InitDisplay(&u8g2); - u8g2_ClearDisplay(&u8g2); - u8g2_SetPowerSave(&u8g2, false); + oled = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R0, 16, 15, 4); + oled->initDisplay(); + oled->clearDisplay(); + oled->setPowerSave(false); } const size_t GPS_BUF_SIZE = 1024; @@ -38,7 +30,7 @@ const char NMEA_Q_RELEASE[] = "$PMTK605*31\r\n"; static void gps_task(void *arg) { ESP_LOGI(TAG, "gps_task start"); - uint8_t * data = malloc(GPS_BUF_SIZE); + uint8_t * data = (uint8_t*) malloc(GPS_BUF_SIZE); size_t read_bytes; esp_err_t ret; uart_write_bytes(GPS_UART, NMEA_OUTPUT_RMCGGA, sizeof(NMEA_OUTPUT_RMCGGA)); @@ -105,7 +97,7 @@ void loop(void) { static char buf[BUF_SZ]; - u8g2_FirstPage(&u8g2); + oled->firstPage(); sx127x_read_rssi(ugv_comms_state.lora, &lora_rssi); sx127x_read_lna_gain(ugv_comms_state.lora, &lora_lna_gain); @@ -115,32 +107,32 @@ void loop(void) { last_packet_snr = ugv_comms_state.last_packet_snr; xSemaphoreGive(ugv_comms_state.mutex); do { - u8g2_DrawRFrame(&u8g2, 0, 0, OLED_W, OLED_H, 4); + oled->drawRFrame(0, 0, OLED_W, OLED_H, 4); multi_heap_info_t heap_info; heap_caps_get_info(&heap_info, MALLOC_CAP_DEFAULT); - u8g2_SetFont(&u8g2, u8g2_font_4x6_mr); - u8g2_DrawStr(&u8g2, 4, 8, "=====UAS UGV====="); + oled->setFont(u8g2_font_4x6_mr); + oled->drawStr(4, 8, "=====UAS UGV====="); snprintf(buf, BUF_SZ, "heap allc/free %d/%d", heap_info.total_allocated_bytes, heap_info.total_free_bytes); - u8g2_DrawStr(&u8g2, 4, 2 * 8, buf); + oled->drawStr(4, 2 * 8, buf); snprintf(buf, BUF_SZ, "rssi: %d lna gain: %d", lora_rssi, lora_lna_gain); - u8g2_DrawStr(&u8g2, 4, 3 * 8, buf); + oled->drawStr(4, 3 * 8, buf); if (last_packet_tick > 0) { double time_since_last_packet = 1000.0f / ((xTaskGetTickCount() - last_packet_tick) * portTICK_RATE_MS); snprintf(buf, BUF_SZ, "last pkt rx %f s ago", time_since_last_packet); - u8g2_DrawStr(&u8g2, 4, 4 * 8, buf); + oled->drawStr(4, 4 * 8, buf); snprintf(buf, BUF_SZ, "pkt rssi: %d, snr: %f", last_packet_rssi, last_packet_snr * 0.25f); - u8g2_DrawStr(&u8g2, 4, 5 * 8, buf); + oled->drawStr(4, 5 * 8, buf); } else { - u8g2_DrawStr(&u8g2, 4, 4 * 8, "no pkt rx"); + oled->drawStr(4, 4 * 8, "no pkt rx"); } - } while (u8g2_NextPage(&u8g2)); + } while (oled->nextPage()); vTaskDelay(pdMS_TO_TICKS(1000)); } @@ -151,6 +143,6 @@ void loopTask(void *pvUser) { } } -void app_main() { +extern "C" void app_main() { xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1); }