|
@ -1220,6 +1220,7 @@ size_t Adafruit_GFX::write(uint8_t c) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set text 'magnification' size. Each increase in s makes 1 pixel that much bigger.
|
||||
|
@ -1606,6 +1607,7 @@ void Adafruit_GFX_Button::drawButton(boolean inverted) {
|
|||
_gfx->setTextColor(text);
|
||||
_gfx->setTextSize(_textsize_x, _textsize_y);
|
||||
_gfx->print(_label);
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
|
@ -17,7 +17,7 @@ class Adafruit_GFX : public Print {
|
|||
Adafruit_GFX(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; ///< Virtual drawPixel() function to draw to the screen/framebuffer/etc, must be overridden in subclass. @param x X coordinate. @param y Y coordinate. @param color 16-bit pixel color.
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; ///< Virtual drawPixel() function to draw to the screen/framebuffer/etc, must be overridden in subclass. @param x X coordinate. @param y Y coordinate. @param color 16-bit pixel color.
|
||||
|
||||
// TRANSACTION API / CORE DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
|
@ -51,20 +51,10 @@ class Adafruit_GFX : public Print {
|
|||
|
||||
// These exist only with Adafruit_GFX (no subclass overrides)
|
||||
void
|
||||
drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
|
||||
uint16_t color),
|
||||
fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
|
||||
int16_t delta, uint16_t color),
|
||||
drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
|
||||
int16_t w, int16_t h, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
|
||||
|
@ -103,10 +93,22 @@ class Adafruit_GFX : public Print {
|
|||
int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h),
|
||||
getTextBounds(const String &str, int16_t x, int16_t y,
|
||||
int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h),
|
||||
setTextSize(uint8_t s),
|
||||
setTextSize(uint8_t sx, uint8_t sy),
|
||||
setFont(const GFXfont *f = NULL);
|
||||
|
||||
virtual void
|
||||
drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
setTextSize(uint8_t s),
|
||||
setTextSize(uint8_t sx, uint8_t sy);
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text cursor location
|
||||
|
@ -114,7 +116,7 @@ class Adafruit_GFX : public Print {
|
|||
@param y Y coordinate in pixels
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setCursor(int16_t x, int16_t y) { cursor_x = x; cursor_y = y; }
|
||||
virtual void setCursor(int16_t x, int16_t y) { cursor_x = x; cursor_y = y; }
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
|
@ -168,7 +170,7 @@ class Adafruit_GFX : public Print {
|
|||
#else
|
||||
virtual void write(uint8_t);
|
||||
#endif
|
||||
|
||||
size_t iwrite(uint8_t);
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get width of the display, accounting for current rotation
|
||||
|
@ -211,6 +213,10 @@ class Adafruit_GFX : public Print {
|
|||
/************************************************************************/
|
||||
int16_t getCursorY(void) const { return cursor_y; };
|
||||
|
||||
uint16_t
|
||||
textcolor, ///< 16-bit background color for print()
|
||||
textbgcolor; ///< 16-bit text color for print()
|
||||
|
||||
protected:
|
||||
void
|
||||
charBounds(char c, int16_t *x, int16_t *y,
|
||||
|
@ -223,9 +229,9 @@ class Adafruit_GFX : public Print {
|
|||
_height, ///< Display height as modified by current rotation
|
||||
cursor_x, ///< x location to start print()ing text
|
||||
cursor_y; ///< y location to start print()ing text
|
||||
uint16_t
|
||||
textcolor, ///< 16-bit background color for print()
|
||||
textbgcolor; ///< 16-bit text color for print()
|
||||
//uint16_t
|
||||
// textcolor, ///< 16-bit background color for print()
|
||||
// textbgcolor; ///< 16-bit text color for print()
|
||||
uint8_t
|
||||
textsize_x, ///< Desired magnification in X-axis of text to print()
|
||||
textsize_y, ///< Desired magnification in Y-axis of text to print()
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
/*********************************************************************
|
||||
This is a library for our Monochrome OLEDs based on SSD1306 drivers
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/category/63_98
|
||||
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen below must be included in any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
/*********************************************************************
|
||||
I change the adafruit SSD1306 to SH1106
|
||||
|
||||
SH1106 driver similar to SSD1306 so, just change the display() method.
|
||||
|
||||
However, SH1106 driver don't provide several functions such as scroll commands.
|
||||
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
//#include <avr/pgmspace.h>
|
||||
#ifndef __SAM3X8E__
|
||||
// #include <util/delay.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <Wire.h>
|
||||
//#include <../../sonoff/settings.h>
|
||||
|
||||
#include "Adafruit_SH1106.h"
|
||||
#define DISPLAY_INIT_MODE 0
|
||||
|
||||
// the memory buffer for the LCD
|
||||
extern uint8_t *buffer;
|
||||
|
||||
Adafruit_SH1106::Adafruit_SH1106(int16_t width, int16_t height) :
|
||||
Renderer(width,height) {
|
||||
}
|
||||
|
||||
void Adafruit_SH1106::DisplayOnff(int8_t on) {
|
||||
if (on) {
|
||||
SH1106_command(SH1106_DISPLAYON);
|
||||
} else {
|
||||
SH1106_command(SH1106_DISPLAYOFF);
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_SH1106::Updateframe() {
|
||||
display();
|
||||
}
|
||||
|
||||
void Adafruit_SH1106::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
// ignore update mode
|
||||
//if (p==DISPLAY_INIT_MODE) {
|
||||
setRotation(rot);
|
||||
invertDisplay(false);
|
||||
setTextWrap(false); // Allow text to run off edges
|
||||
cp437(true);
|
||||
setTextFont(font);
|
||||
setTextSize(size);
|
||||
setTextColor(WHITE,BLACK);
|
||||
setCursor(0,0);
|
||||
fillScreen(BLACK);
|
||||
Updateframe();
|
||||
//}
|
||||
}
|
||||
|
||||
int16_t Adafruit_SH1106::Begin(int16_t p1,int16_t p2,int16_t p3) {
|
||||
begin(p1,p2,p3);
|
||||
}
|
||||
|
||||
|
||||
void Adafruit_SH1106::begin(uint8_t vccstate, uint8_t i2caddr, bool reset) {
|
||||
_vccstate = vccstate;
|
||||
_i2caddr = i2caddr;
|
||||
// I2C Init
|
||||
Wire.begin();
|
||||
|
||||
#if defined SH1106_128_32
|
||||
// Init sequence for 128x32 OLED module
|
||||
SH1106_command(SH1106_DISPLAYOFF); // 0xAE
|
||||
SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
|
||||
SH1106_command(0x80); // the suggested ratio 0x80
|
||||
SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
|
||||
SH1106_command(0x1F);
|
||||
SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
|
||||
SH1106_command(0x0); // no offset
|
||||
SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
|
||||
SH1106_command(SH1106_CHARGEPUMP); // 0x8D
|
||||
if (vccstate == SH1106_EXTERNALVCC)
|
||||
{ SH1106_command(0x10); }
|
||||
else
|
||||
{ SH1106_command(0x14); }
|
||||
SH1106_command(SH1106_MEMORYMODE); // 0x20
|
||||
SH1106_command(0x00); // 0x0 act like ks0108
|
||||
SH1106_command(SH1106_SEGREMAP | 0x1);
|
||||
SH1106_command(SH1106_COMSCANDEC);
|
||||
SH1106_command(SH1106_SETCOMPINS); // 0xDA
|
||||
SH1106_command(0x02);
|
||||
SH1106_command(SH1106_SETCONTRAST); // 0x81
|
||||
SH1106_command(0x8F);
|
||||
SH1106_command(SH1106_SETPRECHARGE); // 0xd9
|
||||
if (vccstate == SH1106_EXTERNALVCC)
|
||||
{ SH1106_command(0x22); }
|
||||
else
|
||||
{ SH1106_command(0xF1); }
|
||||
SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
|
||||
SH1106_command(0x40);
|
||||
SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
|
||||
SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
|
||||
#endif
|
||||
|
||||
#if defined SH1106_128_64
|
||||
// Init sequence for 128x64 OLED module
|
||||
SH1106_command(SH1106_DISPLAYOFF); // 0xAE
|
||||
SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
|
||||
SH1106_command(0x80); // the suggested ratio 0x80
|
||||
SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
|
||||
SH1106_command(0x3F);
|
||||
SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
|
||||
SH1106_command(0x00); // no offset
|
||||
|
||||
SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0 0x40
|
||||
SH1106_command(SH1106_CHARGEPUMP); // 0x8D
|
||||
if (vccstate == SH1106_EXTERNALVCC)
|
||||
{ SH1106_command(0x10); }
|
||||
else
|
||||
{ SH1106_command(0x14); }
|
||||
SH1106_command(SH1106_MEMORYMODE); // 0x20
|
||||
SH1106_command(0x00); // 0x0 act like ks0108
|
||||
SH1106_command(SH1106_SEGREMAP | 0x1);
|
||||
SH1106_command(SH1106_COMSCANDEC);
|
||||
SH1106_command(SH1106_SETCOMPINS); // 0xDA
|
||||
SH1106_command(0x12);
|
||||
SH1106_command(SH1106_SETCONTRAST); // 0x81
|
||||
if (vccstate == SH1106_EXTERNALVCC)
|
||||
{ SH1106_command(0x9F); }
|
||||
else
|
||||
{ SH1106_command(0xCF); }
|
||||
SH1106_command(SH1106_SETPRECHARGE); // 0xd9
|
||||
if (vccstate == SH1106_EXTERNALVCC)
|
||||
{ SH1106_command(0x22); }
|
||||
else
|
||||
{ SH1106_command(0xF1); }
|
||||
SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
|
||||
SH1106_command(0x40);
|
||||
SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
|
||||
SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
|
||||
#endif
|
||||
|
||||
#if defined SH1106_96_16
|
||||
// Init sequence for 96x16 OLED module
|
||||
SH1106_command(SH1106_DISPLAYOFF); // 0xAE
|
||||
SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
|
||||
SH1106_command(0x80); // the suggested ratio 0x80
|
||||
SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
|
||||
SH1106_command(0x0F);
|
||||
SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
|
||||
SH1106_command(0x00); // no offset
|
||||
SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
|
||||
SH1106_command(SH1106_CHARGEPUMP); // 0x8D
|
||||
if (vccstate == SH1106_EXTERNALVCC)
|
||||
{ SH1106_command(0x10); }
|
||||
else
|
||||
{ SH1106_command(0x14); }
|
||||
SH1106_command(SH1106_MEMORYMODE); // 0x20
|
||||
SH1106_command(0x00); // 0x0 act like ks0108
|
||||
SH1106_command(SH1106_SEGREMAP | 0x1);
|
||||
SH1106_command(SH1106_COMSCANDEC);
|
||||
SH1106_command(SH1106_SETCOMPINS); // 0xDA
|
||||
SH1106_command(0x2); //ada x12
|
||||
SH1106_command(SH1106_SETCONTRAST); // 0x81
|
||||
if (vccstate == SH1106_EXTERNALVCC)
|
||||
{ SH1106_command(0x10); }
|
||||
else
|
||||
{ SH1106_command(0xAF); }
|
||||
SH1106_command(SH1106_SETPRECHARGE); // 0xd9
|
||||
if (vccstate == SH1106_EXTERNALVCC)
|
||||
{ SH1106_command(0x22); }
|
||||
else
|
||||
{ SH1106_command(0xF1); }
|
||||
SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
|
||||
SH1106_command(0x40);
|
||||
SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
|
||||
SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
|
||||
#endif
|
||||
|
||||
SH1106_command(SH1106_DISPLAYON);//--turn on oled panel
|
||||
}
|
||||
|
||||
|
||||
void Adafruit_SH1106::invertDisplay(uint8_t i) {
|
||||
if (i) {
|
||||
SH1106_command(SH1106_INVERTDISPLAY);
|
||||
} else {
|
||||
SH1106_command(SH1106_NORMALDISPLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_SH1106::SH1106_command(uint8_t c) {
|
||||
|
||||
// I2C
|
||||
uint8_t control = 0x00; // Co = 0, D/C = 0
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
WIRE_WRITE(control);
|
||||
WIRE_WRITE(c);
|
||||
Wire.endTransmission();
|
||||
|
||||
}
|
||||
|
||||
// Dim the display
|
||||
// dim = true: display is dimmed
|
||||
// dim = false: display is normal
|
||||
void Adafruit_SH1106::dim(uint8_t dim) {
|
||||
uint8_t contrast;
|
||||
|
||||
if (dim) {
|
||||
contrast = 0; // Dimmed display
|
||||
} else {
|
||||
if (_vccstate == SH1106_EXTERNALVCC) {
|
||||
contrast = 0x9F;
|
||||
} else {
|
||||
contrast = 0xCF;
|
||||
}
|
||||
}
|
||||
// the range of contrast to too small to be really useful
|
||||
// it is useful to dim the display
|
||||
SH1106_command(SH1106_SETCONTRAST);
|
||||
SH1106_command(contrast);
|
||||
}
|
||||
|
||||
void Adafruit_SH1106::SH1106_data(uint8_t c) {
|
||||
// I2C
|
||||
uint8_t control = 0x40; // Co = 0, D/C = 1
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
WIRE_WRITE(control);
|
||||
WIRE_WRITE(c);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void Adafruit_SH1106::display(void) {
|
||||
SH1106_command(SH1106_SETLOWCOLUMN | 0x0); // low col = 0
|
||||
SH1106_command(SH1106_SETHIGHCOLUMN | 0x0); // hi col = 0
|
||||
SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
|
||||
// I2C
|
||||
//height >>= 3;
|
||||
//width >>= 3;
|
||||
byte height=64;
|
||||
byte width=132;
|
||||
byte m_row = 0;
|
||||
byte m_col = 2;
|
||||
|
||||
|
||||
height >>= 3;
|
||||
width >>= 3;
|
||||
//Serial.println(width);
|
||||
|
||||
int p = 0;
|
||||
|
||||
byte i, j, k =0;
|
||||
|
||||
for ( i = 0; i < height; i++) {
|
||||
|
||||
// send a bunch of data in one xmission
|
||||
SH1106_command(0xB0 + i + m_row);//set page address
|
||||
SH1106_command(m_col & 0xf);//set lower column address
|
||||
SH1106_command(0x10 | (m_col >> 4));//set higher column address
|
||||
|
||||
for( j = 0; j < 8; j++){
|
||||
Wire.beginTransmission(_i2caddr);
|
||||
Wire.write(0x40);
|
||||
for ( k = 0; k < width; k++, p++) {
|
||||
Wire.write(buffer[p]);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// clear everything
|
||||
void Adafruit_SH1106::clearDisplay(void) {
|
||||
memset(buffer, 0, (SH1106_LCDWIDTH*SH1106_LCDHEIGHT/8));
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/*********************************************************************
|
||||
This is a library for our Monochrome OLEDs based on SSD1306 drivers
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/category/63_98
|
||||
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen must be included in any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
/*********************************************************************
|
||||
I change the adafruit SSD1306 to SH1106
|
||||
|
||||
SH1106 driver similar to SSD1306 so, just change the display() method.
|
||||
|
||||
However, SH1106 driver don't provide several functions such as scroll commands.
|
||||
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#define WIRE_WRITE Wire.write
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#define WIRE_WRITE Wire.send
|
||||
#endif
|
||||
|
||||
#include <renderer.h>
|
||||
|
||||
#define BLACK 0
|
||||
#define WHITE 1
|
||||
#define INVERSE 2
|
||||
|
||||
#define SH1106_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D
|
||||
// Address for 128x32 is 0x3C
|
||||
// Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded)
|
||||
|
||||
/*=========================================================================
|
||||
SH1106 Displays
|
||||
-----------------------------------------------------------------------
|
||||
The driver is used in multiple displays (128x64, 128x32, etc.).
|
||||
Select the appropriate display below to create an appropriately
|
||||
sized framebuffer, etc.
|
||||
|
||||
SH1106_128_64 128x64 pixel display
|
||||
|
||||
SH1106_128_32 128x32 pixel display
|
||||
|
||||
SH1106_96_16
|
||||
|
||||
-----------------------------------------------------------------------*/
|
||||
#define SH1106_128_64
|
||||
// #define SH1106_128_32
|
||||
// #define SH1106_96_16
|
||||
/*=========================================================================*/
|
||||
|
||||
#if defined SH1106_128_64 && defined SH1106_128_32
|
||||
#error "Only one SH1106 display can be specified at once in SH1106.h"
|
||||
#endif
|
||||
#if !defined SH1106_128_64 && !defined SH1106_128_32 && !defined SH1106_96_16
|
||||
#error "At least one SH1106 display must be specified in SH1106.h"
|
||||
#endif
|
||||
|
||||
#if defined SH1106_128_64
|
||||
#define SH1106_LCDWIDTH 128
|
||||
#define SH1106_LCDHEIGHT 64
|
||||
#endif
|
||||
#if defined SH1106_128_32
|
||||
#define SH1106_LCDWIDTH 128
|
||||
#define SH1106_LCDHEIGHT 32
|
||||
#endif
|
||||
#if defined SH1106_96_16
|
||||
#define SH1106_LCDWIDTH 96
|
||||
#define SH1106_LCDHEIGHT 16
|
||||
#endif
|
||||
|
||||
#define SH1106_SETCONTRAST 0x81
|
||||
#define SH1106_DISPLAYALLON_RESUME 0xA4
|
||||
#define SH1106_DISPLAYALLON 0xA5
|
||||
#define SH1106_NORMALDISPLAY 0xA6
|
||||
#define SH1106_INVERTDISPLAY 0xA7
|
||||
#define SH1106_DISPLAYOFF 0xAE
|
||||
#define SH1106_DISPLAYON 0xAF
|
||||
|
||||
#define SH1106_SETDISPLAYOFFSET 0xD3
|
||||
#define SH1106_SETCOMPINS 0xDA
|
||||
|
||||
#define SH1106_SETVCOMDETECT 0xDB
|
||||
|
||||
#define SH1106_SETDISPLAYCLOCKDIV 0xD5
|
||||
#define SH1106_SETPRECHARGE 0xD9
|
||||
|
||||
#define SH1106_SETMULTIPLEX 0xA8
|
||||
|
||||
#define SH1106_SETLOWCOLUMN 0x00
|
||||
#define SH1106_SETHIGHCOLUMN 0x10
|
||||
|
||||
#define SH1106_SETSTARTLINE 0x40
|
||||
|
||||
#define SH1106_MEMORYMODE 0x20
|
||||
#define SH1106_COLUMNADDR 0x21
|
||||
#define SH1106_PAGEADDR 0x22
|
||||
|
||||
#define SH1106_COMSCANINC 0xC0
|
||||
#define SH1106_COMSCANDEC 0xC8
|
||||
|
||||
#define SH1106_SEGREMAP 0xA0
|
||||
|
||||
#define SH1106_CHARGEPUMP 0x8D
|
||||
|
||||
#define SH1106_EXTERNALVCC 0x1
|
||||
#define SH1106_SWITCHCAPVCC 0x2
|
||||
|
||||
// Scrolling #defines
|
||||
#define SH1106_ACTIVATE_SCROLL 0x2F
|
||||
#define SH1106_DEACTIVATE_SCROLL 0x2E
|
||||
#define SH1106_SET_VERTICAL_SCROLL_AREA 0xA3
|
||||
#define SH1106_RIGHT_HORIZONTAL_SCROLL 0x26
|
||||
#define SH1106_LEFT_HORIZONTAL_SCROLL 0x27
|
||||
#define SH1106_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
|
||||
#define SH1106_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A
|
||||
|
||||
class Adafruit_SH1106 : public Renderer {
|
||||
public:
|
||||
Adafruit_SH1106(int16_t width, int16_t height);
|
||||
|
||||
void begin(uint8_t switchvcc = SH1106_SWITCHCAPVCC, uint8_t i2caddr = SH1106_I2C_ADDRESS, bool reset=true);
|
||||
void SH1106_command(uint8_t c);
|
||||
void SH1106_data(uint8_t c);
|
||||
|
||||
void clearDisplay(void);
|
||||
void invertDisplay(uint8_t i);
|
||||
void display();
|
||||
|
||||
|
||||
void DisplayOnff(int8_t on);
|
||||
void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||
int16_t Begin(int16_t p1,int16_t p2,int16_t p3);
|
||||
void Updateframe();
|
||||
void dim(uint8_t contrast);
|
||||
|
||||
private:
|
||||
int8_t _i2caddr, _vccstate, rst;
|
||||
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2012, Adafruit Industries
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,16 @@
|
|||
Adafruit_SH1106
|
||||
===============
|
||||
|
||||
Adafruit graphic library for SH1106 driver lcds.
|
||||
|
||||
some small oled lcd use SH1106 driver.
|
||||
|
||||
I change the adafruit SSD1306 to SH1106
|
||||
|
||||
SH1106 driver similar to SSD1306. thus, just change the display() method.
|
||||
|
||||
However, SH1106 driver don't provide several functions such as scroll commands.
|
||||
|
||||
|
||||
Adafruit-GFX-Library
|
||||
https://github.com/adafruit/Adafruit-GFX-Library
|
|
@ -0,0 +1,363 @@
|
|||
/*********************************************************************
|
||||
This is an example for our Monochrome OLEDs based on SSD1306 drivers
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/category/63_98
|
||||
|
||||
This example is for a 128x64 size display using I2C to communicate
|
||||
3 pins are required to interface (2 I2C and one reset)
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen must be included in any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
/*********************************************************************
|
||||
I change the adafruit SSD1306 to SH1106
|
||||
|
||||
SH1106 driver don't provide several functions such as scroll commands.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_SH1106.h>
|
||||
|
||||
#define OLED_RESET 4
|
||||
Adafruit_SH1106 display(OLED_RESET);
|
||||
|
||||
#define NUMFLAKES 10
|
||||
#define XPOS 0
|
||||
#define YPOS 1
|
||||
#define DELTAY 2
|
||||
|
||||
|
||||
#define LOGO16_GLCD_HEIGHT 16
|
||||
#define LOGO16_GLCD_WIDTH 16
|
||||
static const unsigned char PROGMEM logo16_glcd_bmp[] =
|
||||
{ B00000000, B11000000,
|
||||
B00000001, B11000000,
|
||||
B00000001, B11000000,
|
||||
B00000011, B11100000,
|
||||
B11110011, B11100000,
|
||||
B11111110, B11111000,
|
||||
B01111110, B11111111,
|
||||
B00110011, B10011111,
|
||||
B00011111, B11111100,
|
||||
B00001101, B01110000,
|
||||
B00011011, B10100000,
|
||||
B00111111, B11100000,
|
||||
B00111111, B11110000,
|
||||
B01111100, B11110000,
|
||||
B01110000, B01110000,
|
||||
B00000000, B00110000 };
|
||||
|
||||
#if (SH1106_LCDHEIGHT != 64)
|
||||
#error("Height incorrect, please fix Adafruit_SH1106.h!");
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
|
||||
display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
|
||||
// init done
|
||||
|
||||
// Show image buffer on the display hardware.
|
||||
// Since the buffer is intialized with an Adafruit splashscreen
|
||||
// internally, this will display the splashscreen.
|
||||
display.display();
|
||||
delay(2000);
|
||||
|
||||
// Clear the buffer.
|
||||
display.clearDisplay();
|
||||
|
||||
// draw a single pixel
|
||||
display.drawPixel(10, 10, WHITE);
|
||||
// Show the display buffer on the hardware.
|
||||
// NOTE: You _must_ call display after making any drawing commands
|
||||
// to make them visible on the display hardware!
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw many lines
|
||||
testdrawline();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw rectangles
|
||||
testdrawrect();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw multiple rectangles
|
||||
testfillrect();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw mulitple circles
|
||||
testdrawcircle();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw a white circle, 10 pixel radius
|
||||
display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testdrawroundrect();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testfillroundrect();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testdrawtriangle();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testfilltriangle();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw the first ~12 characters in the font
|
||||
testdrawchar();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw scrolling text
|
||||
/* testscrolltext();
|
||||
delay(2000);
|
||||
display.clearDisplay();*/
|
||||
|
||||
// text display tests
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(0,0);
|
||||
display.println("Hello, world!");
|
||||
display.setTextColor(BLACK, WHITE); // 'inverted' text
|
||||
display.println(3.141592);
|
||||
display.setTextSize(2);
|
||||
display.setTextColor(WHITE);
|
||||
display.print("0x"); display.println(0xDEADBEEF, HEX);
|
||||
display.display();
|
||||
delay(2000);
|
||||
|
||||
// miniature bitmap display
|
||||
display.clearDisplay();
|
||||
display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
|
||||
display.display();
|
||||
|
||||
// invert the display
|
||||
display.invertDisplay(true);
|
||||
delay(1000);
|
||||
display.invertDisplay(false);
|
||||
delay(1000);
|
||||
|
||||
// draw a bitmap icon and 'animate' movement
|
||||
testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
|
||||
uint8_t icons[NUMFLAKES][3];
|
||||
|
||||
// initialize
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
icons[f][XPOS] = random(display.width());
|
||||
icons[f][YPOS] = 0;
|
||||
icons[f][DELTAY] = random(5) + 1;
|
||||
|
||||
Serial.print("x: ");
|
||||
Serial.print(icons[f][XPOS], DEC);
|
||||
Serial.print(" y: ");
|
||||
Serial.print(icons[f][YPOS], DEC);
|
||||
Serial.print(" dy: ");
|
||||
Serial.println(icons[f][DELTAY], DEC);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
// draw each icon
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE);
|
||||
}
|
||||
display.display();
|
||||
delay(200);
|
||||
|
||||
// then erase it + move it
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, BLACK);
|
||||
// move it
|
||||
icons[f][YPOS] += icons[f][DELTAY];
|
||||
// if its gone, reinit
|
||||
if (icons[f][YPOS] > display.height()) {
|
||||
icons[f][XPOS] = random(display.width());
|
||||
icons[f][YPOS] = 0;
|
||||
icons[f][DELTAY] = random(5) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void testdrawchar(void) {
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(0,0);
|
||||
|
||||
for (uint8_t i=0; i < 168; i++) {
|
||||
if (i == '\n') continue;
|
||||
display.write(i);
|
||||
if ((i > 0) && (i % 21 == 0))
|
||||
display.println();
|
||||
}
|
||||
display.display();
|
||||
}
|
||||
|
||||
void testdrawcircle(void) {
|
||||
for (int16_t i=0; i<display.height(); i+=2) {
|
||||
display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfillrect(void) {
|
||||
uint8_t color = 1;
|
||||
for (int16_t i=0; i<display.height()/2; i+=3) {
|
||||
// alternate colors
|
||||
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
|
||||
display.display();
|
||||
color++;
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawtriangle(void) {
|
||||
for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) {
|
||||
display.drawTriangle(display.width()/2, display.height()/2-i,
|
||||
display.width()/2-i, display.height()/2+i,
|
||||
display.width()/2+i, display.height()/2+i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfilltriangle(void) {
|
||||
uint8_t color = WHITE;
|
||||
for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
|
||||
display.fillTriangle(display.width()/2, display.height()/2-i,
|
||||
display.width()/2-i, display.height()/2+i,
|
||||
display.width()/2+i, display.height()/2+i, WHITE);
|
||||
if (color == WHITE) color = BLACK;
|
||||
else color = WHITE;
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawroundrect(void) {
|
||||
for (int16_t i=0; i<display.height()/2-2; i+=2) {
|
||||
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, WHITE);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfillroundrect(void) {
|
||||
uint8_t color = WHITE;
|
||||
for (int16_t i=0; i<display.height()/2-2; i+=2) {
|
||||
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
|
||||
if (color == WHITE) color = BLACK;
|
||||
else color = WHITE;
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawrect(void) {
|
||||
for (int16_t i=0; i<display.height()/2; i+=2) {
|
||||
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawline() {
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(0, 0, i, display.height()-1, WHITE);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=0; i<display.height(); i+=4) {
|
||||
display.drawLine(0, 0, display.width()-1, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(0, display.height()-1, i, 0, WHITE);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=display.height()-1; i>=0; i-=4) {
|
||||
display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=display.width()-1; i>=0; i-=4) {
|
||||
display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=display.height()-1; i>=0; i-=4) {
|
||||
display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=0; i<display.height(); i+=4) {
|
||||
display.drawLine(display.width()-1, 0, 0, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
|
||||
/*void testscrolltext(void) {
|
||||
display.setTextSize(2);
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(10,0);
|
||||
display.clearDisplay();
|
||||
display.println("scroll");
|
||||
display.display();
|
||||
|
||||
display.startscrollright(0x00, 0x0F);
|
||||
delay(2000);
|
||||
display.stopscroll();
|
||||
delay(1000);
|
||||
display.startscrollleft(0x00, 0x0F);
|
||||
delay(2000);
|
||||
display.stopscroll();
|
||||
delay(1000);
|
||||
display.startscrolldiagright(0x00, 0x07);
|
||||
delay(2000);
|
||||
display.startscrolldiagleft(0x00, 0x07);
|
||||
delay(2000);
|
||||
display.stopscroll();
|
||||
}*/
|
|
@ -0,0 +1,369 @@
|
|||
/*********************************************************************
|
||||
This is an example for our Monochrome OLEDs based on SH1106 drivers
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/category/63_98
|
||||
|
||||
This example is for a 128x64 size display using SPI to communicate
|
||||
4 or 5 pins are required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information
|
||||
All text above, and the splash screen must be included in any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_SH1106.h>
|
||||
|
||||
// If using software SPI (the default case):
|
||||
#define OLED_MOSI 9
|
||||
#define OLED_CLK 10
|
||||
#define OLED_DC 11
|
||||
#define OLED_CS 12
|
||||
#define OLED_RESET 13
|
||||
Adafruit_SH1106 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
|
||||
|
||||
/* Uncomment this block to use hardware SPI
|
||||
#define OLED_DC 6
|
||||
#define OLED_CS 7
|
||||
#define OLED_RESET 8
|
||||
Adafruit_SH1106 display(OLED_DC, OLED_RESET, OLED_CS);
|
||||
*/
|
||||
|
||||
#define NUMFLAKES 10
|
||||
#define XPOS 0
|
||||
#define YPOS 1
|
||||
#define DELTAY 2
|
||||
|
||||
#define LOGO16_GLCD_HEIGHT 16
|
||||
#define LOGO16_GLCD_WIDTH 16
|
||||
static const unsigned char PROGMEM logo16_glcd_bmp[] =
|
||||
{ B00000000, B11000000,
|
||||
B00000001, B11000000,
|
||||
B00000001, B11000000,
|
||||
B00000011, B11100000,
|
||||
B11110011, B11100000,
|
||||
B11111110, B11111000,
|
||||
B01111110, B11111111,
|
||||
B00110011, B10011111,
|
||||
B00011111, B11111100,
|
||||
B00001101, B01110000,
|
||||
B00011011, B10100000,
|
||||
B00111111, B11100000,
|
||||
B00111111, B11110000,
|
||||
B01111100, B11110000,
|
||||
B01110000, B01110000,
|
||||
B00000000, B00110000 };
|
||||
|
||||
#if (SH1106_LCDHEIGHT != 64)
|
||||
#error("Height incorrect, please fix Adafruit_SH1106.h!");
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
|
||||
display.begin(SH1106_SWITCHCAPVCC);
|
||||
// init done
|
||||
|
||||
// Show image buffer on the display hardware.
|
||||
// Since the buffer is intialized with an Adafruit splashscreen
|
||||
// internally, this will display the splashscreen.
|
||||
display.display();
|
||||
delay(2000);
|
||||
|
||||
// Clear the buffer.
|
||||
display.clearDisplay();
|
||||
|
||||
// draw a single pixel
|
||||
display.drawPixel(10, 10, WHITE);
|
||||
// Show the display buffer on the hardware.
|
||||
// NOTE: You _must_ call display after making any drawing commands
|
||||
// to make them visible on the display hardware!
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw many lines
|
||||
testdrawline();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw rectangles
|
||||
testdrawrect();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw multiple rectangles
|
||||
testfillrect();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw mulitple circles
|
||||
testdrawcircle();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw a white circle, 10 pixel radius
|
||||
display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testdrawroundrect();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testfillroundrect();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testdrawtriangle();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
testfilltriangle();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw the first ~12 characters in the font
|
||||
testdrawchar();
|
||||
display.display();
|
||||
delay(2000);
|
||||
display.clearDisplay();
|
||||
|
||||
// draw scrolling text
|
||||
/*testscrolltext();
|
||||
delay(2000);
|
||||
display.clearDisplay();*/
|
||||
|
||||
// text display tests
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(0,0);
|
||||
display.println("Hello, world!");
|
||||
display.setTextColor(BLACK, WHITE); // 'inverted' text
|
||||
display.println(3.141592);
|
||||
display.setTextSize(2);
|
||||
display.setTextColor(WHITE);
|
||||
display.print("0x"); display.println(0xDEADBEEF, HEX);
|
||||
display.display();
|
||||
delay(2000);
|
||||
|
||||
// miniature bitmap display
|
||||
display.clearDisplay();
|
||||
display.drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1);
|
||||
display.display();
|
||||
|
||||
// invert the display
|
||||
display.invertDisplay(true);
|
||||
delay(1000);
|
||||
display.invertDisplay(false);
|
||||
delay(1000);
|
||||
|
||||
// draw a bitmap icon and 'animate' movement
|
||||
testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
|
||||
uint8_t icons[NUMFLAKES][3];
|
||||
|
||||
// initialize
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
icons[f][XPOS] = random(display.width());
|
||||
icons[f][YPOS] = 0;
|
||||
icons[f][DELTAY] = random(5) + 1;
|
||||
|
||||
Serial.print("x: ");
|
||||
Serial.print(icons[f][XPOS], DEC);
|
||||
Serial.print(" y: ");
|
||||
Serial.print(icons[f][YPOS], DEC);
|
||||
Serial.print(" dy: ");
|
||||
Serial.println(icons[f][DELTAY], DEC);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
// draw each icon
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE);
|
||||
}
|
||||
display.display();
|
||||
delay(200);
|
||||
|
||||
// then erase it + move it
|
||||
for (uint8_t f=0; f< NUMFLAKES; f++) {
|
||||
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, BLACK);
|
||||
// move it
|
||||
icons[f][YPOS] += icons[f][DELTAY];
|
||||
// if its gone, reinit
|
||||
if (icons[f][YPOS] > display.height()) {
|
||||
icons[f][XPOS] = random(display.width());
|
||||
icons[f][YPOS] = 0;
|
||||
icons[f][DELTAY] = random(5) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void testdrawchar(void) {
|
||||
display.setTextSize(1);
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(0,0);
|
||||
|
||||
for (uint8_t i=0; i < 168; i++) {
|
||||
if (i == '\n') continue;
|
||||
display.write(i);
|
||||
if ((i > 0) && (i % 21 == 0))
|
||||
display.println();
|
||||
}
|
||||
display.display();
|
||||
}
|
||||
|
||||
void testdrawcircle(void) {
|
||||
for (int16_t i=0; i<display.height(); i+=2) {
|
||||
display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfillrect(void) {
|
||||
uint8_t color = 1;
|
||||
for (int16_t i=0; i<display.height()/2; i+=3) {
|
||||
// alternate colors
|
||||
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
|
||||
display.display();
|
||||
color++;
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawtriangle(void) {
|
||||
for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) {
|
||||
display.drawTriangle(display.width()/2, display.height()/2-i,
|
||||
display.width()/2-i, display.height()/2+i,
|
||||
display.width()/2+i, display.height()/2+i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfilltriangle(void) {
|
||||
uint8_t color = WHITE;
|
||||
for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
|
||||
display.fillTriangle(display.width()/2, display.height()/2-i,
|
||||
display.width()/2-i, display.height()/2+i,
|
||||
display.width()/2+i, display.height()/2+i, WHITE);
|
||||
if (color == WHITE) color = BLACK;
|
||||
else color = WHITE;
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawroundrect(void) {
|
||||
for (int16_t i=0; i<display.height()/2-2; i+=2) {
|
||||
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, WHITE);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testfillroundrect(void) {
|
||||
uint8_t color = WHITE;
|
||||
for (int16_t i=0; i<display.height()/2-2; i+=2) {
|
||||
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
|
||||
if (color == WHITE) color = BLACK;
|
||||
else color = WHITE;
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawrect(void) {
|
||||
for (int16_t i=0; i<display.height()/2; i+=2) {
|
||||
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawline() {
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(0, 0, i, display.height()-1, WHITE);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=0; i<display.height(); i+=4) {
|
||||
display.drawLine(0, 0, display.width()-1, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(0, display.height()-1, i, 0, WHITE);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=display.height()-1; i>=0; i-=4) {
|
||||
display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=display.width()-1; i>=0; i-=4) {
|
||||
display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=display.height()-1; i>=0; i-=4) {
|
||||
display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
|
||||
display.clearDisplay();
|
||||
for (int16_t i=0; i<display.height(); i+=4) {
|
||||
display.drawLine(display.width()-1, 0, 0, i, WHITE);
|
||||
display.display();
|
||||
}
|
||||
for (int16_t i=0; i<display.width(); i+=4) {
|
||||
display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE);
|
||||
display.display();
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
|
||||
/*
|
||||
void testscrolltext(void) {
|
||||
display.setTextSize(2);
|
||||
display.setTextColor(WHITE);
|
||||
display.setCursor(10,0);
|
||||
display.clearDisplay();
|
||||
display.println("scroll");
|
||||
display.display();
|
||||
|
||||
display.startscrollright(0x00, 0x0F);
|
||||
delay(2000);
|
||||
display.stopscroll();
|
||||
delay(1000);
|
||||
display.startscrollleft(0x00, 0x0F);
|
||||
delay(2000);
|
||||
display.stopscroll();
|
||||
delay(1000);
|
||||
display.startscrolldiagright(0x00, 0x07);
|
||||
delay(2000);
|
||||
display.startscrolldiagleft(0x00, 0x07);
|
||||
delay(2000);
|
||||
display.stopscroll();
|
||||
}
|
||||
*/
|
|
@ -165,7 +165,7 @@
|
|||
*/
|
||||
Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi,
|
||||
int8_t rst_pin, uint32_t clkDuring, uint32_t clkAfter) :
|
||||
Adafruit_GFX(w, h), spi(NULL), wire(twi ? twi : &Wire), buffer(NULL),
|
||||
Renderer(w, h), spi(NULL), wire(twi ? twi : &Wire), xbuffer(NULL),
|
||||
mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1), rstPin(rst_pin),
|
||||
wireClk(clkDuring), restoreClk(clkAfter) {
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi,
|
|||
*/
|
||||
Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h,
|
||||
int8_t mosi_pin, int8_t sclk_pin, int8_t dc_pin, int8_t rst_pin,
|
||||
int8_t cs_pin) : Adafruit_GFX(w, h), spi(NULL), wire(NULL), buffer(NULL),
|
||||
int8_t cs_pin) : Renderer(w, h), spi(NULL), wire(NULL), xbuffer(NULL),
|
||||
mosiPin(mosi_pin), clkPin(sclk_pin), dcPin(dc_pin), csPin(cs_pin),
|
||||
rstPin(rst_pin) {
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h,
|
|||
*/
|
||||
Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi,
|
||||
int8_t dc_pin, int8_t rst_pin, int8_t cs_pin, uint32_t bitrate) :
|
||||
Adafruit_GFX(w, h), spi(spi ? spi : &SPI), wire(NULL), buffer(NULL),
|
||||
Renderer(w, h), spi(spi ? spi : &SPI), wire(NULL), xbuffer(NULL),
|
||||
mosiPin(-1), clkPin(-1), dcPin(dc_pin), csPin(cs_pin), rstPin(rst_pin) {
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
spiSettings = SPISettings(bitrate, MSBFIRST, SPI_MODE0);
|
||||
|
@ -267,8 +267,8 @@ Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi,
|
|||
*/
|
||||
Adafruit_SSD1306::Adafruit_SSD1306(int8_t mosi_pin, int8_t sclk_pin,
|
||||
int8_t dc_pin, int8_t rst_pin, int8_t cs_pin) :
|
||||
Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(NULL), wire(NULL),
|
||||
buffer(NULL), mosiPin(mosi_pin), clkPin(sclk_pin), dcPin(dc_pin),
|
||||
Renderer(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(NULL), wire(NULL),
|
||||
xbuffer(NULL), mosiPin(mosi_pin), clkPin(sclk_pin), dcPin(dc_pin),
|
||||
csPin(cs_pin), rstPin(rst_pin) {
|
||||
}
|
||||
|
||||
|
@ -294,9 +294,9 @@ Adafruit_SSD1306::Adafruit_SSD1306(int8_t mosi_pin, int8_t sclk_pin,
|
|||
allocation is performed there!
|
||||
*/
|
||||
Adafruit_SSD1306::Adafruit_SSD1306(int8_t dc_pin, int8_t rst_pin,
|
||||
int8_t cs_pin) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT),
|
||||
spi(&SPI), wire(NULL), buffer(NULL), mosiPin(-1), clkPin(-1),
|
||||
dcPin(dc_pin), csPin(cs_pin), rstPin(rst_pin) {
|
||||
int8_t cs_pin) : Renderer(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT),
|
||||
spi(&SPI), wire(NULL), xbuffer(NULL), mosiPin(-1), clkPin(-1),
|
||||
dcPin(dc_pin), csPin(cs_pin), rstPin(rst_pin) {
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
spiSettings = SPISettings(8000000, MSBFIRST, SPI_MODE0);
|
||||
#endif
|
||||
|
@ -317,8 +317,8 @@ Adafruit_SSD1306::Adafruit_SSD1306(int8_t dc_pin, int8_t rst_pin,
|
|||
allocation is performed there!
|
||||
*/
|
||||
Adafruit_SSD1306::Adafruit_SSD1306(int8_t rst_pin) :
|
||||
Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(NULL), wire(&Wire),
|
||||
buffer(NULL), mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1),
|
||||
Renderer(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT), spi(NULL), wire(&Wire),
|
||||
xbuffer(NULL), mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1),
|
||||
rstPin(rst_pin) {
|
||||
}
|
||||
|
||||
|
@ -451,10 +451,12 @@ void Adafruit_SSD1306::ssd1306_command(uint8_t c) {
|
|||
boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset,
|
||||
boolean periphBegin) {
|
||||
|
||||
if((!buffer) && !(buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))))
|
||||
return false;
|
||||
// if((!buffer) && !(buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))))
|
||||
// return false;
|
||||
|
||||
clearDisplay();
|
||||
|
||||
/*
|
||||
if(HEIGHT > 32) {
|
||||
drawBitmap((WIDTH - splash1_width) / 2, (HEIGHT - splash1_height) / 2,
|
||||
splash1_data, splash1_width, splash1_height, 1);
|
||||
|
@ -462,7 +464,7 @@ boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset,
|
|||
drawBitmap((WIDTH - splash2_width) / 2, (HEIGHT - splash2_height) / 2,
|
||||
splash2_data, splash2_width, splash2_height, 1);
|
||||
}
|
||||
|
||||
*/
|
||||
vccstate = vcs;
|
||||
|
||||
// Setup pin directions
|
||||
|
@ -581,6 +583,9 @@ boolean Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, boolean reset,
|
|||
return true; // Success
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
// DRAWING FUNCTIONS -------------------------------------------------------
|
||||
|
||||
/*!
|
||||
|
@ -680,28 +685,7 @@ void Adafruit_SSD1306::drawFastHLine(
|
|||
else drawFastHLineInternal(x, y, w, color);
|
||||
}
|
||||
|
||||
void Adafruit_SSD1306::drawFastHLineInternal(
|
||||
int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
|
||||
if((y >= 0) && (y < HEIGHT)) { // Y coord in bounds?
|
||||
if(x < 0) { // Clip left
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
if((x + w) > WIDTH) { // Clip right
|
||||
w = (WIDTH - x);
|
||||
}
|
||||
if(w > 0) { // Proceed only if width is positive
|
||||
uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x],
|
||||
mask = 1 << (y & 7);
|
||||
switch(color) {
|
||||
case WHITE: while(w--) { *pBuf++ |= mask; }; break;
|
||||
case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
|
||||
case INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Draw a vertical line. This is also invoked by the Adafruit_GFX
|
||||
|
@ -748,6 +732,30 @@ void Adafruit_SSD1306::drawFastVLine(
|
|||
if(bSwap) drawFastHLineInternal(x, y, h, color);
|
||||
else drawFastVLineInternal(x, y, h, color);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Adafruit_SSD1306::drawFastHLineInternal(
|
||||
int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
|
||||
if((y >= 0) && (y < HEIGHT)) { // Y coord in bounds?
|
||||
if(x < 0) { // Clip left
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
if((x + w) > WIDTH) { // Clip right
|
||||
w = (WIDTH - x);
|
||||
}
|
||||
if(w > 0) { // Proceed only if width is positive
|
||||
uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x],
|
||||
mask = 1 << (y & 7);
|
||||
switch(color) {
|
||||
case WHITE: while(w--) { *pBuf++ |= mask; }; break;
|
||||
case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
|
||||
case INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_SSD1306::drawFastVLineInternal(
|
||||
int16_t x, int16_t __y, int16_t __h, uint16_t color) {
|
||||
|
@ -871,9 +879,10 @@ boolean Adafruit_SSD1306::getPixel(int16_t x, int16_t y) {
|
|||
to full byte boundary if needed.
|
||||
*/
|
||||
uint8_t *Adafruit_SSD1306::getBuffer(void) {
|
||||
return buffer;
|
||||
return xbuffer;
|
||||
}
|
||||
|
||||
|
||||
// REFRESH DISPLAY ---------------------------------------------------------
|
||||
|
||||
/*!
|
||||
|
@ -1099,3 +1108,6 @@ void Adafruit_SSD1306::dim(boolean dim) {
|
|||
TRANSACTION_END
|
||||
}
|
||||
|
||||
void Adafruit_SSD1306::Updateframe(void) {
|
||||
display();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#ifndef _Adafruit_SSD1306_H_
|
||||
#define _Adafruit_SSD1306_H_
|
||||
|
||||
#include <renderer.h>
|
||||
|
||||
extern uint8_t *buffer;
|
||||
|
||||
// ONE of the following three lines must be #defined:
|
||||
//#define SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen
|
||||
#define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen
|
||||
|
@ -108,12 +112,12 @@
|
|||
#define SSD1306_LCDHEIGHT 16 ///< DEPRECATED: height w/SSD1306_96_16 defined
|
||||
#endif
|
||||
|
||||
/*!
|
||||
/*!
|
||||
@brief Class that stores state and functions for interacting with
|
||||
SSD1306 OLED displays.
|
||||
*/
|
||||
class Adafruit_SSD1306 : public Adafruit_GFX {
|
||||
public:
|
||||
class Adafruit_SSD1306 : public Renderer {
|
||||
public:
|
||||
// NEW CONSTRUCTORS -- recommended for new projects
|
||||
Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi=&Wire, int8_t rst_pin=-1,
|
||||
uint32_t clkDuring=400000UL, uint32_t clkAfter=100000UL);
|
||||
|
@ -134,12 +138,15 @@ class Adafruit_SSD1306 : public Adafruit_GFX {
|
|||
uint8_t i2caddr=0, boolean reset=true,
|
||||
boolean periphBegin=true);
|
||||
void display(void);
|
||||
void clearDisplay(void);
|
||||
void invertDisplay(boolean i);
|
||||
void dim(boolean dim);
|
||||
|
||||
#if 0
|
||||
void clearDisplay(void);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
#endif
|
||||
void startscrollright(uint8_t start, uint8_t stop);
|
||||
void startscrollleft(uint8_t start, uint8_t stop);
|
||||
void startscrolldiagright(uint8_t start, uint8_t stop);
|
||||
|
@ -148,6 +155,7 @@ class Adafruit_SSD1306 : public Adafruit_GFX {
|
|||
void ssd1306_command(uint8_t c);
|
||||
boolean getPixel(int16_t x, int16_t y);
|
||||
uint8_t *getBuffer(void);
|
||||
void Updateframe(void);
|
||||
|
||||
private:
|
||||
inline void SPIwrite(uint8_t d) __attribute__((always_inline));
|
||||
|
@ -160,7 +168,7 @@ class Adafruit_SSD1306 : public Adafruit_GFX {
|
|||
|
||||
SPIClass *spi;
|
||||
TwoWire *wire;
|
||||
uint8_t *buffer;
|
||||
uint8_t *xbuffer;
|
||||
int8_t i2caddr, vccstate, page_end;
|
||||
int8_t mosiPin , clkPin , dcPin , csPin, rstPin;
|
||||
#ifdef HAVE_PORTREG
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
#include <Wire.h>
|
||||
#include <FT6236.h>
|
||||
|
||||
/*
|
||||
* This is a static library so we need to make sure we process stuff as quick as possible
|
||||
* as we do not want it to interfere with the RTOS by delaying routines unnecessarily.
|
||||
* So, no delay()'s etc and opto the code as much as possible.
|
||||
* ^^^ Need to be on TODO list to go through and make sure everything is as opto as
|
||||
* possible
|
||||
*/
|
||||
|
||||
uint8_t FT6236buf[FT6236_BUFFER_SIZE];
|
||||
uint8_t FT6236_i2c_addr = 0x38;
|
||||
uint8_t lenLibVersion = 0;
|
||||
uint8_t firmwareId = 0;
|
||||
|
||||
struct tbuttonregister {
|
||||
uint16_t BUTTONID;
|
||||
uint16_t xmin;
|
||||
uint16_t xmax;
|
||||
uint16_t ymin;
|
||||
uint16_t ymax;
|
||||
} buttonregister[FT6236_MAX_BUTTONS]; // we're limiting to 16 buttons for now - can reduce or increase later as needed.
|
||||
|
||||
uint8_t buttoncount = 0;
|
||||
|
||||
void FT6236flushbuttonregister(void) {
|
||||
uint16_t bid;
|
||||
for (bid=0;bid<FT6236_MAX_BUTTONS;bid++) {
|
||||
buttonregister[bid].BUTTONID=0;
|
||||
buttonregister[bid].xmin=0;
|
||||
buttonregister[bid].xmax=0;
|
||||
buttonregister[bid].ymin=0;
|
||||
buttonregister[bid].ymax=0;
|
||||
}
|
||||
buttoncount=0;
|
||||
}
|
||||
|
||||
void FT6236registerbutton(uint16_t buttonid,uint16_t xmin,uint16_t ymin,uint16_t xmax, uint16_t ymax) {
|
||||
buttonregister[buttoncount].BUTTONID=buttonid;
|
||||
buttonregister[buttoncount].xmin=xmin;
|
||||
buttonregister[buttoncount].xmax=xmax;
|
||||
buttonregister[buttoncount].ymin=ymin;
|
||||
buttonregister[buttoncount].ymax=ymax;
|
||||
buttoncount++;
|
||||
}
|
||||
|
||||
uint16_t FT6236GetButtonMask(void) {
|
||||
uint16 bid;
|
||||
TouchLocation tl[2];
|
||||
uint8_t count = FT6236readTouchLocation(tl,2);
|
||||
if (count > 0) {
|
||||
uint16_t x = tl[0].x;
|
||||
uint16_t y = tl[0].y;
|
||||
for (bid=0;bid<buttoncount;bid++) {
|
||||
if (x >= buttonregister[bid].xmin) {
|
||||
if (x <= buttonregister[bid].xmax) {
|
||||
if (y >= buttonregister[bid].ymin) {
|
||||
if (y <= buttonregister[bid].ymax) {
|
||||
return buttonregister[bid].BUTTONID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FT6236begin(uint8_t i2c_addr) {
|
||||
FT6236_i2c_addr=i2c_addr;
|
||||
Wire.begin(FT6236_i2c_addr);
|
||||
FT6236writeTouchRegister(0,FT6236_MODE_NORMAL);
|
||||
lenLibVersion = FT6236readTouchAddr(0x0a1, FT6236buf, 2 );
|
||||
firmwareId = FT6236readTouchRegister( 0xa6 );
|
||||
}
|
||||
|
||||
void FT6236writeTouchRegister(uint8_t reg, uint8_t val)
|
||||
{
|
||||
Wire.beginTransmission(FT6236_i2c_addr);
|
||||
Wire.write(reg); // register 0
|
||||
Wire.write(val); // value
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t FT6236readTouchRegister(uint8_t reg)
|
||||
{
|
||||
Wire.beginTransmission(FT6236_i2c_addr);
|
||||
Wire.write(reg); // register 0
|
||||
uint8_t retVal = Wire.endTransmission();
|
||||
uint8_t returned = Wire.requestFrom(FT6236_i2c_addr,uint8_t(1)); // request 6 uint8_ts from slave device #2
|
||||
if (Wire.available())
|
||||
{
|
||||
retVal = Wire.read();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
uint8_t FT6236readTouchAddr( uint8_t regAddr, uint8_t * pBuf, uint8_t len )
|
||||
{
|
||||
Wire.beginTransmission(FT6236_i2c_addr);
|
||||
Wire.write( regAddr ); // register 0
|
||||
uint8_t retVal = Wire.endTransmission();
|
||||
uint8_t returned = Wire.requestFrom(FT6236_i2c_addr, len); // request 1 bytes from slave device #2
|
||||
uint8_t i;
|
||||
for (i = 0; (i < len) && Wire.available(); i++) {
|
||||
pBuf[i] = Wire.read();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
uint8_t FT6236readTouchLocation( TouchLocation * pLoc, uint8_t num )
|
||||
{
|
||||
uint8_t retVal = 0;
|
||||
uint8_t i;
|
||||
uint8_t k;
|
||||
do
|
||||
{
|
||||
if (!pLoc) break; // must have a buffer
|
||||
if (!num) break; // must be able to take at least one
|
||||
uint8_t status = FT6236readTouchRegister(2);
|
||||
static uint8_t tbuf[40];
|
||||
if ((status & 0x0f) == 0) break; // no points detected
|
||||
uint8_t hitPoints = status & 0x0f;
|
||||
FT6236readTouchAddr( 0x03, tbuf, hitPoints*6);
|
||||
for (k=0,i = 0; (i < hitPoints*6)&&(k < num); k++, i += 6) {
|
||||
pLoc[k].x = (tbuf[i+0] & 0x0f) << 8 | tbuf[i+1];
|
||||
pLoc[k].y = (tbuf[i+2] & 0x0f) << 8 | tbuf[i+3];
|
||||
}
|
||||
retVal = k;
|
||||
} while (0);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
uint32_t FT6236dist(const TouchLocation & loc)
|
||||
{
|
||||
uint32_t retVal = 0;
|
||||
uint32_t x = loc.x;
|
||||
uint32_t y = loc.y;
|
||||
retVal = x*x + y*y;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
uint32_t FT6236dist(const TouchLocation & loc1, const TouchLocation & loc2)
|
||||
{
|
||||
uint32_t retVal = 0;
|
||||
uint32_t x = loc1.x - loc2.x;
|
||||
uint32_t y = loc1.y - loc2.y;
|
||||
retVal = sqrt(x*x + y*y);
|
||||
return retVal;
|
||||
}
|
||||
*/
|
||||
|
||||
bool FT6236sameLoc( const TouchLocation & loc, const TouchLocation & loc2 )
|
||||
{
|
||||
return FT6236dist(loc,loc2) < 50;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef FT6236
|
||||
#define FT6236
|
||||
|
||||
#define FT6236_MODE_NORMAL 0x00
|
||||
#define FT6236_MODE_TEST 0x04
|
||||
#define FT6236_MODE_SYSTEM 0x01
|
||||
|
||||
#define FT6236_BUFFER_SIZE 0x1E // 30 bytes buffer
|
||||
#define FT6236_MAX_BUTTONS 1 // 50 buttons should be enough for just about any page
|
||||
|
||||
struct TouchLocation {
|
||||
uint16_t y; // we swop x and y in position because we're using the screen in portrait mode
|
||||
uint16_t x;
|
||||
};
|
||||
|
||||
void FT6236flushbuttonregister(void);
|
||||
void FT6236registerbutton(uint16_t buttonid,uint16_t xmin,uint16_t ymin,uint16_t xmax, uint16_t ymax);
|
||||
uint16_t FT6236GetButtonMask(void);
|
||||
void FT6236begin(uint8_t i2c_addr);
|
||||
uint8_t FT6236readTouchRegister( uint8_t reg );
|
||||
uint8_t FT6236readTouchLocation( TouchLocation * pLoc, uint8_t num );
|
||||
uint8_t FT6236readTouchAddr( uint8_t regAddr, uint8_t * pBuf, uint8_t len );
|
||||
void FT6236writeTouchRegister( uint8_t reg, uint8_t val);
|
||||
uint32_t FT6236dist(const TouchLocation & loc);
|
||||
uint32_t FT6236dist(const TouchLocation & loc1, const TouchLocation & loc2);
|
||||
bool FT6236sameLoc( const TouchLocation & loc, const TouchLocation & loc2 );
|
||||
|
||||
#endif
|
|
@ -0,0 +1,172 @@
|
|||
/***************************************************
|
||||
STM32 Support added by Jaret Burkett at OSHlab.com
|
||||
|
||||
This is our library for the Adafruit ILI9488 Breakout and Shield
|
||||
----> http://www.adafruit.com/products/1651
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface (RST is optional)
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
MIT license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#ifndef _ILI9488H_
|
||||
#define _ILI9488H_
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
#include <renderer.h>
|
||||
#ifdef __AVR
|
||||
#include <avr/pgmspace.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <pgmspace.h>
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_STM32_FEATHER
|
||||
typedef volatile uint32 RwReg;
|
||||
#endif
|
||||
#if defined (__AVR__) || defined(TEENSYDUINO) || defined (__arm__) || defined (__STM32F1__)
|
||||
#define USE_FAST_PINIO
|
||||
#endif
|
||||
|
||||
#define ILI9488_TFTWIDTH 320
|
||||
#define ILI9488_TFTHEIGHT 480
|
||||
|
||||
#define ILI9488_NOP 0x00
|
||||
#define ILI9488_SWRESET 0x01
|
||||
#define ILI9488_RDDID 0x04
|
||||
#define ILI9488_RDDST 0x09
|
||||
|
||||
#define ILI9488_SLPIN 0x10
|
||||
#define ILI9488_SLPOUT 0x11
|
||||
#define ILI9488_PTLON 0x12
|
||||
#define ILI9488_NORON 0x13
|
||||
|
||||
#define ILI9488_RDMODE 0x0A
|
||||
#define ILI9488_RDMADCTL 0x0B
|
||||
#define ILI9488_RDPIXFMT 0x0C
|
||||
#define ILI9488_RDIMGFMT 0x0D
|
||||
#define ILI9488_RDSELFDIAG 0x0F
|
||||
|
||||
#define ILI9488_INVOFF 0x20
|
||||
#define ILI9488_INVON 0x21
|
||||
#define ILI9488_GAMMASET 0x26
|
||||
#define ILI9488_DISPOFF 0x28
|
||||
#define ILI9488_DISPON 0x29
|
||||
|
||||
#define ILI9488_CASET 0x2A
|
||||
#define ILI9488_PASET 0x2B
|
||||
#define ILI9488_RAMWR 0x2C
|
||||
#define ILI9488_RAMRD 0x2E
|
||||
|
||||
#define ILI9488_PTLAR 0x30
|
||||
#define ILI9488_MADCTL 0x36
|
||||
#define ILI9488_PIXFMT 0x3A
|
||||
|
||||
#define ILI9488_WRCTRLD 0x53
|
||||
#define ILI9488_CAPC9 0xCF
|
||||
|
||||
#define ILI9488_FRMCTR1 0xB1
|
||||
#define ILI9488_FRMCTR2 0xB2
|
||||
#define ILI9488_FRMCTR3 0xB3
|
||||
#define ILI9488_INVCTR 0xB4
|
||||
#define ILI9488_DFUNCTR 0xB6
|
||||
|
||||
#define ILI9488_PWCTR1 0xC0
|
||||
#define ILI9488_PWCTR2 0xC1
|
||||
#define ILI9488_PWCTR3 0xC2
|
||||
#define ILI9488_PWCTR4 0xC3
|
||||
#define ILI9488_PWCTR5 0xC4
|
||||
#define ILI9488_VMCTR1 0xC5
|
||||
#define ILI9488_VMCTR2 0xC7
|
||||
|
||||
#define ILI9488_RDID1 0xDA
|
||||
#define ILI9488_RDID2 0xDB
|
||||
#define ILI9488_RDID3 0xDC
|
||||
#define ILI9488_RDID4 0xDD
|
||||
|
||||
#define ILI9488_GMCTRP1 0xE0
|
||||
#define ILI9488_GMCTRN1 0xE1
|
||||
/*
|
||||
#define ILI9488_PWCTR6 0xFC
|
||||
|
||||
*/
|
||||
|
||||
#define PIN_OUT_SET 0x60000304
|
||||
#define PIN_OUT_CLEAR 0x60000308
|
||||
|
||||
// Color definitions
|
||||
#define ILI9488_BLACK 0x0000 /* 0, 0, 0 */
|
||||
#define ILI9488_NAVY 0x000F /* 0, 0, 128 */
|
||||
#define ILI9488_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
||||
#define ILI9488_DARKCYAN 0x03EF /* 0, 128, 128 */
|
||||
#define ILI9488_MAROON 0x7800 /* 128, 0, 0 */
|
||||
#define ILI9488_PURPLE 0x780F /* 128, 0, 128 */
|
||||
#define ILI9488_OLIVE 0x7BE0 /* 128, 128, 0 */
|
||||
#define ILI9488_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
||||
#define ILI9488_DARKGREY 0x7BEF /* 128, 128, 128 */
|
||||
#define ILI9488_BLUE 0x001F /* 0, 0, 255 */
|
||||
#define ILI9488_GREEN 0x07E0 /* 0, 255, 0 */
|
||||
#define ILI9488_CYAN 0x07FF /* 0, 255, 255 */
|
||||
#define ILI9488_RED 0xF800 /* 255, 0, 0 */
|
||||
#define ILI9488_MAGENTA 0xF81F /* 255, 0, 255 */
|
||||
#define ILI9488_YELLOW 0xFFE0 /* 255, 255, 0 */
|
||||
#define ILI9488_WHITE 0xFFFF /* 255, 255, 255 */
|
||||
#define ILI9488_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||
#define ILI9488_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||
#define ILI9488_PINK 0xF81F
|
||||
|
||||
|
||||
|
||||
|
||||
class ILI9488 : public Renderer {
|
||||
|
||||
public:
|
||||
|
||||
ILI9488(int8_t cs,int8_t mosi,int8_t sclk,int8_t bp);
|
||||
|
||||
void begin(void);
|
||||
void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
void setScrollArea(uint16_t topFixedArea, uint16_t bottomFixedArea);
|
||||
void scroll(uint16_t pixels);
|
||||
void pushColor(uint16_t color);
|
||||
void pushColors(uint16_t *data, uint8_t len, boolean first);
|
||||
//void drawImage(const uint8_t* img, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||
void fillScreen(uint16_t color);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h,uint16_t color);
|
||||
void setRotation(uint8_t r);
|
||||
void invertDisplay(boolean i);
|
||||
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
|
||||
uint16_t GetColorFromIndex(uint8_t index);
|
||||
void DisplayOnff(int8_t on);
|
||||
void writecommand(uint8_t c);
|
||||
void writedata(uint8_t d);
|
||||
void write16BitColor(uint16_t color);
|
||||
void commandList(uint8_t *addr);
|
||||
void hw_spi_init();
|
||||
|
||||
|
||||
private:
|
||||
uint8_t tabcolor;
|
||||
void fastSPIwrite(uint8_t d,uint8_t dc);
|
||||
void spi_lcd_mode_init(void);
|
||||
void start(void);
|
||||
void stop(void);
|
||||
int8_t _cs, _mosi, _sclk, _bp, _hwspi;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,8 @@
|
|||
### ILI9488 Arduino Library
|
||||
This library is for support for the 320x480 tft controller over 4 wire SPI. It is based heavily on the [Adafruit_ILI9341](https://github.com/adafruit/Adafruit_ILI9341) library and is designed to work with the [Adafruit_GFX library](https://github.com/adafruit/Adafruit-GFX-Library).
|
||||
|
||||
I have made some heavy modifications, as the typical Adafruit TFT libraries are designed to work with 16bit color (RGB565), and the ILI9488 can only do 24bit (RGB888) color in 4 wire SPI mode. You can still use the library EXACTLY like you would for 16bit mode color, the colors are converted before sending to the display. What this means is, things will be slower than normal. Not only do you have to write twice as many pixels as a normal 240x320 display, 153,600px (320x480) vs 76,800px (240x320), but you also have to do a lightweight conversion on each color, and write 3 bytes vs 2bytes per pixel.
|
||||
|
||||
For this reason, I do not recommend an AVR based Arduino for this library, although it will still work. I highly recommend a faster microcontroller based on ARM such as the Teensy, [STM32duino](https://github.com/rogerclarkmelbourne/Arduino_STM32), Arduino Zero, or the Arduing Due.
|
||||
|
||||
On the STM32duino, DMA is supported and is therefore much faster.
|
|
@ -0,0 +1,350 @@
|
|||
/***************************************************
|
||||
This is our GFX example for the Adafruit ILI9488 Breakout and Shield
|
||||
----> http://www.adafruit.com/products/1651
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface (RST is optional)
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
MIT license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
|
||||
#include "SPI.h"
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <ILI9488.h>
|
||||
|
||||
#define TFT_CS PA1
|
||||
#define TFT_DC PB3
|
||||
#define TFT_LED PB0
|
||||
#define TFT_RST PB4
|
||||
|
||||
// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
|
||||
ILI9488 tft = ILI9488(TFT_CS, TFT_DC, TFT_RST);
|
||||
// If using the breakout, change pins as desired
|
||||
//Adafruit_ILI9488 tft = Adafruit_ILI9488(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.println("ILI9488 Test!");
|
||||
|
||||
tft.begin();
|
||||
|
||||
// read diagnostics (optional but can help debug problems)
|
||||
uint8_t x = tft.readcommand8(ILI9488_RDMODE);
|
||||
Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
|
||||
x = tft.readcommand8(ILI9488_RDMADCTL);
|
||||
Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
|
||||
x = tft.readcommand8(ILI9488_RDPIXFMT);
|
||||
Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
|
||||
x = tft.readcommand8(ILI9488_RDIMGFMT);
|
||||
Serial.print("Image Format: 0x"); Serial.println(x, HEX);
|
||||
x = tft.readcommand8(ILI9488_RDSELFDIAG);
|
||||
Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
|
||||
|
||||
Serial.println(F("Benchmark Time (microseconds)"));
|
||||
|
||||
Serial.print(F("Screen fill "));
|
||||
Serial.println(testFillScreen());
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Text "));
|
||||
Serial.println(testText());
|
||||
delay(3000);
|
||||
|
||||
Serial.print(F("Lines "));
|
||||
Serial.println(testLines(ILI9488_CYAN));
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Horiz/Vert Lines "));
|
||||
Serial.println(testFastLines(ILI9488_RED, ILI9488_BLUE));
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Rectangles (outline) "));
|
||||
Serial.println(testRects(ILI9488_GREEN));
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Rectangles (filled) "));
|
||||
Serial.println(testFilledRects(ILI9488_YELLOW, ILI9488_MAGENTA));
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Circles (filled) "));
|
||||
Serial.println(testFilledCircles(10, ILI9488_MAGENTA));
|
||||
|
||||
Serial.print(F("Circles (outline) "));
|
||||
Serial.println(testCircles(10, ILI9488_WHITE));
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Triangles (outline) "));
|
||||
Serial.println(testTriangles());
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Triangles (filled) "));
|
||||
Serial.println(testFilledTriangles());
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Rounded rects (outline) "));
|
||||
Serial.println(testRoundRects());
|
||||
delay(500);
|
||||
|
||||
Serial.print(F("Rounded rects (filled) "));
|
||||
Serial.println(testFilledRoundRects());
|
||||
delay(500);
|
||||
|
||||
Serial.println(F("Done!"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {
|
||||
for(uint8_t rotation=0; rotation<4; rotation++) {
|
||||
tft.setRotation(rotation);
|
||||
testText();
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long testFillScreen() {
|
||||
unsigned long start = micros();
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
tft.fillScreen(ILI9488_RED);
|
||||
tft.fillScreen(ILI9488_GREEN);
|
||||
tft.fillScreen(ILI9488_BLUE);
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testText() {
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
unsigned long start = micros();
|
||||
tft.setCursor(0, 0);
|
||||
tft.setTextColor(ILI9488_WHITE); tft.setTextSize(1);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(ILI9488_YELLOW); tft.setTextSize(2);
|
||||
tft.println(1234.56);
|
||||
tft.setTextColor(ILI9488_RED); tft.setTextSize(3);
|
||||
tft.println(0xDEADBEEF, HEX);
|
||||
tft.println();
|
||||
tft.setTextColor(ILI9488_GREEN);
|
||||
tft.setTextSize(5);
|
||||
tft.println("Groop");
|
||||
tft.setTextSize(2);
|
||||
tft.println("I implore thee,");
|
||||
tft.setTextSize(1);
|
||||
tft.println("my foonting turlingdromes.");
|
||||
tft.println("And hooptiously drangle me");
|
||||
tft.println("with crinkly bindlewurdles,");
|
||||
tft.println("Or I will rend thee");
|
||||
tft.println("in the gobberwarts");
|
||||
tft.println("with my blurglecruncheon,");
|
||||
tft.println("see if I don't!");
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testLines(uint16_t color) {
|
||||
unsigned long start, t;
|
||||
int x1, y1, x2, y2,
|
||||
w = tft.width(),
|
||||
h = tft.height();
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
|
||||
x1 = y1 = 0;
|
||||
y2 = h - 1;
|
||||
start = micros();
|
||||
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
x2 = w - 1;
|
||||
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
t = micros() - start; // fillScreen doesn't count against timing
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
|
||||
x1 = w - 1;
|
||||
y1 = 0;
|
||||
y2 = h - 1;
|
||||
start = micros();
|
||||
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
x2 = 0;
|
||||
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
t += micros() - start;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
|
||||
x1 = 0;
|
||||
y1 = h - 1;
|
||||
y2 = 0;
|
||||
start = micros();
|
||||
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
x2 = w - 1;
|
||||
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
t += micros() - start;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
|
||||
x1 = w - 1;
|
||||
y1 = h - 1;
|
||||
y2 = 0;
|
||||
start = micros();
|
||||
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
x2 = 0;
|
||||
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testFastLines(uint16_t color1, uint16_t color2) {
|
||||
unsigned long start;
|
||||
int x, y, w = tft.width(), h = tft.height();
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
start = micros();
|
||||
for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
|
||||
for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testRects(uint16_t color) {
|
||||
unsigned long start;
|
||||
int n, i, i2,
|
||||
cx = tft.width() / 2,
|
||||
cy = tft.height() / 2;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
n = min(tft.width(), tft.height());
|
||||
start = micros();
|
||||
for(i=2; i<n; i+=6) {
|
||||
i2 = i / 2;
|
||||
tft.drawRect(cx-i2, cy-i2, i, i, color);
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
|
||||
unsigned long start, t = 0;
|
||||
int n, i, i2,
|
||||
cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
n = min(tft.width(), tft.height());
|
||||
for(i=n; i>0; i-=6) {
|
||||
i2 = i / 2;
|
||||
start = micros();
|
||||
tft.fillRect(cx-i2, cy-i2, i, i, color1);
|
||||
t += micros() - start;
|
||||
// Outlines are not included in timing results
|
||||
tft.drawRect(cx-i2, cy-i2, i, i, color2);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
|
||||
unsigned long start;
|
||||
int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
start = micros();
|
||||
for(x=radius; x<w; x+=r2) {
|
||||
for(y=radius; y<h; y+=r2) {
|
||||
tft.fillCircle(x, y, radius, color);
|
||||
}
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testCircles(uint8_t radius, uint16_t color) {
|
||||
unsigned long start;
|
||||
int x, y, r2 = radius * 2,
|
||||
w = tft.width() + radius,
|
||||
h = tft.height() + radius;
|
||||
|
||||
// Screen is not cleared for this one -- this is
|
||||
// intentional and does not affect the reported time.
|
||||
start = micros();
|
||||
for(x=0; x<w; x+=r2) {
|
||||
for(y=0; y<h; y+=r2) {
|
||||
tft.drawCircle(x, y, radius, color);
|
||||
}
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testTriangles() {
|
||||
unsigned long start;
|
||||
int n, i, cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
n = min(cx, cy);
|
||||
start = micros();
|
||||
for(i=0; i<n; i+=5) {
|
||||
tft.drawTriangle(
|
||||
cx , cy - i, // peak
|
||||
cx - i, cy + i, // bottom left
|
||||
cx + i, cy + i, // bottom right
|
||||
tft.color565(0, 0, i));
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testFilledTriangles() {
|
||||
unsigned long start, t = 0;
|
||||
int i, cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
start = micros();
|
||||
for(i=min(cx,cy); i>10; i-=5) {
|
||||
start = micros();
|
||||
tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
|
||||
tft.color565(0, i, i));
|
||||
t += micros() - start;
|
||||
tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
|
||||
tft.color565(i, i, 0));
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
unsigned long testRoundRects() {
|
||||
unsigned long start;
|
||||
int w, i, i2,
|
||||
cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
w = min(tft.width(), tft.height());
|
||||
start = micros();
|
||||
for(i=0; i<w; i+=6) {
|
||||
i2 = i / 2;
|
||||
tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testFilledRoundRects() {
|
||||
unsigned long start;
|
||||
int i, i2,
|
||||
cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(ILI9488_BLACK);
|
||||
start = micros();
|
||||
for(i=min(tft.width(), tft.height()); i>20; i-=6) {
|
||||
i2 = i / 2;
|
||||
tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ILI9488 KEYWORD1
|
||||
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
setRotation KEYWORD2
|
||||
setAddrWindow KEYWORD2
|
||||
pushColor KEYWORD2
|
||||
drawPixel KEYWORD2
|
||||
drawFastVLine KEYWORD2
|
||||
drawFastHLine KEYWORD2
|
||||
fillRect KEYWORD2
|
||||
setRotation KEYWORD2
|
||||
setRotation KEYWORD2
|
||||
height KEYWORD2
|
||||
width KEYWORD2
|
||||
invertDisplay KEYWORD2
|
||||
drawImage KEYWORD2
|
||||
setScrollArea KEYWORD2
|
||||
scroll KEYWORD2
|
|
@ -0,0 +1,9 @@
|
|||
name=ILI9488
|
||||
version=1.0.2
|
||||
author=Jaret Burkett
|
||||
maintainer=Jaret Burkett <jaretburkett@gmail.com>
|
||||
sentence=Library for ILI9488 displays
|
||||
paragraph=Library for ILI9488 displays
|
||||
category=Display
|
||||
url=https://github.com/jaretburkett/ILI9488
|
||||
architectures=*
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2010 - 2011 Espressif System
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SPI_REGISTER_H_INCLUDED
|
||||
#define SPI_REGISTER_H_INCLUDED
|
||||
|
||||
#define REG_SPI_BASE(i) (0x60000200-i*0x100)
|
||||
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
|
||||
#define SPI_USR (BIT(18))
|
||||
|
||||
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
|
||||
|
||||
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
|
||||
#define SPI_WR_BIT_ORDER (BIT(26))
|
||||
#define SPI_RD_BIT_ORDER (BIT(25))
|
||||
#define SPI_QIO_MODE (BIT(24))
|
||||
#define SPI_DIO_MODE (BIT(23))
|
||||
#define SPI_QOUT_MODE (BIT(20))
|
||||
#define SPI_DOUT_MODE (BIT(14))
|
||||
#define SPI_FASTRD_MODE (BIT(13))
|
||||
|
||||
|
||||
|
||||
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
|
||||
|
||||
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
|
||||
|
||||
#define SPI_CS_DELAY_NUM 0x0000000F
|
||||
#define SPI_CS_DELAY_NUM_S 28
|
||||
#define SPI_CS_DELAY_MODE 0x00000003
|
||||
#define SPI_CS_DELAY_MODE_S 26
|
||||
#define SPI_MOSI_DELAY_NUM 0x00000007
|
||||
#define SPI_MOSI_DELAY_NUM_S 23
|
||||
#define SPI_MOSI_DELAY_MODE 0x00000003
|
||||
#define SPI_MOSI_DELAY_MODE_S 21
|
||||
#define SPI_MISO_DELAY_NUM 0x00000007
|
||||
#define SPI_MISO_DELAY_NUM_S 18
|
||||
#define SPI_MISO_DELAY_MODE 0x00000003
|
||||
#define SPI_MISO_DELAY_MODE_S 16
|
||||
#define SPI_CK_OUT_HIGH_MODE 0x0000000F
|
||||
#define SPI_CK_OUT_HIGH_MODE_S 12
|
||||
#define SPI_CK_OUT_LOW_MODE 0x0000000F
|
||||
#define SPI_CK_OUT_LOW_MODE_S 8
|
||||
|
||||
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
|
||||
#define SPI_CLK_EQU_SYSCLK (BIT(31))
|
||||
#define SPI_CLKDIV_PRE 0x00001FFF
|
||||
#define SPI_CLKDIV_PRE_S 18
|
||||
#define SPI_CLKCNT_N 0x0000003F
|
||||
#define SPI_CLKCNT_N_S 12
|
||||
#define SPI_CLKCNT_H 0x0000003F
|
||||
#define SPI_CLKCNT_H_S 6
|
||||
#define SPI_CLKCNT_L 0x0000003F
|
||||
#define SPI_CLKCNT_L_S 0
|
||||
|
||||
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
|
||||
#define SPI_USR_COMMAND (BIT(31))
|
||||
#define SPI_USR_ADDR (BIT(30))
|
||||
#define SPI_USR_DUMMY (BIT(29))
|
||||
#define SPI_USR_MISO (BIT(28))
|
||||
#define SPI_USR_MOSI (BIT(27))
|
||||
|
||||
#define SPI_USR_MOSI_HIGHPART (BIT(25))
|
||||
#define SPI_USR_MISO_HIGHPART (BIT(24))
|
||||
|
||||
|
||||
#define SPI_SIO (BIT(16))
|
||||
#define SPI_FWRITE_QIO (BIT(15))
|
||||
#define SPI_FWRITE_DIO (BIT(14))
|
||||
#define SPI_FWRITE_QUAD (BIT(13))
|
||||
#define SPI_FWRITE_DUAL (BIT(12))
|
||||
#define SPI_WR_BYTE_ORDER (BIT(11))
|
||||
#define SPI_RD_BYTE_ORDER (BIT(10))
|
||||
#define SPI_CK_OUT_EDGE (BIT(7))
|
||||
#define SPI_CK_I_EDGE (BIT(6))
|
||||
#define SPI_CS_SETUP (BIT(5))
|
||||
#define SPI_CS_HOLD (BIT(4))
|
||||
#define SPI_FLASH_MODE (BIT(2))
|
||||
#define SPI_DOUTDIN (BIT(0))
|
||||
|
||||
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
|
||||
#define SPI_USR_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_USR_ADDR_BITLEN_S 26
|
||||
#define SPI_USR_MOSI_BITLEN 0x000001FF
|
||||
#define SPI_USR_MOSI_BITLEN_S 17
|
||||
#define SPI_USR_MISO_BITLEN 0x000001FF
|
||||
#define SPI_USR_MISO_BITLEN_S 8
|
||||
|
||||
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
|
||||
#define SPI_USR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
|
||||
#define SPI_USR_COMMAND_BITLEN 0x0000000F
|
||||
#define SPI_USR_COMMAND_BITLEN_S 28
|
||||
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
|
||||
#define SPI_USR_COMMAND_VALUE_S 0
|
||||
|
||||
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
|
||||
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
|
||||
#define SPI_CS2_DIS (BIT(2))
|
||||
#define SPI_CS1_DIS (BIT(1))
|
||||
#define SPI_CS0_DIS (BIT(0))
|
||||
#define SPI_IDLE_EDGE (BIT(29))
|
||||
|
||||
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
|
||||
#define SPI_SYNC_RESET (BIT(31))
|
||||
#define SPI_SLAVE_MODE (BIT(30))
|
||||
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
|
||||
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
|
||||
#define SPI_SLV_CMD_DEFINE (BIT(27))
|
||||
#define SPI_TRANS_CNT 0x0000000F
|
||||
#define SPI_TRANS_CNT_S 23
|
||||
#define SPI_TRANS_DONE_EN (BIT(9))
|
||||
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
|
||||
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
|
||||
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
|
||||
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
|
||||
|
||||
|
||||
|
||||
#define SLV_SPI_INT_EN 0x0000001f
|
||||
#define SLV_SPI_INT_EN_S 5
|
||||
|
||||
#define SPI_TRANS_DONE (BIT(4))
|
||||
#define SPI_SLV_WR_STA_DONE (BIT(3))
|
||||
#define SPI_SLV_RD_STA_DONE (BIT(2))
|
||||
#define SPI_SLV_WR_BUF_DONE (BIT(1))
|
||||
#define SPI_SLV_RD_BUF_DONE (BIT(0))
|
||||
|
||||
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
|
||||
#define SPI_SLV_STATUS_BITLEN 0x0000001F
|
||||
#define SPI_SLV_STATUS_BITLEN_S 27
|
||||
#define SPI_SLV_BUF_BITLEN 0x000001FF
|
||||
#define SPI_SLV_BUF_BITLEN_S 16
|
||||
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_SLV_RD_ADDR_BITLEN_S 10
|
||||
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_SLV_WR_ADDR_BITLEN_S 4
|
||||
|
||||
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
|
||||
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
|
||||
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
|
||||
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
|
||||
|
||||
|
||||
|
||||
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
|
||||
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
|
||||
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
|
||||
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
|
||||
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
|
||||
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
|
||||
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
|
||||
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
|
||||
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
|
||||
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
|
||||
|
||||
#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
|
||||
#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
|
||||
#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
|
||||
#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
|
||||
#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
|
||||
#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
|
||||
#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
|
||||
#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
|
||||
#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
|
||||
#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
|
||||
#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
|
||||
#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
|
||||
#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
|
||||
#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
|
||||
#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
|
||||
#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
|
||||
|
||||
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
|
||||
#define SPI_INT_HOLD_ENA 0x00000003
|
||||
#define SPI_INT_HOLD_ENA_S 0
|
||||
#endif // SPI_REGISTER_H_INCLUDED
|
|
@ -0,0 +1,569 @@
|
|||
/***************************************************
|
||||
STM32 Support added by Jaret Burkett at OSHlab.com
|
||||
|
||||
This is our library for the Adafruit RA8876 Breakout and Shield
|
||||
----> http://www.adafruit.com/products/1651
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface (RST is optional)
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
MIT license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#ifndef _RA8876H_
|
||||
#define _RA8876H_
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <SPI.h>
|
||||
#include <renderer.h>
|
||||
|
||||
#define SPRINT(A) {char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);}
|
||||
|
||||
|
||||
#define RA8876_TFTWIDTH 1024
|
||||
#define RA8876_TFTHEIGHT 600
|
||||
|
||||
struct SdramInfo
|
||||
{
|
||||
int speed; // MHz
|
||||
int casLatency; // CAS latency (2 or 3)
|
||||
int banks; // Banks (2 or 4)
|
||||
int rowBits; // Row addressing bits (11-13)
|
||||
int colBits; // Column addressing bits (8-12)
|
||||
int refresh; // Refresh time in microseconds
|
||||
};
|
||||
|
||||
struct DisplayInfo
|
||||
{
|
||||
int width; // Display width
|
||||
int height; // Display height
|
||||
|
||||
uint32_t dotClock; // Pixel clock in kHz
|
||||
|
||||
int hFrontPorch; // Will be rounded to the nearest multiple of 8
|
||||
int hBackPorch;
|
||||
int hPulseWidth; // Will be rounded to the nearest multiple of 8
|
||||
|
||||
int vFrontPorch;
|
||||
int vBackPorch;
|
||||
int vPulseWidth;
|
||||
};
|
||||
|
||||
// Data sheet section 6.1.
|
||||
// Output frequency is: (m_oscClock * (n + 1)) / (2 ** k)
|
||||
// There is also a PLL parameter named 'm', but it's unclear how its value could ever be non-zero.
|
||||
// When it is zero, the divisor is (2 ** 0) = 1, so we simply ignore it.
|
||||
struct PllParams
|
||||
{
|
||||
uint32_t freq; // Frequency in kHz
|
||||
int n; // Multiplier less 1 (range 1..63)
|
||||
int k; // Divisor power of 2 (range 0..3 for CCLK/MCLK; range 0..7 for SCLK)
|
||||
};
|
||||
|
||||
#define RGB332(r, g, b) (((r) & 0xE0) | (((g) & 0xE0) >> 3) | (((b) & 0xE0) >> 6))
|
||||
#define RGB565(r, g, b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3))
|
||||
|
||||
enum FontSource
|
||||
{
|
||||
RA8876_FONT_SOURCE_INTERNAL, // CGROM with four 8-bit ISO Latin variants
|
||||
RA8876_FONT_SOURCE_EXT_ROM // External font ROM chip
|
||||
};
|
||||
|
||||
enum FontSize
|
||||
{
|
||||
RA8876_FONT_SIZE_16 = 0x00,
|
||||
RA8876_FONT_SIZE_24 = 0x01,
|
||||
RA8876_FONT_SIZE_32 = 0x02
|
||||
};
|
||||
|
||||
enum FontEncoding
|
||||
{
|
||||
RA8876_FONT_ENCODING_GB2312 = 0x00, // GB2312 (Simplified Chinese)
|
||||
RA8876_FONT_ENCODING_GB18030 = 0x01, // GB12345/GB18030 (Chinese)
|
||||
RA8876_FONT_ENCODING_BIG5 = 0x02, // Big5 (Traditional Chinese)
|
||||
|
||||
RA8876_FONT_ENCODING_UNICODE = 0x03, // Unicode (UCS-2?)
|
||||
|
||||
RA8876_FONT_ENCODING_ASCII = 0x04, // ASCII
|
||||
|
||||
RA8876_FONT_ENCODING_UNIJAPAN = 0x05, // Uni-Japanese (?)
|
||||
RA8876_FONT_ENCODING_JIS0208 = 0x06, // JIS X 0208 (Shift JIS?)
|
||||
|
||||
RA8876_FONT_ENCODING_LGCATH = 0x07, // Latin/Greek/Cyrillic/Arabic/Thai/Hebrew (?)
|
||||
|
||||
RA8876_FONT_ENCODING_8859_1 = 0x11, // ISO 8859-1 (Latin 1)
|
||||
RA8876_FONT_ENCODING_8859_2 = 0x12, // ISO 8859-2 (Latin 2: Eastern European)
|
||||
RA8876_FONT_ENCODING_8859_3 = 0x13, // ISO 8859-3 (Latin 3: South European)
|
||||
RA8876_FONT_ENCODING_8859_4 = 0x14, // ISO 8859-4 (Latin 4: Northern European)
|
||||
RA8876_FONT_ENCODING_8859_5 = 0x15, // ISO 8859-5 (Latin/Cyrillic)
|
||||
RA8876_FONT_ENCODING_8859_7 = 0x16, // ISO 8859-7 (Latin/Greek)
|
||||
RA8876_FONT_ENCODING_8859_8 = 0x17, // ISO 8859-8 (Latin/Hebrew)
|
||||
RA8876_FONT_ENCODING_8859_9 = 0x18, // ISO 8859-9 (Latin 5: Turkish)
|
||||
RA8876_FONT_ENCODING_8859_10 = 0x19, // ISO 8859-10 (Latin 6: Nordic)
|
||||
RA8876_FONT_ENCODING_8859_11 = 0x1A, // ISO 8859-11 (Latin/Thai)
|
||||
RA8876_FONT_ENCODING_8859_13 = 0x1B, // ISO 8859-13 (Latin 7: Baltic Rim)
|
||||
RA8876_FONT_ENCODING_8859_14 = 0x1C, // ISO 8859-14 (Latin 8: Celtic)
|
||||
RA8876_FONT_ENCODING_8859_15 = 0x1D, // ISO 8859-15 (Latin 9: Western European)
|
||||
RA8876_FONT_ENCODING_8859_16 = 0x1E // ISO 8859-16 (Latin 10: South-Eastern European)
|
||||
};
|
||||
|
||||
enum ExternalFontRom
|
||||
{
|
||||
RA8876_FONT_ROM_GT21L16T1W = 0,
|
||||
RA8876_FONT_ROM_GT30L16U2W = 1,
|
||||
RA8876_FONT_ROM_GT30L24T3Y = 2,
|
||||
RA8876_FONT_ROM_GT30L24M1Z = 3,
|
||||
RA8876_FONT_ROM_GT30L32S4W = 4,
|
||||
RA8876_FONT_ROM_GT20L24F6Y = 5,
|
||||
RA8876_FONT_ROM_GT21L24S1W = 6
|
||||
};
|
||||
|
||||
struct ExternalFontRomInfo
|
||||
{
|
||||
bool present;
|
||||
int spiInterface; // SPI interface that font ROM is connected to (0 or 1)
|
||||
int spiClockDivisor; // SPI interface clock divisor (2..512 in steps of 2)
|
||||
enum ExternalFontRom chip; // Chip type
|
||||
};
|
||||
|
||||
enum ExternalFontFamily
|
||||
{
|
||||
RA8876_FONT_FAMILY_FIXED = 0,
|
||||
RA8876_FONT_FAMILY_ARIAL = 1,
|
||||
RA8876_FONT_FAMILY_TIMES = 2,
|
||||
RA8876_FONT_FAMILY_FIXED_BOLD = 3
|
||||
};
|
||||
|
||||
typedef uint8_t FontFlags;
|
||||
#define RA8876_FONT_FLAG_XLAT_FULLWIDTH 0x01 // Translate ASCII to Unicode fullwidth forms
|
||||
|
||||
// 1MHz. TODO: Figure out actual speed to use
|
||||
// Data sheet section 5.2 says maximum SPI clock is 50MHz.
|
||||
//#define RA8876_SPI_SPEED 10000000
|
||||
#define RA8876_SPI_SPEED 20000000
|
||||
|
||||
// With SPI, the RA8876 expects an initial byte where the top two bits are meaningful. Bit 7
|
||||
// is A0, bit 6 is WR#. See data sheet section 7.3.2 and section 19.
|
||||
// A0: 0 for command/status, 1 for data
|
||||
// WR#: 0 for write, 1 for read
|
||||
#define RA8876_DATA_WRITE 0x80
|
||||
#define RA8876_DATA_READ 0xC0
|
||||
#define RA8876_CMD_WRITE 0x00
|
||||
#define RA8876_STATUS_READ 0x40
|
||||
|
||||
// Data sheet 19.2: Chip configuration registers
|
||||
#define RA8876_REG_SRR 0x00 // Software Reset Register
|
||||
#define RA8876_REG_CCR 0x01 // Chip Configuration Register
|
||||
#define RA8876_REG_MACR 0x02 // Memory Access Control Register
|
||||
#define RA8876_REG_ICR 0x03 // Input Control Register
|
||||
#define RA8876_REG_MRWDP 0x04 // Memory Read/Write Data Port
|
||||
|
||||
// Data sheet 19.3: PLL setting registers
|
||||
#define RA8876_REG_PPLLC1 0x05 // SCLK PLL control register 1
|
||||
#define RA8876_REG_PPLLC2 0x06 // SCLK PLL control register 2
|
||||
#define RA8876_REG_MPLLC1 0x07 // MCLK PLL control register 1
|
||||
#define RA8876_REG_MPLLC2 0x08 // MCLK PLL control register 2
|
||||
#define RA8876_REG_SPLLC1 0x09 // CCLK PLL control register 1
|
||||
#define RA8876_REG_SPLLC2 0x0A // CCLK PLL control register 2
|
||||
|
||||
// Data sheet 19.5: LCD display control registers
|
||||
#define RA8876_REG_MPWCTR 0x10 // Main/PIP Window Control Register
|
||||
#define RA8876_REG_PIPCDEP 0x11 // PIP Window Color Depth register
|
||||
#define RA8876_REG_DPCR 0x12 // Display configuration register
|
||||
#define RA8876_REG_PCSR 0x13 // Panel scan clock and data setting register
|
||||
#define RA8876_REG_HDWR 0x14 // Horizontal Display Width Register
|
||||
#define RA8876_REG_HDWFTR 0x15 // Horizontal Display Width Fine Tuning Register
|
||||
#define RA8876_REG_HNDR 0x16 // Horizontal Non-Display Period Register
|
||||
#define RA8876_REG_HNDFTR 0x17 // Horizontal Non-Display Period Fine Tuning Register
|
||||
#define RA8876_REG_HSTR 0x18 // HSYNC start position register
|
||||
#define RA8876_REG_HPWR 0x19 // HSYNC Pulse Width Register
|
||||
#define RA8876_REG_VDHR0 0x1A // Vertical Display Height Register 0
|
||||
#define RA8876_REG_VDHR1 0x1B // Vertical Display Height Register 1
|
||||
#define RA8876_REG_VNDR0 0x1C // Vertical Non-Display Period Register 0
|
||||
#define RA8876_REG_VNDR1 0x1D // Vertical Non-Display Period Register 1
|
||||
#define RA8876_REG_VSTR 0x1E // VSYNC start position register
|
||||
#define RA8876_REG_VPWR 0x1F // VSYNC pulse width register
|
||||
#define RA8876_REG_MISA0 0x20 // Main Image Start Address 0
|
||||
#define RA8876_REG_MISA1 0x21 // Main Image Start Address 1
|
||||
#define RA8876_REG_MISA2 0x22 // Main Image Start Address 2
|
||||
#define RA8876_REG_MISA3 0x23 // Main Image Start Address 3
|
||||
#define RA8876_REG_MIW0 0x24 // Main Image Width 0
|
||||
#define RA8876_REG_MIW1 0x25 // Main Image Width 1
|
||||
#define RA8876_REG_MWULX0 0x26 // Main Window Upper-Left X coordinate 0
|
||||
#define RA8876_REG_MWULX1 0x27 // Main Window Upper-Left X coordinate 1
|
||||
#define RA8876_REG_MWULY0 0x28 // Main Window Upper-Left Y coordinate 0
|
||||
#define RA8876_REG_MWULY1 0x29 // Main Window Upper-Left Y coordinate 1
|
||||
|
||||
// Data sheet 19.6: Geometric engine control registers
|
||||
#define RA8876_REG_CVSSA0 0x50 // Canvas Start Address 0
|
||||
#define RA8876_REG_CVSSA1 0x51 // Canvas Start Address 1
|
||||
#define RA8876_REG_CVSSA2 0x52 // Canvas Start Address 2
|
||||
#define RA8876_REG_CVSSA3 0x53 // Canvas Start Address 3
|
||||
#define RA8876_REG_CVS_IMWTH0 0x54 // Canvas image width 0
|
||||
#define RA8876_REG_CVS_IMWTH1 0x55 // Canvas image width 1
|
||||
#define RA8876_REG_AWUL_X0 0x56 // Active Window Upper-Left X coordinate 0
|
||||
#define RA8876_REG_AWUL_X1 0x57 // Active Window Upper-Left X coordinate 1
|
||||
#define RA8876_REG_AWUL_Y0 0x58 // Active Window Upper-Left Y coordinate 0
|
||||
#define RA8876_REG_AWUL_Y1 0x59 // Active Window Upper-Left Y coordinate 1
|
||||
#define RA8876_REG_AW_WTH0 0x5A // Active Window Width 0
|
||||
#define RA8876_REG_AW_WTH1 0x5B // Active Window Width 1
|
||||
#define RA8876_REG_AW_HT0 0x5C // Active Window Height 0
|
||||
#define RA8876_REG_AW_HT1 0x5D // Active Window Height 1
|
||||
#define RA8876_REG_AW_COLOR 0x5E // Color Depth of canvas & active window
|
||||
#define RA8876_REG_CURH0 0x5F // Graphic read/write horizontal position 0
|
||||
#define RA8876_REG_CURH1 0x60 // Graphic read/write horizontal position 1
|
||||
#define RA8876_REG_CURV0 0x61 // Graphic read/write vertical position 0
|
||||
#define RA8876_REG_CURV1 0x62 // Graphic read/write vertical position 1
|
||||
#define RA8876_REG_F_CURX0 0x63 // Text cursor X-coordinate register 0
|
||||
#define RA8876_REG_F_CURX1 0x64 // Text cursor X-coordinate register 1
|
||||
#define RA8876_REG_F_CURY0 0x65 // Text cursor Y-coordinate register 0
|
||||
#define RA8876_REG_F_CURY1 0x66 // Text cursor Y-coordinate register 1
|
||||
|
||||
#define RA8876_REG_DCR0 0x67 // Draw shape control register 0
|
||||
|
||||
#define RA8876_REG_DLHSR0 0x68 // Draw shape point 1 X coordinate register 0
|
||||
#define RA8876_REG_DLHSR1 0x69 // Draw shape point 1 X coordinate register 1
|
||||
#define RA8876_REG_DLVSR0 0x6A // Draw shape point 1 Y coordinate register 0
|
||||
#define RA8876_REG_DLVSR1 0x6B // Draw shape point 1 Y coordinate register 1
|
||||
|
||||
#define RA8876_REG_DLHER0 0x6C // Draw shape point 2 X coordinate register 0
|
||||
#define RA8876_REG_DLHER1 0x6D // Draw shape point 2 X coordinate register 1
|
||||
#define RA8876_REG_DLVER0 0x6E // Draw shape point 2 Y coordinate register 0
|
||||
#define RA8876_REG_DLVER1 0x6F // Draw shape point 2 Y coordinate register 1
|
||||
|
||||
#define RA8876_REG_DTPH0 0x70 // Draw shape point 3 X coordinate register 0
|
||||
#define RA8876_REG_DTPH1 0x71 // Draw shape point 3 X coordinate register 1
|
||||
#define RA8876_REG_DTPV0 0x72 // Draw shape point 3 Y coordinate register 0
|
||||
#define RA8876_REG_DTPV1 0x73 // Draw shape point 3 Y coordinate register 1
|
||||
|
||||
#define RA8876_REG_DCR1 0x76 // Draw shape control register 1
|
||||
|
||||
#define RA8876_REG_ELL_A0 0x77 // Draw ellipse major radius 0
|
||||
#define RA8876_REG_ELL_A1 0x78 // Draw ellipse major radius 1
|
||||
#define RA8876_REG_ELL_B0 0x79 // Draw ellipse minor radius 0
|
||||
#define RA8876_REG_ELL_B1 0x7A // Draw ellipse minor radius 1
|
||||
|
||||
#define RA8876_REG_DEHR0 0x7B // Draw ellipse centre X coordinate register 0
|
||||
#define RA8876_REG_DEHR1 0x7C // Draw ellipse centre X coordinate register 1
|
||||
#define RA8876_REG_DEVR0 0x7D // Draw ellipse centre Y coordinate register 0
|
||||
#define RA8876_REG_DEVR1 0x7E // Draw ellipse centre Y coordinate register 1
|
||||
|
||||
// Data sheet 19.7: PWM timer control registers
|
||||
#define RA8876_REG_PSCLR 0x84 // PWM prescaler register
|
||||
#define RA8876_REG_PMUXR 0x85 // PWM clock mux register
|
||||
#define RA8876_REG_PCFGR 0x86 // PWM configuration register
|
||||
|
||||
#define RA8876_REG_TCMPB0L 0x88
|
||||
#define RA8876_REG_TCMPB0H 0x89
|
||||
#define RA8876_REG_TCNTB0L 0x8A
|
||||
#define RA8876_REG_TCNTB0H 0x8B
|
||||
#define RA8876_REG_TCMPB1L 0x8C
|
||||
#define RA8876_REG_TCMPB1H 0x8D
|
||||
#define RA8876_REG_TCNTB1L 0x8E
|
||||
#define RA8876_REG_TCNTB1H 0x8F
|
||||
|
||||
#define RA8876_REG_BTE_CTRL0 0x90
|
||||
#define RA8876_REG_BTE_CTRL1 0x91
|
||||
#define RA8876_REG_BTE_COLR 0x92
|
||||
|
||||
#define RA8876_REG_S1_STR0 0x9D
|
||||
#define RA8876_REG_S1_STR1 0x9E
|
||||
#define RA8876_REG_S1_STR2 0x9F
|
||||
#define RA8876_REG_S1_STR3 0xA0
|
||||
|
||||
#define RA8876_REG_S1_WTH0 0xA1
|
||||
#define RA8876_REG_S1_WTH1 0xA2
|
||||
|
||||
#define RA8876_REG_S1_X0 0xA3
|
||||
#define RA8876_REG_S1_X1 0xA4
|
||||
#define RA8876_REG_S1_Y0 0xA5
|
||||
#define RA8876_REG_S1_Y1 0xA6
|
||||
|
||||
#define RA8876_REG_DT_STR0 0xA7
|
||||
#define RA8876_REG_DT_STR1 0xA8
|
||||
#define RA8876_REG_DT_STR2 0xA9
|
||||
#define RA8876_REG_DT_STR3 0xAA
|
||||
|
||||
#define RA8876_REG_DT_WTH0 0xAB
|
||||
#define RA8876_REG_DT_WTH1 0xAC
|
||||
|
||||
#define RA8876_REG_DT_X0 0xAD
|
||||
#define RA8876_REG_DT_X1 0xAE
|
||||
#define RA8876_REG_DT_Y0 0xAF
|
||||
#define RA8876_REG_DT_Y1 0xB0
|
||||
|
||||
#define RA8876_REG_BTE_WTH0 0xB1
|
||||
#define RA8876_REG_BTE_WTH1 0xB2
|
||||
#define RA8876_REG_BTE_HIG0 0xB3
|
||||
#define RA8876_REG_BTE_HIG1 0xB4
|
||||
|
||||
|
||||
// Data sheet 19.9: Serial flash & SPI master control registers
|
||||
#define RA8876_REG_SFL_CTRL 0xB7 // Serial flash/ROM control register
|
||||
#define RA8876_REG_SPI_DIVSOR 0xBB // SPI clock period
|
||||
|
||||
// Data sheet 19.10: Text engine
|
||||
#define RA8876_REG_CCR0 0xCC // Character Control Register 0
|
||||
#define RA8876_REG_CCR1 0xCD // Character Control Register 1
|
||||
#define RA8876_REG_GTFNT_SEL 0xCE // Genitop character ROM select
|
||||
#define RA8876_REG_GTFNT_CR 0xCF // Genitop character ROM control register
|
||||
|
||||
#define RA8876_REG_FLDR 0xD0 // Chracter line gap register
|
||||
#define RA8876_REG_F2FSSR 0xD1 // Chracter to character space setting register
|
||||
#define RA8876_REG_FGCR 0xD2 // Foreground colour register - red
|
||||
#define RA8876_REG_FGCG 0xD3 // Foreground colour register - green
|
||||
#define RA8876_REG_FGCB 0xD4 // Foreground colour register - blue
|
||||
|
||||
#define RA8876_REG_BGCR 0xD5 // background colour register - red
|
||||
#define RA8876_REG_BGCG 0xD6 // background colour register - green
|
||||
#define RA8876_REG_BGCB 0xD7 // background colour register - blue
|
||||
|
||||
// Data sheet 19.12: SDRAM control registers
|
||||
#define RA8876_REG_SDRAR 0xE0 // SDRAM attribute register
|
||||
#define RA8876_REG_SDRMD 0xE1 // SDRAM mode & extended mode register
|
||||
#define RA8876_REG_SDR_REF_ITVL0 0xE2 // SDRAM auto refresh interval 0
|
||||
#define RA8876_REG_SDR_REF_ITVL1 0xE3 // SDRAM auto refresh interval 1
|
||||
#define RA8876_REG_SDRCR 0xE4 // SDRAM control register
|
||||
|
||||
|
||||
// Color definitions
|
||||
#define RA8876_BLACK 0x0000 /* 0, 0, 0 */
|
||||
#define RA8876_NAVY 0x000F /* 0, 0, 128 */
|
||||
#define RA8876_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
||||
#define RA8876_DARKCYAN 0x03EF /* 0, 128, 128 */
|
||||
#define RA8876_MAROON 0x7800 /* 128, 0, 0 */
|
||||
#define RA8876_PURPLE 0x780F /* 128, 0, 128 */
|
||||
#define RA8876_OLIVE 0x7BE0 /* 128, 128, 0 */
|
||||
#define RA8876_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
||||
#define RA8876_DARKGREY 0x7BEF /* 128, 128, 128 */
|
||||
#define RA8876_BLUE 0x001F /* 0, 0, 255 */
|
||||
#define RA8876_GREEN 0x07E0 /* 0, 255, 0 */
|
||||
#define RA8876_CYAN 0x07FF /* 0, 255, 255 */
|
||||
#define RA8876_RED 0xF800 /* 255, 0, 0 */
|
||||
#define RA8876_MAGENTA 0xF81F /* 255, 0, 255 */
|
||||
#define RA8876_YELLOW 0xFFE0 /* 255, 255, 0 */
|
||||
#define RA8876_WHITE 0xFFFF /* 255, 255, 255 */
|
||||
#define RA8876_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||
#define RA8876_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||
#define RA8876_PINK 0xF81F
|
||||
|
||||
|
||||
#define RA8876_PSCLR 0x84
|
||||
#define RA8876_PRESCALER 0x03
|
||||
#define RA8876_PMUXR 0x85
|
||||
#define RA8876_PWM_TIMER_DIV1 0
|
||||
#define RA8876_PWM_TIMER_DIV2 1
|
||||
#define RA8876_PWM_TIMER_DIV4 2
|
||||
#define RA8876_PWM_TIMER_DIV8 3
|
||||
#define RA8876_XPWM1_OUTPUT_ERROR_FLAG 0
|
||||
#define RA8876_XPWM1_OUTPUT_PWM_TIMER1 2
|
||||
#define RA8876_XPWM1_OUTPUT_OSC_CLK 3
|
||||
#define RA8876_XPWM0_GPIO_C7 0
|
||||
#define RA8876_XPWM0_OUTPUT_PWM_TIMER0 2
|
||||
#define RA8876_XPWM0_OUTPUT_CORE_CLK 3
|
||||
|
||||
#define RA8876_PCFGR 0x86
|
||||
#define RA8876_PWM_TIMER1_INVERTER_OFF 0
|
||||
#define RA8876_PWM_TIMER1_INVERTER_ON 1
|
||||
#define RA8876_PWM_TIMER1_ONE_SHOT 0
|
||||
#define RA8876_PWM_TIMER1_AUTO_RELOAD 1
|
||||
#define RA8876_PWM_TIMER1_STOP 0
|
||||
#define RA8876_PWM_TIMER1_START 1
|
||||
#define RA8876_PWM_TIMER0_DEAD_ZONE_DISABLE 0
|
||||
#define RA8876_PWM_TIMER0_DEAD_ZONE_ENABLE 1
|
||||
#define RA8876_PWM_TIMER0_INVERTER_OFF 0
|
||||
#define RA8876_PWM_TIMER0_INVERTER_ON 1
|
||||
#define RA8876_PWM_TIMER0_ONE_SHOT 0
|
||||
#define RA8876_PWM_TIMER0_AUTO_RELOAD 1
|
||||
#define RA8876_PWM_TIMER0_STOP 0
|
||||
#define RA8876_PWM_TIMER0_START 1
|
||||
|
||||
#define RA8876_BTE_CTRL0 0x90
|
||||
#define RA8876_BTE_ENABLE 1
|
||||
#define RA8876_PATTERN_FORMAT8X8 0
|
||||
#define RA8876_PATTERN_FORMAT16X16 1
|
||||
#define RA8876_BTE_CTRL1 0x91
|
||||
#define RA8876_DESTINATION_COLOR_DEPTH_16BPP 1
|
||||
#define RA8876_S0_COLOR_DEPTH_16BPP 1
|
||||
#define RA8876_S1_COLOR_DEPTH_16BPP 1
|
||||
|
||||
#define RA8876_BTE_ROP_CODE_0 0 //0 ( Blackness )
|
||||
#define RA8876_BTE_ROP_CODE_1 1 //~S0・~S1 or ~ ( S0+S1 )
|
||||
#define RA8876_BTE_ROP_CODE_2 2 //~S0・S1
|
||||
#define RA8876_BTE_ROP_CODE_3 3 //~S0
|
||||
#define RA8876_BTE_ROP_CODE_4 4 //S0・~S1
|
||||
#define RA8876_BTE_ROP_CODE_5 5 //~S1
|
||||
#define RA8876_BTE_ROP_CODE_6 6 //S0^S1
|
||||
#define RA8876_BTE_ROP_CODE_7 7 //~S0+~S1 or ~ ( S0・S1 )
|
||||
#define RA8876_BTE_ROP_CODE_8 8 //S0・S1
|
||||
#define RA8876_BTE_ROP_CODE_9 9 //~ ( S0^S1 )
|
||||
#define RA8876_BTE_ROP_CODE_10 10 //S1
|
||||
#define RA8876_BTE_ROP_CODE_11 11 //~S0+S1
|
||||
#define RA8876_BTE_ROP_CODE_12 12 //S0
|
||||
#define RA8876_BTE_ROP_CODE_13 13 //S0+~S1
|
||||
#define RA8876_BTE_ROP_CODE_14 14 //S0+S1
|
||||
#define RA8876_BTE_ROP_CODE_15 15 //1 ( Whiteness )
|
||||
#define RA8876_BTE_ROP_BUS_WIDTH8 7
|
||||
#define RA8876_BTE_ROP_BUS_WIDTH16 15
|
||||
|
||||
#define RA8876_BTE_MPU_WRITE_WITH_ROP 0
|
||||
#define RA8876_BTE_MEMORY_COPY_WITH_ROP 2
|
||||
#define RA8876_BTE_MPU_WRITE_WITH_CHROMA 4
|
||||
#define RA8876_BTE_MEMORY_COPY_WITH_CHROMA 5
|
||||
#define RA8876_BTE_PATTERN_FILL_WITH_ROP 6
|
||||
#define RA8876_BTE_PATTERN_FILL_WITH_CHROMA 7
|
||||
#define RA8876_BTE_MPU_WRITE_COLOR_EXPANSION 8
|
||||
#define RA8876_BTE_MPU_WRITE_COLOR_EXPANSION_WITH_CHROMA 9
|
||||
#define RA8876_BTE_MEMORY_COPY_WITH_OPACITY 10
|
||||
#define RA8876_BTE_MPU_WRITE_WITH_OPACITY 11
|
||||
#define RA8876_BTE_SOLID_FILL 12
|
||||
#define RA8876_BTE_MEMORY_COPY_WITH_COLOR_EXPANSION 14
|
||||
#define RA8876_BTE_MEMORY_COPY_WITH_COLOR_EXPANSION_CHROMA 15
|
||||
|
||||
#define RA8876_BTE_COLR 0x92
|
||||
|
||||
class RA8876 : public Renderer {
|
||||
|
||||
public:
|
||||
|
||||
RA8876(int8_t cs,int8_t mosi,int8_t miso,int8_t sclk,int8_t bp);
|
||||
|
||||
bool begin(void);
|
||||
|
||||
// Dimensions
|
||||
int getWidth() { return m_width; };
|
||||
int getHeight() { return m_height; };
|
||||
|
||||
void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||
|
||||
// Test
|
||||
void colorBarTest(bool enabled);
|
||||
|
||||
// Drawing
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void drawRect(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void fillRect(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void fillScreen(uint16_t color);
|
||||
void drawTriangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, uint16_t color);
|
||||
void fillTriangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, uint16_t color);
|
||||
|
||||
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
|
||||
|
||||
void drawCircle(int16_t x, int16_t y, int16_t radius, uint16_t color);
|
||||
void fillCircle(int16_t x, int16_t y, int16_t radius, uint16_t color);
|
||||
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
|
||||
void clearScreen(uint16_t color);
|
||||
|
||||
// Text cursor
|
||||
void setCursor(int16_t x, int16_t y);
|
||||
int getCursorX(void);
|
||||
int getCursorY(void);
|
||||
|
||||
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
void pushColors(uint16_t *data, uint8_t len, boolean first);
|
||||
|
||||
// Text
|
||||
void selectInternalFont(enum FontSize size, enum FontEncoding enc = RA8876_FONT_ENCODING_8859_1);
|
||||
void selectExternalFont(enum ExternalFontFamily family, enum FontSize size, enum FontEncoding enc, FontFlags flags = 0);
|
||||
int getTextSizeY(void);
|
||||
//void setTextColor(uint16_t color);
|
||||
//void setTextColor(uint16_t c, uint16_t bg);
|
||||
void setTextScale(int scale);
|
||||
void setTextSize(uint8_t s);
|
||||
void setTextScale(int xScale, int yScale);
|
||||
void putChar(char c) { putChars(&c, 1); };
|
||||
void putChars(const char *buffer, size_t size);
|
||||
void putChar16(uint16_t c) { putChars16(&c, 1); };
|
||||
void putChars16(const uint16_t *buffer, unsigned int count);
|
||||
|
||||
// Internal for Print class
|
||||
size_t xwrite(uint8_t c);
|
||||
size_t xwrite(const uint8_t *buffer, size_t size);
|
||||
|
||||
uint16_t GetColorFromIndex(uint8_t index);
|
||||
void DisplayOnff(int8_t on);
|
||||
void setRotation(uint8_t m);
|
||||
void setDrawMode(uint8_t mode);
|
||||
void setDrawMode_reg(uint8_t mode);
|
||||
void dim(uint8_t contrast);
|
||||
void FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str);
|
||||
|
||||
private:
|
||||
uint8_t tabcolor;
|
||||
void PWM_init(void);
|
||||
void wait_ready(void);
|
||||
void softReset(void);
|
||||
void writeCmd(uint8_t x);
|
||||
void writeData(uint8_t x);
|
||||
uint8_t readData(void);
|
||||
uint8_t readStatus(void);
|
||||
void writeReg(uint8_t reg, uint8_t x);
|
||||
void writeReg16(uint8_t reg, uint16_t x);
|
||||
uint8_t readReg(uint8_t reg);
|
||||
uint16_t readReg16(uint8_t reg);
|
||||
void waitWriteFifo(void);
|
||||
void waitTaskBusy(void);
|
||||
|
||||
bool calcPllParams(uint32_t targetFreq, int kMax, PllParams *pll);
|
||||
bool calcClocks(void);
|
||||
void dumpClocks(void);
|
||||
|
||||
bool initPLL(void);
|
||||
bool initMemory(SdramInfo *info);
|
||||
bool initDisplay(void);
|
||||
|
||||
// Font utils
|
||||
uint8_t internalFontEncoding(enum FontEncoding enc);
|
||||
|
||||
// Text/graphics mode
|
||||
void setTextMode(void);
|
||||
void setGraphicsMode(void);
|
||||
|
||||
// Low-level shapes
|
||||
void drawTwoPointShape(int x1, int y1, int x2, int y2, uint16_t color, uint8_t reg, uint8_t cmd); // drawLine, drawRect, fillRect
|
||||
void drawThreePointShape(int x1, int y1, int x2, int y2, int x3, int y3, uint16_t color, uint8_t reg, uint8_t cmd); // drawTriangle, fillTriangle
|
||||
void drawEllipseShape(int x, int y, int xrad, int yrad, uint16_t color, uint8_t cmd); // drawCircle, fillCircle
|
||||
void drawThreePointShape1(int x1, int y1, int x2, int y2, int x3, int y3, uint16_t color, uint8_t reg, uint8_t cmd);
|
||||
|
||||
int8_t m_csPin, _mosi, _miso, _sclk, dimmer, _hwspi;
|
||||
uint16_t m_width;
|
||||
uint16_t m_height;
|
||||
uint16_t m_depth;
|
||||
uint32_t m_oscClock; // OSC clock (external crystal) frequency in kHz
|
||||
|
||||
PllParams m_memPll; // MCLK (memory) PLL parameters
|
||||
PllParams m_corePll; // CCLK (core) PLL parameters
|
||||
PllParams m_scanPll; // SCLK (LCD panel scan) PLL parameters
|
||||
|
||||
SPISettings m_spiSettings;
|
||||
|
||||
SdramInfo *m_sdramInfo;
|
||||
|
||||
DisplayInfo *m_displayInfo;
|
||||
|
||||
ExternalFontRomInfo m_fontRomInfo;
|
||||
|
||||
uint16_t addrw_x1;
|
||||
uint16_t addrw_x2;
|
||||
|
||||
//uint16_t m_textColor;
|
||||
int m_textScaleX;
|
||||
int m_textScaleY;
|
||||
|
||||
enum FontSource m_fontSource;
|
||||
enum FontSize m_fontSize;
|
||||
FontFlags m_fontFlags;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,8 @@
|
|||
### RA8876 Arduino Library
|
||||
This library is for support for the 1024x600 tft controller over 3 wire SPI. It is based heavily on the [Adafruit_ILI9341](https://github.com/adafruit/Adafruit_ILI9341) library and is designed to work with the [Adafruit_GFX library](https://github.com/adafruit/Adafruit-GFX-Library).
|
||||
|
||||
I have made some heavy modifications, as the typical Adafruit TFT libraries are designed to work with 16bit color (RGB565), and the RA8876 can only do 24bit (RGB888) color in 4 wire SPI mode. You can still use the library EXACTLY like you would for 16bit mode color, the colors are converted before sending to the display. What this means is, things will be slower than normal. Not only do you have to write twice as many pixels as a normal 240x320 display, 153,600px (320x480) vs 76,800px (240x320), but you also have to do a lightweight conversion on each color, and write 3 bytes vs 2bytes per pixel.
|
||||
|
||||
For this reason, I do not recommend an AVR based Arduino for this library, although it will still work. I highly recommend a faster microcontroller based on ARM such as the Teensy, [STM32duino](https://github.com/rogerclarkmelbourne/Arduino_STM32), Arduino Zero, or the Arduing Due.
|
||||
|
||||
On the STM32duino, DMA is supported and is therefore much faster.
|
|
@ -0,0 +1,30 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
RA8876 KEYWORD1
|
||||
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
setRotation KEYWORD2
|
||||
setAddrWindow KEYWORD2
|
||||
pushColor KEYWORD2
|
||||
drawPixel KEYWORD2
|
||||
drawFastVLine KEYWORD2
|
||||
drawFastHLine KEYWORD2
|
||||
fillRect KEYWORD2
|
||||
setRotation KEYWORD2
|
||||
setRotation KEYWORD2
|
||||
height KEYWORD2
|
||||
width KEYWORD2
|
||||
invertDisplay KEYWORD2
|
||||
drawImage KEYWORD2
|
||||
setScrollArea KEYWORD2
|
||||
scroll KEYWORD2
|
|
@ -0,0 +1,9 @@
|
|||
name=RA8876
|
||||
version=1.0.2
|
||||
author=Jaret Burkett
|
||||
maintainer=Jaret Burkett <jaretburkett@gmail.com>
|
||||
sentence=Library for RA8876 displays
|
||||
paragraph=Library for RA8876 displays
|
||||
category=Display
|
||||
url=https://github.com/jaretburkett/ILI9488
|
||||
architectures=*
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2010 - 2011 Espressif System
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SPI_REGISTER_H_INCLUDED
|
||||
#define SPI_REGISTER_H_INCLUDED
|
||||
|
||||
#define REG_SPI_BASE(i) (0x60000200-i*0x100)
|
||||
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
|
||||
#define SPI_USR (BIT(18))
|
||||
|
||||
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
|
||||
|
||||
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
|
||||
#define SPI_WR_BIT_ORDER (BIT(26))
|
||||
#define SPI_RD_BIT_ORDER (BIT(25))
|
||||
#define SPI_QIO_MODE (BIT(24))
|
||||
#define SPI_DIO_MODE (BIT(23))
|
||||
#define SPI_QOUT_MODE (BIT(20))
|
||||
#define SPI_DOUT_MODE (BIT(14))
|
||||
#define SPI_FASTRD_MODE (BIT(13))
|
||||
|
||||
|
||||
|
||||
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
|
||||
|
||||
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
|
||||
|
||||
#define SPI_CS_DELAY_NUM 0x0000000F
|
||||
#define SPI_CS_DELAY_NUM_S 28
|
||||
#define SPI_CS_DELAY_MODE 0x00000003
|
||||
#define SPI_CS_DELAY_MODE_S 26
|
||||
#define SPI_MOSI_DELAY_NUM 0x00000007
|
||||
#define SPI_MOSI_DELAY_NUM_S 23
|
||||
#define SPI_MOSI_DELAY_MODE 0x00000003
|
||||
#define SPI_MOSI_DELAY_MODE_S 21
|
||||
#define SPI_MISO_DELAY_NUM 0x00000007
|
||||
#define SPI_MISO_DELAY_NUM_S 18
|
||||
#define SPI_MISO_DELAY_MODE 0x00000003
|
||||
#define SPI_MISO_DELAY_MODE_S 16
|
||||
#define SPI_CK_OUT_HIGH_MODE 0x0000000F
|
||||
#define SPI_CK_OUT_HIGH_MODE_S 12
|
||||
#define SPI_CK_OUT_LOW_MODE 0x0000000F
|
||||
#define SPI_CK_OUT_LOW_MODE_S 8
|
||||
|
||||
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
|
||||
#define SPI_CLK_EQU_SYSCLK (BIT(31))
|
||||
#define SPI_CLKDIV_PRE 0x00001FFF
|
||||
#define SPI_CLKDIV_PRE_S 18
|
||||
#define SPI_CLKCNT_N 0x0000003F
|
||||
#define SPI_CLKCNT_N_S 12
|
||||
#define SPI_CLKCNT_H 0x0000003F
|
||||
#define SPI_CLKCNT_H_S 6
|
||||
#define SPI_CLKCNT_L 0x0000003F
|
||||
#define SPI_CLKCNT_L_S 0
|
||||
|
||||
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
|
||||
#define SPI_USR_COMMAND (BIT(31))
|
||||
#define SPI_USR_ADDR (BIT(30))
|
||||
#define SPI_USR_DUMMY (BIT(29))
|
||||
#define SPI_USR_MISO (BIT(28))
|
||||
#define SPI_USR_MOSI (BIT(27))
|
||||
|
||||
#define SPI_USR_MOSI_HIGHPART (BIT(25))
|
||||
#define SPI_USR_MISO_HIGHPART (BIT(24))
|
||||
|
||||
|
||||
#define SPI_SIO (BIT(16))
|
||||
#define SPI_FWRITE_QIO (BIT(15))
|
||||
#define SPI_FWRITE_DIO (BIT(14))
|
||||
#define SPI_FWRITE_QUAD (BIT(13))
|
||||
#define SPI_FWRITE_DUAL (BIT(12))
|
||||
#define SPI_WR_BYTE_ORDER (BIT(11))
|
||||
#define SPI_RD_BYTE_ORDER (BIT(10))
|
||||
#define SPI_CK_OUT_EDGE (BIT(7))
|
||||
#define SPI_CK_I_EDGE (BIT(6))
|
||||
#define SPI_CS_SETUP (BIT(5))
|
||||
#define SPI_CS_HOLD (BIT(4))
|
||||
#define SPI_FLASH_MODE (BIT(2))
|
||||
#define SPI_DOUTDIN (BIT(0))
|
||||
|
||||
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
|
||||
#define SPI_USR_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_USR_ADDR_BITLEN_S 26
|
||||
#define SPI_USR_MOSI_BITLEN 0x000001FF
|
||||
#define SPI_USR_MOSI_BITLEN_S 17
|
||||
#define SPI_USR_MISO_BITLEN 0x000001FF
|
||||
#define SPI_USR_MISO_BITLEN_S 8
|
||||
|
||||
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
|
||||
#define SPI_USR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
|
||||
#define SPI_USR_COMMAND_BITLEN 0x0000000F
|
||||
#define SPI_USR_COMMAND_BITLEN_S 28
|
||||
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
|
||||
#define SPI_USR_COMMAND_VALUE_S 0
|
||||
|
||||
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
|
||||
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
|
||||
#define SPI_CS2_DIS (BIT(2))
|
||||
#define SPI_CS1_DIS (BIT(1))
|
||||
#define SPI_CS0_DIS (BIT(0))
|
||||
#define SPI_IDLE_EDGE (BIT(29))
|
||||
|
||||
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
|
||||
#define SPI_SYNC_RESET (BIT(31))
|
||||
#define SPI_SLAVE_MODE (BIT(30))
|
||||
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
|
||||
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
|
||||
#define SPI_SLV_CMD_DEFINE (BIT(27))
|
||||
#define SPI_TRANS_CNT 0x0000000F
|
||||
#define SPI_TRANS_CNT_S 23
|
||||
#define SPI_TRANS_DONE_EN (BIT(9))
|
||||
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
|
||||
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
|
||||
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
|
||||
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
|
||||
|
||||
|
||||
|
||||
#define SLV_SPI_INT_EN 0x0000001f
|
||||
#define SLV_SPI_INT_EN_S 5
|
||||
|
||||
#define SPI_TRANS_DONE (BIT(4))
|
||||
#define SPI_SLV_WR_STA_DONE (BIT(3))
|
||||
#define SPI_SLV_RD_STA_DONE (BIT(2))
|
||||
#define SPI_SLV_WR_BUF_DONE (BIT(1))
|
||||
#define SPI_SLV_RD_BUF_DONE (BIT(0))
|
||||
|
||||
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
|
||||
#define SPI_SLV_STATUS_BITLEN 0x0000001F
|
||||
#define SPI_SLV_STATUS_BITLEN_S 27
|
||||
#define SPI_SLV_BUF_BITLEN 0x000001FF
|
||||
#define SPI_SLV_BUF_BITLEN_S 16
|
||||
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_SLV_RD_ADDR_BITLEN_S 10
|
||||
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_SLV_WR_ADDR_BITLEN_S 4
|
||||
|
||||
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
|
||||
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
|
||||
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
|
||||
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
|
||||
|
||||
|
||||
|
||||
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
|
||||
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
|
||||
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
|
||||
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
|
||||
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
|
||||
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
|
||||
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
|
||||
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
|
||||
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
|
||||
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
|
||||
|
||||
#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
|
||||
#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
|
||||
#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
|
||||
#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
|
||||
#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
|
||||
#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
|
||||
#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
|
||||
#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
|
||||
#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
|
||||
#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
|
||||
#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
|
||||
#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
|
||||
#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
|
||||
#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
|
||||
#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
|
||||
#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
|
||||
|
||||
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
|
||||
#define SPI_INT_HOLD_ENA 0x00000003
|
||||
#define SPI_INT_HOLD_ENA_S 0
|
||||
#endif // SPI_REGISTER_H_INCLUDED
|
|
@ -0,0 +1,2 @@
|
|||
### SSD3115 Arduino Library
|
||||
This library is for support for the 128x128 oled controller over 3 wire SPI. It is based heavily on the [Adafruit_SSD1351](https://github.com/adafruit/Adafruit-SSD1351-library) library and is designed to work with the [Adafruit_GFX library](https://github.com/adafruit/Adafruit-GFX-Library).
|
|
@ -0,0 +1,520 @@
|
|||
/***************************************************
|
||||
This is our library for the Adafruit SSD1351 Breakout and Shield
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface (RST is optional)
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
MIT license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
#include <SPI.h>
|
||||
#include "SSD1351.h"
|
||||
#include <limits.h>
|
||||
#include <pgmspace.h>
|
||||
|
||||
|
||||
const uint16_t ssd1351_colors[]={SSD1351_BLACK,SSD1351_WHITE,SSD1351_RED,SSD1351_GREEN,SSD1351_BLUE,SSD1351_CYAN,SSD1351_MAGENTA,\
|
||||
SSD1351_YELLOW,SSD1351_NAVY,SSD1351_DARKGREEN,SSD1351_DARKCYAN,SSD1351_MAROON,SSD1351_PURPLE,SSD1351_OLIVE,\
|
||||
SSD1351_LIGHTGREY,SSD1351_DARKGREY,SSD1351_ORANGE,SSD1351_GREENYELLOW,SSD1351_PINK};
|
||||
|
||||
// Constructor when using software SPI. All output pins are configurable.
|
||||
SSD1351::SSD1351(int8_t cs,int8_t mosi,int8_t sclk) : Renderer(SSD1351_WIDTH, SSD1351_HEIGHT) {
|
||||
_cs = cs;
|
||||
_mosi = mosi;
|
||||
_sclk = sclk;
|
||||
_hwspi = 0;
|
||||
}
|
||||
|
||||
#include "spi_register.h"
|
||||
|
||||
/* CPU Clock = 80 Mhz
|
||||
max clock of display is 4.545 Mhz (220ns sclk cycle)
|
||||
so cpu/18 => 4.44 Mhz should be ok
|
||||
HSPI CLK 5 GPIO14
|
||||
HSPI /CS 8 GPIO15
|
||||
HSPI MOSI 7 GPIO13
|
||||
*/
|
||||
|
||||
uint8_t ssd131_start;
|
||||
|
||||
uint32_t ssd1351_clock;
|
||||
uint32_t ssd1351_usr;
|
||||
uint32_t ssd1351_usr1;
|
||||
uint32_t ssd1351_usr2;
|
||||
uint32_t ssd1351_spi1c;
|
||||
uint32_t ssd1351_spi1p;
|
||||
//uint32_t ssd1351_gpmux;
|
||||
uint32_t ssd1351_mtdo;
|
||||
|
||||
|
||||
uint32_t ssd1351_clock_prev;
|
||||
uint32_t ssd1351_usr_prev;
|
||||
uint32_t ssd1351_usr1_prev;
|
||||
uint32_t ssd1351_usr2_prev;
|
||||
uint32_t ssd1351_spi1c_prev;
|
||||
uint32_t ssd1351_spi1p_prev;
|
||||
//uint32_t ssd1351_gpmux_prev;
|
||||
uint32_t ssd1351_mtdo_prev;
|
||||
|
||||
// code from espressif SDK
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_lcd_mode_init
|
||||
* Description : SPI master initial function for driving LCD 3 wire spi
|
||||
*******************************************************************************/
|
||||
void SSD1351::spi_lcd_mode_init(void) {
|
||||
uint32 regvalue;
|
||||
|
||||
ssd1351_clock_prev=SPI1CLK;
|
||||
ssd1351_usr_prev=SPI1U;
|
||||
ssd1351_usr1_prev=SPI1U1;
|
||||
ssd1351_usr2_prev=SPI1U2;
|
||||
ssd1351_spi1c_prev=SPI1C;
|
||||
ssd1351_spi1p_prev=SPI1P;
|
||||
//ssd1351_gpmux_prev=GPMUX;
|
||||
ssd1351_mtdo_prev=READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U);
|
||||
|
||||
SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE;
|
||||
SPI1U1=0;
|
||||
SPI1C = 0;
|
||||
|
||||
//bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock
|
||||
//bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock
|
||||
|
||||
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9
|
||||
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure miso to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure mosi to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure sclk to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure cs to spi mode
|
||||
|
||||
// the current implementation leaves about 1 us between transfers ????
|
||||
// due to lack of documentation i could not find the reason
|
||||
// skipping this would double the speed !!!
|
||||
|
||||
//SET_PERI_REG_MASK(SPI_USER(1), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND);
|
||||
|
||||
SET_PERI_REG_MASK(SPI_USER(1), SPI_USR_COMMAND);
|
||||
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_FLASH_MODE);
|
||||
// SPI clock=CPU clock/8 => 10 Mhz
|
||||
/*
|
||||
WRITE_PERI_REG(SPI_CLOCK(1),
|
||||
((1&SPI_CLKDIV_PRE)<<SPI_CLKDIV_PRE_S)|
|
||||
((3&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)|
|
||||
((1&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)|
|
||||
((3&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
|
||||
*/
|
||||
// will result in 80/18 = 4,4 Mhz
|
||||
SPI.setFrequency(4500000);
|
||||
|
||||
ssd1351_clock=SPI1CLK;
|
||||
ssd1351_usr=SPI1U;
|
||||
ssd1351_usr1=SPI1U1;
|
||||
ssd1351_usr2=SPI1U2;
|
||||
ssd1351_spi1c=SPI1C;
|
||||
ssd1351_spi1p=SPI1P;
|
||||
//ssd1351_gpmux=GPMUX;
|
||||
ssd1351_mtdo=READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U);
|
||||
ssd131_start=0;
|
||||
}
|
||||
|
||||
void SSD1351::start(void) {
|
||||
if (ssd131_start) return;
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
while(READ_PERI_REG(SPI_CMD(1))&SPI_USR);
|
||||
SPI1CLK=ssd1351_clock;
|
||||
SPI1U=ssd1351_usr;
|
||||
SPI1U1=ssd1351_usr1;
|
||||
SPI1U2=ssd1351_usr2;
|
||||
SPI1C=ssd1351_spi1c;
|
||||
SPI1P=ssd1351_spi1p;
|
||||
//GPMUX=ssd1351_gpmux;
|
||||
WRITE_PERI_REG(PERIPHS_IO_MUX_MTDO_U,ssd1351_mtdo);
|
||||
ssd131_start=1;
|
||||
}
|
||||
|
||||
void SSD1351::stop(void) {
|
||||
if (!ssd131_start) return;
|
||||
//while(SPI1CMD & SPIBUSY) {}
|
||||
while(READ_PERI_REG(SPI_CMD(1))&SPI_USR);
|
||||
SPI1CLK=ssd1351_clock_prev;
|
||||
SPI1U=ssd1351_usr_prev;
|
||||
SPI1U1=ssd1351_usr1_prev;
|
||||
SPI1U2=ssd1351_usr2_prev;
|
||||
SPI1C=ssd1351_spi1c_prev;
|
||||
SPI1P=ssd1351_spi1p_prev;
|
||||
//GPMUX=ssd1351_gpmux_prev;
|
||||
WRITE_PERI_REG(PERIPHS_IO_MUX_MTDO_U,ssd1351_mtdo_prev);
|
||||
ssd131_start=0;
|
||||
}
|
||||
|
||||
// dc = 0
|
||||
void SSD1351::writecommand(uint8_t c) {
|
||||
if (_hwspi) {
|
||||
uint32_t regvalue;
|
||||
uint8_t bytetemp;
|
||||
bytetemp=(c>>1)&0x7f;
|
||||
|
||||
start();
|
||||
|
||||
//#define SPI_USR_COMMAND_BITLEN 0x0000000F
|
||||
//#define SPI_USR_COMMAND_BITLEN_S 28
|
||||
|
||||
regvalue= ((8&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|((uint32)bytetemp); //configure transmission variable,9bit transmission length and first 8 command bit
|
||||
if(c&0x01) regvalue|=BIT15; //write the 9th bit
|
||||
while(READ_PERI_REG(SPI_CMD(1))&SPI_USR); //waiting for spi module available
|
||||
WRITE_PERI_REG(SPI_USER2(1), regvalue); //write command and command length into spi reg
|
||||
SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR); //transmission start
|
||||
} else fastSPIwrite(c,0);
|
||||
}
|
||||
|
||||
// dc = 1
|
||||
void SSD1351::writedata(uint8_t d) {
|
||||
if (_hwspi) {
|
||||
uint32_t regvalue;
|
||||
uint8_t bytetemp;
|
||||
bytetemp=(d>>1)|0x80;
|
||||
|
||||
start();
|
||||
|
||||
regvalue= ((8&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|((uint32)bytetemp); //configure transmission variable,9bit transmission length and first 8 command bit
|
||||
if(d&0x01) regvalue|=BIT15; //write the 9th bit
|
||||
while(READ_PERI_REG(SPI_CMD(1))&SPI_USR); //waiting for spi module available
|
||||
WRITE_PERI_REG(SPI_USER2(1), regvalue); //write command and command length into spi reg
|
||||
SET_PERI_REG_MASK(SPI_CMD(1), SPI_USR); //transmission start
|
||||
} else fastSPIwrite(d,1);
|
||||
}
|
||||
|
||||
|
||||
uint16_t SSD1351::GetColorFromIndex(uint8_t index) {
|
||||
if (index>=sizeof(ssd1351_colors)/2) index=0;
|
||||
return ssd1351_colors[index];
|
||||
}
|
||||
|
||||
void SSD1351::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
setRotation(rot);
|
||||
invertDisplay(false);
|
||||
setTextWrap(false); // Allow text to run off edges
|
||||
cp437(true);
|
||||
setTextFont(font&3);
|
||||
setTextSize(size&7);
|
||||
setTextColor(SSD1351_WHITE,SSD1351_BLACK);
|
||||
setCursor(0,0);
|
||||
fillScreen(SSD1351_BLACK);
|
||||
stop();
|
||||
}
|
||||
|
||||
void SSD1351::DisplayOnff(int8_t on) {
|
||||
if (on) {
|
||||
writecommand(SSD1351_CMD_DISPLAYON); //Display on
|
||||
} else {
|
||||
writecommand(SSD1351_CMD_DISPLAYOFF);
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
// dimmer 0-100
|
||||
void SSD1351::dim(uint8_t contrast) {
|
||||
writecommand(SSD1351_CMD_CONTRASTMASTER);
|
||||
if (contrast>15) contrast=15;
|
||||
writedata(contrast);
|
||||
stop();
|
||||
}
|
||||
|
||||
/*
|
||||
if (SSD_COMSPLIT == 1){
|
||||
_remapReg |= ((1 << 5));
|
||||
} else {
|
||||
_remapReg |= ((0 << 5));
|
||||
}
|
||||
setRegister_cont(CMD_CMDLOCK,SSD_COMMANDLOCK1);
|
||||
setRegister_cont(CMD_CMDLOCK,SSD_COMMANDLOCK2);
|
||||
writecommand_cont(CMD_DISPLAYOFF);
|
||||
setRegister_cont(CMD_CLOCKDIV,SSD_CLOCKDIV);
|
||||
setRegister_cont(CMD_MUXRATIO,SSD_MUXRATIO);
|
||||
setRegister_cont(CMD_STARTLINE,SSD_STARTLINE); >>>
|
||||
setRegister_cont(CMD_DISPLAYOFFSET,SSD_DISPLAYOFFSET);
|
||||
setRegister_cont(CMD_SETGPIO,SSD_SETGPIO);
|
||||
setRegister_cont(CMD_FUNCTIONSELECT,SSD_FUNCTIONSELECT);
|
||||
writecommand_cont(CMD_SETVSL);
|
||||
writedata8_cont(SSD_SETVSL_A);writedata8_cont(SSD_SETVSL_B);writedata8_cont(SSD_SETVSL_C);
|
||||
writecommand_cont(CMD_CONTRASTABC);
|
||||
writedata8_cont(SSD_CONTRAST_A);writedata8_cont(SSD_CONTRAST_B);writedata8_cont(SSD_CONTRAST_C);
|
||||
setRegister_cont(CMD_MASTERCURRENT,SSD_MASTERCURRENT); >>>
|
||||
writecommand_cont(CMD_DISPLAYENHANCE); >>
|
||||
if (SSD_ENHANCE){
|
||||
writedata8_cont(0xA4);
|
||||
} else {
|
||||
writedata8_cont(0x00);
|
||||
}
|
||||
writedata8_cont(0x00);
|
||||
writedata8_cont(0x00);
|
||||
#if defined(SSD_GAMMASET)
|
||||
//writecommand_cont(CMD_GRAYSCALE); for (uint8_t i =0;i<32;i++){writedata8_cont(SSD_GRAYTABLE[i]);}
|
||||
#else
|
||||
writecommand_cont(CMD_USELUT);
|
||||
#endif
|
||||
// phase here
|
||||
setRegister_cont(CMD_PRECHARGE,SSD_PRECHARGE); >>
|
||||
setRegister_cont(CMD_PRECHARGE2,SSD_PRECHARGE2);
|
||||
setRegister_cont(CMD_VCOMH,SSD_VCOMH);
|
||||
#endif
|
||||
//setAddrWindow_cont(0,0,SSD_WIDTH-1,SSD_HEIGHT-1,false);// ???
|
||||
//_pushColors_cont(_defaultBgColor, SSD_CGRAM);//???
|
||||
//Normal Display and turn ON
|
||||
writecommand_cont(CMD_NORMALDISPLAY);
|
||||
*/
|
||||
static const uint8_t PROGMEM initList[] = {
|
||||
SSD1351_CMD_COMMANDLOCK, 1, // Set command lock, 1 arg
|
||||
0x12,
|
||||
SSD1351_CMD_COMMANDLOCK, 1, // Set command lock, 1 arg
|
||||
0xB1,
|
||||
SSD1351_CMD_DISPLAYOFF, 0, // Display off, no args
|
||||
SSD1351_CMD_CLOCKDIV, 1,
|
||||
0xF1, // 7:4 = Oscillator Freq, 3:0 = CLK Div Ratio (A[3:0]+1 = 1..16)
|
||||
SSD1351_CMD_MUXRATIO, 1,
|
||||
127,
|
||||
SSD1351_CMD_DISPLAYOFFSET, 1,
|
||||
0x0,
|
||||
SSD1351_CMD_SETGPIO, 1,
|
||||
0x00,
|
||||
SSD1351_CMD_FUNCTIONSELECT, 1,
|
||||
0x01, // internal (diode drop)
|
||||
SSD1351_CMD_PRECHARGE, 1,
|
||||
0x32,
|
||||
SSD1351_CMD_VCOMH, 1,
|
||||
0x05,
|
||||
SSD1351_CMD_STARTLINE, 1,
|
||||
0x00,
|
||||
SSD1351_CMD_NORMALDISPLAY, 0,
|
||||
SSD1351_CMD_CONTRASTABC, 3,
|
||||
0xC8, 0x80, 0xC8,
|
||||
SSD1351_CMD_CONTRASTMASTER, 1,
|
||||
0x0F,
|
||||
SSD1351_CMD_SETVSL, 3,
|
||||
0xA0, 0xB5, 0x55,
|
||||
SSD1351_CMD_PRECHARGE2, 1,
|
||||
0x01,
|
||||
SSD1351_CMD_HORIZSCROLL, 1,
|
||||
0x00,
|
||||
SSD1351_CMD_STOPSCROLL, 0,
|
||||
SSD1351_CMD_DISPLAYON, 0, // Main screen turn on
|
||||
0 }; // END OF COMMAND LIST
|
||||
|
||||
|
||||
void SSD1351::sendcommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes) {
|
||||
writecommand(commandByte);
|
||||
for (int i=0; i<numDataBytes; i++) {
|
||||
writedata(pgm_read_byte(dataBytes++)); // Send the data bytes
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1351::sendcommand(uint8_t commandByte,uint8_t *dataBytes, uint8_t numDataBytes) {
|
||||
writecommand(commandByte);
|
||||
for (int i=0; i<numDataBytes; i++) {
|
||||
writedata(*dataBytes++); // Send the data bytes
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1351::begin(void) {
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs,HIGH);
|
||||
pinMode(_sclk, OUTPUT);
|
||||
pinMode(_mosi, OUTPUT);
|
||||
if ((_sclk==14) && (_mosi==13) && (_cs==15)) {
|
||||
// we use hardware spi
|
||||
_hwspi=1;
|
||||
spi_lcd_mode_init();
|
||||
} else {
|
||||
// we must use software spi
|
||||
_hwspi=0;
|
||||
}
|
||||
|
||||
|
||||
const uint8_t *addr = (const uint8_t *)initList;
|
||||
uint8_t cmd, x, numArgs;
|
||||
|
||||
while ((cmd = pgm_read_byte(addr++)) > 0) { // '0' command ends list
|
||||
x = pgm_read_byte(addr++);
|
||||
numArgs = x & 0x7F;
|
||||
if (cmd != 0xFF) { // '255' is ignored
|
||||
sendcommand(cmd, addr, numArgs);
|
||||
}
|
||||
addr += numArgs;
|
||||
}
|
||||
delay(100);
|
||||
setRotation(0);
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
#define ssd1351_swap(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) ///< No-temp-var swap operation
|
||||
|
||||
|
||||
|
||||
void SSD1351::setAddrWindow_i(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h) {
|
||||
uint16_t x2 = x1 + w - 1,
|
||||
y2 = y1 + h - 1;
|
||||
if (rotation&1) { // Vertical address increment mode
|
||||
ssd1351_swap(x1,y1);
|
||||
ssd1351_swap(x2,y2);
|
||||
}
|
||||
writecommand(SSD1351_CMD_SETCOLUMN); // X range
|
||||
writedata(x1);
|
||||
writedata(x2);
|
||||
writecommand(SSD1351_CMD_SETROW); // Y range
|
||||
writedata(y1);
|
||||
writedata(y2);
|
||||
writecommand(SSD1351_CMD_WRITERAM); // Begin write
|
||||
}
|
||||
|
||||
void SSD1351::write16BitColor(uint16_t color){
|
||||
writedata(color>>8);
|
||||
writedata(color&0xff);
|
||||
}
|
||||
|
||||
#define MADCTL_MY 0x80
|
||||
#define MADCTL_MX 0x40
|
||||
#define MADCTL_MV 0x20
|
||||
#define MADCTL_ML 0x10
|
||||
#define MADCTL_RGB 0x00
|
||||
#define MADCTL_BGR 0x08
|
||||
#define MADCTL_MH 0x04
|
||||
|
||||
void SSD1351::setRotation(uint8_t r) {
|
||||
// madctl bits:
|
||||
// 6,7 Color depth (01 = 64K)
|
||||
// 5 Odd/even split COM (0: disable, 1: enable)
|
||||
// 4 Scan direction (0: top-down, 1: bottom-up)
|
||||
// 3 Reserved
|
||||
// 2 Color remap (0: A->B->C, 1: C->B->A)
|
||||
// 1 Column remap (0: 0-127, 1: 127-0)
|
||||
// 0 Address increment (0: horizontal, 1: vertical)
|
||||
uint8_t madctl = 0b01100100; // 64K, enable split, CBA
|
||||
|
||||
rotation = r & 3; // Clip input to valid range
|
||||
|
||||
switch(rotation) {
|
||||
case 0:
|
||||
madctl |= 0b00010000; // Scan bottom-up
|
||||
_width = SSD1351_WIDTH;
|
||||
_height = SSD1351_HEIGHT;
|
||||
break;
|
||||
case 1:
|
||||
madctl |= 0b00010011; // Scan bottom-up, column remap 127-0, vertical
|
||||
_width = SSD1351_HEIGHT;
|
||||
_height = SSD1351_WIDTH;
|
||||
break;
|
||||
case 2:
|
||||
madctl |= 0b00000010; // Column remap 127-0
|
||||
_width = SSD1351_WIDTH;
|
||||
_height = SSD1351_HEIGHT;
|
||||
break;
|
||||
case 3:
|
||||
madctl |= 0b00000001; // Vertical
|
||||
_width = SSD1351_HEIGHT;
|
||||
_height = SSD1351_WIDTH;
|
||||
break;
|
||||
}
|
||||
|
||||
sendcommand(SSD1351_CMD_SETREMAP, &madctl, 1);
|
||||
uint8_t startline = (rotation < 2) ? SSD1351_HEIGHT : 0;
|
||||
sendcommand(SSD1351_CMD_STARTLINE, &startline, 1);
|
||||
stop();
|
||||
}
|
||||
|
||||
void SSD1351::invertDisplay(boolean i) {
|
||||
writecommand(i ? SSD1351_CMD_INVERTDISPLAY : SSD1351_CMD_NORMALDISPLAY);
|
||||
stop();
|
||||
}
|
||||
|
||||
void SSD1351::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
|
||||
setAddrWindow_i(x,y,1,1);
|
||||
write16BitColor(color);
|
||||
stop();
|
||||
}
|
||||
|
||||
void SSD1351::setAddrWindow(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
|
||||
// uint16_t x2 = x1 + w - 1,
|
||||
// y2 = y1 + h - 1;
|
||||
uint8_t flag=0;
|
||||
|
||||
if (!x1 && !y1 && !x2 && !y2) {
|
||||
x1=0;
|
||||
y1=0;
|
||||
x2=_width;
|
||||
y2=_height;
|
||||
flag=1;
|
||||
}
|
||||
|
||||
if (x2>_width) x2=_width;
|
||||
if (y2>_height) y2=_height;
|
||||
|
||||
x2--;
|
||||
y2--;
|
||||
if (rotation&1) { // Vertical address increment mode
|
||||
ssd1351_swap(x1,y1);
|
||||
ssd1351_swap(x2,y2);
|
||||
}
|
||||
//Serial.printf("x1:%d x2:%d y1:%d y2:%d\n",x1,x2,y1,y2);
|
||||
writecommand(SSD1351_CMD_SETCOLUMN); // X range
|
||||
writedata(x1);
|
||||
writedata(x2);
|
||||
writecommand(SSD1351_CMD_SETROW); // Y range
|
||||
writedata(y1);
|
||||
writedata(y2);
|
||||
writecommand(SSD1351_CMD_WRITERAM); // Begin write
|
||||
if (flag) stop();
|
||||
}
|
||||
|
||||
void SSD1351::pushColors(uint16_t *data, uint8_t len, boolean first) {
|
||||
for (uint16_t b=0; b<len; b++){
|
||||
write16BitColor(*data++);
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
void SSD1351::drawFastVLine(int16_t x,int16_t y,int16_t h,uint16_t color) {
|
||||
// Rudimentary clipping
|
||||
if ((x >= _width) || (y >= _height)) return;
|
||||
if ((y+h-1) >= _height) h = _height-y;
|
||||
|
||||
setAddrWindow_i(x,y,1,h);
|
||||
while (h--) {
|
||||
write16BitColor(color);
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
void SSD1351::drawFastHLine(int16_t x,int16_t y,int16_t w,uint16_t color) {
|
||||
// Rudimentary clipping
|
||||
if ((x >= _width) || (y >= _height)) return;
|
||||
if ((x+w-1) >= _width) w = _width-x;
|
||||
|
||||
setAddrWindow_i(x,y,w,1);
|
||||
while (w--) {
|
||||
write16BitColor(color);
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR SSD1351::fastSPIwrite(uint8_t d,uint8_t dc) {
|
||||
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_cs);
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk);
|
||||
if(dc) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi);
|
||||
else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi);
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk);
|
||||
|
||||
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk);
|
||||
if(d&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi);
|
||||
else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi);
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk);
|
||||
}
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<_cs);
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/***************************************************
|
||||
This is our library for the Adafruit SSD1351 Breakout and Shield
|
||||
----> http://www.adafruit.com/products/1651
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These displays use SPI to communicate, 3 pins are required to
|
||||
interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
MIT license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#ifndef _SSD1351_
|
||||
#define _SSD1351_
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include <renderer.h>
|
||||
#include <pgmspace.h>
|
||||
|
||||
|
||||
|
||||
#define SSD1351_WIDTH 128
|
||||
#define SSD1351_HEIGHT 128
|
||||
|
||||
|
||||
// Color definitions
|
||||
#define SSD1351_BLACK 0x0000 /* 0, 0, 0 */
|
||||
#define SSD1351_NAVY 0x000F /* 0, 0, 128 */
|
||||
#define SSD1351_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
||||
#define SSD1351_DARKCYAN 0x03EF /* 0, 128, 128 */
|
||||
#define SSD1351_MAROON 0x7800 /* 128, 0, 0 */
|
||||
#define SSD1351_PURPLE 0x780F /* 128, 0, 128 */
|
||||
#define SSD1351_OLIVE 0x7BE0 /* 128, 128, 0 */
|
||||
#define SSD1351_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
||||
#define SSD1351_DARKGREY 0x7BEF /* 128, 128, 128 */
|
||||
#define SSD1351_BLUE 0x001F /* 0, 0, 255 */
|
||||
#define SSD1351_GREEN 0x07E0 /* 0, 255, 0 */
|
||||
#define SSD1351_CYAN 0x07FF /* 0, 255, 255 */
|
||||
#define SSD1351_RED 0xF800 /* 255, 0, 0 */
|
||||
#define SSD1351_MAGENTA 0xF81F /* 255, 0, 255 */
|
||||
#define SSD1351_YELLOW 0xFFE0 /* 255, 255, 0 */
|
||||
#define SSD1351_WHITE 0xFFFF /* 255, 255, 255 */
|
||||
#define SSD1351_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||
#define SSD1351_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||
#define SSD1351_PINK 0xF81F
|
||||
|
||||
#define SSD1351_CMD_SETCOLUMN 0x15
|
||||
#define SSD1351_CMD_SETROW 0x75
|
||||
#define SSD1351_CMD_WRITERAM 0x5C
|
||||
#define SSD1351_CMD_READRAM 0x5D
|
||||
#define SSD1351_CMD_SETREMAP 0xA0
|
||||
#define SSD1351_CMD_STARTLINE 0xA1
|
||||
#define SSD1351_CMD_DISPLAYOFFSET 0xA2
|
||||
#define SSD1351_CMD_DISPLAYALLOFF 0xA4
|
||||
#define SSD1351_CMD_DISPLAYALLON 0xA5
|
||||
#define SSD1351_CMD_NORMALDISPLAY 0xA6
|
||||
#define SSD1351_CMD_INVERTDISPLAY 0xA7
|
||||
#define SSD1351_CMD_FUNCTIONSELECT 0xAB
|
||||
#define SSD1351_CMD_DISPLAYOFF 0xAE
|
||||
#define SSD1351_CMD_DISPLAYON 0xAF
|
||||
#define SSD1351_CMD_PRECHARGE 0xB1
|
||||
#define SSD1351_CMD_DISPLAYENHANCE 0xB2
|
||||
#define SSD1351_CMD_CLOCKDIV 0xB3
|
||||
#define SSD1351_CMD_SETVSL 0xB4
|
||||
#define SSD1351_CMD_SETGPIO 0xB5
|
||||
#define SSD1351_CMD_PRECHARGE2 0xB6
|
||||
#define SSD1351_CMD_SETGRAY 0xB8
|
||||
#define SSD1351_CMD_USELUT 0xB9
|
||||
#define SSD1351_CMD_PRECHARGELEVEL 0xBB
|
||||
#define SSD1351_CMD_VCOMH 0xBE
|
||||
#define SSD1351_CMD_CONTRASTABC 0xC1
|
||||
#define SSD1351_CMD_CONTRASTMASTER 0xC7
|
||||
#define SSD1351_CMD_MUXRATIO 0xCA
|
||||
#define SSD1351_CMD_COMMANDLOCK 0xFD
|
||||
#define SSD1351_CMD_HORIZSCROLL 0x96
|
||||
#define SSD1351_CMD_STOPSCROLL 0x9E
|
||||
#define SSD1351_CMD_STARTSCROLL 0x9F
|
||||
|
||||
|
||||
#define PIN_OUT_SET 0x60000304
|
||||
#define PIN_OUT_CLEAR 0x60000308
|
||||
|
||||
class SSD1351 : public Renderer {
|
||||
|
||||
public:
|
||||
|
||||
SSD1351(int8_t cs,int8_t mosi,int8_t sclk);
|
||||
|
||||
void begin(void);
|
||||
void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||
void setAddrWindow_i(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
void pushColors(uint16_t *data, uint8_t len, boolean first);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void write16BitColor(uint16_t color);
|
||||
void setRotation(uint8_t r);
|
||||
void invertDisplay(boolean i);
|
||||
uint16_t GetColorFromIndex(uint8_t index);
|
||||
void DisplayOnff(int8_t on);
|
||||
void writecommand(uint8_t c);
|
||||
void writedata(uint8_t d);
|
||||
void commandList(uint8_t *addr);
|
||||
void hw_spi_init();
|
||||
void sendcommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes);
|
||||
void sendcommand(uint8_t commandByte,uint8_t *dataBytes, uint8_t numDataBytes);
|
||||
void drawFastVLine(int16_t x,int16_t y,int16_t h,uint16_t color);
|
||||
void drawFastHLine(int16_t x,int16_t y,int16_t w,uint16_t color);
|
||||
void spi_lcd_mode_init(void);
|
||||
void dim(uint8_t contrast);
|
||||
|
||||
private:
|
||||
uint8_t tabcolor;
|
||||
void fastSPIwrite(uint8_t d,uint8_t dc);
|
||||
void start(void);
|
||||
void stop(void);
|
||||
int8_t _cs, _mosi, _sclk, _hwspi;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
#include <pgmspace.h>
|
||||
// picture with 51 x 34 pixels
|
||||
// table size 3468 bytes
|
||||
#if 0
|
||||
const uint16_t picture[] = {
|
||||
0x0000,0x0841,0x0841,0x0840,0x0841,0x0841,0x1041,0x1041,0x1041,0x1041,0x1041,0x1880,0x1041,0x1041,0x1040,0x1041,0x1881,0x1880,0x1880,0x1880,0x2081,0x2081,0x2080,0x20c1,0x3942,0x3942,0x3101,0x2080,0x2881,0x2880,0x2881,0x2881,0x2881,0x2880,0x2881,0x30c1,0x30c1,0x1840,0x2881,0x30c1,0x3901,0x3941,0x3901,0x3101,0x3101,0x3101,0x3101,0x3101,0x4182,0x4182,0x0000,
|
||||
0x0000,0x0841,0x0841,0x0841,0x1881,0x1881,0x1881,0x1881,0x1881,0x1881,0x2081,0x28c1,0x2081,0x2080,0x2081,0x2081,0x28c1,0x28c1,0x2901,0x3101,0x3101,0x3101,0x3101,0x3942,0x5a04,0x6244,0x6244,0x51c2,0x4101,0x4101,0x4101,0x4101,0x3901,0x4101,0x4101,0x5181,0x4941,0x59c2,0x4141,0x30c1,0x4941,0x4982,0x38c1,0x5182,0x4141,0x4101,0x4941,0x5182,0x5182,0x6a43,0x0000,
|
||||
0x0000,0x1041,0x0841,0x1041,0x1881,0x20c1,0x2081,0x20c1,0x2081,0x28c1,0x20c1,0x2901,0x2081,0x2081,0x20c1,0x28c1,0x28c1,0x3101,0x3101,0x3101,0x3101,0x3941,0x3942,0x4183,0x5a45,0x6244,0x6a85,0x6a84,0x5a03,0x4141,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101,0x4941,0x4141,0x59c2,0x2880,0x38c1,0x4941,0x4941,0x4141,0x4941,0x5181,0x5182,0x6203,0x6203,0x0000,
|
||||
0x0000,0x20c1,0x1041,0x1881,0x2901,0x3142,0x20c1,0x28c1,0x2901,0x2901,0x2901,0x2901,0x2901,0x2901,0x3101,0x3101,0x3141,0x3942,0x4182,0x4182,0x49c3,0x49c3,0x5204,0x5a45,0x5a45,0x5a45,0x6245,0x6245,0x5a45,0x5a04,0x51c2,0x4141,0x4101,0x4101,0x4101,0x6244,0x8388,0x5a04,0x4101,0x4101,0x4901,0x5182,0x30c1,0x4982,0x4982,0x5182,0x4941,0x4941,0x5181,0x4141,0x0000,
|
||||
0x0000,0x1881,0x1041,0x1881,0x2101,0x2902,0x28c1,0x2901,0x2901,0x2901,0x2901,0x28c1,0x20c1,0x20c1,0x28c1,0x28c1,0x28c1,0x3942,0x4182,0x4141,0x4182,0x4982,0x4982,0x51c3,0x51c3,0x51c3,0x51c3,0x51c3,0x51c3,0x51c3,0x5a04,0x51c3,0x4982,0x4141,0x9c09,0xd612,0xbd50,0xa48c,0x4100,0x4101,0x4101,0x4101,0x59c2,0x4981,0x3901,0x3901,0x3901,0x4941,0x4101,0x5182,0x0000,
|
||||
0x0000,0x1881,0x1041,0x1881,0x2902,0x2902,0x2902,0x3142,0x3102,0x3102,0x2901,0x28c1,0x28c1,0x28c1,0x28c1,0x28c1,0x3942,0x51c3,0x6a84,0x3941,0x4182,0x4982,0x4982,0x5a03,0x5a03,0x6244,0x5a04,0x51c3,0x51c3,0x5a03,0x5a44,0x5204,0x3942,0x9bc8,0xcd8f,0xc590,0xc5d1,0xcdd2,0x4100,0x4101,0x4101,0x4101,0x4941,0x4941,0x5182,0x3101,0x4941,0x4941,0x4941,0x4941,0x0000,
|
||||
0x0000,0x1881,0x1041,0x1881,0x3142,0x3142,0x3102,0x3142,0x3142,0x3102,0x3101,0x28c1,0x28c1,0x28c1,0x28c1,0x5204,0x8bc9,0xbd4f,0xcdd1,0xcdd0,0x6244,0x4982,0x51c2,0x5a45,0xac4a,0x9387,0x4982,0x8b87,0x9387,0x8346,0x6a86,0x5204,0xac89,0xaccc,0xc54f,0xb4ce,0x9c4b,0xc5d1,0x4100,0x4901,0x4101,0x4941,0x4941,0x4101,0x4142,0x6203,0x4941,0x2081,0x38c1,0x5182,0x0000,
|
||||
0x0000,0x1881,0x1041,0x2081,0x3143,0x3142,0x3142,0x3983,0x3943,0x3102,0x3101,0x28c1,0x28c1,0x28c1,0x2901,0x8b89,0x9c0b,0x9c0a,0xd612,0xac8c,0xd5d1,0x9bc8,0xbc8a,0x9bc7,0xa3c7,0x9bc7,0x9b86,0x9bc7,0x8347,0x93c8,0xac8b,0xc50c,0xcd4b,0xb48a,0xde12,0xde94,0xaccd,0x6ac6,0x4101,0x4101,0x4941,0x4901,0x4101,0x4941,0x4101,0x38c1,0x3901,0x4141,0x2081,0x3901,0x0000,
|
||||
0x0000,0x1881,0x1041,0x20c1,0x3984,0x3143,0x3943,0x41c4,0x3983,0x3142,0x3101,0x3101,0x3101,0x3101,0x3101,0x9c0a,0x7ac5,0x6203,0xa48c,0xc54f,0xa44b,0xbd0c,0xac08,0x8306,0xc54c,0x72c5,0x7b06,0x6a85,0xddcd,0xcd4c,0x93c7,0xcd0b,0x9386,0xdd8c,0xe60f,0xac8b,0x8389,0x6244,0x6203,0x5181,0x4101,0x4101,0x4901,0x4901,0x4101,0x3901,0x3081,0x38c1,0x59c2,0x4141,0x0000,
|
||||
0x0000,0x2081,0x1841,0x28c1,0x41c4,0x3142,0x3983,0x49c5,0x4184,0x3102,0x3101,0x3101,0x3101,0x3101,0x3101,0x8348,0xa44b,0x6203,0x6204,0xb50e,0xbd0d,0xe60f,0xe650,0xee90,0x8346,0xb48b,0xb48b,0x7b07,0x72c6,0xd54c,0xbd0b,0xf758,0xffd9,0xb489,0xac07,0xe60e,0xee92,0x5204,0x51c3,0x5181,0x4941,0x4941,0x4101,0x4101,0x4941,0x4101,0x4101,0x3081,0x30c1,0x6a43,0x0000,
|
||||
0x0000,0x1881,0x1841,0x28c1,0x41c4,0x3983,0x3983,0x41c4,0x3983,0x3102,0x3101,0x3101,0x3101,0x3101,0x3101,0x3941,0x6245,0x7285,0x9c4b,0xa44b,0xee90,0xdd8c,0x8b05,0xde10,0x940b,0xd58e,0xddcd,0xcd0b,0xdd8c,0x8b47,0x9b87,0xbd90,0xd654,0xffda,0xb48b,0xa3c7,0x9c08,0x6285,0x49c3,0x4983,0x4942,0x4941,0x5181,0x4101,0x4101,0x4941,0x4101,0x38c1,0x30c1,0x4141,0x0000,
|
||||
0x0000,0x1881,0x1881,0x28c1,0x41c4,0x3983,0x41c4,0x4183,0x3942,0x3101,0x3101,0x3101,0x3101,0x3901,0x3901,0x3901,0x4142,0x8bc9,0x6286,0x8b87,0xbc89,0x9345,0xc50b,0xffd9,0xce13,0xe716,0xcd4b,0x7ac5,0xc4ca,0x7284,0x9bc8,0xcdd0,0xde53,0xbd91,0xce13,0xbd0d,0xe60f,0xb4cc,0x6ac6,0x51c4,0x49c3,0x4982,0x5182,0x5181,0x4941,0x4101,0x4101,0x4101,0x4101,0x4101,0x0000,
|
||||
0x0000,0x1881,0x1881,0x2901,0x41c4,0x3983,0x41c4,0x4183,0x3942,0x3101,0x3101,0x3901,0x3901,0x3101,0x3101,0x6244,0x8b05,0xa409,0xd58d,0xb448,0x82c4,0xbcca,0xee93,0xf757,0xb50f,0xbd4f,0x9c4b,0xb489,0x8b46,0xcd0a,0x7ac4,0x9bc8,0xff98,0xb50f,0xacce,0x940a,0xb4cc,0xac8b,0xeed4,0x51c4,0x49c3,0x49c3,0x4983,0x51c3,0x4941,0x4101,0x4101,0x3901,0x4101,0x38c1,0x0000,
|
||||
0x0000,0x2081,0x2081,0x2901,0x4184,0x3983,0x4183,0x3942,0x3142,0x3101,0x3101,0x3101,0x3941,0x3101,0x7ac5,0x7ac5,0x6a43,0x6a43,0x6a43,0xbcca,0xe5cd,0x4182,0x9c4b,0x4183,0x8bca,0xa44c,0xb4cd,0xb447,0xb448,0xccc9,0xccca,0xc4c9,0xee94,0x6245,0x838a,0x8b46,0xd5cf,0xde52,0xef15,0x51c3,0x49c3,0x49c3,0x49c3,0x5a45,0x4982,0x4941,0x5141,0x4941,0x3901,0x4101,0x0000,
|
||||
0x0000,0x2081,0x2080,0x3102,0x3983,0x4184,0x3942,0x3142,0x3942,0x3942,0x3901,0x3941,0x3942,0x7ac5,0x7ac4,0x82c4,0x59c2,0xa3c8,0x5a45,0xd5cd,0xe60f,0xbccb,0x9c09,0xc54e,0x8389,0x93c8,0x9b87,0x69c2,0x8ac4,0xbc89,0xcd0a,0xbc88,0x8bca,0x8b86,0xbd92,0x8305,0xddcf,0xb50e,0xacce,0x5a45,0x51c3,0x49c3,0x49c3,0x5a46,0x4982,0x4982,0x4941,0x4101,0x30c1,0x30c1,0x0000,
|
||||
0x0000,0x2081,0x2081,0x3142,0x49c4,0x4a05,0x4184,0x4183,0x4183,0x49c3,0x4183,0x7ac6,0x9bc8,0x9b86,0xa386,0x6a44,0x3901,0xb48b,0x4182,0xd54c,0x3101,0xc4ca,0x6244,0x8348,0x61c2,0x6202,0x5a04,0x7a84,0x69c2,0xac07,0xcd0a,0xb448,0x7307,0xf79a,0x7284,0xbc89,0xaccd,0x940b,0x6245,0x51c3,0x51c3,0x49c3,0x49c3,0x6246,0x4982,0x4982,0x4982,0x4141,0x3081,0x2881,0x0000,
|
||||
0x0000,0x28c1,0x28c1,0x4184,0x5206,0x4a05,0x49c4,0x49c4,0x49c4,0x5205,0x9b87,0x7b06,0x9386,0xa3c6,0x51c2,0x61c2,0x5981,0xe652,0x5204,0xa449,0x3901,0xa3c7,0xac07,0x9305,0x8348,0xb4ce,0x28c1,0x61c2,0x7243,0x9b45,0xcd0a,0xbc89,0x8b05,0xcd8e,0xcd4b,0x8347,0xffd9,0xd654,0x6a87,0x6286,0x6286,0x5a46,0x5a46,0x6287,0x5a45,0x5204,0x5204,0x5204,0x4182,0x2081,0x0000,
|
||||
0x0000,0x28c1,0x28c1,0x3983,0x41c4,0x41c4,0x4184,0x4184,0x7285,0x82c5,0xa387,0x49c3,0xa3c7,0x9b86,0x4182,0x6a02,0x61c2,0x8b88,0x4142,0x72c5,0x6a84,0xa3c7,0x4982,0x3101,0xa3c6,0xbc8a,0x51c3,0x4941,0x7202,0xac07,0xbc89,0xcd0a,0xccca,0x9b87,0xcd0b,0x8b89,0x7b8a,0xa48e,0x5204,0x5204,0x49c4,0x49c3,0x49c3,0x49c4,0x49c3,0x4983,0x4183,0x4182,0x4182,0x3982,0x0000,
|
||||
0x0000,0x2081,0x28c1,0x3983,0x41c4,0x4184,0x4184,0x5a03,0x9b86,0x9b86,0x7ac5,0x6244,0x9346,0x9b46,0x4141,0x6a02,0x69c2,0x8305,0x7285,0x3941,0xa449,0xac08,0xcd0c,0x9b86,0x7ac5,0xac08,0x9388,0x6202,0x7a83,0xac09,0xa408,0xcd0b,0xc50b,0xa3c6,0xbcca,0xff99,0x940c,0xaccf,0x49c3,0x49c3,0x49c3,0x4183,0x4183,0x4183,0x4183,0x4182,0x3942,0x3942,0x3942,0x4183,0x0000,
|
||||
0x0000,0x2081,0x28c1,0x3943,0x41c4,0x4184,0x4183,0x9386,0x9b87,0xa408,0x9346,0x6a44,0x8b05,0x8284,0x5982,0x7a43,0x5181,0x7a43,0x9c09,0x72c6,0xbd0c,0x5a03,0x93c8,0x6a45,0x8b05,0x9b86,0x7a84,0x7243,0x7243,0x9b86,0xb489,0xbccb,0xbccb,0xb447,0xbc8a,0x6ac7,0xce13,0xc5d2,0x49c3,0x49c3,0x4983,0x4183,0x4183,0x4182,0x4182,0x4182,0x3942,0x3942,0x3942,0x4183,0x0000,
|
||||
0x0000,0x2080,0x28c1,0x3942,0x3984,0x7b06,0x7285,0x7ac5,0x9b87,0x9b86,0x9345,0x6203,0x8284,0x7a83,0x5982,0x7202,0x7203,0x7243,0x9387,0x7b07,0x8b88,0x8347,0x2080,0xb4cb,0xbccc,0x5a03,0x6a03,0x8b04,0x61c2,0x8b05,0xb48b,0xbccb,0xcd4c,0xac09,0xcd0b,0xc590,0x9c8d,0x7b89,0x4983,0x4983,0x4983,0x4183,0x4182,0x4182,0x4182,0x4182,0x3942,0x3942,0x3941,0x4183,0x0000,
|
||||
0x0000,0x2081,0x28c1,0x3942,0x8b46,0x8b05,0x8b05,0x3101,0x9b86,0x9345,0x8ac4,0x82c4,0x7a43,0x7a83,0x6a02,0x8283,0x8283,0x61c2,0x9b86,0x8b88,0x5204,0xb48b,0x51c3,0xac8a,0x3942,0x6a03,0x7243,0x9345,0x7284,0x8305,0xbccc,0xc54d,0xcd8d,0xc58e,0xcd4c,0xac8c,0xcdd2,0x7307,0x4183,0x4983,0x4982,0x4182,0x4182,0x4182,0x4182,0x3982,0x3942,0x3942,0x3101,0x4183,0x0000,
|
||||
0x0000,0x2081,0x5a03,0x59c2,0x4141,0x8283,0x82c4,0x4982,0x8b05,0x8b05,0x8284,0x82c4,0x8283,0x8283,0x7a43,0x8283,0x7a02,0x8ac3,0x9346,0x7285,0x93c9,0x5a44,0xa44a,0xb4cb,0x9388,0x7284,0x7a84,0x7243,0x4182,0x7ac5,0xa44a,0x9c4b,0xcd4e,0xbd0e,0xb4cb,0xde53,0xa4ce,0x7308,0x8bca,0x49c3,0x4182,0x4182,0x4182,0x4182,0x4142,0x3942,0x3942,0x3942,0x3101,0x4183,0x0000,
|
||||
0x0000,0x7243,0x7a43,0x8283,0x3101,0x59c2,0x7a83,0x7a83,0x4141,0x9345,0x8b05,0x7202,0x7203,0x7a43,0x7a43,0x69c2,0x61c2,0x7a02,0x82c4,0x9387,0xa44b,0x3101,0x4182,0x6a86,0x8b88,0xbd4e,0x6244,0x4981,0xac8b,0x4142,0x6203,0xb3c8,0x8307,0xffd9,0xac8b,0x8389,0xa48d,0xa4cd,0x8bca,0x7b49,0x49c3,0x4182,0x4182,0x3982,0x4182,0x3942,0x3942,0x3141,0x3101,0x4183,0x0000,
|
||||
0x0000,0x6a02,0x7a43,0x7a83,0x8283,0x3901,0x7243,0x7a43,0x7a43,0x4982,0x8283,0x7a43,0x7243,0x5981,0x7202,0x7202,0x69c2,0x5981,0x7a42,0x9bc7,0x51c3,0x93c8,0xa449,0x93c9,0x7b48,0x8347,0x4142,0x6a84,0x8346,0xbccc,0x8b88,0x5182,0xde53,0xcdd1,0xd613,0x8bca,0xb50f,0x8bca,0x8bca,0x8389,0x6286,0x5204,0x4a04,0x49c3,0x4183,0x4183,0x4183,0x4182,0x3982,0x4a04,0x0000,
|
||||
0x0000,0x8283,0x61c2,0x59c2,0x7202,0x8283,0x4941,0x7a83,0x7243,0x7243,0x7a83,0x7a43,0x7a43,0x7242,0x6182,0x6181,0x7202,0x61c2,0x5981,0x7a43,0x6a43,0x8347,0x8346,0xb48b,0xb4cb,0x9c09,0x5a04,0x7b07,0x93c9,0x9c0a,0x9c0a,0x5a44,0xb4cd,0xa44d,0x8389,0xb50e,0xa44c,0x8b89,0x8b89,0x93ca,0x8388,0x8348,0x8348,0x7b48,0x7b07,0x7307,0x7307,0x72c7,0x6ac7,0x7307,0x0000,
|
||||
0x0000,0x8ac4,0x8283,0x7a83,0x61c2,0x7a43,0x7a43,0x4942,0x8ac4,0x6a02,0x4982,0x7a83,0x7202,0x7243,0x7a43,0x6a02,0x5941,0x69c2,0x5981,0x5981,0x9386,0x8b46,0x7284,0x5a03,0x51c3,0x8b88,0x6244,0x4183,0x4142,0x7b07,0x3941,0x5a44,0x3982,0x7b07,0x9c0b,0x8348,0x8bc9,0x8b89,0x8388,0x8388,0x8348,0x8348,0x8348,0x8348,0x7b47,0x7b07,0x7b07,0x7307,0x72c6,0x72c7,0x0000,
|
||||
0x0000,0x8ac4,0x8b04,0x82c3,0x82c4,0x82c4,0x8283,0x82c4,0x4982,0x8ac4,0x6a02,0x5182,0x7243,0x7202,0x7202,0x7202,0x6182,0x5141,0x6182,0x69c2,0x4941,0x7284,0x8b46,0x9bc8,0x8b46,0x93c8,0x49c3,0x3101,0x5a03,0x8306,0x72c7,0xb50e,0xacce,0xb50e,0x8348,0x8348,0x8b89,0x8348,0x8348,0x8348,0x8348,0x8348,0x8347,0x7b07,0x7b07,0x7b07,0x7307,0x72c7,0x72c6,0x72c6,0x0000,
|
||||
0x0000,0x8b04,0x8ac4,0x9305,0x8ac4,0x8ac4,0x9304,0x8ac4,0x8b04,0x59c2,0x6a03,0x7a43,0x6a03,0x6a02,0x7203,0x69c2,0x69c2,0x6182,0x5141,0x5941,0x69c2,0x5141,0x6203,0x7243,0x7ac5,0x7ac5,0x8346,0xa44a,0xb50d,0xbd0e,0xcd8f,0xd613,0xbd50,0x8bca,0x72c7,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x7307,0x7b07,0x7b07,0x7b07,0x7b07,0x7307,0x72c6,0x72c6,0x72c6,0x72c6,0x0000,
|
||||
0x0000,0x9345,0x9304,0x9345,0x9345,0x9345,0x9305,0x9345,0x9305,0x8ac4,0x7283,0x5182,0x6202,0x7243,0x6a02,0x69c2,0x61c2,0x5981,0x5982,0x5141,0x4101,0x5101,0x5982,0x5141,0x5141,0x61c2,0x8284,0x9386,0xa44a,0xde53,0xad0f,0xef16,0xe6d6,0x6245,0x4982,0x4982,0x4982,0x4982,0x49c2,0x49c2,0x49c3,0x49c3,0x51c3,0x51c3,0x51c3,0x5203,0x5203,0x5203,0x5203,0x5203,0x0000,
|
||||
0x0000,0x7a84,0x51c2,0x9b86,0x9b85,0x9304,0x8b04,0x8b04,0x8b04,0x9345,0x7a83,0x7a83,0x7a84,0x30c0,0x7243,0x61c2,0x6182,0x5981,0x5981,0x5141,0x5141,0x38c1,0x2881,0x38c1,0x5181,0x6a02,0x8b04,0xa407,0xcd4c,0xde52,0xef16,0xef57,0xd695,0x6285,0x5a04,0x51c3,0x49c3,0x4982,0x4182,0x3942,0x3941,0x3101,0x3101,0x28c1,0x28c1,0x20c1,0x2081,0x2081,0x2081,0x2081,0x0000,
|
||||
0x0000,0xa407,0x9b86,0x3901,0x9b86,0xa386,0x9345,0x82c4,0x8b04,0x82c4,0x9304,0x7243,0x59c2,0x7243,0x28c1,0x69c2,0x5981,0x5981,0x4941,0x4901,0x4901,0x5141,0x5141,0x5141,0x4101,0x4941,0x5182,0x5182,0x4182,0xcd8f,0xef16,0xef57,0xa4cf,0x7b07,0x7b07,0x7b07,0x7ac6,0x72c6,0x72c6,0x6a85,0x6a85,0x6245,0x6244,0x5a04,0x5203,0x49c3,0x4182,0x3942,0x3941,0x3101,0x0000,
|
||||
0x0000,0xac48,0xa407,0xac08,0x30c1,0x8b45,0xa3c7,0x9345,0x8b04,0x8ac4,0x82c4,0x82c4,0x7a83,0x6202,0x6a02,0x30c1,0x59c2,0x61c2,0x5141,0x4901,0x4101,0x4101,0x4101,0x4901,0x5141,0x6182,0x7202,0x8ac4,0xa407,0xac8a,0xa48d,0xef57,0xb550,0x7b06,0x7306,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x72c6,0x6ac6,0x6ac6,0x6a85,0x6a85,0x6a85,0x0000,
|
||||
0x0000,0x0000,0x1081,0x1081,0x1081,0x0000,0x1041,0x1041,0x0841,0x0840,0x0841,0x0840,0x0841,0x0000,0x0840,0x0840,0x0000,0x0800,0x0840,0x0800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0800,0x0840,0x0840,0x1041,0x1082,0x1082,0x18c3,0x1081,0x0841,0x0841,0x0841,0x0841,0x0841,0x0840,0x0840,0x0841,0x0841,0x0840,0x0841,0x0840,0x0841,0x0840,0x0840,0x0840,0x0840,0x0000,
|
||||
0x0000
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
SSD3115 KEYWORD1
|
||||
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
setRotation KEYWORD2
|
||||
setAddrWindow KEYWORD2
|
||||
pushColor KEYWORD2
|
||||
drawPixel KEYWORD2
|
||||
drawFastVLine KEYWORD2
|
||||
drawFastHLine KEYWORD2
|
||||
fillRect KEYWORD2
|
||||
setRotation KEYWORD2
|
||||
setRotation KEYWORD2
|
||||
height KEYWORD2
|
||||
width KEYWORD2
|
||||
invertDisplay KEYWORD2
|
||||
drawImage KEYWORD2
|
||||
setScrollArea KEYWORD2
|
||||
scroll KEYWORD2
|
|
@ -0,0 +1,9 @@
|
|||
name=SSD3115
|
||||
version=1.0
|
||||
author=Limor Fried/Ladyada
|
||||
maintainer=Limor Fried/Ladyada
|
||||
sentence=Library for SSD3115 displays
|
||||
paragraph=Library for SSD3115 displays
|
||||
category=Display
|
||||
url=https://github.com/adafruit/Adafruit-SSD1351-library
|
||||
architectures=*
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2010 - 2011 Espressif System
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SPI_REGISTER_H_INCLUDED
|
||||
#define SPI_REGISTER_H_INCLUDED
|
||||
|
||||
#define REG_SPI_BASE(i) (0x60000200-i*0x100)
|
||||
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
|
||||
#define SPI_USR (BIT(18))
|
||||
|
||||
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
|
||||
|
||||
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
|
||||
#define SPI_WR_BIT_ORDER (BIT(26))
|
||||
#define SPI_RD_BIT_ORDER (BIT(25))
|
||||
#define SPI_QIO_MODE (BIT(24))
|
||||
#define SPI_DIO_MODE (BIT(23))
|
||||
#define SPI_QOUT_MODE (BIT(20))
|
||||
#define SPI_DOUT_MODE (BIT(14))
|
||||
#define SPI_FASTRD_MODE (BIT(13))
|
||||
|
||||
|
||||
|
||||
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
|
||||
|
||||
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
|
||||
|
||||
#define SPI_CS_DELAY_NUM 0x0000000F
|
||||
#define SPI_CS_DELAY_NUM_S 28
|
||||
#define SPI_CS_DELAY_MODE 0x00000003
|
||||
#define SPI_CS_DELAY_MODE_S 26
|
||||
#define SPI_MOSI_DELAY_NUM 0x00000007
|
||||
#define SPI_MOSI_DELAY_NUM_S 23
|
||||
#define SPI_MOSI_DELAY_MODE 0x00000003
|
||||
#define SPI_MOSI_DELAY_MODE_S 21
|
||||
#define SPI_MISO_DELAY_NUM 0x00000007
|
||||
#define SPI_MISO_DELAY_NUM_S 18
|
||||
#define SPI_MISO_DELAY_MODE 0x00000003
|
||||
#define SPI_MISO_DELAY_MODE_S 16
|
||||
#define SPI_CK_OUT_HIGH_MODE 0x0000000F
|
||||
#define SPI_CK_OUT_HIGH_MODE_S 12
|
||||
#define SPI_CK_OUT_LOW_MODE 0x0000000F
|
||||
#define SPI_CK_OUT_LOW_MODE_S 8
|
||||
|
||||
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
|
||||
#define SPI_CLK_EQU_SYSCLK (BIT(31))
|
||||
#define SPI_CLKDIV_PRE 0x00001FFF
|
||||
#define SPI_CLKDIV_PRE_S 18
|
||||
#define SPI_CLKCNT_N 0x0000003F
|
||||
#define SPI_CLKCNT_N_S 12
|
||||
#define SPI_CLKCNT_H 0x0000003F
|
||||
#define SPI_CLKCNT_H_S 6
|
||||
#define SPI_CLKCNT_L 0x0000003F
|
||||
#define SPI_CLKCNT_L_S 0
|
||||
|
||||
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
|
||||
#define SPI_USR_COMMAND (BIT(31))
|
||||
#define SPI_USR_ADDR (BIT(30))
|
||||
#define SPI_USR_DUMMY (BIT(29))
|
||||
#define SPI_USR_MISO (BIT(28))
|
||||
#define SPI_USR_MOSI (BIT(27))
|
||||
|
||||
#define SPI_USR_MOSI_HIGHPART (BIT(25))
|
||||
#define SPI_USR_MISO_HIGHPART (BIT(24))
|
||||
|
||||
|
||||
#define SPI_SIO (BIT(16))
|
||||
#define SPI_FWRITE_QIO (BIT(15))
|
||||
#define SPI_FWRITE_DIO (BIT(14))
|
||||
#define SPI_FWRITE_QUAD (BIT(13))
|
||||
#define SPI_FWRITE_DUAL (BIT(12))
|
||||
#define SPI_WR_BYTE_ORDER (BIT(11))
|
||||
#define SPI_RD_BYTE_ORDER (BIT(10))
|
||||
#define SPI_CK_OUT_EDGE (BIT(7))
|
||||
#define SPI_CK_I_EDGE (BIT(6))
|
||||
#define SPI_CS_SETUP (BIT(5))
|
||||
#define SPI_CS_HOLD (BIT(4))
|
||||
#define SPI_FLASH_MODE (BIT(2))
|
||||
#define SPI_DOUTDIN (BIT(0))
|
||||
|
||||
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
|
||||
#define SPI_USR_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_USR_ADDR_BITLEN_S 26
|
||||
#define SPI_USR_MOSI_BITLEN 0x000001FF
|
||||
#define SPI_USR_MOSI_BITLEN_S 17
|
||||
#define SPI_USR_MISO_BITLEN 0x000001FF
|
||||
#define SPI_USR_MISO_BITLEN_S 8
|
||||
|
||||
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
|
||||
#define SPI_USR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
|
||||
#define SPI_USR_COMMAND_BITLEN 0x0000000F
|
||||
#define SPI_USR_COMMAND_BITLEN_S 28
|
||||
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
|
||||
#define SPI_USR_COMMAND_VALUE_S 0
|
||||
|
||||
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
|
||||
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
|
||||
#define SPI_CS2_DIS (BIT(2))
|
||||
#define SPI_CS1_DIS (BIT(1))
|
||||
#define SPI_CS0_DIS (BIT(0))
|
||||
#define SPI_IDLE_EDGE (BIT(29))
|
||||
|
||||
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
|
||||
#define SPI_SYNC_RESET (BIT(31))
|
||||
#define SPI_SLAVE_MODE (BIT(30))
|
||||
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
|
||||
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
|
||||
#define SPI_SLV_CMD_DEFINE (BIT(27))
|
||||
#define SPI_TRANS_CNT 0x0000000F
|
||||
#define SPI_TRANS_CNT_S 23
|
||||
#define SPI_TRANS_DONE_EN (BIT(9))
|
||||
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
|
||||
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
|
||||
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
|
||||
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
|
||||
|
||||
|
||||
|
||||
#define SLV_SPI_INT_EN 0x0000001f
|
||||
#define SLV_SPI_INT_EN_S 5
|
||||
|
||||
#define SPI_TRANS_DONE (BIT(4))
|
||||
#define SPI_SLV_WR_STA_DONE (BIT(3))
|
||||
#define SPI_SLV_RD_STA_DONE (BIT(2))
|
||||
#define SPI_SLV_WR_BUF_DONE (BIT(1))
|
||||
#define SPI_SLV_RD_BUF_DONE (BIT(0))
|
||||
|
||||
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
|
||||
#define SPI_SLV_STATUS_BITLEN 0x0000001F
|
||||
#define SPI_SLV_STATUS_BITLEN_S 27
|
||||
#define SPI_SLV_BUF_BITLEN 0x000001FF
|
||||
#define SPI_SLV_BUF_BITLEN_S 16
|
||||
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_SLV_RD_ADDR_BITLEN_S 10
|
||||
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
|
||||
#define SPI_SLV_WR_ADDR_BITLEN_S 4
|
||||
|
||||
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
|
||||
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
|
||||
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
|
||||
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
|
||||
|
||||
|
||||
|
||||
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
|
||||
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
|
||||
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
|
||||
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
|
||||
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
|
||||
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
|
||||
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
|
||||
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
|
||||
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
|
||||
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
|
||||
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
|
||||
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
|
||||
|
||||
#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
|
||||
#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
|
||||
#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
|
||||
#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
|
||||
#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
|
||||
#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
|
||||
#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
|
||||
#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
|
||||
#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
|
||||
#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
|
||||
#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
|
||||
#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
|
||||
#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
|
||||
#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
|
||||
#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
|
||||
#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
|
||||
|
||||
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
|
||||
#define SPI_INT_HOLD_ENA 0x00000003
|
||||
#define SPI_INT_HOLD_ENA_S 0
|
||||
#endif // SPI_REGISTER_H_INCLUDED
|
|
@ -1,322 +0,0 @@
|
|||
/**
|
||||
* @filename : epdpaint.cpp
|
||||
* @brief : Paint tools
|
||||
* @author : Yehui from Waveshare
|
||||
*
|
||||
* Copyright (C) Waveshare September 9 2017
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documnetation 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
|
||||
* furished 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 OR 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.
|
||||
*/
|
||||
|
||||
#include <pgmspace.h>
|
||||
#include "epdpaint.h"
|
||||
|
||||
Paint::Paint(unsigned char* image, int width, int height) {
|
||||
this->rotate = ROTATE_0;
|
||||
this->image = image;
|
||||
/* 1 byte = 8 pixels, so the width should be the multiple of 8 */
|
||||
this->width = width % 8 ? width + 8 - (width % 8) : width;
|
||||
this->height = height;
|
||||
}
|
||||
|
||||
Paint::~Paint() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: clear the image
|
||||
*/
|
||||
void Paint::Clear(int colored) {
|
||||
for (int x = 0; x < this->width; x++) {
|
||||
for (int y = 0; y < this->height; y++) {
|
||||
DrawAbsolutePixel(x, y, colored);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a pixel by absolute coordinates.
|
||||
* this function won't be affected by the rotate parameter.
|
||||
*/
|
||||
void Paint::DrawAbsolutePixel(int x, int y, int colored) {
|
||||
if (x < 0 || x >= this->width || y < 0 || y >= this->height) {
|
||||
return;
|
||||
}
|
||||
if (IF_INVERT_COLOR) {
|
||||
if (colored) {
|
||||
image[(x + y * this->width) / 8] |= 0x80 >> (x % 8);
|
||||
} else {
|
||||
image[(x + y * this->width) / 8] &= ~(0x80 >> (x % 8));
|
||||
}
|
||||
} else {
|
||||
if (colored) {
|
||||
image[(x + y * this->width) / 8] &= ~(0x80 >> (x % 8));
|
||||
} else {
|
||||
image[(x + y * this->width) / 8] |= 0x80 >> (x % 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: Getters and Setters
|
||||
*/
|
||||
unsigned char* Paint::GetImage(void) {
|
||||
return this->image;
|
||||
}
|
||||
|
||||
int Paint::GetWidth(void) {
|
||||
return this->width;
|
||||
}
|
||||
|
||||
void Paint::SetWidth(int width) {
|
||||
this->width = width % 8 ? width + 8 - (width % 8) : width;
|
||||
}
|
||||
|
||||
int Paint::GetHeight(void) {
|
||||
return this->height;
|
||||
}
|
||||
|
||||
void Paint::SetHeight(int height) {
|
||||
this->height = height;
|
||||
}
|
||||
|
||||
int Paint::GetRotate(void) {
|
||||
return this->rotate;
|
||||
}
|
||||
|
||||
void Paint::SetRotate(int rotate){
|
||||
this->rotate = rotate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a pixel by the coordinates
|
||||
*/
|
||||
void Paint::DrawPixel(int x, int y, int colored) {
|
||||
int point_temp;
|
||||
if (this->rotate == ROTATE_0) {
|
||||
if(x < 0 || x >= this->width || y < 0 || y >= this->height) {
|
||||
return;
|
||||
}
|
||||
DrawAbsolutePixel(x, y, colored);
|
||||
} else if (this->rotate == ROTATE_90) {
|
||||
if(x < 0 || x >= this->height || y < 0 || y >= this->width) {
|
||||
return;
|
||||
}
|
||||
point_temp = x;
|
||||
x = this->width - y;
|
||||
y = point_temp;
|
||||
DrawAbsolutePixel(x, y, colored);
|
||||
} else if (this->rotate == ROTATE_180) {
|
||||
if(x < 0 || x >= this->width || y < 0 || y >= this->height) {
|
||||
return;
|
||||
}
|
||||
x = this->width - x;
|
||||
y = this->height - y;
|
||||
DrawAbsolutePixel(x, y, colored);
|
||||
} else if (this->rotate == ROTATE_270) {
|
||||
if(x < 0 || x >= this->height || y < 0 || y >= this->width) {
|
||||
return;
|
||||
}
|
||||
point_temp = x;
|
||||
x = y;
|
||||
y = this->height - point_temp;
|
||||
DrawAbsolutePixel(x, y, colored);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a charactor on the frame buffer but not refresh
|
||||
*/
|
||||
void Paint::DrawCharAt(int x, int y, char ascii_char, sFONT* font, int colored) {
|
||||
int i, j;
|
||||
unsigned int char_offset = (ascii_char - ' ') * font->Height * (font->Width / 8 + (font->Width % 8 ? 1 : 0));
|
||||
const unsigned char* ptr = &font->table[char_offset];
|
||||
|
||||
for (j = 0; j < font->Height; j++) {
|
||||
for (i = 0; i < font->Width; i++) {
|
||||
if (pgm_read_byte(ptr) & (0x80 >> (i % 8))) {
|
||||
DrawPixel(x + i, y + j, colored);
|
||||
} else {
|
||||
// fill background
|
||||
DrawPixel(x + i, y + j, 1);
|
||||
}
|
||||
if (i % 8 == 7) {
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
if (font->Width % 8 != 0) {
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this displays a string on the frame buffer but not refresh
|
||||
*/
|
||||
void Paint::DrawStringAt(int x, int y, const char* text, sFONT* font, int colored) {
|
||||
const char* p_text = text;
|
||||
unsigned int counter = 0;
|
||||
int refcolumn = x;
|
||||
|
||||
/* Send the string character by character on EPD */
|
||||
while (*p_text != 0) {
|
||||
/* Display one character on EPD */
|
||||
DrawCharAt(refcolumn, y, *p_text, font, colored);
|
||||
/* Decrement the column position by 16 */
|
||||
refcolumn += font->Width;
|
||||
/* Point on the next character */
|
||||
p_text++;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a line on the frame buffer
|
||||
*/
|
||||
void Paint::DrawLine(int x0, int y0, int x1, int y1, int colored) {
|
||||
/* Bresenham algorithm */
|
||||
int dx = x1 - x0 >= 0 ? x1 - x0 : x0 - x1;
|
||||
int sx = x0 < x1 ? 1 : -1;
|
||||
int dy = y1 - y0 <= 0 ? y1 - y0 : y0 - y1;
|
||||
int sy = y0 < y1 ? 1 : -1;
|
||||
int err = dx + dy;
|
||||
|
||||
while((x0 != x1) && (y0 != y1)) {
|
||||
DrawPixel(x0, y0 , colored);
|
||||
if (2 * err >= dy) {
|
||||
err += dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (2 * err <= dx) {
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a horizontal line on the frame buffer
|
||||
*/
|
||||
void Paint::DrawHorizontalLine(int x, int y, int line_width, int colored) {
|
||||
int i;
|
||||
for (i = x; i < x + line_width; i++) {
|
||||
DrawPixel(i, y, colored);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a vertical line on the frame buffer
|
||||
*/
|
||||
void Paint::DrawVerticalLine(int x, int y, int line_height, int colored) {
|
||||
int i;
|
||||
for (i = y; i < y + line_height; i++) {
|
||||
DrawPixel(x, i, colored);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a rectangle
|
||||
*/
|
||||
void Paint::DrawRectangle(int x0, int y0, int x1, int y1, int colored) {
|
||||
int min_x, min_y, max_x, max_y;
|
||||
min_x = x1 > x0 ? x0 : x1;
|
||||
max_x = x1 > x0 ? x1 : x0;
|
||||
min_y = y1 > y0 ? y0 : y1;
|
||||
max_y = y1 > y0 ? y1 : y0;
|
||||
|
||||
DrawHorizontalLine(min_x, min_y, max_x - min_x + 1, colored);
|
||||
DrawHorizontalLine(min_x, max_y, max_x - min_x + 1, colored);
|
||||
DrawVerticalLine(min_x, min_y, max_y - min_y + 1, colored);
|
||||
DrawVerticalLine(max_x, min_y, max_y - min_y + 1, colored);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a filled rectangle
|
||||
*/
|
||||
void Paint::DrawFilledRectangle(int x0, int y0, int x1, int y1, int colored) {
|
||||
int min_x, min_y, max_x, max_y;
|
||||
int i;
|
||||
min_x = x1 > x0 ? x0 : x1;
|
||||
max_x = x1 > x0 ? x1 : x0;
|
||||
min_y = y1 > y0 ? y0 : y1;
|
||||
max_y = y1 > y0 ? y1 : y0;
|
||||
|
||||
for (i = min_x; i <= max_x; i++) {
|
||||
DrawVerticalLine(i, min_y, max_y - min_y + 1, colored);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a circle
|
||||
*/
|
||||
void Paint::DrawCircle(int x, int y, int radius, int colored) {
|
||||
/* Bresenham algorithm */
|
||||
int x_pos = -radius;
|
||||
int y_pos = 0;
|
||||
int err = 2 - 2 * radius;
|
||||
int e2;
|
||||
|
||||
do {
|
||||
DrawPixel(x - x_pos, y + y_pos, colored);
|
||||
DrawPixel(x + x_pos, y + y_pos, colored);
|
||||
DrawPixel(x + x_pos, y - y_pos, colored);
|
||||
DrawPixel(x - x_pos, y - y_pos, colored);
|
||||
e2 = err;
|
||||
if (e2 <= y_pos) {
|
||||
err += ++y_pos * 2 + 1;
|
||||
if(-x_pos == y_pos && e2 <= x_pos) {
|
||||
e2 = 0;
|
||||
}
|
||||
}
|
||||
if (e2 > x_pos) {
|
||||
err += ++x_pos * 2 + 1;
|
||||
}
|
||||
} while (x_pos <= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a filled circle
|
||||
*/
|
||||
void Paint::DrawFilledCircle(int x, int y, int radius, int colored) {
|
||||
/* Bresenham algorithm */
|
||||
int x_pos = -radius;
|
||||
int y_pos = 0;
|
||||
int err = 2 - 2 * radius;
|
||||
int e2;
|
||||
|
||||
do {
|
||||
DrawPixel(x - x_pos, y + y_pos, colored);
|
||||
DrawPixel(x + x_pos, y + y_pos, colored);
|
||||
DrawPixel(x + x_pos, y - y_pos, colored);
|
||||
DrawPixel(x - x_pos, y - y_pos, colored);
|
||||
DrawHorizontalLine(x + x_pos, y + y_pos, 2 * (-x_pos) + 1, colored);
|
||||
DrawHorizontalLine(x + x_pos, y - y_pos, 2 * (-x_pos) + 1, colored);
|
||||
e2 = err;
|
||||
if (e2 <= y_pos) {
|
||||
err += ++y_pos * 2 + 1;
|
||||
if(-x_pos == y_pos && e2 <= x_pos) {
|
||||
e2 = 0;
|
||||
}
|
||||
}
|
||||
if(e2 > x_pos) {
|
||||
err += ++x_pos * 2 + 1;
|
||||
}
|
||||
} while(x_pos <= 0);
|
||||
}
|
||||
|
||||
/* END OF FILE */
|
|
@ -1,7 +1,7 @@
|
|||
name=Waveshare esp 2.9 inch e-paper display driver
|
||||
version=1.0
|
||||
author=Gerhard Muntz
|
||||
maintainer=Gerhard Muntz
|
||||
author=Gerhard Mutz
|
||||
maintainer=Gerhard Mutz
|
||||
sentence=ESP8266 library for Waveshare e-paper display.
|
||||
paragraph=
|
||||
category=Display
|
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 407 KiB |
Before Width: | Height: | Size: 623 KiB After Width: | Height: | Size: 623 KiB |
Before Width: | Height: | Size: 455 KiB After Width: | Height: | Size: 455 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
@ -27,20 +27,78 @@
|
|||
#include <stdlib.h>
|
||||
#include "epd2in9.h"
|
||||
|
||||
Epd::~Epd() {
|
||||
};
|
||||
extern uint8_t *buffer;
|
||||
|
||||
Epd::Epd(int16_t width, int16_t height) :
|
||||
Paint(width,height) {
|
||||
}
|
||||
|
||||
void Epd::DisplayOnff(int8_t on) {
|
||||
}
|
||||
|
||||
void Epd::Updateframe() {
|
||||
SetFrameMemory(buffer, 0, 0, EPD_WIDTH,EPD_HEIGHT);
|
||||
DisplayFrame();
|
||||
//Serial.printf("update\n");
|
||||
}
|
||||
|
||||
#define DISPLAY_INIT_MODE 0
|
||||
#define DISPLAY_INIT_PARTIAL 1
|
||||
#define DISPLAY_INIT_FULL 2
|
||||
|
||||
|
||||
Epd::Epd() {
|
||||
//reset_pin = RST_PIN;
|
||||
//dc_pin = DC_PIN;
|
||||
cs_pin = CS_PIN;
|
||||
mosi_pin = MOSI_PIN;
|
||||
sclk_pin = SCLK_PIN;
|
||||
//busy_pin = BUSY_PIN;
|
||||
width = EPD_WIDTH;
|
||||
height = EPD_HEIGHT;
|
||||
};
|
||||
void Epd::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
// ignore update mode
|
||||
if (p==DISPLAY_INIT_PARTIAL) {
|
||||
Init(lut_partial_update);
|
||||
//ClearFrameMemory(0xFF); // bit set = white, bit reset = black
|
||||
DisplayFrame();
|
||||
delay(500);
|
||||
return;
|
||||
//Serial.printf("partial\n");
|
||||
} else if (p==DISPLAY_INIT_FULL) {
|
||||
Init(lut_full_update);
|
||||
//ClearFrameMemory(0xFF); // bit set = white, bit reset = black
|
||||
DisplayFrame();
|
||||
delay(3500);
|
||||
//Serial.printf("full\n");
|
||||
return;
|
||||
} else {
|
||||
Updateframe();
|
||||
}
|
||||
setRotation(rot);
|
||||
invertDisplay(false);
|
||||
setTextWrap(false); // Allow text to run off edges
|
||||
cp437(true);
|
||||
setTextFont(font&3);
|
||||
setTextSize(size&7);
|
||||
setTextColor(WHITE,BLACK);
|
||||
setCursor(0,0);
|
||||
fillScreen(BLACK);
|
||||
}
|
||||
|
||||
int16_t Epd::Begin(int16_t cs,int16_t mosi,int16_t sclk) {
|
||||
cs_pin=cs;
|
||||
mosi_pin=mosi;
|
||||
sclk_pin=sclk;
|
||||
}
|
||||
|
||||
|
||||
void Epd::Init(int8_t p) {
|
||||
if (p==DISPLAY_INIT_PARTIAL) {
|
||||
Init(lut_partial_update);
|
||||
} else {
|
||||
Init(lut_full_update);
|
||||
}
|
||||
ClearFrameMemory(0xFF);
|
||||
DisplayFrame();
|
||||
if (p==DISPLAY_INIT_PARTIAL) {
|
||||
delay(350);
|
||||
} else {
|
||||
delay(3500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Epd::Init(const unsigned char* lut) {
|
||||
/* this calls the peripheral hardware interface, see epdif */
|
||||
|
@ -56,6 +114,13 @@ int Epd::Init(const unsigned char* lut) {
|
|||
pinMode(mosi_pin, OUTPUT);
|
||||
pinMode(sclk_pin, OUTPUT);
|
||||
|
||||
digitalWrite(cs_pin,HIGH);
|
||||
digitalWrite(mosi_pin,LOW);
|
||||
digitalWrite(sclk_pin,LOW);
|
||||
|
||||
width = EPD_WIDTH;
|
||||
height = EPD_HEIGHT;
|
||||
|
||||
/* EPD hardware init start */
|
||||
this->lut = lut;
|
||||
Reset();
|
||||
|
@ -103,9 +168,9 @@ void Epd::SendData(unsigned char data) {
|
|||
*/
|
||||
void Epd::WaitUntilIdle(void) {
|
||||
return;
|
||||
while(DigitalRead(busy_pin) == HIGH) { //LOW: idle, HIGH: busy
|
||||
DelayMs(100);
|
||||
}
|
||||
//while(DigitalRead(busy_pin) == HIGH) { //LOW: idle, HIGH: busy
|
||||
// DelayMs(100);
|
||||
//}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,9 +180,9 @@ void Epd::WaitUntilIdle(void) {
|
|||
*/
|
||||
void Epd::Reset(void) {
|
||||
//DigitalWrite(reset_pin, LOW); //module reset
|
||||
DelayMs(200);
|
||||
//delay(200);
|
||||
//DigitalWrite(reset_pin, HIGH);
|
||||
DelayMs(200);
|
||||
//delay(200);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,7 +244,7 @@ void Epd::SetFrameMemory(
|
|||
/* send the image data */
|
||||
for (uint16_t j = 0; j < y_end - y + 1; j++) {
|
||||
for (uint16_t i = 0; i < (x_end - x + 1) / 8; i++) {
|
||||
SendData(image_buffer[i + j * (image_width / 8)]);
|
||||
SendData(image_buffer[i + j * (image_width / 8)]^0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +272,7 @@ void Epd::SetFrameMemory(const unsigned char* image_buffer) {
|
|||
SendCommand(WRITE_RAM);
|
||||
/* send the image data */
|
||||
for (int i = 0; i < this->width / 8 * this->height; i++) {
|
||||
SendData(pgm_read_byte(&image_buffer[i]));
|
||||
SendData(pgm_read_byte(&image_buffer[i])^0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,23 +360,68 @@ const unsigned char lut_partial_update[] =
|
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void Epd::fastSPIwrite(uint8_t d,uint8_t dc) {
|
||||
|
||||
digitalWrite(cs_pin, LOW);
|
||||
#define PIN_OUT_SET 0x60000304
|
||||
#define PIN_OUT_CLEAR 0x60000308
|
||||
|
||||
// transfer dc
|
||||
digitalWrite(sclk_pin, LOW);
|
||||
if(dc) digitalWrite(mosi_pin, HIGH);
|
||||
else digitalWrite(mosi_pin, LOW);
|
||||
digitalWrite(sclk_pin, HIGH);
|
||||
#define PWRITE xdigitalWrite
|
||||
|
||||
|
||||
#ifndef SSPI_USEANYPIN
|
||||
// uses about 2.75 usecs, 365 kb /sec
|
||||
// however does not work with GPIO 16 !!!!
|
||||
void ICACHE_RAM_ATTR Epd::fastSPIwrite(uint8_t d,uint8_t dc) {
|
||||
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<cs_pin);
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<sclk_pin);
|
||||
if(dc) WRITE_PERI_REG( PIN_OUT_SET, 1<<mosi_pin);
|
||||
else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<mosi_pin);
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<sclk_pin);
|
||||
|
||||
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
||||
digitalWrite(sclk_pin, LOW);
|
||||
if(d & bit) digitalWrite(mosi_pin, HIGH);
|
||||
else digitalWrite(mosi_pin, LOW);
|
||||
digitalWrite(sclk_pin, HIGH);
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<sclk_pin);
|
||||
if(d&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<mosi_pin);
|
||||
else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<mosi_pin);
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<sclk_pin);
|
||||
}
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<cs_pin);
|
||||
}
|
||||
#else
|
||||
|
||||
extern void ICACHE_RAM_ATTR xdigitalWrite(uint8_t pin, uint8_t val) {
|
||||
//stopWaveform(pin);
|
||||
if(pin < 16){
|
||||
if(val) GPOS = (1 << pin);
|
||||
else GPOC = (1 << pin);
|
||||
} else if(pin == 16){
|
||||
if(val) GP16O |= 1;
|
||||
else GP16O &= ~1;
|
||||
}
|
||||
}
|
||||
|
||||
// about 13 us => 76 kb / sec
|
||||
// can use any pin
|
||||
void Epd::fastSPIwrite(uint8_t d,uint8_t dc) {
|
||||
|
||||
PWRITE(cs_pin, LOW);
|
||||
|
||||
// transfer dc
|
||||
PWRITE(sclk_pin, LOW);
|
||||
if(dc) PWRITE(mosi_pin, HIGH);
|
||||
else PWRITE(mosi_pin, LOW);
|
||||
PWRITE(sclk_pin, HIGH);
|
||||
|
||||
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
||||
PWRITE(sclk_pin, LOW);
|
||||
if(d & bit) PWRITE(mosi_pin, HIGH);
|
||||
else PWRITE(mosi_pin, LOW);
|
||||
PWRITE(sclk_pin, HIGH);
|
||||
}
|
||||
|
||||
digitalWrite(cs_pin, HIGH);
|
||||
PWRITE(cs_pin, HIGH);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* END OF FILE */
|
|
@ -27,11 +27,14 @@
|
|||
#ifndef EPD2IN9_H
|
||||
#define EPD2IN9_H
|
||||
|
||||
#include "epdif.h"
|
||||
#include "epdpaint.h"
|
||||
|
||||
|
||||
// Display resolution
|
||||
#define EPD_WIDTH 128
|
||||
#define EPD_HEIGHT 296
|
||||
//#define EPD_WIDTH 296
|
||||
//#define EPD_HEIGHT 128
|
||||
|
||||
// EPD2IN9 commands
|
||||
#define DRIVER_OUTPUT_CONTROL 0x01
|
||||
|
@ -59,14 +62,16 @@
|
|||
extern const unsigned char lut_full_update[];
|
||||
extern const unsigned char lut_partial_update[];
|
||||
|
||||
class Epd : EpdIf {
|
||||
class Epd : public Paint {
|
||||
public:
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
Epd(int16_t width, int16_t height);
|
||||
int16_t width;
|
||||
int16_t height;
|
||||
|
||||
Epd();
|
||||
~Epd();
|
||||
int Init(const unsigned char* lut);
|
||||
void Init(int8_t p);
|
||||
void SendCommand(unsigned char command);
|
||||
void SendData(unsigned char data);
|
||||
void WaitUntilIdle(void);
|
||||
|
@ -82,23 +87,26 @@ public:
|
|||
void ClearFrameMemory(unsigned char color);
|
||||
void DisplayFrame(void);
|
||||
void Sleep(void);
|
||||
void fastSPIwrite(uint8_t d,uint8_t dc);
|
||||
|
||||
void DisplayOnff(int8_t on);
|
||||
void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||
int16_t Begin(int16_t p1,int16_t p2,int16_t p3);
|
||||
void Updateframe();
|
||||
|
||||
unsigned int cs_pin;
|
||||
unsigned int mosi_pin;
|
||||
unsigned int sclk_pin;
|
||||
|
||||
private:
|
||||
unsigned int reset_pin;
|
||||
unsigned int dc_pin;
|
||||
unsigned int busy_pin;
|
||||
const unsigned char* lut;
|
||||
|
||||
|
||||
unsigned int cs_pin;
|
||||
unsigned int mosi_pin;
|
||||
unsigned int sclk_pin;
|
||||
|
||||
void SetLut(const unsigned char* lut);
|
||||
void SetMemoryArea(int x_start, int y_start, int x_end, int y_end);
|
||||
void SetMemoryPointer(int x, int y);
|
||||
void fastSPIwrite(uint8_t d,uint8_t dc);
|
||||
//void fastSPIwrite(uint8_t d,uint8_t dc);
|
||||
};
|
||||
|
||||
#endif /* EPD2IN9_H */
|
|
@ -0,0 +1,558 @@
|
|||
/**
|
||||
* @filename : epd4in2.cpp
|
||||
* @brief : Implements for Dual-color e-paper library
|
||||
* @author : Yehui from Waveshare
|
||||
*
|
||||
* Copyright (C) Waveshare August 10 2017
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documnetation 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
|
||||
* furished 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 OR 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <epd4in2.h>
|
||||
|
||||
|
||||
//#define SSPI_USEANYPIN
|
||||
|
||||
extern uint8_t *buffer;
|
||||
uint8_t epd42_mode;
|
||||
|
||||
Epd42::Epd42(int16_t width, int16_t height) :
|
||||
Paint(width,height) {
|
||||
}
|
||||
|
||||
void Epd42::DisplayOnff(int8_t on) {
|
||||
}
|
||||
|
||||
|
||||
#define DISPLAY_INIT_MODE 0
|
||||
#define DISPLAY_INIT_PARTIAL 1
|
||||
#define DISPLAY_INIT_FULL 2
|
||||
|
||||
void Epd42::Updateframe() {
|
||||
//SetFrameMemory(buffer, 0, 0, EPD_WIDTH,EPD_HEIGHT);
|
||||
SetPartialWindow(buffer, 0, 0, width,height,2);
|
||||
if (epd42_mode==DISPLAY_INIT_PARTIAL) {
|
||||
DisplayFrameQuick();
|
||||
} else {
|
||||
DisplayFrame();
|
||||
}
|
||||
//Serial.printf("update\n");
|
||||
}
|
||||
|
||||
void Epd42::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
// ignore update mode
|
||||
if (p==DISPLAY_INIT_PARTIAL) {
|
||||
epd42_mode=p;
|
||||
//Init(lut_partial_update);
|
||||
//ClearFrameMemory(0xFF); // bit set = white, bit reset = black
|
||||
DisplayFrameQuick();
|
||||
delay(500);
|
||||
return;
|
||||
//Serial.printf("partial\n");
|
||||
} else if (p==DISPLAY_INIT_FULL) {
|
||||
epd42_mode=p;
|
||||
//Init(lut_full_update);
|
||||
//ClearFrameMemory(0xFF); // bit set = white, bit reset = black
|
||||
DisplayFrame();
|
||||
delay(4500);
|
||||
return;
|
||||
//Serial.printf("full\n");
|
||||
} else {
|
||||
epd42_mode=DISPLAY_INIT_FULL;
|
||||
Updateframe();
|
||||
}
|
||||
|
||||
setRotation(rot);
|
||||
invertDisplay(false);
|
||||
setTextWrap(false); // Allow text to run off edges
|
||||
cp437(true);
|
||||
setTextFont(font);
|
||||
setTextSize(size);
|
||||
setTextColor(WHITE,BLACK);
|
||||
setCursor(0,0);
|
||||
fillScreen(BLACK);
|
||||
}
|
||||
|
||||
int16_t Epd42::Begin(int16_t cs,int16_t mosi,int16_t sclk) {
|
||||
cs_pin=cs;
|
||||
mosi_pin=mosi;
|
||||
sclk_pin=sclk;
|
||||
}
|
||||
|
||||
void Epd42::Init(int8_t p) {
|
||||
epd42_mode=p;
|
||||
DisplayFrame();
|
||||
delay(4000);
|
||||
}
|
||||
|
||||
int Epd42::Init(void) {
|
||||
pinMode(cs_pin, OUTPUT);
|
||||
pinMode(mosi_pin, OUTPUT);
|
||||
pinMode(sclk_pin, OUTPUT);
|
||||
|
||||
digitalWrite(cs_pin,HIGH);
|
||||
digitalWrite(mosi_pin,LOW);
|
||||
digitalWrite(sclk_pin,LOW);
|
||||
|
||||
width = EPD_WIDTH42;
|
||||
height = EPD_HEIGHT42;
|
||||
|
||||
Reset();
|
||||
SendCommand(POWER_SETTING);
|
||||
SendData(0x03); // VDS_EN, VDG_EN
|
||||
SendData(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
|
||||
SendData(0x2b); // VDH
|
||||
SendData(0x2b); // VDL
|
||||
SendData(0xff); // VDHR
|
||||
SendCommand(BOOSTER_SOFT_START);
|
||||
SendData(0x17);
|
||||
SendData(0x17);
|
||||
SendData(0x17); //07 0f 17 1f 27 2F 37 2f
|
||||
SendCommand(POWER_ON);
|
||||
WaitUntilIdle();
|
||||
SendCommand(PANEL_SETTING);
|
||||
// SendData(0xbf); // KW-BF KWR-AF BWROTP 0f
|
||||
// SendData(0x0b);
|
||||
// SendData(0x0F); //300x400 Red mode, LUT from OTP
|
||||
// SendData(0x1F); //300x400 B/W mode, LUT from OTP
|
||||
SendData(0x3F); //300x400 B/W mode, LUT set by register
|
||||
// SendData(0x2F); //300x400 Red mode, LUT set by register
|
||||
|
||||
SendCommand(PLL_CONTROL);
|
||||
SendData(0x3C); // 3A 100Hz 29 150Hz 39 200Hz 31 171Hz 3C 50Hz (default) 0B 10Hz
|
||||
//SendData(0x0B); //0B is 10Hz
|
||||
/* EPD hardware init end */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: basic function for sending commands
|
||||
*/
|
||||
void Epd42::SendCommand(unsigned char command) {
|
||||
//DigitalWrite(dc_pin, LOW);
|
||||
//SpiTransfer(command);
|
||||
fastSPIwrite(command,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: basic function for sending data
|
||||
*/
|
||||
void Epd42::SendData(unsigned char data) {
|
||||
//DigitalWrite(dc_pin, HIGH);
|
||||
//SpiTransfer(data);
|
||||
fastSPIwrite(data,1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: Wait until the busy_pin goes HIGH
|
||||
*/
|
||||
void Epd42::WaitUntilIdle(void) {
|
||||
// while(DigitalRead(busy_pin) == 0) { //0: busy, 1: idle
|
||||
// DelayMs(1);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: module reset.
|
||||
* often used to awaken the module in deep sleep,
|
||||
* see Epd::Sleep();
|
||||
*/
|
||||
void Epd42::Reset(void) {
|
||||
//DigitalWrite(reset_pin, LOW);
|
||||
//DelayMs(200);
|
||||
//DigitalWrite(reset_pin, HIGH);
|
||||
//DelayMs(200);
|
||||
}
|
||||
/**
|
||||
* @brief: transmit partial data to the SRAM. The final parameter chooses between dtm=1 and dtm=2
|
||||
*/
|
||||
void Epd42::SetPartialWindow(const unsigned char* buffer_black, int x, int y, int w, int l, int dtm) {
|
||||
SendCommand(PARTIAL_IN);
|
||||
SendCommand(PARTIAL_WINDOW);
|
||||
SendData(x >> 8);
|
||||
SendData(x & 0xf8); // x should be the multiple of 8, the last 3 bit will always be ignored
|
||||
SendData(((x & 0xf8) + w - 1) >> 8);
|
||||
SendData(((x & 0xf8) + w - 1) | 0x07);
|
||||
SendData(y >> 8);
|
||||
SendData(y & 0xff);
|
||||
SendData((y + l - 1) >> 8);
|
||||
SendData((y + l - 1) & 0xff);
|
||||
SendData(0x01); // Gates scan both inside and outside of the partial window. (default)
|
||||
// DelayMs(2);
|
||||
SendCommand((dtm == 1) ? DATA_START_TRANSMISSION_1 : DATA_START_TRANSMISSION_2);
|
||||
if (buffer_black != NULL) {
|
||||
for(int i = 0; i < w / 8 * l; i++) {
|
||||
SendData(buffer_black[i]^0xff);
|
||||
}
|
||||
} else {
|
||||
for(int i = 0; i < w / 8 * l; i++) {
|
||||
SendData(0x00);
|
||||
}
|
||||
}
|
||||
// DelayMs(2);
|
||||
SendCommand(PARTIAL_OUT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief: set the look-up table
|
||||
*/
|
||||
void Epd42::SetLut(void) {
|
||||
unsigned int count;
|
||||
SendCommand(LUT_FOR_VCOM); //vcom
|
||||
for(count = 0; count < 44; count++) {
|
||||
SendData(lut_vcom0[count]);
|
||||
}
|
||||
|
||||
SendCommand(LUT_WHITE_TO_WHITE); //ww --
|
||||
for(count = 0; count < 42; count++) {
|
||||
SendData(lut_ww[count]);
|
||||
}
|
||||
|
||||
SendCommand(LUT_BLACK_TO_WHITE); //bw r
|
||||
for(count = 0; count < 42; count++) {
|
||||
SendData(lut_bw[count]);
|
||||
}
|
||||
|
||||
SendCommand(LUT_WHITE_TO_BLACK); //wb w
|
||||
for(count = 0; count < 42; count++) {
|
||||
SendData(lut_wb[count]);
|
||||
}
|
||||
|
||||
SendCommand(LUT_BLACK_TO_BLACK); //bb b
|
||||
for(count = 0; count < 42; count++) {
|
||||
SendData(lut_bb[count]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief: set the look-up table for quick display (partial refresh)
|
||||
*/
|
||||
|
||||
void Epd42::SetLutQuick(void) {
|
||||
unsigned int count;
|
||||
SendCommand(LUT_FOR_VCOM); //vcom
|
||||
for(count = 0; count < 44; count++) {
|
||||
SendData(lut_vcom0_quick[count]);
|
||||
}
|
||||
|
||||
SendCommand(LUT_WHITE_TO_WHITE); //ww --
|
||||
for(count = 0; count < 42; count++) {
|
||||
SendData(lut_ww_quick[count]);
|
||||
}
|
||||
|
||||
SendCommand(LUT_BLACK_TO_WHITE); //bw r
|
||||
for(count = 0; count < 42; count++) {
|
||||
SendData(lut_bw_quick[count]);
|
||||
}
|
||||
|
||||
SendCommand(LUT_WHITE_TO_BLACK); //wb w
|
||||
for(count = 0; count < 42; count++) {
|
||||
SendData(lut_wb_quick[count]);
|
||||
}
|
||||
|
||||
SendCommand(LUT_BLACK_TO_BLACK); //bb b
|
||||
for(count = 0; count < 42; count++) {
|
||||
SendData(lut_bb_quick[count]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief: refresh and displays the frame
|
||||
*/
|
||||
void Epd42::DisplayFrame(const unsigned char* frame_buffer) {
|
||||
SendCommand(RESOLUTION_SETTING);
|
||||
SendData(width >> 8);
|
||||
SendData(width & 0xff);
|
||||
SendData(height >> 8);
|
||||
SendData(height & 0xff);
|
||||
|
||||
SendCommand(VCM_DC_SETTING);
|
||||
SendData(0x12);
|
||||
|
||||
SendCommand(VCOM_AND_DATA_INTERVAL_SETTING);
|
||||
SendCommand(0x97); //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7
|
||||
|
||||
if (frame_buffer != NULL) {
|
||||
SendCommand(DATA_START_TRANSMISSION_1);
|
||||
for(int i = 0; i < width / 8 * height; i++) {
|
||||
SendData(0xFF); // bit set: white, bit reset: black
|
||||
}
|
||||
delay(2);
|
||||
SendCommand(DATA_START_TRANSMISSION_2);
|
||||
for(int i = 0; i < width / 8 * height; i++) {
|
||||
SendData(pgm_read_byte(&frame_buffer[i]));
|
||||
}
|
||||
delay(2);
|
||||
}
|
||||
|
||||
SetLut();
|
||||
|
||||
SendCommand(DISPLAY_REFRESH);
|
||||
delay(100);
|
||||
WaitUntilIdle();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief: clear the frame data from the SRAM, this won't refresh the display
|
||||
*/
|
||||
void Epd42::ClearFrame(void) {
|
||||
SendCommand(RESOLUTION_SETTING);
|
||||
SendData(width >> 8);
|
||||
SendData(width & 0xff);
|
||||
SendData(height >> 8);
|
||||
SendData(height & 0xff);
|
||||
|
||||
SendCommand(DATA_START_TRANSMISSION_1);
|
||||
delay(2);
|
||||
for(int i = 0; i < width / 8 * height; i++) {
|
||||
SendData(0xFF);
|
||||
}
|
||||
delay(2);
|
||||
SendCommand(DATA_START_TRANSMISSION_2);
|
||||
delay(2);
|
||||
for(int i = 0; i < width / 8 * height; i++) {
|
||||
SendData(0xFF);
|
||||
}
|
||||
delay(2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief: This displays the frame data from SRAM
|
||||
*/
|
||||
void Epd42::DisplayFrame(void) {
|
||||
SetLut();
|
||||
SendCommand(DISPLAY_REFRESH);
|
||||
delay(100);
|
||||
WaitUntilIdle();
|
||||
}
|
||||
|
||||
void Epd42::DisplayFrameQuick(void) {
|
||||
SetLutQuick();
|
||||
SendCommand(DISPLAY_REFRESH);
|
||||
// DelayMs(100);
|
||||
// WaitUntilIdle();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief: After this command is transmitted, the chip would enter the deep-sleep mode to save power.
|
||||
* The deep sleep mode would return to standby by hardware reset. The only one parameter is a
|
||||
* check code, the command would be executed if check code = 0xA5.
|
||||
* You can use Epd::Reset() to awaken and use Epd::Init() to initialize.
|
||||
*/
|
||||
void Epd42::Sleep() {
|
||||
SendCommand(VCOM_AND_DATA_INTERVAL_SETTING);
|
||||
SendData(0x17); //border floating
|
||||
SendCommand(VCM_DC_SETTING); //VCOM to 0V
|
||||
SendCommand(PANEL_SETTING);
|
||||
delay(100);
|
||||
|
||||
SendCommand(POWER_SETTING); //VG&VS to 0V fast
|
||||
SendData(0x00);
|
||||
SendData(0x00);
|
||||
SendData(0x00);
|
||||
SendData(0x00);
|
||||
SendData(0x00);
|
||||
delay(100);
|
||||
|
||||
SendCommand(POWER_OFF); //power off
|
||||
WaitUntilIdle();
|
||||
SendCommand(DEEP_SLEEP); //deep sleep
|
||||
SendData(0xA5);
|
||||
}
|
||||
|
||||
const unsigned char lut_vcom0[] =
|
||||
{
|
||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x00, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const unsigned char lut_vcom0_quick[] =
|
||||
{
|
||||
0x00, 0x0E, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
|
||||
const unsigned char lut_ww[] ={
|
||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const unsigned char lut_ww_quick[] ={
|
||||
0xA0, 0x0E, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
const unsigned char lut_bw[] ={
|
||||
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
const unsigned char lut_bw_quick[] ={
|
||||
0xA0, 0x0E, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const unsigned char lut_bb[] ={
|
||||
0x80, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x80, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const unsigned char lut_bb_quick[] ={
|
||||
0x50, 0x0E, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
const unsigned char lut_wb[] ={
|
||||
0x80, 0x17, 0x00, 0x00, 0x00, 0x02,
|
||||
0x90, 0x17, 0x17, 0x00, 0x00, 0x02,
|
||||
0x80, 0x0A, 0x01, 0x00, 0x00, 0x01,
|
||||
0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
const unsigned char lut_wb_quick[] ={
|
||||
0x50, 0x0E, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define PIN_OUT_SET 0x60000304
|
||||
#define PIN_OUT_CLEAR 0x60000308
|
||||
|
||||
#define PWRITE ydigitalWrite
|
||||
|
||||
#ifndef SSPI_USEANYPIN
|
||||
// uses about 2.75 usecs, 365 kb /sec
|
||||
// however does not work with GPIO 16 !!!!
|
||||
void ICACHE_RAM_ATTR Epd42::fastSPIwrite(uint8_t d,uint8_t dc) {
|
||||
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<cs_pin);
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<sclk_pin);
|
||||
if(dc) WRITE_PERI_REG( PIN_OUT_SET, 1<<mosi_pin);
|
||||
else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<mosi_pin);
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<sclk_pin);
|
||||
|
||||
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
||||
WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<sclk_pin);
|
||||
if(d&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<mosi_pin);
|
||||
else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<mosi_pin);
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<sclk_pin);
|
||||
}
|
||||
WRITE_PERI_REG( PIN_OUT_SET, 1<<cs_pin);
|
||||
}
|
||||
#else
|
||||
|
||||
extern void ICACHE_RAM_ATTR ydigitalWrite(uint8_t pin, uint8_t val) {
|
||||
//stopWaveform(pin);
|
||||
if(pin < 16){
|
||||
if(val) GPOS = (1 << pin);
|
||||
else GPOC = (1 << pin);
|
||||
} else if(pin == 16){
|
||||
if(val) GP16O |= 1;
|
||||
else GP16O &= ~1;
|
||||
}
|
||||
}
|
||||
// about 13 us => 76 kb / sec
|
||||
// can use any pin
|
||||
void Epd42::fastSPIwrite(uint8_t d,uint8_t dc) {
|
||||
|
||||
PWRITE(cs_pin, LOW);
|
||||
|
||||
// transfer dc
|
||||
PWRITE(sclk_pin, LOW);
|
||||
if(dc) PWRITE(mosi_pin, HIGH);
|
||||
else PWRITE(mosi_pin, LOW);
|
||||
PWRITE(sclk_pin, HIGH);
|
||||
|
||||
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
||||
PWRITE(sclk_pin, LOW);
|
||||
if(d & bit) PWRITE(mosi_pin, HIGH);
|
||||
else PWRITE(mosi_pin, LOW);
|
||||
PWRITE(sclk_pin, HIGH);
|
||||
}
|
||||
|
||||
PWRITE(cs_pin, HIGH);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* END OF FILE */
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* @filename : epd4in2.h
|
||||
* @brief : Header file for Dual-color e-paper library epd4in2.cpp
|
||||
* @author : Yehui from Waveshare
|
||||
*
|
||||
* Copyright (C) Waveshare August 10 2017
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documnetation 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
|
||||
* furished 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 OR 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.
|
||||
*/
|
||||
|
||||
#ifndef EPD4IN2_H
|
||||
#define EPD4IN2_H
|
||||
|
||||
#include "epdpaint.h"
|
||||
|
||||
// Display resolution
|
||||
#define EPD_WIDTH42 400
|
||||
#define EPD_HEIGHT42 300
|
||||
|
||||
// EPD4IN2 commands
|
||||
#define PANEL_SETTING 0x00
|
||||
#define POWER_SETTING 0x01
|
||||
#define POWER_OFF 0x02
|
||||
#define POWER_OFF_SEQUENCE_SETTING 0x03
|
||||
#define POWER_ON 0x04
|
||||
#define POWER_ON_MEASURE 0x05
|
||||
#define BOOSTER_SOFT_START 0x06
|
||||
#define DEEP_SLEEP 0x07
|
||||
#define DATA_START_TRANSMISSION_1 0x10
|
||||
#define DATA_STOP 0x11
|
||||
#define DISPLAY_REFRESH 0x12
|
||||
#define DATA_START_TRANSMISSION_2 0x13
|
||||
#define LUT_FOR_VCOM 0x20
|
||||
#define LUT_WHITE_TO_WHITE 0x21
|
||||
#define LUT_BLACK_TO_WHITE 0x22
|
||||
#define LUT_WHITE_TO_BLACK 0x23
|
||||
#define LUT_BLACK_TO_BLACK 0x24
|
||||
#define PLL_CONTROL 0x30
|
||||
#define TEMPERATURE_SENSOR_COMMAND 0x40
|
||||
#define TEMPERATURE_SENSOR_SELECTION 0x41
|
||||
#define TEMPERATURE_SENSOR_WRITE 0x42
|
||||
#define TEMPERATURE_SENSOR_READ 0x43
|
||||
#define VCOM_AND_DATA_INTERVAL_SETTING 0x50
|
||||
#define LOW_POWER_DETECTION 0x51
|
||||
#define TCON_SETTING 0x60
|
||||
#define RESOLUTION_SETTING 0x61
|
||||
#define GSST_SETTING 0x65
|
||||
#define GET_STATUS 0x71
|
||||
#define AUTO_MEASUREMENT_VCOM 0x80
|
||||
#define READ_VCOM_VALUE 0x81
|
||||
#define VCM_DC_SETTING 0x82
|
||||
#define PARTIAL_WINDOW 0x90
|
||||
#define PARTIAL_IN 0x91
|
||||
#define PARTIAL_OUT 0x92
|
||||
#define PROGRAM_MODE 0xA0
|
||||
#define ACTIVE_PROGRAMMING 0xA1
|
||||
#define READ_OTP 0xA2
|
||||
#define POWER_SAVING 0xE3
|
||||
|
||||
extern const unsigned char lut_vcom0[];
|
||||
extern const unsigned char lut_ww[];
|
||||
extern const unsigned char lut_bw[];
|
||||
extern const unsigned char lut_bb[];
|
||||
extern const unsigned char lut_wb[];
|
||||
|
||||
extern const unsigned char lut_vcom0_quick[];
|
||||
extern const unsigned char lut_ww_quick[];
|
||||
extern const unsigned char lut_bw_quick[];
|
||||
extern const unsigned char lut_bb_quick[];
|
||||
extern const unsigned char lut_wb_quick[];
|
||||
|
||||
|
||||
|
||||
|
||||
class Epd42 : public Paint {
|
||||
public:
|
||||
Epd42(int16_t width, int16_t height);
|
||||
|
||||
int Init(void);
|
||||
void Init(int8_t p);
|
||||
void SendCommand(unsigned char command);
|
||||
void SendData(unsigned char data);
|
||||
void WaitUntilIdle(void);
|
||||
void Reset(void);
|
||||
|
||||
void SetPartialWindow(const unsigned char* frame_buffer, int x, int y, int w, int l, int dtm);
|
||||
|
||||
void SetPartialWindowBlack(const unsigned char* buffer_black, int x, int y, int w, int l);
|
||||
void SetPartialWindowRed(const unsigned char* buffer_red, int x, int y, int w, int l);
|
||||
void SetLut(void);
|
||||
void SetLutQuick(void);
|
||||
void DisplayFrame(const unsigned char* frame_buffer);
|
||||
void DisplayFrame(void);
|
||||
void DisplayFrameQuick(void);
|
||||
void ClearFrame(void);
|
||||
void Sleep(void);
|
||||
|
||||
void DisplayOnff(int8_t on);
|
||||
void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||
int16_t Begin(int16_t p1,int16_t p2,int16_t p3);
|
||||
void Updateframe();
|
||||
|
||||
private:
|
||||
void fastSPIwrite(uint8_t d,uint8_t dc);
|
||||
uint8_t cs_pin;
|
||||
uint8_t mosi_pin;
|
||||
uint8_t sclk_pin;
|
||||
int16_t width;
|
||||
int16_t height;
|
||||
};
|
||||
|
||||
#endif /* EPD4IN2_H */
|
||||
|
||||
/* END OF FILE */
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* @filename : epdpaint.cpp
|
||||
* @brief : Paint tools
|
||||
* @author : Yehui from Waveshare
|
||||
*
|
||||
* Copyright (C) Waveshare September 9 2017
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documnetation 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
|
||||
* furished 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 OR 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.
|
||||
*/
|
||||
|
||||
#include <pgmspace.h>
|
||||
#include "epdpaint.h"
|
||||
|
||||
extern uint8_t *buffer;
|
||||
|
||||
Paint::Paint(int16_t width, int16_t height) :
|
||||
Renderer(width,height) {
|
||||
}
|
||||
|
||||
|
||||
void Paint::DisplayOnff(int8_t on) {
|
||||
}
|
||||
|
||||
int16_t Paint::Begin(int16_t p1,int16_t p2,int16_t p3) {
|
||||
|
||||
}
|
||||
|
||||
void Paint::Updateframe() {
|
||||
}
|
||||
|
||||
void Paint::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
#define renderer_swap(a, b) { int16_t t = a; a = b; b = t; }
|
||||
/**
|
||||
* @brief: this draws a pixel by absolute coordinates.
|
||||
* this function won't be affected by the rotate parameter.
|
||||
* we must use this for epaper because these displays have a strange and different bit pattern
|
||||
*/
|
||||
void Paint::DrawAbsolutePixel(int x, int y, int16_t color) {
|
||||
|
||||
int16_t w=width(),h=height(),rot=getRotation();
|
||||
if (rot==1 || rot==3) {
|
||||
renderer_swap(w,h);
|
||||
}
|
||||
|
||||
if (x < 0 || x >= w || y < 0 || y >= h) {
|
||||
return;
|
||||
}
|
||||
if (IF_INVERT_COLOR) {
|
||||
if (color) {
|
||||
buffer[(x + y * w) / 8] |= 0x80 >> (x % 8);
|
||||
} else {
|
||||
buffer[(x + y * w) / 8] &= ~(0x80 >> (x % 8));
|
||||
}
|
||||
} else {
|
||||
if (color) {
|
||||
buffer[(x + y * w) / 8] &= ~(0x80 >> (x % 8));
|
||||
} else {
|
||||
buffer[(x + y * w) / 8] |= 0x80 >> (x % 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief: this draws a pixel by the coordinates
|
||||
*/
|
||||
void Paint::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
int16_t point_temp;
|
||||
int8_t rot=getRotation();
|
||||
if (rot == ROTATE_0) {
|
||||
if(x < 0 || x >= width() || y < 0 || y >= height()) {
|
||||
return;
|
||||
}
|
||||
DrawAbsolutePixel(x, y, color);
|
||||
} else if (rot== ROTATE_90) {
|
||||
if(x < 0 || x >= width() || y < 0 || y >=height() ) {
|
||||
return;
|
||||
}
|
||||
point_temp = x;
|
||||
x = height() - y;
|
||||
y = point_temp;
|
||||
DrawAbsolutePixel(x, y, color);
|
||||
} else if (rot == ROTATE_180) {
|
||||
if(x < 0 || x >= width() || y < 0 || y >= height()) {
|
||||
return;
|
||||
}
|
||||
x = width() - x;
|
||||
y = height() - y;
|
||||
DrawAbsolutePixel(x, y, color);
|
||||
} else if (rot == ROTATE_270) {
|
||||
if(x < 0 || x >= width() || y < 0 || y >= height()) {
|
||||
return;
|
||||
}
|
||||
point_temp = x;
|
||||
x = y;
|
||||
y = width() - point_temp;
|
||||
DrawAbsolutePixel(x, y, color);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
void Paint::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
if (!buffer) return;
|
||||
if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
|
||||
return;
|
||||
|
||||
// check rotation, move pixel around if necessary
|
||||
switch (getRotation()) {
|
||||
case 1:
|
||||
renderer_swap(x, y);
|
||||
x = WIDTH - x - 1;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - 1;
|
||||
y = HEIGHT - y - 1;
|
||||
break;
|
||||
case 3:
|
||||
renderer_swap(x, y);
|
||||
y = HEIGHT - y - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// x is which column
|
||||
DrawAbsolutePixel(x,y,color);
|
||||
/*
|
||||
switch (color)
|
||||
{
|
||||
case WHITE: buffer[x+ (y/8)*WIDTH] |= (1 << (y&7)); break;
|
||||
case BLACK: buffer[x+ (y/8)*WIDTH] &= ~(1 << (y&7)); break;
|
||||
case INVERSE: buffer[x+ (y/8)*WIDTH] ^= (1 << (y&7)); break;
|
||||
}*/
|
||||
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @brief: this draws a horizontal line on the frame buffer
|
||||
*/
|
||||
void Paint::drawFastHLine(int16_t x, int16_t y, int16_t line_width, uint16_t colored) {
|
||||
int i;
|
||||
for (i = x; i < x + line_width; i++) {
|
||||
drawPixel(i, y, colored);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a vertical line on the frame buffer
|
||||
*/
|
||||
void Paint::drawFastVLine(int16_t x, int16_t y, int16_t line_height, uint16_t colored) {
|
||||
int i;
|
||||
for (i = y; i < y + line_height; i++) {
|
||||
drawPixel(x, i, colored);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* END OF FILE */
|
|
@ -37,36 +37,21 @@
|
|||
#define IF_INVERT_COLOR 1
|
||||
|
||||
#include "fonts.h"
|
||||
#include "renderer.h"
|
||||
|
||||
class Paint {
|
||||
class Paint : public Renderer {
|
||||
public:
|
||||
Paint(unsigned char* image, int width, int height);
|
||||
~Paint();
|
||||
void Clear(int colored);
|
||||
int GetWidth(void);
|
||||
void SetWidth(int width);
|
||||
int GetHeight(void);
|
||||
void SetHeight(int height);
|
||||
int GetRotate(void);
|
||||
void SetRotate(int rotate);
|
||||
unsigned char* GetImage(void);
|
||||
void DrawAbsolutePixel(int x, int y, int colored);
|
||||
void DrawPixel(int x, int y, int colored);
|
||||
void DrawCharAt(int x, int y, char ascii_char, sFONT* font, int colored);
|
||||
void DrawStringAt(int x, int y, const char* text, sFONT* font, int colored);
|
||||
void DrawLine(int x0, int y0, int x1, int y1, int colored);
|
||||
void DrawHorizontalLine(int x, int y, int width, int colored);
|
||||
void DrawVerticalLine(int x, int y, int height, int colored);
|
||||
void DrawRectangle(int x0, int y0, int x1, int y1, int colored);
|
||||
void DrawFilledRectangle(int x0, int y0, int x1, int y1, int colored);
|
||||
void DrawCircle(int x, int y, int radius, int colored);
|
||||
void DrawFilledCircle(int x, int y, int radius, int colored);
|
||||
Paint(int16_t width, int16_t height);
|
||||
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void drawFastVLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void DrawAbsolutePixel(int x, int y, int16_t color);
|
||||
|
||||
void DisplayOnff(int8_t on);
|
||||
void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||
int16_t Begin(int16_t p1,int16_t p2,int16_t p3);
|
||||
void Updateframe();
|
||||
|
||||
private:
|
||||
unsigned char* image;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint8_t rotate;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -51,12 +51,14 @@
|
|||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
|
||||
#define USE_TINY_FONT
|
||||
|
||||
typedef struct _tFont
|
||||
{
|
||||
{
|
||||
const uint8_t *table;
|
||||
uint16_t Width;
|
||||
uint16_t Height;
|
||||
|
||||
|
||||
} sFONT;
|
||||
|
||||
extern sFONT Font24;
|
||||
|
@ -68,8 +70,8 @@ extern sFONT Font8;
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __FONTS_H */
|
||||
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,519 @@
|
|||
/**
|
||||
* @filename : epdpaint.cpp
|
||||
* @brief : Paint tools
|
||||
* @author : Yehui from Waveshare
|
||||
*
|
||||
* Copyright (C) Waveshare September 9 2017
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documnetation 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
|
||||
* furished 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 OR 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.
|
||||
*/
|
||||
|
||||
#include <pgmspace.h>
|
||||
#include "renderer.h"
|
||||
|
||||
#define USE_EPD_FONTS
|
||||
//#define USE_ALL_EPD_FONTS
|
||||
//#define USE_GFX_FONTS
|
||||
#define USE_TINY_FONT
|
||||
|
||||
uint8_t wr_redir=0;
|
||||
|
||||
uint8_t *buffer;
|
||||
|
||||
#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);
|
||||
|
||||
#define OLED_FONT_WIDTH 6
|
||||
#define OLED_FONT_HEIGTH 8
|
||||
#define BLACK 0
|
||||
|
||||
Renderer::Renderer(int16_t x, int16_t y) :
|
||||
Adafruit_GFX(x, y) {
|
||||
font=0;
|
||||
#ifdef USE_EPD_FONTS
|
||||
selected_font = &Font12;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
uint16_t Renderer::GetColorFromIndex(uint8_t index) {
|
||||
if (index>0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Renderer::dim(uint8_t contrast) {
|
||||
|
||||
}
|
||||
|
||||
void Renderer::pushColors(uint16_t *data, uint8_t len, boolean first) {
|
||||
|
||||
}
|
||||
|
||||
void Renderer::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||
|
||||
}
|
||||
|
||||
void Renderer::DisplayOnff(int8_t on) {
|
||||
|
||||
}
|
||||
void Renderer::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
|
||||
}
|
||||
|
||||
int16_t Renderer::Begin(int16_t p1,int16_t p2,int16_t p3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Renderer::Updateframe() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this draws a charactor on the frame buffer but not refresh
|
||||
*/
|
||||
void Renderer::DrawCharAt(int16_t x, int16_t y, char ascii_char,int16_t colored) {
|
||||
#ifdef USE_EPD_FONTS
|
||||
sFONT *xfont = selected_font;
|
||||
int i, j;
|
||||
unsigned int char_offset = (ascii_char - ' ') * xfont->Height * (xfont->Width / 8 + (xfont->Width % 8 ? 1 : 0));
|
||||
const unsigned char* ptr = &xfont->table[char_offset];
|
||||
|
||||
for (j = 0; j < xfont->Height; j++) {
|
||||
for (i = 0; i < xfont->Width; i++) {
|
||||
if (pgm_read_byte(ptr) & (0x80 >> (i % 8))) {
|
||||
writePixel(x + i, y + j, colored);
|
||||
} else {
|
||||
// fill background
|
||||
if (!drawmode) writePixel(x + i, y + j, textbgcolor);
|
||||
}
|
||||
if (i % 8 == 7) {
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
if (xfont->Width % 8 != 0) {
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief: this displays a string on the frame buffer but not refresh
|
||||
*/
|
||||
void Renderer::DrawStringAt(int16_t x, int16_t y, const char* text, uint16_t colored, uint8_t flag) {
|
||||
const char* p_text = text;
|
||||
unsigned int counter = 0;
|
||||
int refcolumn = x;
|
||||
sFONT *xfont = selected_font;
|
||||
|
||||
#ifndef USE_EPD_FONTS
|
||||
font=0;
|
||||
#endif
|
||||
|
||||
#ifndef USE_GFX_FONTS
|
||||
if (!font) {
|
||||
#endif
|
||||
if (flag) {
|
||||
x=(x-1)*OLED_FONT_WIDTH*textsize_x;
|
||||
y=(y-1)*OLED_FONT_HEIGTH*textsize_y;
|
||||
}
|
||||
setCursor(x,y);
|
||||
setTextColor(colored,textbgcolor);
|
||||
print(text);
|
||||
return;
|
||||
#ifndef USE_GFX_FONTS
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (flag) {
|
||||
x=(x-1)*xfont->Width;
|
||||
y=(y-1)*xfont->Height;
|
||||
refcolumn = x;
|
||||
}
|
||||
|
||||
/* Send the string character by character on EPD */
|
||||
if (font==7) {
|
||||
return FastString(x,y,colored,p_text);
|
||||
}
|
||||
while (*p_text != 0) {
|
||||
/* Display one character on EPD */
|
||||
DrawCharAt(refcolumn, y, *p_text, colored);
|
||||
/* increment the column position */
|
||||
refcolumn += xfont->Width;
|
||||
/* Point on the next character */
|
||||
p_text++;
|
||||
counter++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Renderer::FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str) {
|
||||
|
||||
}
|
||||
|
||||
#include <Fonts/FreeMono12pt7b.h>
|
||||
#include <Fonts/FreeMono18pt7b.h>
|
||||
#include <Fonts/FreeMono24pt7b.h>
|
||||
|
||||
sFONT RAFont = {
|
||||
0,
|
||||
7, /* Width */
|
||||
12, /* Height */
|
||||
};
|
||||
|
||||
void Renderer::setTextFont(uint8_t f) {
|
||||
font=f;
|
||||
|
||||
#ifdef USE_GFX_FONTS
|
||||
switch (f) {
|
||||
case 0:
|
||||
setFont(0);
|
||||
break;
|
||||
case 1:
|
||||
setFont(&FreeMono12pt7b);
|
||||
break;
|
||||
case 2:
|
||||
setFont(&FreeMono18pt7b);
|
||||
break;
|
||||
case 3:
|
||||
setFont(&FreeMono24pt7b);
|
||||
break;
|
||||
default:
|
||||
setFont(0);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_ALL_EPD_FONTS
|
||||
switch (font) {
|
||||
case 1:
|
||||
selected_font = &Font12;
|
||||
break;
|
||||
case 2:
|
||||
selected_font = &Font24;
|
||||
break;
|
||||
case 3:
|
||||
selected_font = &Font8;
|
||||
break;
|
||||
case 4:
|
||||
selected_font = &Font16;
|
||||
break;
|
||||
case 5:
|
||||
selected_font = &Font20;
|
||||
break;
|
||||
case 7:
|
||||
selected_font = &RAFont;
|
||||
default:
|
||||
font=0;
|
||||
}
|
||||
#else
|
||||
#ifdef USE_EPD_FONTS
|
||||
if (1 == font) {
|
||||
selected_font = &Font12;
|
||||
} else {
|
||||
#ifdef USE_TINY_FONT
|
||||
if (2 == font) {
|
||||
selected_font = &Font24;
|
||||
} else {
|
||||
selected_font = &Font8;
|
||||
}
|
||||
#else
|
||||
selected_font = &Font24;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Renderer::clearDisplay(void) {
|
||||
fillScreen(BLACK);
|
||||
}
|
||||
|
||||
#define renderer_swap(a, b) { int16_t t = a; a = b; b = t; }
|
||||
|
||||
void Renderer::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
boolean bSwap = false;
|
||||
if (!buffer) return;
|
||||
switch(getRotation()) {
|
||||
case 0:
|
||||
// 0 degree rotation, do nothing
|
||||
break;
|
||||
case 1:
|
||||
// 90 degree rotation, swap x & y for rotation, then invert x
|
||||
bSwap = true;
|
||||
renderer_swap(x, y);
|
||||
x = WIDTH - x - 1;
|
||||
break;
|
||||
case 2:
|
||||
// 180 degree rotation, invert x and y - then shift y around for height.
|
||||
x = WIDTH - x - 1;
|
||||
y = HEIGHT - y - 1;
|
||||
x -= (w-1);
|
||||
break;
|
||||
case 3:
|
||||
// 270 degree rotation, swap x & y for rotation, then invert y and adjust y for w (not to become h)
|
||||
bSwap = true;
|
||||
renderer_swap(x, y);
|
||||
y = HEIGHT - y - 1;
|
||||
y -= (w-1);
|
||||
break;
|
||||
}
|
||||
|
||||
if(bSwap) {
|
||||
drawFastVLineInternal(x, y, w, color);
|
||||
} else {
|
||||
drawFastHLineInternal(x, y, w, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
// Do bounds/limit checks
|
||||
if(y < 0 || y >= HEIGHT) { return; }
|
||||
|
||||
// make sure we don't try to draw below 0
|
||||
if(x < 0) {
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
// make sure we don't go off the edge of the display
|
||||
if( (x + w) > WIDTH) {
|
||||
w = (WIDTH - x);
|
||||
}
|
||||
|
||||
// if our width is now negative, punt
|
||||
if(w <= 0) { return; }
|
||||
|
||||
// set up the pointer for movement through the buffer
|
||||
register uint8_t *pBuf = buffer;
|
||||
// adjust the buffer pointer for the current row
|
||||
pBuf += ((y/8) * WIDTH);
|
||||
// and offset x columns in
|
||||
pBuf += x;
|
||||
|
||||
register uint8_t mask = 1 << (y&7);
|
||||
|
||||
switch (color)
|
||||
{
|
||||
case WHITE: while(w--) { *pBuf++ |= mask; }; break;
|
||||
case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
|
||||
case INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
||||
if (!buffer) return;
|
||||
bool bSwap = false;
|
||||
switch(getRotation()) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
// 90 degree rotation, swap x & y for rotation, then invert x and adjust x for h (now to become w)
|
||||
bSwap = true;
|
||||
renderer_swap(x, y);
|
||||
x = WIDTH - x - 1;
|
||||
x -= (h-1);
|
||||
break;
|
||||
case 2:
|
||||
// 180 degree rotation, invert x and y - then shift y around for height.
|
||||
x = WIDTH - x - 1;
|
||||
y = HEIGHT - y - 1;
|
||||
y -= (h-1);
|
||||
break;
|
||||
case 3:
|
||||
// 270 degree rotation, swap x & y for rotation, then invert y
|
||||
bSwap = true;
|
||||
renderer_swap(x, y);
|
||||
y = HEIGHT - y - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(bSwap) {
|
||||
drawFastHLineInternal(x, y, h, color);
|
||||
} else {
|
||||
drawFastVLineInternal(x, y, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color) {
|
||||
|
||||
// do nothing if we're off the left or right side of the screen
|
||||
if(x < 0 || x >= WIDTH) { return; }
|
||||
|
||||
// make sure we don't try to draw below 0
|
||||
if(__y < 0) {
|
||||
// __y is negative, this will subtract enough from __h to account for __y being 0
|
||||
__h += __y;
|
||||
__y = 0;
|
||||
|
||||
}
|
||||
|
||||
// make sure we don't go past the height of the display
|
||||
if( (__y + __h) > HEIGHT) {
|
||||
__h = (HEIGHT - __y);
|
||||
}
|
||||
|
||||
// if our height is now negative, punt
|
||||
if(__h <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// this display doesn't need ints for coordinates, use local byte registers for faster juggling
|
||||
register uint8_t y = __y;
|
||||
register uint8_t h = __h;
|
||||
|
||||
|
||||
// set up the pointer for fast movement through the buffer
|
||||
register uint8_t *pBuf = buffer;
|
||||
// adjust the buffer pointer for the current row
|
||||
pBuf += ((y/8) * WIDTH);
|
||||
// and offset x columns in
|
||||
pBuf += x;
|
||||
|
||||
// do the first partial byte, if necessary - this requires some masking
|
||||
register uint8_t mod = (y&7);
|
||||
if(mod) {
|
||||
// mask off the high n bits we want to set
|
||||
mod = 8-mod;
|
||||
|
||||
// note - lookup table results in a nearly 10% performance improvement in fill* functions
|
||||
// register uint8_t mask = ~(0xFF >> (mod));
|
||||
static uint8_t premask[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
|
||||
register uint8_t mask = premask[mod];
|
||||
|
||||
// adjust the mask if we're not going to reach the end of this byte
|
||||
if( h < mod) {
|
||||
mask &= (0XFF >> (mod-h));
|
||||
}
|
||||
|
||||
switch (color)
|
||||
{
|
||||
case WHITE: *pBuf |= mask; break;
|
||||
case BLACK: *pBuf &= ~mask; break;
|
||||
case INVERSE: *pBuf ^= mask; break;
|
||||
}
|
||||
|
||||
// fast exit if we're done here!
|
||||
if(h<mod) { return; }
|
||||
|
||||
h -= mod;
|
||||
|
||||
pBuf += WIDTH;
|
||||
}
|
||||
|
||||
|
||||
// write solid bytes while we can - effectively doing 8 rows at a time
|
||||
if(h >= 8) {
|
||||
if (color == INVERSE) { // separate copy of the code so we don't impact performance of the black/white write version with an extra comparison per loop
|
||||
do {
|
||||
*pBuf=~(*pBuf);
|
||||
|
||||
// adjust the buffer forward 8 rows worth of data
|
||||
pBuf += WIDTH;
|
||||
|
||||
// adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
|
||||
h -= 8;
|
||||
} while(h >= 8);
|
||||
}
|
||||
else {
|
||||
// store a local value to work with
|
||||
register uint8_t val = (color == WHITE) ? 255 : 0;
|
||||
|
||||
do {
|
||||
// write our value in
|
||||
*pBuf = val;
|
||||
|
||||
// adjust the buffer forward 8 rows worth of data
|
||||
pBuf += WIDTH;
|
||||
|
||||
// adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
|
||||
h -= 8;
|
||||
} while(h >= 8);
|
||||
}
|
||||
}
|
||||
|
||||
// now do the final partial byte, if necessary
|
||||
if(h) {
|
||||
mod = h & 7;
|
||||
// this time we want to mask the low bits of the byte, vs the high bits we did above
|
||||
// register uint8_t mask = (1 << mod) - 1;
|
||||
// note - lookup table results in a nearly 10% performance improvement in fill* functions
|
||||
static uint8_t postmask[8] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
|
||||
register uint8_t mask = postmask[mod];
|
||||
switch (color)
|
||||
{
|
||||
case WHITE: *pBuf |= mask; break;
|
||||
case BLACK: *pBuf &= ~mask; break;
|
||||
case INVERSE: *pBuf ^= mask; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
void Renderer::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
if (jdrawPixel)(*jdrawPixel)(x,y,color);
|
||||
}
|
||||
*/
|
||||
|
||||
// the most basic function, set a single pixel
|
||||
void Renderer::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
if (!buffer) return;
|
||||
if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
|
||||
return;
|
||||
|
||||
// check rotation, move pixel around if necessary
|
||||
switch (getRotation()) {
|
||||
case 1:
|
||||
renderer_swap(x, y);
|
||||
x = WIDTH - x - 1;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - 1;
|
||||
y = HEIGHT - y - 1;
|
||||
break;
|
||||
case 3:
|
||||
renderer_swap(x, y);
|
||||
y = HEIGHT - y - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// x is which column
|
||||
switch (color)
|
||||
{
|
||||
case WHITE: buffer[x+ (y/8)*WIDTH] |= (1 << (y&7)); break;
|
||||
case BLACK: buffer[x+ (y/8)*WIDTH] &= ~(1 << (y&7)); break;
|
||||
case INVERSE: buffer[x+ (y/8)*WIDTH] ^= (1 << (y&7)); break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Renderer::setDrawMode(uint8_t mode) {
|
||||
drawmode=mode;
|
||||
}
|
||||
|
||||
void VButton::xdrawButton(bool inverted) {
|
||||
wr_redir=1;
|
||||
drawButton(inverted);
|
||||
wr_redir=0;
|
||||
}
|
||||
|
||||
/* END OF FILE */
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
#ifndef RENDERER_H
|
||||
#define RENDERER_H
|
||||
|
||||
#include <Adafruit_GFX.h>
|
||||
#include "fonts.h"
|
||||
|
||||
#define BLACK 0
|
||||
#define WHITE 1
|
||||
#define INVERSE 2
|
||||
|
||||
// depends on GFX driver
|
||||
// GFX patched
|
||||
// a. in class GFX setCursor,setTextSize => virtual
|
||||
// b. textcolor,textbgcolor => public;
|
||||
|
||||
|
||||
class Renderer : public Adafruit_GFX {
|
||||
//Paint(unsigned char* image, int width, int height);
|
||||
//~Renderer();
|
||||
public:
|
||||
Renderer(int16_t x, int16_t y);
|
||||
void setTextFont(uint8_t f);
|
||||
void clearDisplay(void);
|
||||
virtual void DrawStringAt(int16_t x, int16_t y, const char* text,uint16_t colored,uint8_t flag);
|
||||
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
virtual uint16_t GetColorFromIndex(uint8_t index);
|
||||
|
||||
virtual void DisplayOnff(int8_t on);
|
||||
virtual void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font);
|
||||
virtual int16_t Begin(int16_t p1,int16_t p2,int16_t p3);
|
||||
virtual void Updateframe();
|
||||
virtual void dim(uint8_t contrast);
|
||||
virtual void pushColors(uint16_t *data, uint8_t len, boolean first);
|
||||
virtual void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||
void setDrawMode(uint8_t mode);
|
||||
uint8_t drawmode;
|
||||
virtual void FastString(uint16_t x,uint16_t y,uint16_t tcolor, const char* str);
|
||||
private:
|
||||
void DrawCharAt(int16_t x, int16_t y, char ascii_char,int16_t colored);
|
||||
inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline));
|
||||
inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline));
|
||||
sFONT *selected_font;
|
||||
uint8_t font;
|
||||
};
|
||||
|
||||
class VButton : public Adafruit_GFX_Button {
|
||||
public:
|
||||
uint8_t vpower;
|
||||
void xdrawButton(bool inverted);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* END OF FILE */
|
|
@ -23,7 +23,7 @@ build_dir = .pioenvs
|
|||
;default_envs = sonoff-BR
|
||||
;default_envs = sonoff-CN
|
||||
;default_envs = sonoff-CZ
|
||||
;default_envs = sonoff-DE
|
||||
default_envs = sonoff-DE
|
||||
;default_envs = sonoff-ES
|
||||
;default_envs = sonoff-FR
|
||||
;default_envs = sonoff-GR
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
xdsp_02_ssd1306.ino - Display Oled ssd1306 support for Sonoff-Tasmota
|
||||
xdsp_02_SSD1306.ino - Display Oled SSD1306 support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2019 Theo Arends and Adafruit
|
||||
Copyright (C) 2018 Theo Arends and Adafruit
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -21,58 +21,33 @@
|
|||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_SSD1306
|
||||
|
||||
#define OLED_RESET 4
|
||||
|
||||
#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);
|
||||
|
||||
extern uint8_t *buffer;
|
||||
|
||||
#define XDSP_02 2
|
||||
|
||||
#define OLED_ADDRESS1 0x3C // Oled 128x32 I2C address
|
||||
#define OLED_ADDRESS2 0x3D // Oled 128x64 I2C address
|
||||
|
||||
#define OLED_BUFFER_COLS 40 // Max number of columns in display shadow buffer
|
||||
#define OLED_BUFFER_ROWS 16 // Max number of lines in display shadow buffer
|
||||
|
||||
#define OLED_FONT_WIDTH 6
|
||||
#define OLED_FONT_HEIGTH 8
|
||||
|
||||
//#define OLED_BUFFER_COLS 21 or 11 // Max number of columns in display shadow buffer
|
||||
//#define OLED_BUFFER_ROWS 8 or 16 // Max number of lines in display shadow buffer
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <renderer.h>
|
||||
#include <Adafruit_SSD1306.h>
|
||||
|
||||
Adafruit_SSD1306 *oled;
|
||||
|
||||
uint8_t ssd1306_font_x = OLED_FONT_WIDTH;
|
||||
uint8_t ssd1306_font_y = OLED_FONT_HEIGTH;
|
||||
Adafruit_SSD1306 *oled1306;
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void Ssd1306InitMode(void)
|
||||
{
|
||||
oled->setRotation(Settings.display_rotate); // 0
|
||||
oled->invertDisplay(false);
|
||||
oled->clearDisplay();
|
||||
oled->setTextWrap(false); // Allow text to run off edges
|
||||
oled->cp437(true);
|
||||
|
||||
oled->setTextSize(Settings.display_size);
|
||||
oled->setTextColor(WHITE);
|
||||
oled->setCursor(0,0);
|
||||
oled->display();
|
||||
}
|
||||
|
||||
void Ssd1306Init(uint8_t mode)
|
||||
{
|
||||
switch(mode) {
|
||||
case DISPLAY_INIT_MODE:
|
||||
Ssd1306InitMode();
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
DisplayClearScreenBuffer();
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
break;
|
||||
case DISPLAY_INIT_PARTIAL:
|
||||
case DISPLAY_INIT_FULL:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Ssd1306InitDriver(void)
|
||||
void SSD1306InitDriver()
|
||||
{
|
||||
if (!Settings.display_model) {
|
||||
if (I2cDevice(OLED_ADDRESS1)) {
|
||||
|
@ -86,61 +61,47 @@ void Ssd1306InitDriver(void)
|
|||
}
|
||||
|
||||
if (XDSP_02 == Settings.display_model) {
|
||||
|
||||
if ((Settings.display_width != 96) && (Settings.display_width != 128)) {
|
||||
Settings.display_width = 128;
|
||||
}
|
||||
if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 64)) {
|
||||
Settings.display_height = 64;
|
||||
}
|
||||
int8_t reset_pin = -1;
|
||||
|
||||
uint8_t reset_pin = -1;
|
||||
if (pin[GPIO_OLED_RESET] < 99) {
|
||||
reset_pin = pin[GPIO_OLED_RESET];
|
||||
}
|
||||
oled = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, reset_pin);
|
||||
oled->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0]);
|
||||
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
DisplayAllocScreenBuffer();
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
// allocate screen buffer
|
||||
if (buffer) free(buffer);
|
||||
buffer=(unsigned char*)calloc((Settings.display_width * Settings.display_height) / 8,1);
|
||||
if (!buffer) return;
|
||||
|
||||
// init renderer
|
||||
//oled1306 = new Adafruit_SSD1306(SSD1306_LCDWIDTH,SSD1306_LCDHEIGHT);
|
||||
oled1306 = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, reset_pin);
|
||||
oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0],0);
|
||||
renderer=oled1306;
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
|
||||
renderer->setTextColor(1,0);
|
||||
|
||||
#ifdef SHOW_SPLASH
|
||||
renderer->setTextFont(0);
|
||||
renderer->setTextSize(2);
|
||||
renderer->setCursor(20,20);
|
||||
renderer->println(F("SSD1306"));
|
||||
renderer->Updateframe();
|
||||
renderer->DisplayOnff(1);
|
||||
#endif
|
||||
|
||||
Ssd1306InitMode();
|
||||
}
|
||||
}
|
||||
|
||||
void Ssd1306Clear(void)
|
||||
{
|
||||
oled->clearDisplay();
|
||||
oled->setCursor(0, 0);
|
||||
oled->display();
|
||||
}
|
||||
|
||||
void Ssd1306DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag)
|
||||
{
|
||||
if (!flag) {
|
||||
oled->setCursor(x, y);
|
||||
} else {
|
||||
oled->setCursor((x-1) * ssd1306_font_x * Settings.display_size, (y-1) * ssd1306_font_y * Settings.display_size);
|
||||
}
|
||||
oled->println(str);
|
||||
}
|
||||
|
||||
void Ssd1306DisplayOnOff(uint8_t on)
|
||||
{
|
||||
if (on) {
|
||||
oled->ssd1306_command(SSD1306_DISPLAYON);
|
||||
} else {
|
||||
oled->ssd1306_command(SSD1306_DISPLAYOFF);
|
||||
}
|
||||
}
|
||||
|
||||
void Ssd1306OnOff(void)
|
||||
{
|
||||
Ssd1306DisplayOnOff(disp_power);
|
||||
oled->display();
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
|
||||
void Ssd1306PrintLog(void)
|
||||
|
@ -151,23 +112,24 @@ void Ssd1306PrintLog(void)
|
|||
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
|
||||
|
||||
char* txt = DisplayLogBuffer('\370');
|
||||
if (txt != nullptr) {
|
||||
if (txt != NULL) {
|
||||
uint8_t last_row = Settings.display_rows -1;
|
||||
|
||||
oled->clearDisplay();
|
||||
oled->setTextSize(Settings.display_size);
|
||||
oled->setCursor(0,0);
|
||||
for (uint32_t i = 0; i < last_row; i++) {
|
||||
renderer->clearDisplay();
|
||||
renderer->setTextSize(Settings.display_size);
|
||||
renderer->setCursor(0,0);
|
||||
for (byte i = 0; i < last_row; i++) {
|
||||
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
|
||||
oled->println(disp_screen_buffer[i]);
|
||||
renderer->println(disp_screen_buffer[i]);
|
||||
}
|
||||
strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols);
|
||||
DisplayFillScreen(last_row);
|
||||
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]);
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
oled->println(disp_screen_buffer[last_row]);
|
||||
oled->display();
|
||||
renderer->println(disp_screen_buffer[last_row]);
|
||||
renderer->Updateframe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,14 +138,14 @@ void Ssd1306Time(void)
|
|||
{
|
||||
char line[12];
|
||||
|
||||
oled->clearDisplay();
|
||||
oled->setTextSize(2);
|
||||
oled->setCursor(0, 0);
|
||||
renderer->clearDisplay();
|
||||
renderer->setTextSize(2);
|
||||
renderer->setCursor(0, 0);
|
||||
snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ]
|
||||
oled->println(line);
|
||||
renderer->println(line);
|
||||
snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); // [01-02-2018]
|
||||
oled->println(line);
|
||||
oled->display();
|
||||
renderer->println(line);
|
||||
renderer->Updateframe();
|
||||
}
|
||||
|
||||
void Ssd1306Refresh(void) // Every second
|
||||
|
@ -209,70 +171,20 @@ void Ssd1306Refresh(void) // Every second
|
|||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdsp02(uint8_t function)
|
||||
bool Xdsp02(byte function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||
Ssd1306InitDriver();
|
||||
SSD1306InitDriver();
|
||||
}
|
||||
else if (XDSP_02 == Settings.display_model) {
|
||||
|
||||
if (!dsp_color) { dsp_color = WHITE; }
|
||||
|
||||
switch (function) {
|
||||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
case FUNC_DISPLAY_INIT:
|
||||
Ssd1306Init(dsp_init);
|
||||
break;
|
||||
case FUNC_DISPLAY_POWER:
|
||||
Ssd1306OnOff();
|
||||
break;
|
||||
case FUNC_DISPLAY_CLEAR:
|
||||
Ssd1306Clear();
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_HLINE:
|
||||
oled->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_VLINE:
|
||||
oled->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_LINE:
|
||||
oled->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_CIRCLE:
|
||||
oled->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_FILL_CIRCLE:
|
||||
oled->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_RECTANGLE:
|
||||
oled->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_FILL_RECTANGLE:
|
||||
oled->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_FRAME:
|
||||
oled->display();
|
||||
break;
|
||||
case FUNC_DISPLAY_TEXT_SIZE:
|
||||
oled->setTextSize(Settings.display_size);
|
||||
break;
|
||||
case FUNC_DISPLAY_FONT_SIZE:
|
||||
// oled->setTextSize(Settings.display_font);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_STRING:
|
||||
Ssd1306DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag);
|
||||
break;
|
||||
case FUNC_DISPLAY_ONOFF:
|
||||
Ssd1306DisplayOnOff(dsp_on);
|
||||
break;
|
||||
case FUNC_DISPLAY_ROTATION:
|
||||
oled->setRotation(Settings.display_rotate);
|
||||
break;
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
case FUNC_DISPLAY_EVERY_SECOND:
|
||||
Ssd1306Refresh();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
xdsp_05_epaper_29.ino - 2.9 Inch display e-paper support for Sonoff-Tasmota
|
||||
xdsp_05_epaper.ino - Display e-paper support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2019 Theo Arends, Gerhard Mutz and Waveshare
|
||||
Copyright (C) 2018 Theo Arends, Gerhard Mutz and Waveshare
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -19,15 +19,15 @@
|
|||
|
||||
#ifdef USE_SPI
|
||||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_EPAPER_29
|
||||
#ifdef USE_DISPLAY_EPAPER29
|
||||
|
||||
#define XDSP_05 5
|
||||
|
||||
#define EPD_TOP 12
|
||||
#define EPD_FONT_HEIGTH 12
|
||||
|
||||
#define COLORED 0
|
||||
#define UNCOLORED 1
|
||||
#define COLORED 1
|
||||
#define UNCOLORED 0
|
||||
|
||||
// using font 8 is opional (num=3)
|
||||
// very badly readable, but may be useful for graphs
|
||||
|
@ -36,82 +36,15 @@
|
|||
#include <epd2in9.h>
|
||||
#include <epdpaint.h>
|
||||
|
||||
unsigned char image[(EPD_HEIGHT * EPD_WIDTH) / 8];
|
||||
|
||||
Paint paint(image, EPD_WIDTH, EPD_HEIGHT); // width should be the multiple of 8
|
||||
Epd epd;
|
||||
sFONT *selected_font;
|
||||
|
||||
//unsigned char image[(EPD_HEIGHT * EPD_WIDTH) / 8];
|
||||
extern uint8_t *buffer;
|
||||
uint16_t epd_scroll;
|
||||
|
||||
Epd *epd;
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void EpdInitMode(void)
|
||||
{
|
||||
// whiten display with full update
|
||||
epd.Init(lut_full_update);
|
||||
|
||||
epd.ClearFrameMemory(0xFF); // bit set = white, bit reset = black
|
||||
epd.DisplayFrame();
|
||||
delay(3000);
|
||||
|
||||
// switch to partial update
|
||||
epd.Init(lut_partial_update);
|
||||
|
||||
// Clear image memory
|
||||
epd.ClearFrameMemory(0xFF); // bit set = white, bit reset = black
|
||||
epd.DisplayFrame();
|
||||
delay(500);
|
||||
|
||||
selected_font = &Font12;
|
||||
|
||||
paint.SetRotate(Settings.display_rotate);
|
||||
/*
|
||||
// Welcome text
|
||||
paint.Clear(UNCOLORED);
|
||||
paint.DrawStringAt(50, 50, "Waveshare E-Paper Display!", selected_font, COLORED);
|
||||
epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight());
|
||||
epd.DisplayFrame();
|
||||
delay(1000);
|
||||
*/
|
||||
paint.Clear(UNCOLORED);
|
||||
|
||||
epd_scroll = EPD_TOP;
|
||||
}
|
||||
|
||||
void EpdInitPartial(void)
|
||||
{
|
||||
epd.Init(lut_partial_update);
|
||||
//paint.Clear(UNCOLORED);
|
||||
epd.DisplayFrame();
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void EpdInitFull(void)
|
||||
{
|
||||
epd.Init(lut_full_update);
|
||||
//paint.Clear(UNCOLORED);
|
||||
//epd.ClearFrameMemory(0xFF);
|
||||
epd.DisplayFrame();
|
||||
delay(3000);
|
||||
}
|
||||
|
||||
void EpdInit(uint8_t mode)
|
||||
{
|
||||
switch(mode) {
|
||||
case DISPLAY_INIT_MODE:
|
||||
EpdInitMode();
|
||||
break;
|
||||
case DISPLAY_INIT_PARTIAL:
|
||||
EpdInitPartial();
|
||||
break;
|
||||
case DISPLAY_INIT_FULL:
|
||||
EpdInitFull();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EpdInitDriver(void)
|
||||
void EpdInitDriver29()
|
||||
{
|
||||
if (!Settings.display_model) {
|
||||
Settings.display_model = XDSP_05;
|
||||
|
@ -125,79 +58,55 @@ void EpdInitDriver(void)
|
|||
Settings.display_height = EPD_HEIGHT;
|
||||
}
|
||||
|
||||
// allocate screen buffer
|
||||
if (buffer) free(buffer);
|
||||
buffer=(unsigned char*)calloc((EPD_WIDTH * EPD_HEIGHT) / 8,1);
|
||||
if (!buffer) return;
|
||||
|
||||
// init renderer
|
||||
epd = new Epd(EPD_WIDTH,EPD_HEIGHT);
|
||||
|
||||
// whiten display with full update, takes 3 seconds
|
||||
if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) {
|
||||
epd.cs_pin = pin[GPIO_SPI_CS];
|
||||
epd.sclk_pin = pin[GPIO_SPI_CLK]; // 14
|
||||
epd.mosi_pin = pin[GPIO_SPI_MOSI]; // 13
|
||||
EpdInitMode();
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"), epd.cs_pin, epd.sclk_pin, epd.mosi_pin);
|
||||
epd->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]);
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SPI_CS], pin[GPIO_SPI_CLK], pin[GPIO_SPI_MOSI]);
|
||||
}
|
||||
else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) {
|
||||
epd.cs_pin = pin[GPIO_SSPI_CS];
|
||||
epd.sclk_pin = pin[GPIO_SSPI_SCLK];
|
||||
epd.mosi_pin = pin[GPIO_SSPI_MOSI];
|
||||
EpdInitMode();
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"), epd.cs_pin, epd.sclk_pin, epd.mosi_pin);
|
||||
epd->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]);
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SSPI_CS], pin[GPIO_SSPI_SCLK], pin[GPIO_SSPI_MOSI]);
|
||||
} else {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
renderer = epd;
|
||||
epd->Init(DISPLAY_INIT_FULL);
|
||||
epd->Init(DISPLAY_INIT_PARTIAL);
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
|
||||
renderer->setTextColor(1,0);
|
||||
|
||||
#ifdef SHOW_SPLASH
|
||||
// Welcome text
|
||||
renderer->setTextFont(1);
|
||||
renderer->DrawStringAt(50, 50, "Waveshare E-Paper Display!", COLORED,0);
|
||||
renderer->Updateframe();
|
||||
delay(1000);
|
||||
renderer->fillScreen(0);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void EpdClear(void)
|
||||
{
|
||||
paint.Clear(UNCOLORED);
|
||||
}
|
||||
|
||||
void EpdSetFont(uint8_t font)
|
||||
{
|
||||
if (1 == font) {
|
||||
selected_font = &Font12;
|
||||
} else {
|
||||
#ifdef USE_TINY_FONT
|
||||
if (2 == font) {
|
||||
selected_font = &Font24;
|
||||
} else {
|
||||
selected_font = &Font8;
|
||||
}
|
||||
#else
|
||||
selected_font = &Font24;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void EpdDisplayFrame(void)
|
||||
{
|
||||
epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight());
|
||||
epd.DisplayFrame();
|
||||
epd.Sleep();
|
||||
}
|
||||
|
||||
void EpdDrawStringAt(uint16_t x, uint16_t y, char *str, uint8_t color, uint8_t flag)
|
||||
{
|
||||
if (!flag) {
|
||||
paint.DrawStringAt(x, y, str, selected_font, color);
|
||||
} else {
|
||||
paint.DrawStringAt((x-1) * selected_font->Width, (y-1) * selected_font->Height, str, selected_font, color);
|
||||
}
|
||||
}
|
||||
|
||||
// not needed
|
||||
void EpdDisplayOnOff(uint8_t on)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void EpdOnOff(void)
|
||||
{
|
||||
EpdDisplayOnOff(disp_power);
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
|
||||
void EpdPrintLog(void)
|
||||
#define EPD_FONT_HEIGTH 12
|
||||
void EpdPrintLog29(void)
|
||||
{
|
||||
disp_refresh--;
|
||||
if (!disp_refresh) {
|
||||
|
@ -211,19 +120,19 @@ void EpdPrintLog(void)
|
|||
uint8_t size = Settings.display_size;
|
||||
uint16_t theight = size * EPD_FONT_HEIGTH;
|
||||
|
||||
EpdSetFont(size);
|
||||
renderer->setTextFont(size);
|
||||
uint8_t last_row = Settings.display_rows -1;
|
||||
|
||||
// epd_scroll = theight; // Start below header
|
||||
epd_scroll = 0; // Start at top with no header
|
||||
for (uint32_t i = 0; i < last_row; i++) {
|
||||
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
|
||||
EpdDrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0);
|
||||
renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0);
|
||||
epd_scroll += theight;
|
||||
}
|
||||
strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols);
|
||||
DisplayFillScreen(last_row);
|
||||
EpdDrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0);
|
||||
renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0);
|
||||
// EpdDisplayFrame();
|
||||
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt);
|
||||
|
@ -231,7 +140,7 @@ void EpdPrintLog(void)
|
|||
}
|
||||
}
|
||||
|
||||
void EpdRefresh(void) // Every second
|
||||
void EpdRefresh29(void) // Every second
|
||||
{
|
||||
if (Settings.display_mode) { // Mode 0 is User text
|
||||
/*
|
||||
|
@ -256,8 +165,8 @@ void EpdRefresh(void) // Every second
|
|||
case 3: // Local
|
||||
case 4: // Mqtt
|
||||
case 5: // Mqtt
|
||||
EpdPrintLog();
|
||||
EpdDisplayFrame();
|
||||
EpdPrintLog29();
|
||||
renderer->Updateframe();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -271,81 +180,27 @@ void EpdRefresh(void) // Every second
|
|||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdsp05(uint8_t function)
|
||||
bool Xdsp05(byte function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (spi_flg || soft_spi_flg) {
|
||||
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||
EpdInitDriver();
|
||||
EpdInitDriver29();
|
||||
}
|
||||
else if (XDSP_05 == Settings.display_model) {
|
||||
|
||||
if (!dsp_color) { dsp_color = COLORED; }
|
||||
|
||||
switch (function) {
|
||||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
case FUNC_DISPLAY_INIT:
|
||||
EpdInit(dsp_init);
|
||||
break;
|
||||
case FUNC_DISPLAY_POWER:
|
||||
EpdOnOff();
|
||||
break;
|
||||
case FUNC_DISPLAY_CLEAR:
|
||||
EpdClear();
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_HLINE:
|
||||
paint.DrawHorizontalLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_VLINE:
|
||||
paint.DrawVerticalLine(dsp_x, dsp_y, dsp_len, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_LINE:
|
||||
paint.DrawLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_CIRCLE:
|
||||
paint.DrawCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_FILL_CIRCLE:
|
||||
paint.DrawFilledCircle(dsp_x, dsp_y, dsp_rad, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_RECTANGLE:
|
||||
paint.DrawRectangle(dsp_x, dsp_y, dsp_x + dsp_x2, dsp_y + dsp_y2, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_FILL_RECTANGLE:
|
||||
paint.DrawFilledRectangle(dsp_x, dsp_y, dsp_x + dsp_x2, dsp_y + dsp_y2, dsp_color);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_FRAME:
|
||||
EpdDisplayFrame();
|
||||
break;
|
||||
case FUNC_DISPLAY_TEXT_SIZE:
|
||||
// EpdSetFontorSize(Settings.display_size);
|
||||
break;
|
||||
case FUNC_DISPLAY_FONT_SIZE:
|
||||
EpdSetFont(Settings.display_font);
|
||||
break;
|
||||
case FUNC_DISPLAY_DRAW_STRING:
|
||||
EpdDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag);
|
||||
break;
|
||||
case FUNC_DISPLAY_ONOFF:
|
||||
EpdDisplayOnOff(dsp_on);
|
||||
break;
|
||||
case FUNC_DISPLAY_ROTATION:
|
||||
paint.SetRotate(Settings.display_rotate);
|
||||
break;
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
case FUNC_DISPLAY_EVERY_SECOND:
|
||||
EpdRefresh();
|
||||
EpdRefresh29();
|
||||
break;
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY_EPAPER_29
|
||||
#endif // USE_DISPLAY_EPAPER
|
||||
#endif // USE_DISPLAY
|
||||
#endif // USE_SPI
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
xdsp_05_epaper.ino - Display e-paper support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends, Gerhard Mutz and Waveshare
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_SPI
|
||||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_EPAPER42
|
||||
|
||||
#define XDSP_06 6
|
||||
|
||||
#define COLORED42 1
|
||||
#define UNCOLORED42 0
|
||||
|
||||
// using font 8 is opional (num=3)
|
||||
// very badly readable, but may be useful for graphs
|
||||
#define USE_TINY_FONT
|
||||
|
||||
#include <epd4in2.h>
|
||||
#include <epdpaint.h>
|
||||
|
||||
//unsigned char image[(EPD_HEIGHT * EPD_WIDTH) / 8];
|
||||
extern uint8_t *buffer;
|
||||
|
||||
Epd42 *epd42;
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void EpdInitDriver42()
|
||||
{
|
||||
if (!Settings.display_model) {
|
||||
Settings.display_model = XDSP_06;
|
||||
}
|
||||
|
||||
if (XDSP_06 == Settings.display_model) {
|
||||
|
||||
if (Settings.display_width != EPD_WIDTH42) {
|
||||
Settings.display_width = EPD_WIDTH42;
|
||||
}
|
||||
if (Settings.display_height != EPD_HEIGHT42) {
|
||||
Settings.display_height = EPD_HEIGHT42;
|
||||
}
|
||||
|
||||
// allocate screen buffer
|
||||
if (buffer) free(buffer);
|
||||
buffer=(unsigned char*)calloc((EPD_WIDTH42 * EPD_HEIGHT42) / 8,1);
|
||||
if (!buffer) return;
|
||||
|
||||
// init renderer
|
||||
epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42);
|
||||
|
||||
#ifdef USE_SPI
|
||||
if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)) {
|
||||
epd42->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]);
|
||||
} else {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) {
|
||||
epd42->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]);
|
||||
} else {
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
renderer = epd42;
|
||||
|
||||
epd42->Init();
|
||||
|
||||
renderer->fillScreen(0);
|
||||
|
||||
// whiten display with full update, takes 4 seconds
|
||||
epd42->Init(DISPLAY_INIT_FULL);
|
||||
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
|
||||
epd42->ClearFrame();
|
||||
renderer->Updateframe();
|
||||
delay(3000);
|
||||
renderer->setTextColor(1,0);
|
||||
|
||||
#ifdef SHOW_SPLASH
|
||||
// Welcome text
|
||||
renderer->setTextFont(2);
|
||||
renderer->DrawStringAt(50, 140, "Waveshare E-Paper!", COLORED42,0);
|
||||
renderer->Updateframe();
|
||||
delay(350);
|
||||
renderer->fillScreen(0);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
|
||||
void EpdRefresh42() // Every second
|
||||
{
|
||||
if (Settings.display_mode) { // Mode 0 is User text
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdsp06(byte function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
//if (spi_flg) {
|
||||
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||
EpdInitDriver42();
|
||||
}
|
||||
else if (XDSP_06 == Settings.display_model) {
|
||||
|
||||
switch (function) {
|
||||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
case FUNC_DISPLAY_EVERY_SECOND:
|
||||
EpdRefresh42();
|
||||
break;
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
}
|
||||
}
|
||||
//}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY_EPAPER42
|
||||
#endif // USE_DISPLAY
|
||||
#endif // USE_SPI
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
xdsp_07_SH1106.ino - Display Oled SH1106 support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends and Adafruit
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_SH1106
|
||||
|
||||
#define OLED_RESET 4
|
||||
|
||||
#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str);
|
||||
|
||||
extern uint8_t *buffer;
|
||||
|
||||
#define XDSP_07 7
|
||||
|
||||
#define OLED_ADDRESS1 0x3C // Oled 128x32 I2C address
|
||||
#define OLED_ADDRESS2 0x3D // Oled 128x64 I2C address
|
||||
|
||||
#define OLED_BUFFER_COLS 40 // Max number of columns in display shadow buffer
|
||||
#define OLED_BUFFER_ROWS 16 // Max number of lines in display shadow buffer
|
||||
|
||||
#define OLED_FONT_WIDTH 6
|
||||
#define OLED_FONT_HEIGTH 8
|
||||
|
||||
#include <Wire.h>
|
||||
#include <renderer.h>
|
||||
#include <Adafruit_SH1106.h>
|
||||
|
||||
Adafruit_SH1106 *oled1106;
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
|
||||
void SH1106InitDriver()
|
||||
{
|
||||
if (!Settings.display_model) {
|
||||
if (I2cDevice(OLED_ADDRESS1)) {
|
||||
Settings.display_address[0] = OLED_ADDRESS1;
|
||||
Settings.display_model = XDSP_07;
|
||||
}
|
||||
else if (I2cDevice(OLED_ADDRESS2)) {
|
||||
Settings.display_address[0] = OLED_ADDRESS2;
|
||||
Settings.display_model = XDSP_07;
|
||||
}
|
||||
}
|
||||
|
||||
if (XDSP_07 == Settings.display_model) {
|
||||
|
||||
if (Settings.display_width != SH1106_LCDWIDTH) {
|
||||
Settings.display_width = SH1106_LCDWIDTH;
|
||||
}
|
||||
if (Settings.display_height != SH1106_LCDHEIGHT) {
|
||||
Settings.display_height = SH1106_LCDHEIGHT;
|
||||
}
|
||||
|
||||
// allocate screen buffer
|
||||
if (buffer) free(buffer);
|
||||
buffer=(unsigned char*)calloc((SH1106_LCDWIDTH * SH1106_LCDHEIGHT) / 8,1);
|
||||
if (!buffer) return;
|
||||
|
||||
// init renderer
|
||||
oled1106 = new Adafruit_SH1106(SH1106_LCDWIDTH,SH1106_LCDHEIGHT);
|
||||
renderer=oled1106;
|
||||
renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0);
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
renderer->setTextColor(1,0);
|
||||
|
||||
#ifdef SHOW_SPLASH
|
||||
renderer->setTextFont(0);
|
||||
renderer->setTextSize(2);
|
||||
renderer->setCursor(20,20);
|
||||
renderer->println(F("SH1106"));
|
||||
renderer->Updateframe();
|
||||
renderer->DisplayOnff(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************/
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
|
||||
void SH1106PrintLog(void)
|
||||
{
|
||||
disp_refresh--;
|
||||
if (!disp_refresh) {
|
||||
disp_refresh = Settings.display_refresh;
|
||||
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
|
||||
|
||||
char* txt = DisplayLogBuffer('\370');
|
||||
if (txt != NULL) {
|
||||
uint8_t last_row = Settings.display_rows -1;
|
||||
|
||||
renderer->clearDisplay();
|
||||
renderer->setTextSize(Settings.display_size);
|
||||
renderer->setCursor(0,0);
|
||||
for (byte i = 0; i < last_row; i++) {
|
||||
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
|
||||
renderer->println(disp_screen_buffer[i]);
|
||||
}
|
||||
strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols);
|
||||
DisplayFillScreen(last_row);
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
renderer->println(disp_screen_buffer[last_row]);
|
||||
renderer->Updateframe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SH1106Time(void)
|
||||
{
|
||||
char line[12];
|
||||
|
||||
renderer->clearDisplay();
|
||||
renderer->setTextSize(2);
|
||||
renderer->setCursor(0, 0);
|
||||
snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ]
|
||||
renderer->println(line);
|
||||
snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); // [01-02-2018]
|
||||
renderer->println(line);
|
||||
renderer->Updateframe();
|
||||
}
|
||||
|
||||
void SH1106Refresh(void) // Every second
|
||||
{
|
||||
if (Settings.display_mode) { // Mode 0 is User text
|
||||
switch (Settings.display_mode) {
|
||||
case 1: // Time
|
||||
Ssd1306Time();
|
||||
break;
|
||||
case 2: // Local
|
||||
case 3: // Local
|
||||
case 4: // Mqtt
|
||||
case 5: // Mqtt
|
||||
Ssd1306PrintLog();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdsp07(byte function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||
SH1106InitDriver();
|
||||
}
|
||||
else if (XDSP_07 == Settings.display_model) {
|
||||
|
||||
switch (function) {
|
||||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
case FUNC_DISPLAY_EVERY_SECOND:
|
||||
SH1106Refresh();
|
||||
break;
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY_SH1106
|
||||
#endif // USE_DISPLAY
|
||||
#endif // USE_I2C
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
xdsp_08_ILI9488.ino - Display ILI9488 support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends, Gerhard Mutz
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_SPI
|
||||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_ILI9488
|
||||
|
||||
#define XDSP_08 8
|
||||
|
||||
#define COLORED 1
|
||||
#define UNCOLORED 0
|
||||
|
||||
// touch panel controller
|
||||
#define FT6236_address 0x38
|
||||
|
||||
// using font 8 is opional (num=3)
|
||||
// very badly readable, but may be useful for graphs
|
||||
#define USE_TINY_FONT
|
||||
|
||||
|
||||
#include <ILI9488.h>
|
||||
#include <FT6236.h>
|
||||
|
||||
TouchLocation pLoc;
|
||||
uint8_t ctouch_counter = 0;
|
||||
|
||||
// currently fixed
|
||||
#define BACKPLANE_PIN 2
|
||||
|
||||
extern uint8_t *buffer;
|
||||
extern uint8_t color_type;
|
||||
ILI9488 *ili9488;
|
||||
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
extern VButton *buttons[];
|
||||
#endif
|
||||
|
||||
extern const uint16_t picture[];
|
||||
uint8_t FT6236_found;
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void ILI9488_InitDriver()
|
||||
{
|
||||
if (!Settings.display_model) {
|
||||
Settings.display_model = XDSP_08;
|
||||
}
|
||||
|
||||
if (XDSP_08 == Settings.display_model) {
|
||||
|
||||
if (Settings.display_width != ILI9488_TFTWIDTH) {
|
||||
Settings.display_width = ILI9488_TFTWIDTH;
|
||||
}
|
||||
if (Settings.display_height != ILI9488_TFTHEIGHT) {
|
||||
Settings.display_height = ILI9488_TFTHEIGHT;
|
||||
}
|
||||
|
||||
// disable screen buffer
|
||||
buffer=NULL;
|
||||
|
||||
// default colors
|
||||
fg_color = ILI9488_WHITE;
|
||||
bg_color = ILI9488_BLACK;
|
||||
|
||||
uint8_t bppin=BACKPLANE_PIN;
|
||||
if (pin[GPIO_BACKLIGHT]<99) {
|
||||
bppin=pin[GPIO_BACKLIGHT];
|
||||
}
|
||||
|
||||
// init renderer
|
||||
if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){
|
||||
ili9488 = new ILI9488(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK],bppin);
|
||||
} else {
|
||||
if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) {
|
||||
ili9488 = new ILI9488(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK],bppin);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SPI.begin();
|
||||
ili9488->begin();
|
||||
renderer = ili9488;
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
|
||||
#ifdef SHOW_SPLASH
|
||||
// Welcome text
|
||||
renderer->setTextFont(2);
|
||||
renderer->setTextColor(ILI9488_WHITE,ILI9488_BLACK);
|
||||
renderer->DrawStringAt(50, 50, "ILI9488 TFT Display!", ILI9488_WHITE,0);
|
||||
delay(1000);
|
||||
|
||||
//renderer->drawRGBBitmap(100,100, picture,51,34);
|
||||
#endif
|
||||
|
||||
color_type = COLOR_COLOR;
|
||||
// start digitizer with fixed adress
|
||||
|
||||
if (i2c_flg && I2cDevice(FT6236_address)) {
|
||||
FT6236begin(FT6236_address);
|
||||
FT6236_found=1;
|
||||
} else {
|
||||
FT6236_found=0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
void ILI9488_MQTT(uint8_t count,const char *cp) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"RA8876\":{\"%s%d\":\"%d\"}}"), mqtt_data,cp,count+1,(buttons[count]->vpower&0x80)>>7);
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
}
|
||||
// check digitizer hit
|
||||
void FT6236Check() {
|
||||
uint16_t temp;
|
||||
ctouch_counter++;
|
||||
if (2 == ctouch_counter) {
|
||||
// every 100 ms should be enough
|
||||
ctouch_counter=0;
|
||||
if (FT6236readTouchLocation(&pLoc,1)) {
|
||||
// did find a hit
|
||||
if (renderer) {
|
||||
uint8_t rot=renderer->getRotation();
|
||||
switch (rot) {
|
||||
case 0:
|
||||
temp=pLoc.y;
|
||||
pLoc.y=renderer->height()-pLoc.x;
|
||||
pLoc.x=temp;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
temp=pLoc.y;
|
||||
pLoc.y=pLoc.x;
|
||||
pLoc.x=renderer->width()-temp;
|
||||
break;
|
||||
}
|
||||
// now must compare with defined buttons
|
||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||
if (buttons[count]) {
|
||||
if (buttons[count]->contains(pLoc.x,pLoc.y)) {
|
||||
// did hit
|
||||
buttons[count]->press(true);
|
||||
if (buttons[count]->justPressed()) {
|
||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||
if (!bflags) {
|
||||
// real button
|
||||
if (!SendKey(0, count+1, POWER_TOGGLE)) {
|
||||
ExecuteCommandPower(count+1, POWER_TOGGLE, SRC_BUTTON);
|
||||
}
|
||||
buttons[count]->xdrawButton(bitRead(power,count));
|
||||
} else {
|
||||
// virtual button
|
||||
const char *cp;
|
||||
if (bflags==1) {
|
||||
// toggle button
|
||||
buttons[count]->vpower^=0x80;
|
||||
cp="TBT";
|
||||
} else {
|
||||
// push button
|
||||
buttons[count]->vpower|=0x80;
|
||||
cp="PBT";
|
||||
}
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower&0x80);
|
||||
ILI9488_MQTT(count,cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no hit
|
||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||
if (buttons[count]) {
|
||||
buttons[count]->press(false);
|
||||
if (buttons[count]->justReleased()) {
|
||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||
if (bflags>1) {
|
||||
// push button
|
||||
buttons[count]->vpower&=0x7f;
|
||||
ILI9488_MQTT(count,"PBT");
|
||||
}
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower&0x80);
|
||||
}
|
||||
}
|
||||
}
|
||||
pLoc.x=0;
|
||||
pLoc.y=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
/*********************************************************************************************/
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
bool Xdsp08(byte function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||
ILI9488_InitDriver();
|
||||
}
|
||||
else if (XDSP_08 == Settings.display_model) {
|
||||
|
||||
switch (function) {
|
||||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
case FUNC_DISPLAY_EVERY_50_MSECOND:
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
if (FT6236_found) FT6236Check();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY_ILI9488
|
||||
#endif // USE_DISPLAY
|
||||
#endif // USE_SPI
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
xdsp_09_SSD1351.ino - Display SSD1351 support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2019 Gerhard Mutz and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_SPI
|
||||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_SSD1351
|
||||
|
||||
#define XDSP_09 9
|
||||
|
||||
#define COLORED 1
|
||||
#define UNCOLORED 0
|
||||
|
||||
// uses about 1.9k flash + renderer class
|
||||
// using font 8 is opional (num=3)
|
||||
// very badly readable, but may be useful for graphs
|
||||
#define USE_TINY_FONT
|
||||
|
||||
#include <SSD1351.h>
|
||||
|
||||
extern uint8_t *buffer;
|
||||
extern uint8_t color_type;
|
||||
SSD1351 *ssd1351;
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void SSD1351_InitDriver() {
|
||||
if (!Settings.display_model) {
|
||||
Settings.display_model = XDSP_09;
|
||||
}
|
||||
|
||||
if (XDSP_09 == Settings.display_model) {
|
||||
|
||||
if (Settings.display_width != SSD1351_WIDTH) {
|
||||
Settings.display_width = SSD1351_WIDTH;
|
||||
}
|
||||
if (Settings.display_height != SSD1351_HEIGHT) {
|
||||
Settings.display_height = SSD1351_HEIGHT;
|
||||
}
|
||||
|
||||
buffer=0;
|
||||
|
||||
// default colors
|
||||
fg_color = SSD1351_WHITE;
|
||||
bg_color = SSD1351_BLACK;
|
||||
|
||||
// init renderer
|
||||
if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){
|
||||
ssd1351 = new SSD1351(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]);
|
||||
} else {
|
||||
if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)){
|
||||
ssd1351 = new SSD1351(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
delay(100);
|
||||
SPI.begin();
|
||||
ssd1351->begin();
|
||||
renderer = ssd1351;
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
renderer->dim(Settings.display_dimmer);
|
||||
|
||||
#ifdef SHOW_SPLASH
|
||||
// Welcome text
|
||||
renderer->setTextFont(2);
|
||||
renderer->setTextColor(SSD1351_WHITE,SSD1351_BLACK);
|
||||
renderer->DrawStringAt(10, 60, "SSD1351", SSD1351_RED,0);
|
||||
delay(1000);
|
||||
|
||||
#endif
|
||||
color_type = COLOR_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
|
||||
void SSD1351PrintLog(void)
|
||||
{
|
||||
disp_refresh--;
|
||||
if (!disp_refresh) {
|
||||
disp_refresh = Settings.display_refresh;
|
||||
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
|
||||
|
||||
char* txt = DisplayLogBuffer('\370');
|
||||
if (txt != NULL) {
|
||||
uint8_t last_row = Settings.display_rows -1;
|
||||
|
||||
renderer->clearDisplay();
|
||||
renderer->setTextSize(Settings.display_size);
|
||||
renderer->setCursor(0,0);
|
||||
for (byte i = 0; i < last_row; i++) {
|
||||
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
|
||||
renderer->println(disp_screen_buffer[i]);
|
||||
}
|
||||
strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols);
|
||||
DisplayFillScreen(last_row);
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
renderer->println(disp_screen_buffer[last_row]);
|
||||
renderer->Updateframe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1351Time(void)
|
||||
{
|
||||
char line[12];
|
||||
|
||||
renderer->clearDisplay();
|
||||
renderer->setTextSize(2);
|
||||
renderer->setCursor(0, 0);
|
||||
snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ]
|
||||
renderer->println(line);
|
||||
snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); // [01-02-2018]
|
||||
renderer->println(line);
|
||||
renderer->Updateframe();
|
||||
}
|
||||
|
||||
void SSD1351Refresh(void) // Every second
|
||||
{
|
||||
if (Settings.display_mode) { // Mode 0 is User text
|
||||
switch (Settings.display_mode) {
|
||||
case 1: // Time
|
||||
SSD1351Time();
|
||||
break;
|
||||
case 2: // Local
|
||||
case 3: // Local
|
||||
case 4: // Mqtt
|
||||
case 5: // Mqtt
|
||||
SSD1351PrintLog();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
/*********************************************************************************************/
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
bool Xdsp09(byte function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||
SSD1351_InitDriver();
|
||||
}
|
||||
else if (XDSP_09 == Settings.display_model) {
|
||||
switch (function) {
|
||||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
case FUNC_DISPLAY_EVERY_SECOND:
|
||||
SSD1351Refresh();
|
||||
break;
|
||||
#endif // USE_DISPLAY_MODES1TO5
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif // USE_DISPLAY_SSD1351
|
||||
#endif // USE_DISPLAY
|
||||
#endif // USE_SPI
|