File oled_ssd1351.h¶
File List > dev > oled_ssd1351.h
Go to the documentation of this file
Source Code¶
#pragma once
#include "per/spi.h"
#include "per/gpio.h"
#include "sys/system.h"
#define oled_white 0xffff
#define oled_black 0x0000
#define oled_red 0x00f1
#define oled_green 0xe007
#define oled_blue 0x1f00
#define oled_cyan (oled_green | oled_blue)
#define oled_yellow (oled_green | oled_red)
#define oled_magenta (oled_red | oled_blue)
namespace daisy
{
class SSD13514WireSpiTransport
{
public:
struct Config
{
Config()
{
// Initialize using defaults
Defaults();
}
SpiHandle::Config spi_config;
struct
{
Pin dc;
Pin reset;
} pin_config;
void Defaults()
{
// SPI peripheral config
spi_config.periph = SpiHandle::Config::Peripheral::SPI_1;
spi_config.mode = SpiHandle::Config::Mode::MASTER;
spi_config.direction
= SpiHandle::Config::Direction::TWO_LINES_TX_ONLY;
spi_config.datasize = 8;
spi_config.clock_polarity = SpiHandle::Config::ClockPolarity::LOW;
spi_config.clock_phase = SpiHandle::Config::ClockPhase::ONE_EDGE;
spi_config.nss = SpiHandle::Config::NSS::HARD_OUTPUT;
spi_config.baud_prescaler = SpiHandle::Config::BaudPrescaler::PS_8;
// SPI pin config
spi_config.pin_config.sclk = Pin(PORTG, 11);
spi_config.pin_config.miso = Pin(PORTX, 0);
spi_config.pin_config.mosi = Pin(PORTB, 5);
spi_config.pin_config.nss = Pin(PORTG, 10);
// SSD1351 control pin config
pin_config.dc = Pin(PORTB, 4);
pin_config.reset = Pin(PORTB, 15);
}
};
void Init(const Config& config)
{
// Initialize both GPIO
pin_reset_.Init(config.pin_config.reset, GPIO::Mode::OUTPUT);
pin_dc_.Init(config.pin_config.dc, GPIO::Mode::OUTPUT);
// Initialize SPI
spi_.Init(config.spi_config);
// Reset and Configure OLED.
pin_reset_.Write(false);
System::Delay(10);
pin_reset_.Write(true);
System::Delay(10);
};
void SendCommand(uint8_t cmd)
{
pin_dc_.Write(false);
spi_.BlockingTransmit(&cmd, 1);
};
void SendData(uint8_t* buff, size_t size)
{
pin_dc_.Write(true);
spi_.BlockingTransmit(buff, size);
};
void SendData(uint8_t data)
{
pin_dc_.Write(true);
spi_.BlockingTransmit(&data, 1);
};
private:
SpiHandle spi_;
GPIO pin_reset_;
GPIO pin_dc_;
};
template <size_t width, size_t height, typename Transport>
class SSD1351Driver
{
public:
struct Config
{
typename Transport::Config transport_config;
};
void Init(Config config)
{
fg_color_ = oled_white;
bg_color_ = oled_black;
transport_.Init(config.transport_config);
transport_.SendCommand(0xfd); // lock IC
transport_.SendData(0x12);
transport_.SendCommand(0xfd); // unlock IC
transport_.SendData(0xb1); //
transport_.SendCommand(0xae); // display off
transport_.SendCommand(0x15); // set column address
transport_.SendData(0x00); // column address start 00
transport_.SendData(0x7f); // column address end 127
transport_.SendCommand(0x75); // set row address
transport_.SendData(0x00); // row address start 00
transport_.SendData(0x7f); // row address end 127
transport_.SendCommand(
0xB3); // Set Front Clock Divider / Oscillator Frequency
transport_.SendData(0xF1);
transport_.SendCommand(0xCA); // Set Multiplex Ratio
transport_.SendData(0x7F);
transport_.SendCommand(0xa0); // Set Re-map & Dual COM Line Mode
transport_.SendData(
0x74); // color mode 64k, enable com split, reverse com scan, color swapped, hz scan
transport_.SendCommand(0xa1); // set display start line
transport_.SendData(0x00); // line 0
transport_.SendCommand(0xa2); // set display offset
transport_.SendData(0x00); // column 0
transport_.SendCommand(0xAB); // Function Selection
transport_.SendData(0x01);
transport_.SendCommand(0xB4); // Set Segment Low Voltage
transport_.SendData(0xA0);
transport_.SendData(0xB5);
transport_.SendData(0x55);
transport_.SendCommand(0xC1); // Set Contrast Current for Color A,B,C
transport_.SendData(0xC8);
transport_.SendData(0x80);
transport_.SendData(0xC0);
transport_.SendCommand(0xC7); // Master Contrast Current Control
transport_.SendData(0x0F);
transport_.SendCommand(
0xB1); // Set Reset (Phase 1) / Pre-charge (Phase 2) period
transport_.SendData(0x32);
transport_.SendCommand(0xB2); // Display Enhancement
transport_.SendData(0xA4);
transport_.SendData(0x00);
transport_.SendData(0x00);
transport_.SendCommand(0xBB); // Set Pre-charge voltage
transport_.SendData(0x17);
transport_.SendCommand(0xB6); // Set Second Precharge Period
transport_.SendData(0x01);
transport_.SendCommand(0xBE); // Set VCOMH Voltage
transport_.SendData(0x05);
transport_.SendCommand(0xA6); // Normal display
System::Delay(300); // wait 300ms
transport_.SendCommand(0xaf); // turn on display
Fill(false);
};
size_t Width() const { return width; };
size_t Height() const { return height; };
void DrawPixel(uint_fast8_t x, uint_fast8_t y, bool on)
{
if((x >= width) || (y >= height))
return;
if(on)
{
buffer_[(y * width) + x] = fg_color_;
}
else
{
buffer_[(y * width) + x] = bg_color_;
}
};
void Fill(bool on)
{
for(size_t i = 0; i < sizeof(buffer_) / 2; i++)
{
buffer_[i] = on ? fg_color_ : bg_color_;
}
};
void Update()
{
transport_.SendCommand(0x15); // column
transport_.SendData(0x00);
transport_.SendData(width - 1);
transport_.SendCommand(0x75); // row
transport_.SendData(0x00);
transport_.SendData(height - 1);
transport_.SendCommand(0x5c); // write display buffer
transport_.SendData((uint8_t*)buffer_, sizeof(buffer_));
};
void SetColorFG(uint8_t red, uint8_t green, uint8_t blue)
{
uint16_t t1, t2;
fg_color_ = (red & 0x1f) << 11 | (green & 0x3f) << 5 | (blue & 0x1f);
t1 = (fg_color_ >> 8) & 0xff;
t2 = (fg_color_ & 0xff);
fg_color_ = t2 << 8 | t1;
};
void SetColorBG(uint8_t red, uint8_t green, uint8_t blue)
{
uint16_t t1, t2;
bg_color_ = (red & 0x1f) << 11 | (green & 0x3f) << 5 | (blue & 0x1f);
t1 = (bg_color_ >> 8) & 0xff;
t2 = (bg_color_ & 0xff);
bg_color_ = t2 << 8 | t1;
};
protected:
Transport transport_;
uint16_t buffer_[width * height];
uint16_t fg_color_;
uint16_t bg_color_;
};
using SSD13514WireSpi128x128Driver
= daisy::SSD1351Driver<128, 128, SSD13514WireSpiTransport>;
}; // namespace daisy