mirror of https://github.com/meshcore-dev/MeshCore
71 changed files with 3970 additions and 250 deletions
@ -0,0 +1,22 @@ |
|||
#ifndef NODE_PREFS_H |
|||
#define NODE_PREFS_H |
|||
|
|||
#include <cstdint> // For uint8_t, uint32_t |
|||
|
|||
struct NodePrefs { // persisted to file
|
|||
float airtime_factor; |
|||
char node_name[32]; |
|||
double node_lat, node_lon; |
|||
float freq; |
|||
uint8_t sf; |
|||
uint8_t cr; |
|||
uint8_t reserved1; |
|||
uint8_t manual_add_contacts; |
|||
float bw; |
|||
uint8_t tx_power_dbm; |
|||
uint8_t unused[3]; |
|||
float rx_delay_base; |
|||
uint32_t ble_pin; |
|||
}; |
|||
|
|||
#endif // NODE_PREFS_H
|
|||
@ -1,18 +1,19 @@ |
|||
#pragma once |
|||
|
|||
#include <helpers/ui/DisplayDriver.h> |
|||
#include <helpers/CommonCLI.h> |
|||
|
|||
class UITask { |
|||
DisplayDriver* _display; |
|||
unsigned long _next_read, _next_refresh, _auto_off; |
|||
int _prevBtnState; |
|||
const char* _node_name; |
|||
NodePrefs* _node_prefs; |
|||
char _version_info[32]; |
|||
|
|||
void renderCurrScreen(); |
|||
public: |
|||
UITask(DisplayDriver& display) : _display(&display) { _next_read = _next_refresh = 0; } |
|||
void begin(const char* node_name, const char* build_date, const char* firmware_version); |
|||
void begin(NodePrefs* node_prefs, const char* build_date, const char* firmware_version); |
|||
|
|||
void loop(); |
|||
}; |
|||
@ -1,18 +1,19 @@ |
|||
#pragma once |
|||
|
|||
#include <helpers/ui/DisplayDriver.h> |
|||
#include <helpers/CommonCLI.h> |
|||
|
|||
class UITask { |
|||
DisplayDriver* _display; |
|||
unsigned long _next_read, _next_refresh, _auto_off; |
|||
int _prevBtnState; |
|||
const char* _node_name; |
|||
NodePrefs* _node_prefs; |
|||
char _version_info[32]; |
|||
|
|||
void renderCurrScreen(); |
|||
public: |
|||
UITask(DisplayDriver& display) : _display(&display) { _next_read = _next_refresh = 0; } |
|||
void begin(const char* node_name, const char* build_date, const char* firmware_version); |
|||
void begin(NodePrefs* node_prefs, const char* build_date, const char* firmware_version); |
|||
|
|||
void loop(); |
|||
}; |
|||
@ -0,0 +1,14 @@ |
|||
#pragma once |
|||
|
|||
#include <CayenneLPP.h> |
|||
|
|||
#define TELEM_PERM_LOCATION 0x02 |
|||
|
|||
#define TELEM_CHANNEL_SELF 1 // LPP data channel for 'self' device
|
|||
|
|||
class SensorManager { |
|||
public: |
|||
virtual bool begin() { return false; } |
|||
virtual bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { return false; } |
|||
virtual void loop() { } |
|||
}; |
|||
File diff suppressed because it is too large
@ -0,0 +1,395 @@ |
|||
/**
|
|||
* The MIT License (MIT) |
|||
* |
|||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn |
|||
* Copyright (c) 2018 by Fabrice Weinberg |
|||
* Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in all |
|||
* copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
* SOFTWARE. |
|||
* |
|||
* ThingPulse invests considerable time and money to develop these open source libraries. |
|||
* Please support us by buying our products (and not the clones) from |
|||
* https://thingpulse.com
|
|||
* |
|||
*/ |
|||
|
|||
#ifndef OLEDDISPLAY_h |
|||
#define OLEDDISPLAY_h |
|||
|
|||
#include <cstdarg> |
|||
|
|||
#ifdef ARDUINO |
|||
#include <Arduino.h> |
|||
#elif __MBED__ |
|||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) |
|||
|
|||
#include <mbed.h> |
|||
#define delay(x) wait_ms(x) |
|||
#define yield() void() |
|||
|
|||
/*
|
|||
* This is a little Arduino String emulation to keep the OLEDDisplay |
|||
* library code in common between Arduino and mbed-os |
|||
*/ |
|||
class String { |
|||
public: |
|||
String(const char *s) { _str = s; }; |
|||
int length() { return strlen(_str); }; |
|||
const char *c_str() { return _str; }; |
|||
void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const { |
|||
memcpy(buf, _str + index, std::min(bufsize, strlen(_str))); |
|||
}; |
|||
private: |
|||
const char *_str; |
|||
}; |
|||
|
|||
#else |
|||
#error "Unkown operating system" |
|||
#endif |
|||
|
|||
#include "OLEDDisplayFonts.h" |
|||
|
|||
//#define DEBUG_OLEDDISPLAY(...) Serial.printf( __VA_ARGS__ )
|
|||
//#define DEBUG_OLEDDISPLAY(...) dprintf("%s", __VA_ARGS__ )
|
|||
|
|||
#ifndef DEBUG_OLEDDISPLAY |
|||
#define DEBUG_OLEDDISPLAY(...) |
|||
#endif |
|||
|
|||
// Use DOUBLE BUFFERING by default
|
|||
#ifndef OLEDDISPLAY_REDUCE_MEMORY |
|||
#define OLEDDISPLAY_DOUBLE_BUFFER |
|||
#endif |
|||
|
|||
// Header Values
|
|||
#define JUMPTABLE_BYTES 4 |
|||
|
|||
#define JUMPTABLE_LSB 1 |
|||
#define JUMPTABLE_SIZE 2 |
|||
#define JUMPTABLE_WIDTH 3 |
|||
#define JUMPTABLE_START 4 |
|||
|
|||
#define WIDTH_POS 0 |
|||
#define HEIGHT_POS 1 |
|||
#define FIRST_CHAR_POS 2 |
|||
#define CHAR_NUM_POS 3 |
|||
|
|||
|
|||
// Display commands
|
|||
#define CHARGEPUMP 0x8D |
|||
#define COLUMNADDR 0x21 |
|||
#define COMSCANDEC 0xC8 |
|||
#define COMSCANINC 0xC0 |
|||
#define DISPLAYALLON 0xA5 |
|||
#define DISPLAYALLON_RESUME 0xA4 |
|||
#define DISPLAYOFF 0xAE |
|||
#define DISPLAYON 0xAF |
|||
#define EXTERNALVCC 0x1 |
|||
#define INVERTDISPLAY 0xA7 |
|||
#define MEMORYMODE 0x20 |
|||
#define NORMALDISPLAY 0xA6 |
|||
#define PAGEADDR 0x22 |
|||
#define SEGREMAP 0xA0 |
|||
#define SETCOMPINS 0xDA |
|||
#define SETCONTRAST 0x81 |
|||
#define SETDISPLAYCLOCKDIV 0xD5 |
|||
#define SETDISPLAYOFFSET 0xD3 |
|||
#define SETHIGHCOLUMN 0x10 |
|||
#define SETLOWCOLUMN 0x00 |
|||
#define SETMULTIPLEX 0xA8 |
|||
#define SETPRECHARGE 0xD9 |
|||
#define SETSEGMENTREMAP 0xA1 |
|||
#define SETSTARTLINE 0x40 |
|||
#define SETVCOMDETECT 0xDB |
|||
#define SWITCHCAPVCC 0x2 |
|||
|
|||
#ifndef _swap_int16_t |
|||
#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } |
|||
#endif |
|||
|
|||
enum OLEDDISPLAY_COLOR { |
|||
BLACK = 0, |
|||
WHITE = 1, |
|||
INVERSE = 2 |
|||
}; |
|||
|
|||
enum OLEDDISPLAY_TEXT_ALIGNMENT { |
|||
TEXT_ALIGN_LEFT = 0, |
|||
TEXT_ALIGN_RIGHT = 1, |
|||
TEXT_ALIGN_CENTER = 2, |
|||
TEXT_ALIGN_CENTER_BOTH = 3 |
|||
}; |
|||
|
|||
|
|||
enum OLEDDISPLAY_GEOMETRY { |
|||
GEOMETRY_128_64 = 0, |
|||
GEOMETRY_128_32 = 1, |
|||
GEOMETRY_64_48 = 2, |
|||
GEOMETRY_64_32 = 3, |
|||
GEOMETRY_RAWMODE = 4, |
|||
GEOMETRY_128_128 = 5 |
|||
}; |
|||
|
|||
enum HW_I2C { |
|||
I2C_ONE, |
|||
I2C_TWO |
|||
}; |
|||
|
|||
typedef char (*FontTableLookupFunction)(const uint8_t ch); |
|||
char DefaultFontTableLookup(const uint8_t ch); |
|||
|
|||
|
|||
#ifdef ARDUINO |
|||
class OLEDDisplay : public Print { |
|||
#elif __MBED__ |
|||
class OLEDDisplay : public Stream { |
|||
#else |
|||
#error "Unkown operating system" |
|||
#endif |
|||
|
|||
public: |
|||
OLEDDisplay(); |
|||
virtual ~OLEDDisplay(); |
|||
|
|||
uint16_t width(void) const { return displayWidth; }; |
|||
uint16_t height(void) const { return displayHeight; }; |
|||
|
|||
// Use this to resume after a deep sleep without resetting the display (what init() would do).
|
|||
// Returns true if connection to the display was established and the buffer allocated, false otherwise.
|
|||
bool allocateBuffer(); |
|||
|
|||
// Allocates the buffer and initializes the driver & display. Resets the display!
|
|||
// Returns false if buffer allocation failed, true otherwise.
|
|||
bool init(); |
|||
|
|||
// Free the memory used by the display
|
|||
void end(); |
|||
|
|||
// Cycle through the initialization
|
|||
void resetDisplay(void); |
|||
|
|||
/* Drawing functions */ |
|||
// Sets the color of all pixel operations
|
|||
void setColor(OLEDDISPLAY_COLOR color); |
|||
|
|||
// Returns the current color.
|
|||
OLEDDISPLAY_COLOR getColor(); |
|||
|
|||
// Draw a pixel at given position
|
|||
void setPixel(int16_t x, int16_t y); |
|||
|
|||
// Draw a pixel at given position and color
|
|||
void setPixelColor(int16_t x, int16_t y, OLEDDISPLAY_COLOR color); |
|||
|
|||
// Clear a pixel at given position FIXME: INVERSE is untested with this function
|
|||
void clearPixel(int16_t x, int16_t y); |
|||
|
|||
// Draw a line from position 0 to position 1
|
|||
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); |
|||
|
|||
// Draw the border of a rectangle at the given location
|
|||
void drawRect(int16_t x, int16_t y, int16_t width, int16_t height); |
|||
|
|||
// Fill the rectangle
|
|||
void fillRect(int16_t x, int16_t y, int16_t width, int16_t height); |
|||
|
|||
// Draw the border of a circle
|
|||
void drawCircle(int16_t x, int16_t y, int16_t radius); |
|||
|
|||
// Draw all Quadrants specified in the quads bit mask
|
|||
void drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads); |
|||
|
|||
// Fill circle
|
|||
void fillCircle(int16_t x, int16_t y, int16_t radius); |
|||
|
|||
// Draw an empty triangle i.e. only the outline
|
|||
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); |
|||
|
|||
// Draw a solid triangle i.e. filled
|
|||
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); |
|||
|
|||
// Draw a line horizontally
|
|||
void drawHorizontalLine(int16_t x, int16_t y, int16_t length); |
|||
|
|||
// Draw a line vertically
|
|||
void drawVerticalLine(int16_t x, int16_t y, int16_t length); |
|||
|
|||
// Draws a rounded progress bar with the outer dimensions given by width and height. Progress is
|
|||
// a unsigned byte value between 0 and 100
|
|||
void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress); |
|||
|
|||
// Draw a bitmap in the internal image format
|
|||
void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *image); |
|||
|
|||
// Draw a XBM
|
|||
void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *xbm); |
|||
|
|||
// Draw icon 16x16 xbm format
|
|||
void drawIco16x16(int16_t x, int16_t y, const uint8_t *ico, bool inverse = false); |
|||
|
|||
/* Text functions */ |
|||
|
|||
// Draws a string at the given location, returns how many chars have been written
|
|||
uint16_t drawString(int16_t x, int16_t y, const String &text); |
|||
|
|||
// Draws a formatted string (like printf) at the given location
|
|||
void drawStringf(int16_t x, int16_t y, char* buffer, String format, ... ); |
|||
|
|||
// Draws a String with a maximum width at the given location.
|
|||
// If the given String is wider than the specified width
|
|||
// The text will be wrapped to the next line at a space or dash
|
|||
// returns 0 if everything fits on the screen or the numbers of characters in the
|
|||
// first line if not
|
|||
uint16_t drawStringMaxWidth(int16_t x, int16_t y, uint16_t maxLineWidth, const String &text); |
|||
|
|||
// Returns the width of the const char* with the current
|
|||
// font settings
|
|||
uint16_t getStringWidth(const char* text, uint16_t length, bool utf8 = false); |
|||
|
|||
// Convencience method for the const char version
|
|||
uint16_t getStringWidth(const String &text); |
|||
|
|||
// Specifies relative to which anchor point
|
|||
// the text is rendered. Available constants:
|
|||
// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH
|
|||
void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment); |
|||
|
|||
// Sets the current font. Available default fonts
|
|||
// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24
|
|||
void setFont(const uint8_t *fontData); |
|||
|
|||
// Set the function that will convert utf-8 to font table index
|
|||
void setFontTableLookupFunction(FontTableLookupFunction function); |
|||
|
|||
/* Display functions */ |
|||
|
|||
// Turn the display on
|
|||
void displayOn(void); |
|||
|
|||
// Turn the display offs
|
|||
void displayOff(void); |
|||
|
|||
// Inverted display mode
|
|||
void invertDisplay(void); |
|||
|
|||
// Normal display mode
|
|||
void normalDisplay(void); |
|||
|
|||
// Set display contrast
|
|||
// really low brightness & contrast: contrast = 10, precharge = 5, comdetect = 0
|
|||
// normal brightness & contrast: contrast = 100
|
|||
void setContrast(uint8_t contrast, uint8_t precharge = 241, uint8_t comdetect = 64); |
|||
|
|||
// Convenience method to access
|
|||
virtual void setBrightness(uint8_t); |
|||
|
|||
// Reset display rotation or mirroring
|
|||
void resetOrientation(); |
|||
|
|||
// Turn the display upside down
|
|||
void flipScreenVertically(); |
|||
|
|||
// Mirror the display (to be used in a mirror or as a projector)
|
|||
void mirrorScreen(); |
|||
|
|||
// Write the buffer to the display memory
|
|||
virtual void display(void) = 0; |
|||
|
|||
// Clear the local pixel buffer
|
|||
void clear(void); |
|||
|
|||
// Log buffer implementation
|
|||
|
|||
// This will define the lines and characters you can
|
|||
// print to the screen. When you exeed the buffer size (lines * chars)
|
|||
// the output may be truncated due to the size constraint.
|
|||
bool setLogBuffer(uint16_t lines, uint16_t chars); |
|||
|
|||
// Draw the log buffer at position (x, y)
|
|||
void drawLogBuffer(uint16_t x, uint16_t y); |
|||
|
|||
// Get screen geometry
|
|||
uint16_t getWidth(void); |
|||
uint16_t getHeight(void); |
|||
|
|||
// Implement needed function to be compatible with Print class
|
|||
size_t write(uint8_t c); |
|||
size_t write(const char* s); |
|||
|
|||
// Implement needed function to be compatible with Stream class
|
|||
#ifdef __MBED__ |
|||
int _putc(int c); |
|||
int _getc() { return -1; }; |
|||
#endif |
|||
|
|||
|
|||
uint8_t *buffer; |
|||
|
|||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER |
|||
uint8_t *buffer_back; |
|||
#endif |
|||
|
|||
// Set the correct height, width and buffer for the geometry
|
|||
void setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width = 0, uint16_t height = 0); |
|||
|
|||
protected: |
|||
|
|||
OLEDDISPLAY_GEOMETRY geometry; |
|||
|
|||
uint16_t displayWidth; |
|||
uint16_t displayHeight; |
|||
uint16_t displayBufferSize; |
|||
|
|||
OLEDDISPLAY_TEXT_ALIGNMENT textAlignment; |
|||
OLEDDISPLAY_COLOR color; |
|||
|
|||
const uint8_t *fontData; |
|||
|
|||
// State values for logBuffer
|
|||
uint16_t logBufferSize; |
|||
uint16_t logBufferFilled; |
|||
uint16_t logBufferLine; |
|||
uint16_t logBufferMaxLines; |
|||
char *logBuffer; |
|||
|
|||
|
|||
// the header size of the buffer used, e.g. for the SPI command header
|
|||
int BufferOffset; |
|||
virtual int getBufferOffset(void) = 0; |
|||
|
|||
// Send a command to the display (low level function)
|
|||
virtual void sendCommand(uint8_t com) {(void)com;}; |
|||
|
|||
// Connect to the display
|
|||
virtual bool connect() { return false; }; |
|||
|
|||
// Send all the init commands
|
|||
virtual void sendInitCommands(); |
|||
|
|||
// converts utf8 characters to extended ascii
|
|||
char* utf8ascii(const String &s); |
|||
|
|||
void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline)); |
|||
|
|||
uint16_t drawStringInternal(int16_t xMove, int16_t yMove, const char* text, uint16_t textLength, uint16_t textWidth, bool utf8); |
|||
|
|||
FontTableLookupFunction fontTableLookupFunction; |
|||
}; |
|||
|
|||
#endif |
|||
File diff suppressed because it is too large
@ -0,0 +1,13 @@ |
|||
#ifndef OLEDDISPLAYFONTS_h |
|||
#define OLEDDISPLAYFONTS_h |
|||
|
|||
#ifdef ARDUINO |
|||
#include <Arduino.h> |
|||
#elif __MBED__ |
|||
#define PROGMEM |
|||
#endif |
|||
|
|||
extern const uint8_t ArialMT_Plain_10[] PROGMEM; |
|||
extern const uint8_t ArialMT_Plain_16[] PROGMEM; |
|||
extern const uint8_t ArialMT_Plain_24[] PROGMEM; |
|||
#endif |
|||
@ -0,0 +1,461 @@ |
|||
/**
|
|||
* The MIT License (MIT) |
|||
* |
|||
* Copyright (c) 2018 by ThingPulse, Daniel Eichhorn |
|||
* Copyright (c) 2018 by Fabrice Weinberg |
|||
* Copyright (c) 2024 by Heltec AutoMation |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in all |
|||
* copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
* SOFTWARE. |
|||
* |
|||
* ThingPulse invests considerable time and money to develop these open source libraries. |
|||
* Please support us by buying our products (and not the clones) from |
|||
* https://thingpulse.com
|
|||
* |
|||
*/ |
|||
|
|||
#ifndef ST7789Spi_h |
|||
#define ST7789Spi_h |
|||
|
|||
#include "OLEDDisplay.h" |
|||
#include <SPI.h> |
|||
|
|||
|
|||
#define ST_CMD_DELAY 0x80 // special signifier for command lists
|
|||
|
|||
#define ST77XX_NOP 0x00 |
|||
#define ST77XX_SWRESET 0x01 |
|||
#define ST77XX_RDDID 0x04 |
|||
#define ST77XX_RDDST 0x09 |
|||
|
|||
#define ST77XX_SLPIN 0x10 |
|||
#define ST77XX_SLPOUT 0x11 |
|||
#define ST77XX_PTLON 0x12 |
|||
#define ST77XX_NORON 0x13 |
|||
|
|||
#define ST77XX_INVOFF 0x20 |
|||
#define ST77XX_INVON 0x21 |
|||
#define ST77XX_DISPOFF 0x28 |
|||
#define ST77XX_DISPON 0x29 |
|||
#define ST77XX_CASET 0x2A |
|||
#define ST77XX_RASET 0x2B |
|||
#define ST77XX_RAMWR 0x2C |
|||
#define ST77XX_RAMRD 0x2E |
|||
|
|||
#define ST77XX_PTLAR 0x30 |
|||
#define ST77XX_TEOFF 0x34 |
|||
#define ST77XX_TEON 0x35 |
|||
#define ST77XX_MADCTL 0x36 |
|||
#define ST77XX_COLMOD 0x3A |
|||
|
|||
#define ST77XX_MADCTL_MY 0x80 |
|||
#define ST77XX_MADCTL_MX 0x40 |
|||
#define ST77XX_MADCTL_MV 0x20 |
|||
#define ST77XX_MADCTL_ML 0x10 |
|||
#define ST77XX_MADCTL_RGB 0x00 |
|||
|
|||
#define ST77XX_RDID1 0xDA |
|||
#define ST77XX_RDID2 0xDB |
|||
#define ST77XX_RDID3 0xDC |
|||
#define ST77XX_RDID4 0xDD |
|||
|
|||
// Some ready-made 16-bit ('565') color settings:
|
|||
#define ST77XX_BLACK 0x0000 |
|||
#define ST77XX_WHITE 0xFFFF |
|||
#define ST77XX_RED 0xF800 |
|||
#define ST77XX_GREEN 0x07E0 |
|||
#define ST77XX_BLUE 0x001F |
|||
#define ST77XX_CYAN 0x07FF |
|||
#define ST77XX_MAGENTA 0xF81F |
|||
#define ST77XX_YELLOW 0xFFE0 |
|||
#define ST77XX_ORANGE 0xFC00 |
|||
|
|||
#define LED_A_ON LOW |
|||
|
|||
#ifdef ESP_PLATFORM |
|||
#undef LED_A_ON |
|||
#define LED_A_ON HIGH |
|||
#define rtos_free free |
|||
#define rtos_malloc malloc |
|||
//SPIClass SPI1(HSPI);
|
|||
#endif |
|||
class ST7789Spi : public OLEDDisplay { |
|||
private: |
|||
uint8_t _rst; |
|||
uint8_t _dc; |
|||
uint8_t _cs; |
|||
uint8_t _ledA; |
|||
int _miso; |
|||
int _mosi; |
|||
int _clk; |
|||
SPIClass * _spi; |
|||
SPISettings _spiSettings; |
|||
uint16_t _RGB=0xFFFF; |
|||
uint8_t _buffheight; |
|||
public: |
|||
/* pass _cs as -1 to indicate "do not use CS pin", for cases where it is hard wired low */ |
|||
ST7789Spi(SPIClass *spiClass,uint8_t _rst, uint8_t _dc, uint8_t _cs, OLEDDISPLAY_GEOMETRY g = GEOMETRY_RAWMODE,uint16_t width=240,uint16_t height=135,int mosi=-1,int miso=-1,int clk=-1) { |
|||
this->_spi = spiClass; |
|||
this->_rst = _rst; |
|||
this->_dc = _dc; |
|||
this->_cs = _cs; |
|||
this->_mosi=mosi; |
|||
this->_miso=miso; |
|||
this->_clk=clk; |
|||
//this->_ledA = _ledA;
|
|||
_spiSettings = SPISettings(40000000, MSBFIRST, SPI_MODE0); |
|||
setGeometry(g,width,height); |
|||
} |
|||
|
|||
bool connect(){ |
|||
this->_buffheight=displayHeight / 8; |
|||
this->_buffheight+=displayHeight % 8 ? 1:0; |
|||
pinMode(_cs, OUTPUT); |
|||
pinMode(_dc, OUTPUT); |
|||
//pinMode(_ledA, OUTPUT);
|
|||
if (_cs != (uint8_t) -1) { |
|||
pinMode(_cs, OUTPUT); |
|||
} |
|||
pinMode(_rst, OUTPUT); |
|||
|
|||
#ifdef ESP_PLATFORM |
|||
_spi->begin(_clk,_miso,_mosi,-1); |
|||
#else |
|||
_spi->begin(); |
|||
#endif |
|||
_spi->setClockDivider (SPI_CLOCK_DIV2); |
|||
|
|||
// Pulse Reset low for 10ms
|
|||
digitalWrite(_rst, HIGH); |
|||
delay(1); |
|||
digitalWrite(_rst, LOW); |
|||
delay(10); |
|||
digitalWrite(_rst, HIGH); |
|||
_spi->begin (); |
|||
//digitalWrite(_ledA, LED_A_ON);
|
|||
return true; |
|||
} |
|||
|
|||
void display(void) { |
|||
#ifdef OLEDDISPLAY_DOUBLE_BUFFER |
|||
|
|||
uint16_t minBoundY = UINT16_MAX; |
|||
uint16_t maxBoundY = 0; |
|||
|
|||
uint16_t minBoundX = UINT16_MAX; |
|||
uint16_t maxBoundX = 0; |
|||
|
|||
uint16_t x, y; |
|||
|
|||
// Calculate the Y bounding box of changes
|
|||
// and copy buffer[pos] to buffer_back[pos];
|
|||
for (y = 0; y < _buffheight; y++) { |
|||
for (x = 0; x < displayWidth; x++) { |
|||
//Serial.printf("x %d y %d\r\n",x,y);
|
|||
uint16_t pos = x + y * displayWidth; |
|||
if (buffer[pos] != buffer_back[pos]) { |
|||
minBoundY = min(minBoundY, y); |
|||
maxBoundY = max(maxBoundY, y); |
|||
minBoundX = min(minBoundX, x); |
|||
maxBoundX = max(maxBoundX, x); |
|||
} |
|||
buffer_back[pos] = buffer[pos]; |
|||
} |
|||
yield(); |
|||
} |
|||
|
|||
// If the minBoundY wasn't updated
|
|||
// we can savely assume that buffer_back[pos] == buffer[pos]
|
|||
// holdes true for all values of pos
|
|||
if (minBoundY == UINT16_MAX) return; |
|||
|
|||
set_CS(LOW); |
|||
_spi->beginTransaction(_spiSettings); |
|||
|
|||
for (y = minBoundY; y <= maxBoundY; y++) |
|||
{ |
|||
for(int temp = 0; temp<8;temp++) |
|||
{ |
|||
//setAddrWindow(minBoundX,y*8+temp,maxBoundX-minBoundX+1,1);
|
|||
setAddrWindow(minBoundX,y*8+temp,maxBoundX-minBoundX+1,1); |
|||
//setAddrWindow(y*8+temp,minBoundX,1,maxBoundX-minBoundX+1);
|
|||
uint32_t const pixbufcount = maxBoundX-minBoundX+1; |
|||
uint16_t *pixbuf = (uint16_t *)rtos_malloc(2 * pixbufcount); |
|||
for (x = minBoundX; x <= maxBoundX; x++) |
|||
{ |
|||
pixbuf[x-minBoundX] = ((buffer[x + y * displayWidth]>>temp)&0x01)==1?_RGB:0; |
|||
} |
|||
#ifdef ESP_PLATFORM |
|||
_spi->transferBytes((uint8_t *)pixbuf, NULL, 2 * pixbufcount); |
|||
#else |
|||
_spi->transfer(pixbuf, NULL, 2 * pixbufcount); |
|||
#endif |
|||
rtos_free(pixbuf); |
|||
} |
|||
} |
|||
_spi->endTransaction(); |
|||
set_CS(HIGH); |
|||
|
|||
#else |
|||
set_CS(LOW); |
|||
_spi->beginTransaction(_spiSettings); |
|||
uint8_t x, y; |
|||
for (y = 0; y < _buffheight; y++) |
|||
{ |
|||
for(int temp = 0; temp<8;temp++) |
|||
{ |
|||
//setAddrWindow(minBoundX,y*8+temp,maxBoundX-minBoundX+1,1);
|
|||
//setAddrWindow(minBoundX,y*8+temp,maxBoundX-minBoundX+1,1);
|
|||
setAddrWindow(y*8+temp,0,1,displayWidth); |
|||
uint32_t const pixbufcount = displayWidth; |
|||
uint16_t *pixbuf = (uint16_t *)rtos_malloc(2 * pixbufcount); |
|||
for (x = 0; x < displayWidth; x++) |
|||
{ |
|||
pixbuf[x] = ((buffer[x + y * displayWidth]>>temp)&0x01)==1?_RGB:0; |
|||
} |
|||
#ifdef ESP_PLATFORM |
|||
_spi->transferBytes((uint8_t *)pixbuf, NULL, 2 * pixbufcount); |
|||
#else |
|||
_spi->transfer(pixbuf, NULL, 2 * pixbufcount); |
|||
#endif |
|||
rtos_free(pixbuf); |
|||
} |
|||
} |
|||
_spi->endTransaction(); |
|||
set_CS(HIGH); |
|||
|
|||
#endif |
|||
} |
|||
|
|||
virtual void resetOrientation() { |
|||
uint8_t madctl = ST77XX_MADCTL_RGB|ST77XX_MADCTL_MV|ST77XX_MADCTL_MX; |
|||
sendCommand(ST77XX_MADCTL); |
|||
WriteData(madctl); |
|||
delay(10); |
|||
} |
|||
|
|||
virtual void flipScreenVertically() { |
|||
uint8_t madctl = ST77XX_MADCTL_RGB|ST77XX_MADCTL_MV|ST77XX_MADCTL_MY; |
|||
sendCommand(ST77XX_MADCTL); |
|||
WriteData(madctl); |
|||
delay(10); |
|||
} |
|||
|
|||
virtual void mirrorScreen() { |
|||
uint8_t madctl = ST77XX_MADCTL_RGB|ST77XX_MADCTL_MV|ST77XX_MADCTL_MX|ST77XX_MADCTL_MY; |
|||
sendCommand(ST77XX_MADCTL); |
|||
WriteData(madctl); |
|||
delay(10); |
|||
} |
|||
|
|||
virtual void landscapeScreen() { |
|||
|
|||
|
|||
uint8_t madctl = ST77XX_MADCTL_RGB; |
|||
sendCommand(ST77XX_MADCTL); |
|||
WriteData(madctl); |
|||
delay(10); |
|||
|
|||
} |
|||
|
|||
|
|||
void setRGB(uint16_t c) |
|||
{ |
|||
|
|||
this->_RGB=0x00|c>>8|c<<8&0xFF00; |
|||
} |
|||
|
|||
void displayOn(void) { |
|||
//sendCommand(DISPLAYON);
|
|||
} |
|||
|
|||
void displayOff(void) { |
|||
//sendCommand(DISPLAYOFF);
|
|||
} |
|||
|
|||
void drawBitmap(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *xbm) { |
|||
int16_t widthInXbm = (width + 7) / 8; |
|||
uint8_t data = 0; |
|||
|
|||
for(int16_t y = 0; y < height; y++) { |
|||
for(int16_t x = 0; x < width; x++ ) { |
|||
if (x & 7) { |
|||
data <<= 1; // Move a bit
|
|||
} else { // Read new data every 8 bit
|
|||
data = pgm_read_byte(xbm + (x / 8) + y * widthInXbm); |
|||
} |
|||
// if there is a bit draw it
|
|||
if (data & 0x80) { |
|||
setPixel(xMove + x, yMove + y); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
//#define ST77XX_MADCTL_MY 0x80
|
|||
//#define ST77XX_MADCTL_MX 0x40
|
|||
//#define ST77XX_MADCTL_MV 0x20
|
|||
//#define ST77XX_MADCTL_ML 0x10
|
|||
protected: |
|||
// Send all the init commands
|
|||
virtual void sendInitCommands() |
|||
{ |
|||
sendCommand(ST77XX_SWRESET); // 1: Software reset, no args, w/delay
|
|||
delay(150); |
|||
|
|||
sendCommand(ST77XX_SLPOUT); // 2: Out of sleep mode, no args, w/delay
|
|||
delay(10); |
|||
|
|||
sendCommand(ST77XX_COLMOD); // 3: Set color mode, 16-bit color
|
|||
WriteData(0x55); |
|||
delay(10); |
|||
|
|||
sendCommand(ST77XX_MADCTL); // 4: Mem access ctrl (directions), Row/col addr, bottom-top refresh
|
|||
WriteData(0x08); |
|||
|
|||
sendCommand(ST77XX_CASET); // 5: Column addr set,
|
|||
WriteData(0x00); |
|||
WriteData(0x00); // XSTART = 0
|
|||
WriteData(0x00); |
|||
WriteData(240); // XEND = 240
|
|||
|
|||
sendCommand(ST77XX_RASET); // 6: Row addr set,
|
|||
WriteData(0x00); |
|||
WriteData(0x00); // YSTART = 0
|
|||
WriteData(320>>8); |
|||
WriteData(320&0xFF); // YSTART = 320
|
|||
|
|||
sendCommand(ST77XX_SLPOUT); // 7: hack
|
|||
delay(10); |
|||
|
|||
sendCommand(ST77XX_NORON); // 8: Normal display on, no args, w/delay
|
|||
delay(10); |
|||
|
|||
sendCommand(ST77XX_DISPON); // 9: Main screen turn on, no args, delay
|
|||
delay(10); |
|||
|
|||
sendCommand(ST77XX_INVON); // 10: invert
|
|||
delay(10); |
|||
|
|||
//uint8_t madctl = ST77XX_MADCTL_RGB|ST77XX_MADCTL_MX;
|
|||
uint8_t madctl = ST77XX_MADCTL_RGB|ST77XX_MADCTL_MV|ST77XX_MADCTL_MX; |
|||
sendCommand(ST77XX_MADCTL); |
|||
WriteData(madctl); |
|||
delay(10); |
|||
setRGB(ST77XX_GREEN); |
|||
} |
|||
|
|||
|
|||
private: |
|||
|
|||
void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { |
|||
x += (320-displayWidth)/2; |
|||
y += (240-displayHeight)/2; |
|||
uint32_t xa = ((uint32_t)x << 16) | (x + w - 1); |
|||
uint32_t ya = ((uint32_t)y << 16) | (y + h - 1); |
|||
|
|||
writeCommand(ST77XX_CASET); // Column addr set
|
|||
SPI_WRITE32(xa); |
|||
|
|||
writeCommand(ST77XX_RASET); // Row addr set
|
|||
SPI_WRITE32(ya); |
|||
|
|||
writeCommand(ST77XX_RAMWR); // write to RAM
|
|||
} |
|||
int getBufferOffset(void) { |
|||
return 0; |
|||
} |
|||
inline void set_CS(bool level) { |
|||
if (_cs != (uint8_t) -1) { |
|||
digitalWrite(_cs, level); |
|||
} |
|||
}; |
|||
inline void sendCommand(uint8_t com) __attribute__((always_inline)){ |
|||
set_CS(HIGH); |
|||
digitalWrite(_dc, LOW); |
|||
set_CS(LOW); |
|||
_spi->beginTransaction(_spiSettings); |
|||
_spi->transfer(com); |
|||
_spi->endTransaction(); |
|||
set_CS(HIGH); |
|||
digitalWrite(_dc, HIGH); |
|||
} |
|||
|
|||
inline void WriteData(uint8_t data) __attribute__((always_inline)){ |
|||
digitalWrite(_cs, LOW); |
|||
_spi->beginTransaction(_spiSettings); |
|||
_spi->transfer(data); |
|||
_spi->endTransaction(); |
|||
digitalWrite(_cs, HIGH); |
|||
} |
|||
void SPI_WRITE32(uint32_t l) |
|||
{ |
|||
_spi->transfer(l >> 24); |
|||
_spi->transfer(l >> 16); |
|||
_spi->transfer(l >> 8); |
|||
_spi->transfer(l); |
|||
} |
|||
void writeCommand(uint8_t cmd) { |
|||
digitalWrite(_dc, LOW); |
|||
_spi->transfer(cmd); |
|||
digitalWrite(_dc, HIGH); |
|||
} |
|||
|
|||
// Private functions
|
|||
void setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width, uint16_t height) { |
|||
this->geometry = g; |
|||
|
|||
switch (g) { |
|||
case GEOMETRY_128_128: |
|||
this->displayWidth = 128; |
|||
this->displayHeight = 128; |
|||
break; |
|||
case GEOMETRY_128_64: |
|||
this->displayWidth = 128; |
|||
this->displayHeight = 64; |
|||
break; |
|||
case GEOMETRY_128_32: |
|||
this->displayWidth = 128; |
|||
this->displayHeight = 32; |
|||
break; |
|||
case GEOMETRY_64_48: |
|||
this->displayWidth = 64; |
|||
this->displayHeight = 48; |
|||
break; |
|||
case GEOMETRY_64_32: |
|||
this->displayWidth = 64; |
|||
this->displayHeight = 32; |
|||
break; |
|||
case GEOMETRY_RAWMODE: |
|||
this->displayWidth = width > 0 ? width : 128; |
|||
this->displayHeight = height > 0 ? height : 64; |
|||
break; |
|||
} |
|||
uint8_t tmp=displayHeight % 8; |
|||
uint8_t _buffheight=displayHeight / 8; |
|||
|
|||
if(tmp!=0) |
|||
_buffheight++; |
|||
this->displayBufferSize = displayWidth * _buffheight ; |
|||
} |
|||
|
|||
|
|||
|
|||
}; |
|||
|
|||
#endif |
|||
Loading…
Reference in new issue