/* * WaveShareOLED1in5.cpp * * Created on: Mar 23, 2021 * Author: spinner */ #include #include 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(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(Xpoint), static_cast(Xpoint), 0x75, static_cast(Ypoint), static_cast(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(Xstart), static_cast(Xend - 1), 0x75, static_cast(Ystart), static_cast(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* 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)); }