ssd1322_v1

This commit is contained in:
e2002
2023-03-10 15:57:34 +03:00
parent b88574c1c1
commit 391c68b1ba
8 changed files with 975 additions and 2 deletions

View File

@@ -0,0 +1,554 @@
/*!
* @file Jamis_SSD1322.h
*
* This is a partial port of Adafruit's SSD1306 library to the SSD1322
* display.
*
* These displays use SPI to communicate. SPI requires 4 pins (MOSI, SCK,
* select, data/command) and optionally a reset pin.
*
* 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, with
* contributions from the open source community.
*
* BSD license, all text above, and the splash screen header file,
* must be included in any redistribution.
*
*/
#include "../core/options.h"
#if DSP_MODEL==DSP_SSD1322
#define pgm_read_byte(addr) \
(*(const unsigned char *)(addr)) ///< PROGMEM workaround for non-AVR
#include <Adafruit_GFX.h>
#include "SSD1322.h"
//#include "splash.h"
#define ssd1322_swap(a, b) \
(((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b))) ///< No-temp-var swap operation
#define SSD1322_SELECT digitalWrite(csPin, LOW); ///< Device select
#define SSD1322_DESELECT digitalWrite(csPin, HIGH); ///< Device deselect
#define SSD1322_MODE_COMMAND digitalWrite(dcPin, LOW); ///< Command mode
#define SSD1322_MODE_DATA digitalWrite(dcPin, HIGH); ///< Data mode
#if defined(SPI_HAS_TRANSACTION)
#define SPI_TRANSACTION_START spi->beginTransaction(spiSettings) ///< Pre-SPI
#define SPI_TRANSACTION_END spi->endTransaction() ///< Post-SPI
#else // SPI transactions likewise not present in older Arduino SPI lib
#define SPI_TRANSACTION_START ///< Dummy stand-in define
#define SPI_TRANSACTION_END ///< keeps compiler happy
#endif
#define TRANSACTION_START \
if(spi) { \
SPI_TRANSACTION_START; \
} \
SSD1322_SELECT;
#define TRANSACTION_END \
SSD1322_DESELECT; \
if(spi) { \
SPI_TRANSACTION_END; \
}
/*!
@brief Constructor for SPI SSD1306 displays, using native hardware SPI.
@param w
Display width in pixels
@param h
Display height in pixels
@param spi
Pointer to an existing SPIClass instance (e.g. &SPI, the
microcontroller's primary SPI bus).
@param dc_pin
Data/command pin (using Arduino pin numbering), selects whether
display is receiving commands (low) or data (high).
@param rst_pin
Reset pin (using Arduino pin numbering), or -1 if not used
(some displays might be wired to share the microcontroller's
reset pin).
@param cs_pin
Chip-select pin (using Arduino pin numbering) for sharing the
bus with other devices. Active low.
@param bitrate
SPI clock rate for transfers to this display. Default if
unspecified is 8000000UL (8 MHz).
@return Jamis_SSD1322 object.
@note Call the object's begin() function before use -- buffer
allocation is performed there!
*/
Jamis_SSD1322::Jamis_SSD1322(int16_t w, int16_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), buffer(NULL),
mosiPin(-1), clkPin(-1), dcPin(dc_pin), csPin(cs_pin), rstPin(rst_pin) {
#ifdef SPI_HAS_TRANSACTION
spiSettings = SPISettings(bitrate, MSBFIRST, SPI_MODE3);
#endif
}
/*!
@brief Destructor for Jamis_SSD1322 object.
*/
Jamis_SSD1322::~Jamis_SSD1322(void) {
if(buffer) {
free(buffer);
buffer = NULL;
}
}
// LOW-LEVEL UTILS ---------------------------------------------------------
// Issue single byte out SPI, either soft or hardware as appropriate.
// SPI transaction/selection must be performed in calling function.
inline void Jamis_SSD1322::SPIwrite(uint8_t d) {
spi->transfer(d);
}
// Issue single command to SSD1322, using hard SPI.
// Because command calls are often grouped, SPI transaction and selection
// must be started/ended in calling function for efficiency.
// This is a private function, not exposed (see ssd1322_command() instead).
void Jamis_SSD1322::ssd1322_command1(uint8_t c) {
SSD1322_MODE_COMMAND
SPIwrite(c);
}
// Issue single byte of data out SPI.
void Jamis_SSD1322::ssd1322_data1(uint8_t c) {
SSD1322_MODE_DATA
SPIwrite(c);
}
// A public version of ssd1322_command1(), for existing user code that
// might rely on that function. This encapsulates the command transfer
// in a transaction start/end, similar to old library's handling of it.
/*!
@brief Issue a single low-level command directly to the SSD1306
display, bypassing the library.
@param c
Command to issue (0x00 to 0xFF, see datasheet).
@return None (void).
*/
void Jamis_SSD1322::ssd1322_command(uint8_t c) {
TRANSACTION_START
ssd1322_command1(c);
TRANSACTION_END
}
// ALLOCATE & INIT DISPLAY -------------------------------------------------
/*!
@brief Allocate RAM for image buffer, initialize peripherals and pins.
@param reset
If true, and if the reset pin passed to the constructor is
valid, a hard reset will be performed before initializing the
display. If using multiple SSD1322 displays on the same bus, and
if they all share the same reset pin, you should only pass true
on the first display being initialized, false on all others,
else the already-initialized displays would be reset. Default if
unspecified is true.
@param periphBegin
If true, and if a hardware peripheral is being used (I2C or SPI,
but not software SPI), call that peripheral's begin() function,
else (false) it has already been done in one's sketch code.
Cases where false might be used include multiple displays or
other devices sharing a common bus, or situations on some
platforms where a nonstandard begin() function is available
(e.g. a TwoWire interface on non-default pins, as can be done
on the ESP8266 and perhaps others).
@return true on successful allocation/init, false otherwise.
Well-behaved code should check the return value before
proceeding.
@note MUST call this function before any drawing or updates!
*/
boolean Jamis_SSD1322::begin(boolean reset, boolean periphBegin) {
// Note: The SSD1322 has 4 bit grayscale color.
if((!buffer) && !(buffer = (uint8_t *)malloc( WIDTH * ((HEIGHT) / 2) )))
return false;
clearDisplay();
// Setup pin directions
pinMode(dcPin, OUTPUT); // Set data/command pin as output
pinMode(csPin, OUTPUT); // Same for chip select
SSD1322_DESELECT
// SPI peripheral begin same as wire check above.
if(periphBegin) spi->begin();
// Reset SSD1322 if requested and reset pin specified in constructor
if(reset && (rstPin >= 0)) {
pinMode( rstPin, OUTPUT);
digitalWrite(rstPin, HIGH);
delay(1); // VDD goes high at start, pause for 1 ms
digitalWrite(rstPin, LOW); // Bring reset low
delay(10); // Wait 10 ms
digitalWrite(rstPin, HIGH); // Bring out of reset
}
TRANSACTION_START
ssd1322_command1(0xFD); // Set Command Lock (MCU protection status)
ssd1322_data1(0x12); // 0x12 = Unlock Basic Commands; 0x16 = lock
ssd1322_command1(0xA4); // Set Display Mode = OFF
ssd1322_command1(0xB3); // Set Front Clock Divider / Oscillator Frequency
ssd1322_data1(0x91); // 0x91 = 80FPS; 0xD0 = default / 1100b
ssd1322_command1(0xCA); // Set MUX Ratio
ssd1322_data1(0x3F); // 0x3F = 63d = 64MUX (1/64 duty cycle)
ssd1322_command1(0xA2); // Set Display Offset
ssd1322_data1(0x00); // 0x00 = (default)
ssd1322_command1(0xA1); // Set Display Start Line
ssd1322_data1(0x00); // 0x00 = register 00h
ssd1322_command1(0xA0); // Set Re-map and Dual COM Line mode
ssd1322_data1(0x14); // 0x14 = Default except Enable Nibble Re-map, Scan from COM[N-1] to COM0, where N is the Multiplex ratio
ssd1322_data1(0x11); // 0x11 = Enable Dual COM mode (MUX <= 63)
ssd1322_command1(0xB5); // Set GPIO
ssd1322_data1(0x00); // 0x00 = {GPIO0, GPIO1 = HiZ (Input Disabled)}
ssd1322_command1(0xAB); // Function Selection
ssd1322_data1(0x01); // 0x01 = Enable internal VDD regulator (default)
ssd1322_command1(0xB4); // Display Enhancement A
ssd1322_data1(0xA0); // 0xA0 = Enable external VSL; 0xA2 = internal VSL
ssd1322_data1(0xB5); // 0xB5 = Normal (default); 0xFD = 11111101b = Enhanced low GS display quality
ssd1322_command1(0xC1); // Set Contrast Current
ssd1322_data1(0x7F); // 0x7F = (default)
ssd1322_command1(0xC7); // Master Contrast Current Control
ssd1322_data1(0x0F); // 0x0F = (default)
ssd1322_command1(0xB9); // Select Default Linear Gray Scale table
// ssd1322_command1(0xB8); // Select Custom Gray Scale table (GS0 = 0)
// ssd1322_command1(0x00); // GS1
// ssd1322_command1(0x08); // GS2
// ssd1322_command1(0x10); // GS3
// ssd1322_command1(0x18); // GS4
// ssd1322_command1(0x20); // GS5
// ssd1322_command1(0x28); // GS6
// ssd1322_command1(0x30); // GS7
// ssd1322_command1(0x38); // GS8
// ssd1322_command1(0x40); // GS9
// ssd1322_command1(0x48); // GS10
// ssd1322_command1(0x50); // GS11
// ssd1322_command1(0x58); // GS12
// ssd1322_command1(0x60); // GS13
// ssd1322_command1(0x68); // GS14
// ssd1322_command1(0x70); // GS15
// ssd1322_command1(0x00); // Enable Custom Gray Scale table
ssd1322_command1(0xB1); // Set Phase Length
ssd1322_data1(0xE2); // 0xE2 = Phase 1 period (reset phase length) = 5 DCLKs,
// Phase 2 period (first pre-charge phase length) = 14 DCLKs
ssd1322_command1(0xD1); // Display Enhancement B
ssd1322_data1(0xA2); // 0xA2 = Normal (default); 0x82 = reserved
ssd1322_data1(0x20); // 0x20 = as-is
ssd1322_command1(0xBB); // Set Pre-charge voltage
ssd1322_data1(0x1F); // 0x17 = default; 0x1F = 0.60*Vcc (spec example)
ssd1322_command1(0xB6); // Set Second Precharge Period
ssd1322_data1(0x08); // 0x08 = 8 dclks (default)
ssd1322_command1(0xBE); // Set VCOMH
ssd1322_data1(0x07); // 0x04 = 0.80*Vcc (default); 0x07 = 0.86*Vcc (spec example)
ssd1322_command1(0xA6); // Set Display Mode = Normal Display
ssd1322_command1(0xA9); // Exit Partial Display
ssd1322_command1(0xAF); // Set Sleep mode OFF (Display ON)
TRANSACTION_END
return true; // Success
}
// DRAWING FUNCTIONS -------------------------------------------------------
/*!
@brief Set/clear/invert a single pixel. This is also invoked by the
Adafruit_GFX library in generating many higher-level graphics
primitives.
@param x
Column of display -- 0 at left to (screen width - 1) at right.
@param y
Row of display -- 0 at top to (screen height -1) at bottom.
@param color
Pixel color, one of: BLACK, WHITE or INVERT.
@return None (void).
@note Changes buffer contents only, no immediate effect on display.
Follow up with a call to display(), or with other graphics
commands as needed by one's own application.
*/
void Jamis_SSD1322::drawPixel(int16_t x, int16_t y, uint16_t color) {
if((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
// Pixel is in-bounds. Rotate coordinates if needed.
switch(getRotation()) {
case 1:
ssd1322_swap(x, y);
x = WIDTH - x - 1;
break;
case 2:
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
break;
case 3:
ssd1322_swap(x, y);
y = HEIGHT - y - 1;
break;
}
buffer[(x >> 1) + (y)*WIDTH/2] &= (x % 2) ? 0xF0 : 0x0F;
buffer[(x >> 1) + (y)*WIDTH/2] |= (color << (!(x & 1) * 4) );
}
}
/*!
@brief Clear contents of display buffer (set all pixels to off).
@return None (void).
@note Changes buffer contents only, no immediate effect on display.
Follow up with a call to display(), or with other graphics
commands as needed by one's own application.
*/
void Jamis_SSD1322::clearDisplay(void) {
memset(buffer, 0, WIDTH * ((HEIGHT) / 2));
}
/*!
@brief Draw a horizontal line. This is also invoked by the Adafruit_GFX
library in generating many higher-level graphics primitives.
@param x
Leftmost column -- 0 at left to (screen width - 1) at right.
@param y
Row of display -- 0 at top to (screen height -1) at bottom.
@param w
Width of line, in pixels.
@param color
Line color, one of: BLACK, WHITE or INVERT.
@return None (void).
@note Changes buffer contents only, no immediate effect on display.
Follow up with a call to display(), or with other graphics
commands as needed by one's own application.
*/
void Jamis_SSD1322::drawFastHLine(
int16_t x, int16_t y, int16_t w, uint16_t color) {
boolean bSwap = false;
switch(rotation) {
case 1:
// 90 degree rotation, swap x & y for rotation, then invert x
bSwap = true;
ssd1322_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;
ssd1322_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 Jamis_SSD1322::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
// NOTE: This is _not_ fast. But with 4bit packing, I just want this done.
uint16_t yOffset = (y)*WIDTH/2;
uint8_t b1 = (x % 2) ? 0xF0 : 0x0F;
while(w--) {
buffer[((x + w) >> 1) + yOffset] &= b1;
buffer[((x + w) >> 1) + yOffset] |= (color << (!((x + w) & 1) * 4) );
}
}
}
}
/*!
@brief Draw a vertical line. This is also invoked by the Adafruit_GFX
library in generating many higher-level graphics primitives.
@param x
Column of display -- 0 at left to (screen width -1) at right.
@param y
Topmost row -- 0 at top to (screen height - 1) at bottom.
@param h
Height of line, in pixels.
@param color
Line color, one of: BLACK, WHITE or INVERT.
@return None (void).
@note Changes buffer contents only, no immediate effect on display.
Follow up with a call to display(), or with other graphics
commands as needed by one's own application.
*/
void Jamis_SSD1322::drawFastVLine(
int16_t x, int16_t y, int16_t h, uint16_t color) {
boolean bSwap = false;
switch(rotation) {
case 1:
// 90 degree rotation, swap x & y for rotation,
// then invert x and adjust x for h (now to become w)
bSwap = true;
ssd1322_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;
ssd1322_swap(x, y);
y = HEIGHT - y - 1;
break;
}
if(bSwap) drawFastHLineInternal(x, y, h, color);
else drawFastVLineInternal(x, y, h, color);
}
void Jamis_SSD1322::drawFastVLineInternal(
int16_t x, int16_t __y, int16_t __h, uint16_t color) {
if((x >= 0) && (x < WIDTH)) { // X coord in bounds?
if(__y < 0) { // Clip top
__h += __y;
__y = 0;
}
if((__y + __h) > HEIGHT) { // Clip bottom
__h = (HEIGHT - __y);
}
if(__h > 0) { // Proceed only if height is now positive
//buffer[((x + w) >> 1) + yOffset] |= (color << (!(w & 1) * 4) );
uint16_t xOffset = (x >> 1);
uint16_t mask = (color << (!(x & 1) * 4) );
uint8_t b1 = (x % 2) ? 0xF0 : 0x0F;
while(__h--) {
//Serial.printf("xOffset + (__y+__h)*WIDTH/2=%d, WIDTH=%d\n", xOffset + (__y+__h)*WIDTH/2, WIDTH);
buffer[xOffset + (__y+__h)*WIDTH/2] &= b1;
buffer[xOffset + (__y+__h)*WIDTH/2] |= mask;
}
} // endif positive height
} // endif x in bounds
}
/*!
@brief Return color of a single pixel in display buffer.
@param x
Column of display -- 0 at left to (screen width - 1) at right.
@param y
Row of display -- 0 at top to (screen height -1) at bottom.
@return true if pixel is set (usually WHITE, unless display invert mode
is enabled), false if clear (BLACK).
@note Reads from buffer contents; may not reflect current contents of
screen if display() has not been called.
*/
boolean Jamis_SSD1322::getPixel(int16_t x, int16_t y) {
if((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
// Pixel is in-bounds. Rotate coordinates if needed.
switch(getRotation()) {
case 1:
ssd1322_swap(x, y);
x = WIDTH - x - 1;
break;
case 2:
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
break;
case 3:
ssd1322_swap(x, y);
y = HEIGHT - y - 1;
break;
}
return (buffer[x + (y / 8) * WIDTH] & (1 << (y & 7)));
}
return false; // Pixel out of bounds
}
/*!
@brief Get base address of display buffer for direct reading or writing.
@return Pointer to an unsigned 8-bit array, column-major, columns padded
to full byte boundary if needed.
*/
uint8_t *Jamis_SSD1322::getBuffer(void) {
return buffer;
}
// REFRESH DISPLAY ---------------------------------------------------------
/*!
@brief Push data currently in RAM to SSD1306 display.
@return None (void).
@note Drawing operations are not visible until this function is
called. Call after each graphics command, or after a whole set
of graphics commands, as best needed by one's own application.
*/
void Jamis_SSD1322::display(void) {
TRANSACTION_START
// Set column address: Set_Column_Address(0x00, MAXCOLS-1);
ssd1322_command1(0x15);
// Each Column address holds 4 horizontal pixels worth of data
const uint16_t Col0Off = 0x70;
const uint16_t ColDiv = 4;
ssd1322_data1( (Col0Off+0x00)/ColDiv );
ssd1322_data1( (Col0Off+WIDTH-1)/ColDiv );
// Set row address: Set_Row_Address(0x00, MAXROWS-1);
ssd1322_command1(0x75);
ssd1322_data1(0x00);
ssd1322_data1(HEIGHT-1);
// Enable writing into MCU RAM: Set_Write_RAM();
ssd1322_command1(0x5C);
uint16_t count = WIDTH * ((HEIGHT) / 2);
//Serial.printlnf("%i", count);
uint8_t *ptr = buffer;
SSD1322_MODE_DATA
while(count--) SPIwrite(*ptr++);
TRANSACTION_END
}
#endif //if DSP_MODEL==DSP_SSD1322

View File

@@ -0,0 +1,83 @@
/*!
* @file Jamis_SSD1322.h
*
* This is a partial port of Adafruit's SSD1306 library to the SSD1322
* display.
*
* These displays use SPI to communicate. SPI requires 4 pins (MOSI, SCK,
* select, data/command) and optionally a reset pin.
*
* 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, with
* contributions from the open source community.
*
* BSD license, all text above, and the splash screen header file,
* must be included in any redistribution.
*
*/
#ifndef _Jamis_SSD1322_H_
#define _Jamis_SSD1322_H_
#if defined(PARTICLE)
#include "Particle.h"
#define SPI_HAS_TRANSACTION
#define SPISettings __SPISettings
#define BUFFER_LENGTH 32
#else
#include <Wire.h>
#include <SPI.h>
#endif
#include <Adafruit_GFX.h>
#define BLACK 0 ///< Draw 'off' pixels
#define WHITE 0xf ///< Draw 'on' pixels
#define INVERSE 2 ///< Invert pixels
#define SSD1322_DISPLAYOFF 0xAE
#define SSD1322_DISPLAYON 0xAF
/*!
@brief Class that stores state and functions for interacting with
SSD1322 OLED displays.
*/
class Jamis_SSD1322 : public Adafruit_GFX {
public:
Jamis_SSD1322(int16_t w, int16_t h, SPIClass *spi, int8_t dc_pin,
int8_t rst_pin, int8_t cs_pin, uint32_t bitrate=8000000UL);
~Jamis_SSD1322(void);
boolean begin(boolean reset=true, boolean periphBegin=true);
void display(void);
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);
void ssd1322_command(uint8_t c);
boolean getPixel(int16_t x, int16_t y);
uint8_t *getBuffer(void);
void oled_command(uint8_t c) { ssd1322_command1(c); }
private:
inline void SPIwrite(uint8_t d) __attribute__((always_inline));
void drawFastHLineInternal(int16_t x, int16_t y, int16_t w,
uint16_t color);
void drawFastVLineInternal(int16_t x, int16_t y, int16_t h,
uint16_t color);
void ssd1322_command1(uint8_t c);
void ssd1322_data1(uint8_t c);
void ssd1322_commandList(const uint8_t *c, uint8_t n);
SPIClass *spi;
uint8_t *buffer;
int8_t mosiPin , clkPin , dcPin , csPin, rstPin;
#if defined(SPI_HAS_TRANSACTION)
SPISettings spiSettings;
#endif
};
#endif // _Jamis_SSD1322_H_

View File

@@ -1,7 +1,7 @@
#ifndef options_h #ifndef options_h
#define options_h #define options_h
#define YOVERSION "0.9.022" #define YOVERSION "0.9.042"
/******************************************************* /*******************************************************
DO NOT EDIT THIS FILE. DO NOT EDIT THIS FILE.
@@ -48,6 +48,7 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#define DSP_GC9A01A 20 // 240x240 1.28' https://aliexpress.com/item/1005004069703494.html?sku_id=12000029869654615 #define DSP_GC9A01A 20 // 240x240 1.28' https://aliexpress.com/item/1005004069703494.html?sku_id=12000029869654615
#define DSP_ILI9488 21 // 480x320 3.5' https://aliexpress.com/item/1005001999296476.html?sku_id=12000018365356570 #define DSP_ILI9488 21 // 480x320 3.5' https://aliexpress.com/item/1005001999296476.html?sku_id=12000018365356570
#define DSP_ILI9486 22 // (Testing mode) 480x320 3.5' https://aliexpress.com/item/1005001999296476.html?sku_id=12000018365356568 #define DSP_ILI9486 22 // (Testing mode) 480x320 3.5' https://aliexpress.com/item/1005001999296476.html?sku_id=12000018365356568
#define DSP_SSD1322 23 // 256x64 2.8' https://aliexpress.com/item/1005003480981568.html
#define DSP_CUSTOM 101 // your display #define DSP_CUSTOM 101 // your display
#ifndef DSP_MODEL #ifndef DSP_MODEL

View File

@@ -0,0 +1,70 @@
/*************************************************************************************
SSD1305 128x64 displays configuration file.
Copy this file to yoRadio/src/displays/conf/displaySSD1305conf_custom.h
and modify it
More info on https://github.com/e2002/yoradio/wiki/Widgets#widgets-description
*************************************************************************************/
#ifndef displaySSD1322conf_h
#define displaySSD1322conf_h
#define DSP_WIDTH 256
#define TFT_FRAMEWDT 1
#define MAX_WIDTH DSP_WIDTH-TFT_FRAMEWDT*2
#define HIDE_HEAPBAR
#define HIDE_VOL
#define HIDE_VU
//#define HIDE_TITLE2
#define bootLogoTop 68
/* SROLLS */ /* {{ left, top, fontsize, align }, buffsize, uppercase, width, scrolldelay, scrolldelta, scrolltime } */
const ScrollConfig metaConf PROGMEM = {{ TFT_FRAMEWDT+1, TFT_FRAMEWDT+1, 2, WA_LEFT }, 140, true, MAX_WIDTH-2, 5000, 2, 25 };
const ScrollConfig title1Conf PROGMEM = {{ 0, 20, 1, WA_LEFT }, 140, true, DSP_WIDTH/2+6, 5000, 2, 25 };
const ScrollConfig title2Conf PROGMEM = {{ 0, 29, 1, WA_LEFT }, 140, true, DSP_WIDTH/2+6, 5000, 2, 25 };
const ScrollConfig playlistConf PROGMEM = {{ TFT_FRAMEWDT, 30, 1, WA_LEFT }, 140, true, MAX_WIDTH, 500, 2, 25 };
const ScrollConfig apTitleConf PROGMEM = {{ TFT_FRAMEWDT+1, TFT_FRAMEWDT+1, 1, WA_CENTER }, 140, false, MAX_WIDTH-2, 0, 2, 25 };
const ScrollConfig apSettConf PROGMEM = {{ TFT_FRAMEWDT, 64-7, 1, WA_LEFT }, 140, false, MAX_WIDTH, 0, 2, 25 };
const ScrollConfig weatherConf PROGMEM = {{ 0, 64-12, 1, WA_LEFT }, 140, true, DSP_WIDTH/2+6, 0, 2, 25 }; // ПОГОДА!!
/* BACKGROUNGC9106DS */ /* {{ left, top, fontsize, align }, width, height, outlined } */
const FillConfig metaBGConf PROGMEM = {{ 0, 0, 0, WA_LEFT }, DSP_WIDTH, 18, false };
const FillConfig volbarConf PROGMEM = {{ 0, 64-1-1-1, 0, WA_LEFT }, DSP_WIDTH, 3, true };
const FillConfig playlBGConf PROGMEM = {{ 0, 26, 0, WA_LEFT }, DSP_WIDTH, 12, false };
const FillConfig heapbarConf PROGMEM = {{ 0, 63, 0, WA_LEFT }, DSP_WIDTH, 1, false };
/* WIDGETS */ /* { left, top, fontsize, align } */
const WidgetConfig bootstrConf PROGMEM = { 0, 64-8, 1, WA_CENTER };
const WidgetConfig bitrateConf PROGMEM = { TFT_FRAMEWDT+20, 64-11-10, 1, WA_LEFT };
//const WidgetConfig voltxtConf PROGMEM = { 32, 108, 1, WA_RIGHT };
const WidgetConfig iptxtConf PROGMEM = { 0, 64-12, 1, WA_LEFT };
const WidgetConfig rssiConf PROGMEM = { 0, 64-11-10, 1, WA_LEFT };
const WidgetConfig numConf PROGMEM = { TFT_FRAMEWDT, 57, 35, WA_CENTER };
const WidgetConfig apNameConf PROGMEM = { 0, 18, 1, WA_CENTER };
const WidgetConfig apName2Conf PROGMEM = { 0, 26, 1, WA_CENTER };
const WidgetConfig apPassConf PROGMEM = { 0, 37, 1, WA_CENTER };
const WidgetConfig apPass2Conf PROGMEM = { 0, 45, 1, WA_CENTER };
//const WidgetConfig clockConf PROGMEM = { 6, 34, 2, WA_CENTER };
const WidgetConfig clockConf PROGMEM = { 0, 57, 35, WA_RIGHT }; /* 35 is a fixed font size. do not change */
const WidgetConfig vuConf PROGMEM = { 1, 28, 1, WA_LEFT };
const WidgetConfig bootWdtConf PROGMEM = { 0, 64-8*2-5, 1, WA_CENTER };
const ProgressConfig bootPrgConf PROGMEM = { 90, 10, 4 };
/* BANDS */ /* { onebandwidth, onebandheight, bandsHspace, bandsVspace, numofbands, fadespeed } */
const VUBandsConfig bandsConf PROGMEM = { 12, 48, 2, 1, 8, 3 };
/* STRINGS */
const char numtxtFmt[] PROGMEM = "%d";
const char rssiFmt[] PROGMEM = "%d";
const char iptxtFmt[] PROGMEM = "%s";
//const char voltxtFmt[] PROGMEM = "%d";
const char bitrateFmt[] PROGMEM = "%d kBs";
/* MOVES */ /* { left, top, width } */
const MoveConfig clockMove PROGMEM = { 0, 0, -1 };
const MoveConfig weatherMove PROGMEM = { 0, 0, -1 };
const MoveConfig weatherMoveVU PROGMEM = { 0, 0, -1 };
#endif

View File

@@ -0,0 +1,220 @@
#include "../core/options.h"
#if DSP_MODEL==DSP_SSD1322
#include "displaySSD1322.h"
#include "../core/player.h"
#include "../core/config.h"
#include "../core/network.h"
#define LOGO_WIDTH 21
#define LOGO_HEIGHT 32
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
#ifndef DEF_SPI_FREQ
#define DEF_SPI_FREQ 16000000UL /* set it to 0 for system default */
#endif
const unsigned char logo [] PROGMEM=
{
0x06, 0x03, 0x00, 0x0f, 0x07, 0x80, 0x1f, 0x8f, 0xc0, 0x1f, 0x8f, 0xc0,
0x0f, 0x07, 0x80, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x03, 0xff, 0x00, 0x0f, 0xff, 0x80,
0x1f, 0xff, 0xc0, 0x1f, 0xff, 0xc0, 0x3f, 0x8f, 0xe0, 0x7e, 0x03, 0xf0,
0x7c, 0x01, 0xf0, 0x7c, 0x01, 0xf0, 0x7f, 0xff, 0xf0, 0xff, 0xff, 0xf8,
0xff, 0xff, 0xf8, 0xff, 0xff, 0xf8, 0x7c, 0x00, 0x00, 0x7c, 0x00, 0x00,
0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x3f, 0xc0, 0xe0, 0x3f, 0xff, 0xe0,
0x1f, 0xff, 0xe0, 0x0f, 0xff, 0xe0, 0x03, 0xff, 0xc0, 0x00, 0xfe, 0x00
};
#if DSP_HSPI
DspCore::DspCore(): Jamis_SSD1322(256, 64, &SPI2, TFT_DC, TFT_RST, TFT_CS, DEF_SPI_FREQ) {}
#else
DspCore::DspCore(): Jamis_SSD1322(256, 64, &SPI, TFT_DC, TFT_RST, TFT_CS, DEF_SPI_FREQ) {}
#endif
#include "tools/utf8RusGFX.h"
void DspCore::initDisplay() {
#include "tools/oledcolorfix.h"
begin();
cp437(true);
flip();
invert();
setTextWrap(false);
plItemHeight = playlistConf.widget.textsize*(CHARHEIGHT-1)+playlistConf.widget.textsize*4;
plTtemsCount = round((float)height()/plItemHeight);
if(plTtemsCount%2==0) plTtemsCount++;
plCurrentPos = plTtemsCount/2;
plYStart = (height() / 2 - plItemHeight / 2) - plItemHeight * (plTtemsCount - 1) / 2 + playlistConf.widget.textsize*2;
}
void DspCore::drawLogo(uint16_t top) {
drawBitmap( (width() - LOGO_WIDTH ) / 2, 8, logo, LOGO_WIDTH, LOGO_HEIGHT, 1);
display();
}
void DspCore::printPLitem(uint8_t pos, const char* item, ScrollWidget& current){
setTextSize(playlistConf.widget.textsize);
if (pos == plCurrentPos) {
current.setText(item);
} else {
uint8_t plColor = (abs(pos - plCurrentPos)-1)>4?4:abs(pos - plCurrentPos)-1;
setTextColor(config.theme.playlist[plColor], config.theme.background);
setCursor(TFT_FRAMEWDT, plYStart + pos * plItemHeight);
fillRect(0, plYStart + pos * plItemHeight - 1, width(), plItemHeight - 2, config.theme.background);
print(utf8Rus(item, true));
}
}
void DspCore::drawPlaylist(uint16_t currentItem) {
uint8_t lastPos = config.fillPlMenu(currentItem - plCurrentPos, plTtemsCount);
if(lastPos<plTtemsCount){
fillRect(0, lastPos*plItemHeight+plYStart, width(), height()/2, config.theme.background);
}
}
void DspCore::clearDsp(bool black) {
//fillScreen(TFT_BG);
clearDisplay();
}
GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c) {
return gfxFont->glyph + c;
}
uint8_t DspCore::_charWidth(unsigned char c){
GFXglyph *glyph = pgm_read_glyph_ptr(&DS_DIGI28pt7b, c - 0x20);
return pgm_read_byte(&glyph->xAdvance);
}
uint16_t DspCore::textWidth(const char *txt){
uint16_t w = 0, l=strlen(txt);
for(uint16_t c=0;c<l;c++) w+=_charWidth(txt[c]);
return w;
}
void DspCore::_getTimeBounds() {
_timewidth = textWidth(_timeBuf);
char buf[4];
strftime(buf, 4, "%H", &network.timeinfo);
_dotsLeft=textWidth(buf);
}
void DspCore::_clockSeconds(){
setTextSize(1);
setFont(&DS_DIGI28pt7b);
setTextColor((network.timeinfo.tm_sec % 2 == 0) ? config.theme.clock : config.theme.background, config.theme.background);
setCursor(_timeleft+_dotsLeft, clockTop);
print(":");
setFont();
/*
setTextSize(1);
setCursor(_timeleft+_timewidth+2, clockTop-CHARHEIGHT*2-1);
setTextColor(config.theme.clock, config.theme.background);
sprintf(_bufforseconds, "%02d", network.timeinfo.tm_sec);
print(_bufforseconds); */
}
void DspCore::_clockDate(){ }
void DspCore::_clockTime(){
if(_oldtimeleft>0) dsp.fillRect(_oldtimeleft, clockTop-clockTimeHeight+1, _oldtimewidth+CHARWIDTH*2+2, clockTimeHeight, config.theme.background);
//if(_oldtimeleft>0) dsp.fillRect(_oldtimeleft, clockTop-clockTimeHeight+1, _oldtimewidth, clockTimeHeight, config.theme.background);
_timeleft = (width()/*/2*/ - _timewidth/*/2*/)-clockRightSpace;
setTextSize(1);
setFont(&DS_DIGI28pt7b);
setTextColor(config.theme.clock, config.theme.background);
setCursor(_timeleft, clockTop);
print(_timeBuf);
setFont();
strlcpy(_oldTimeBuf, _timeBuf, sizeof(_timeBuf));
_oldtimewidth = _timewidth;
_oldtimeleft = _timeleft;
}
void DspCore::printClock(uint16_t top, uint16_t rightspace, uint16_t timeheight, bool redraw){
clockTop = top;
clockRightSpace = rightspace;
clockTimeHeight = timeheight;
strftime(_timeBuf, sizeof(_timeBuf), "%H:%M", &network.timeinfo);
if(strcmp(_oldTimeBuf, _timeBuf)!=0 || redraw){
_getTimeBounds();
_clockTime();
}
_clockSeconds();
}
void DspCore::clearClock(){
dsp.fillRect(_timeleft, clockTop-clockTimeHeight, _timewidth+2, clockTimeHeight, config.theme.background);
//dsp.fillRect(_timeleft, clockTop-clockTimeHeight, _timewidth+CHARWIDTH*3*2+24, clockTimeHeight+10+CHARHEIGHT, config.theme.background);
}
void DspCore::startWrite(void) {
//TAKE_MUTEX();
Jamis_SSD1322::startWrite();
}
void DspCore::endWrite(void) {
Jamis_SSD1322::endWrite();
//GIVE_MUTEX();
}
void DspCore::loop(bool force) {
//clearDisplay();
display();
delay(5);
}
void DspCore::charSize(uint8_t textsize, uint8_t& width, uint16_t& height){
width = textsize * CHARWIDTH;
height = textsize * CHARHEIGHT;
}
void DspCore::setTextSize(uint8_t s){
Adafruit_GFX::setTextSize(s);
}
void DspCore::flip(){
setRotation(config.store.flipscreen?2:0);
}
void DspCore::invert(){
invertDisplay(config.store.invertdisplay);
}
void DspCore::sleep(void) { oled_command(SSD1322_DISPLAYOFF); }
void DspCore::wake(void) { oled_command(SSD1322_DISPLAYON); }
void DspCore::writePixel(int16_t x, int16_t y, uint16_t color) {
if(_clipping){
if ((x < _cliparea.left) || (x > _cliparea.left+_cliparea.width) || (y < _cliparea.top) || (y > _cliparea.top + _cliparea.height)) return;
}
Jamis_SSD1322::writePixel(x, y, color);
}
void DspCore::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
if(_clipping){
if ((x < _cliparea.left) || (x >= _cliparea.left+_cliparea.width) || (y < _cliparea.top) || (y > _cliparea.top + _cliparea.height)) return;
}
Jamis_SSD1322::writeFillRect(x, y, w, h, color);
}
void DspCore::setClipping(clipArea ca){
_cliparea = ca;
_clipping = true;
}
void DspCore::clearClipping(){
_clipping = false;
}
void DspCore::setNumFont(){
setFont(&DS_DIGI28pt7b);
setTextSize(1);
}
#endif

View File

@@ -0,0 +1,43 @@
#ifndef displaySSD1305_h
#define displaySSD1305_h
#include "../core/options.h"
#include "Arduino.h"
#include <Adafruit_GFX.h>
#include "../SSD1322/SSD1322.h"
#include "fonts/DS_DIGI28pt7b.h"
#include "tools/l10n.h"
#define CHARWIDTH 6
#define CHARHEIGHT 8
#define DSP_OLED
typedef GFXcanvas1 Canvas;
#include "widgets/widgets.h"
#include "widgets/pages.h"
#if __has_include("conf/displaySSD1305conf_custom.h")
#include "conf/displaySSD1322conf_custom.h"
#else
#include "conf/displaySSD1322conf.h"
#endif
class DspCore: public Jamis_SSD1322 {
#include "tools/commongfx.h"
};
extern DspCore dsp;
/*
* OLED COLORS
*/
#define BOOT_PRG_COLOR WHITE
#define BOOT_TXT_COLOR WHITE
#define PINK WHITE
#define SILVER WHITE
#define TFT_BG BLACK
#define TFT_FG WHITE
#define TFT_LOGO WHITE
#endif

View File

@@ -40,6 +40,8 @@
#include "displayGC9A01A.h" #include "displayGC9A01A.h"
#elif DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486 #elif DSP_MODEL==DSP_ILI9488 || DSP_MODEL==DSP_ILI9486
#include "displayILI9488.h" #include "displayILI9488.h"
#elif DSP_MODEL==DSP_SSD1322
#include "displaySSD1322.h"
#endif #endif
//extern DspCore dsp; //extern DspCore dsp;

View File

@@ -381,7 +381,7 @@ void NumWidget::setText(const char* txt) {
_getBounds(); _getBounds();
if (strcmp(_oldtext, _text) == 0) return; if (strcmp(_oldtext, _text) == 0) return;
uint16_t realth = _textheight; uint16_t realth = _textheight;
#ifdef DSP_OLED #if defined(DSP_OLED) && DSP_MODEL!=DSP_SSD1322
realth = _textheight*CHARHEIGHT; realth = _textheight*CHARHEIGHT;
#endif #endif
if (_active) dsp.fillRect(_oldleft == 0 ? _realLeft() : min(_oldleft, _realLeft()), _config.top-_textheight+1, max(_oldtextwidth, _textwidth), realth, _bgcolor); if (_active) dsp.fillRect(_oldleft == 0 ? _realLeft() : min(_oldleft, _realLeft()), _config.top-_textheight+1, max(_oldtextwidth, _textwidth), realth, _bgcolor);