|
@@ -0,0 +1,264 @@
|
|
|
+/*
|
|
|
+ * WaveShareOLED1in5.cpp
|
|
|
+ *
|
|
|
+ * Created on: Mar 23, 2021
|
|
|
+ * Author: spinner
|
|
|
+ */
|
|
|
+
|
|
|
+#include <WaveShareOLED1in5.h>
|
|
|
+#include <cstring>
|
|
|
+
|
|
|
+
|
|
|
+static uint8_t rxPad[WSOLED_MAX_TX] = {};
|
|
|
+
|
|
|
+
|
|
|
+void oledOnTxComplete() {
|
|
|
+ WaveShare_OLED1in5::instance.onTxComplete();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+WaveShare_OLED1in5 WaveShare_OLED1in5::instance = WaveShare_OLED1in5();
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::init(SPI_HandleTypeDef* hspi) {
|
|
|
+ this->hspi = hspi;
|
|
|
+
|
|
|
+ if (txCompleteId == nullptr) {
|
|
|
+ txCompleteId = osSemaphoreNew(1, 0, nullptr);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (spiLock == nullptr) {
|
|
|
+ spiLock = osMutexNew(nullptr);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::_write(uint8_t byte) {
|
|
|
+ HAL_SPI_TransmitReceive_DMA(hspi, &byte, rxPad, 1);
|
|
|
+ waitTxComplete();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::_write(uint8_t const* data, size_t size) {
|
|
|
+ size_t sent = 0;
|
|
|
+ size_t slice;
|
|
|
+ size_t left;
|
|
|
+
|
|
|
+ while(sent < size) {
|
|
|
+ left = (size - sent);
|
|
|
+ slice = (left > WSOLED_MAX_TX) ? WSOLED_MAX_TX : left;
|
|
|
+ HAL_SPI_TransmitReceive_DMA(hspi, const_cast<uint8_t*>(data + sent), rxPad, slice);
|
|
|
+ waitTxComplete();
|
|
|
+ sent += slice;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::waitTxComplete() {
|
|
|
+ while(osSemaphoreAcquire(txCompleteId, osWaitForever) != osOK);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::onTxComplete() {
|
|
|
+ osSemaphoreRelease(txCompleteId);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::reset() {
|
|
|
+ OLED_RST_1;
|
|
|
+ osDelay(100);
|
|
|
+ OLED_RST_0;
|
|
|
+ osDelay(100);
|
|
|
+ OLED_RST_1;
|
|
|
+ osDelay(100);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::writeReg(uint8_t const* reg, size_t size) {
|
|
|
+ if (osMutexAcquire(spiLock, osWaitForever) == osOK) {
|
|
|
+ OLED_DC_0;
|
|
|
+ OLED_CS_0;
|
|
|
+ _write(reg, size);
|
|
|
+ OLED_CS_1;
|
|
|
+ osMutexRelease(spiLock);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::writeReg(uint8_t reg) {
|
|
|
+ writeReg(®, 1);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::writeData(uint8_t const* data, size_t size) {
|
|
|
+ if (osMutexAcquire(spiLock, osWaitForever) == osOK) {
|
|
|
+ OLED_DC_1;
|
|
|
+ OLED_CS_0;
|
|
|
+ _write(data, size);
|
|
|
+ OLED_CS_1;
|
|
|
+ osMutexRelease(spiLock);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::initReg() {
|
|
|
+ static const uint8_t regSequence [] = {
|
|
|
+ 0xae, // turn off oled panel
|
|
|
+
|
|
|
+ 0x15, // set column address
|
|
|
+ 0x00, // start column 0
|
|
|
+ 0x7f, // end column 12
|
|
|
+
|
|
|
+ 0x75, // set row address
|
|
|
+ 0x00, // start row 0
|
|
|
+ 0x7f, // end row 127
|
|
|
+
|
|
|
+ 0x81, // set contrast control
|
|
|
+ 0xFF,
|
|
|
+
|
|
|
+ 0xa0, // gment remap
|
|
|
+ 0x51, // 51
|
|
|
+
|
|
|
+ 0xa1, // start line
|
|
|
+ 0x00,
|
|
|
+
|
|
|
+ 0xa2, // display offset
|
|
|
+ 0x00,
|
|
|
+
|
|
|
+ 0xa4, // Normal display
|
|
|
+
|
|
|
+ 0xa8, // set multiplex ratio
|
|
|
+ 0x7f,
|
|
|
+
|
|
|
+ 0xb1, // set phase leghth
|
|
|
+ 0xf1,
|
|
|
+
|
|
|
+ 0xb3, // set dclk
|
|
|
+ 0x70, // 80Hz:0xc1 90Hz:0xe1 100Hz:0x00 110Hz:0x30 120Hz:0x50 130Hz:0x70 01
|
|
|
+
|
|
|
+ 0xab, // Internal regulator
|
|
|
+ 0x01, // Enabled
|
|
|
+
|
|
|
+ 0xb6, // set phase leghth
|
|
|
+ 0x0f, // 15CLK
|
|
|
+
|
|
|
+ 0xbe, // set COM deselect voltage level
|
|
|
+ 0x08, //
|
|
|
+
|
|
|
+ 0xbc, // set PRECHARGE voltage
|
|
|
+ 0x00,
|
|
|
+
|
|
|
+ 0xd5, // Enable second precharge and VSL pin
|
|
|
+ 0x62,
|
|
|
+
|
|
|
+ 0xb8,
|
|
|
+ 1, 2, 3, 4, 6, 8, 10, 13, 17, 22, 28, 35, 44, 55,
|
|
|
+ //0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x10, 0x15, 0x19, 0x20, 0x28, 0x32,
|
|
|
+
|
|
|
+ 0xfd,
|
|
|
+ 0x12,
|
|
|
+
|
|
|
+ // Set the grayscale
|
|
|
+ //0xB9,
|
|
|
+ };
|
|
|
+
|
|
|
+ writeReg(regSequence, sizeof(regSequence));
|
|
|
+}
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::setGramScanWay(OLED_SCAN_DIR scanDir) {
|
|
|
+ desc.OLED_Scan_Dir = scanDir;
|
|
|
+
|
|
|
+ //Get GRAM and OLED width and height
|
|
|
+ if(scanDir == L2R_U2D || scanDir == L2R_D2U || scanDir == R2L_U2D || scanDir == R2L_D2U) {
|
|
|
+ desc.OLED_Dis_Column = OLED_WIDTH;
|
|
|
+ desc.OLED_Dis_Page = OLED_HEIGHT;
|
|
|
+ desc.OLED_X_Adjust = OLED_X;
|
|
|
+ desc.OLED_Y_Adjust = OLED_Y;
|
|
|
+ } else {
|
|
|
+ desc.OLED_Dis_Column = OLED_HEIGHT;
|
|
|
+ desc.OLED_Dis_Page = OLED_WIDTH;
|
|
|
+ desc.OLED_X_Adjust = OLED_Y;
|
|
|
+ desc.OLED_Y_Adjust = OLED_X;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::displayInit(OLED_SCAN_DIR scanDir) {
|
|
|
+ //Hardware reset
|
|
|
+ reset();
|
|
|
+
|
|
|
+ //Set the initialization register
|
|
|
+ initReg();
|
|
|
+
|
|
|
+ //Set the display scan and color transfer modes
|
|
|
+ setGramScanWay(scanDir);
|
|
|
+ osDelay(200);
|
|
|
+
|
|
|
+ //Turn on the OLED display
|
|
|
+ writeReg(0xAF);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::setCursor(POINT Xpoint, POINT Ypoint) {
|
|
|
+ if((Xpoint > desc.OLED_Dis_Column) || (Ypoint > desc.OLED_Dis_Page)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ uint8_t sequence[] = {
|
|
|
+ 0x15, static_cast<uint8_t>(Xpoint), static_cast<uint8_t>(Xpoint),
|
|
|
+ 0x75, static_cast<uint8_t>(Ypoint), static_cast<uint8_t>(Ypoint),
|
|
|
+ };
|
|
|
+
|
|
|
+ writeReg(sequence, sizeof(sequence));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::setWindow(POINT Xstart, POINT Ystart, POINT Xend, POINT Yend) {
|
|
|
+ if((Xstart > desc.OLED_Dis_Column) || (Ystart > desc.OLED_Dis_Page) ||
|
|
|
+ (Xend > desc.OLED_Dis_Column) || (Yend > desc.OLED_Dis_Page))
|
|
|
+ return;
|
|
|
+
|
|
|
+ uint8_t sequence[] = {
|
|
|
+ 0x15, static_cast<uint8_t>(Xstart), static_cast<uint8_t>(Xend - 1),
|
|
|
+ 0x75, static_cast<uint8_t>(Ystart), static_cast<uint8_t>(Yend - 1),
|
|
|
+ };
|
|
|
+
|
|
|
+ writeReg(sequence, sizeof(sequence));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::setColor(POINT Xpoint, POINT Ypoint, COLOR Color)
|
|
|
+{
|
|
|
+ if(Xpoint > desc.OLED_Dis_Column || Ypoint > desc.OLED_Dis_Page) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Color &= 0x0F;
|
|
|
+
|
|
|
+ //1 byte control two points
|
|
|
+ if(Xpoint % 2 == 0) {
|
|
|
+ pixBuf[Xpoint / 2 + Ypoint * 64] = (Color << 4) | (pixBuf[Xpoint / 2 + Ypoint * 64] & 0x0F);
|
|
|
+ } else {
|
|
|
+ pixBuf[Xpoint / 2 + Ypoint * 64] = (Color & 0x0F) | (pixBuf[Xpoint / 2 + Ypoint * 64] & 0xf0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::display(Surface4Bit<SCR_PARAMS>* surface) {
|
|
|
+ memcpy(pixBuf, surface->getSurface(), sizeof(pixBuf));
|
|
|
+ display();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::display() {
|
|
|
+ setWindow(0, 0, desc.OLED_Dis_Column, desc.OLED_Dis_Page);
|
|
|
+ //write data
|
|
|
+ writeData(pixBuf, sizeof(pixBuf));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void WaveShare_OLED1in5::clear(COLOR color) {
|
|
|
+ color &= 0x0F;
|
|
|
+ uint8_t c = (color << 4) | color;
|
|
|
+ memset(pixBuf, c, sizeof(pixBuf));
|
|
|
+}
|
|
|
+
|