/** *! * \file b_drv_oled.c * \version v0.0.1 * \date 2020/03/02 * \author Bean(notrynohigh@outlook.com) ******************************************************************************* * @attention * * Copyright (c) 2020 Bean * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation 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 * furnished 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 FOR 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. ******************************************************************************* */ /*Includes ----------------------------------------------*/ #include "drivers/inc/b_drv_oled.h" #include <string.h> /** * \addtogroup BABYOS * \{ */ /** * \addtogroup B_DRIVER * \{ */ /** * \addtogroup OLED * \{ */ /** * \defgroup OLED_Private_Defines * \{ */ #define DRIVER_NAME OLED #ifndef LCD_X_SIZE #define LCD_X_SIZE 128 #endif #ifndef LCD_Y_SIZE #define LCD_Y_SIZE 64 #endif /** * \} */ /** * \defgroup OLED_Private_TypesDefinitions * \{ */ typedef struct { uint8_t data[LCD_X_SIZE * LCD_Y_SIZE / 8]; } bOledPrivate_t; /** * \} */ /** * \defgroup OLED_Private_Macros * \{ */ /** * \} */ /** * \defgroup OLED_Private_Variables * \{ */ bDRIVER_HALIF_TABLE(bOLED_HalIf_t, DRIVER_NAME); static bOledPrivate_t bOledPrivateTable[bDRIVER_HALIF_NUM(bOLED_HalIf_t, DRIVER_NAME)]; /** * \} */ /** * \defgroup OLED_Private_FunctionPrototypes * \{ */ /** * \} */ /** * \defgroup OLED_Private_Functions * \{ */ static void _bOLED_WriteCmd(bDriverInterface_t *pdrv, uint8_t cmd) { int ret = 0; bDRIVER_GET_HALIF(_if, bOLED_HalIf_t, pdrv); if (_if->is_spi) { ret = -1; // add spi ... } else { ret = bHalI2CMemWrite(&_if->_if._i2c, 0x00, 1, &cmd, 1); } (void)ret; } static void _bOLED_WriteData(bDriverInterface_t *pdrv, uint8_t dat) { int ret = 0; bDRIVER_GET_HALIF(_if, bOLED_HalIf_t, pdrv); if (_if->is_spi) { ret = -1; // add spi ... } else { ret = bHalI2CMemWrite(&_if->_if._i2c, 0x40, 1, &dat, 1); } (void)ret; } static void _bOLEDSetCursor(bDriverInterface_t *pdrv, uint8_t x, uint8_t y) { _bOLED_WriteCmd(pdrv, 0xb0 + y); _bOLED_WriteCmd(pdrv, x % 16); _bOLED_WriteCmd(pdrv, (x / 16) | 0x10); } static void _bOLEDDrawPixel(bDriverInterface_t *pdrv, uint8_t x, uint8_t y, uint8_t t) { uint16_t index; uint8_t tmp = 0, off; index = (y / 8) * LCD_X_SIZE + x; tmp = ((bOledPrivate_t *)(pdrv->_private._p))->data[index]; off = y % 8; if (t) { tmp |= 1 << off; } else { tmp &= ~(1 << off); } ((bOledPrivate_t *)(pdrv->_private._p))->data[index] = tmp; _bOLEDSetCursor(pdrv, x, y / 8); _bOLED_WriteData(pdrv, tmp); } static int _bOLEDFillRect(bDriverInterface_t *pdrv, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { int i = 0, j = 0; uint16_t tmp = 0; uint16_t index; if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; } if (x2 >= LCD_X_SIZE || y2 >= LCD_Y_SIZE) { return -1; } for (i = x1; i <= x2; i++) { for (j = y1; j <= y2; j++) { index = (j / 8) * LCD_X_SIZE + i; if (color) { ((bOledPrivate_t *)(pdrv->_private._p))->data[index] |= 1 << (j % 8); } else { ((bOledPrivate_t *)(pdrv->_private._p))->data[index] &= ~(1 << (j % 8)); } } } for (i = 0; i < (LCD_Y_SIZE / 8); i++) { _bOLED_WriteCmd(pdrv, 0xb0 + i); /// page0-page1 _bOLED_WriteCmd(pdrv, 0x00); /// low column start address _bOLED_WriteCmd(pdrv, 0x10); /// high column start address for (j = 0; j < LCD_X_SIZE; j++) { _bOLED_WriteData(pdrv, ((bOledPrivate_t *)(pdrv->_private._p))->data[i * LCD_X_SIZE + j]); } } return 0; } static int _bOLEDCtl(bDriverInterface_t *pdrv, uint8_t cmd, void *param) { int retval = -1; bLcdRectInfo_t *pinfo = (bLcdRectInfo_t *)param; switch (cmd) { case bCMD_FILL_RECT: if (param == NULL) { return -1; } retval = _bOLEDFillRect(pdrv, pinfo->x1, pinfo->y1, pinfo->x2, pinfo->y2, pinfo->color); break; default: break; } return retval; } static int _bOLEDWrite(bDriverInterface_t *pdrv, uint32_t addr, uint8_t *pbuf, uint32_t len) { uint16_t x = addr % LCD_X_SIZE; uint16_t y = addr / LCD_X_SIZE; bLcdWrite_t *pcolor = (bLcdWrite_t *)pbuf; if (y >= LCD_Y_SIZE || pbuf == NULL || len < sizeof(bLcdWrite_t)) { return -1; } _bOLEDDrawPixel(pdrv, x, y, pcolor->color); return 2; } /** * \} */ /** * \addtogroup OLED_Exported_Functions * \{ */ int bOLED_Init(bDriverInterface_t *pdrv) { bDRIVER_STRUCT_INIT(pdrv, DRIVER_NAME, bOLED_Init); pdrv->ctl = _bOLEDCtl; pdrv->write = _bOLEDWrite; pdrv->_private._p = &bOledPrivateTable[pdrv->drv_no]; memset(pdrv->_private._p, 0, sizeof(bOledPrivate_t)); bHalDelayMs(100); _bOLED_WriteCmd(pdrv, 0xAE); /// display off _bOLED_WriteCmd(pdrv, 0x20); /// Set Memory Addressing Mode _bOLED_WriteCmd(pdrv, 0x10); /// 00,Horizontal Addressing Mode;01,Vertical Addressing /// Mode;10,Page Addressing Mode (RESET);11,Invalid _bOLED_WriteCmd(pdrv, 0xb0); /// Set Page Start Address for Page Addressing Mode,0-7 _bOLED_WriteCmd(pdrv, 0xc8); /// Set COM Output Scan Direction _bOLED_WriteCmd(pdrv, 0x00); ///---set low column address _bOLED_WriteCmd(pdrv, 0x10); ///---set high column address _bOLED_WriteCmd(pdrv, 0x40); ///--set start line address _bOLED_WriteCmd(pdrv, 0x81); ///--set contrast control register _bOLED_WriteCmd(pdrv, 0xff); /// 0x00~0xff **** Brightness control _bOLED_WriteCmd(pdrv, 0xa1); ///--set segment re-map 0 to 127 _bOLED_WriteCmd(pdrv, 0xa6); ///--set normal display _bOLED_WriteCmd(pdrv, 0xa8); ///--set multiplex ratio(1 to 64) _bOLED_WriteCmd(pdrv, 0x3F); /// _bOLED_WriteCmd(pdrv, 0xa4); /// 0xa4,Output follows RAM content; /// 0xa5,Output ignores RAM content _bOLED_WriteCmd(pdrv, 0xd3); ///-set display offset _bOLED_WriteCmd(pdrv, 0x00); ///-not offset _bOLED_WriteCmd(pdrv, 0xd5); ///--set display clock divide ratio/oscillator frequency _bOLED_WriteCmd(pdrv, 0xf0); ///--set divide ratio _bOLED_WriteCmd(pdrv, 0xd9); //--set pre-charge period _bOLED_WriteCmd(pdrv, 0x22); /// _bOLED_WriteCmd(pdrv, 0xda); ///--set com pins hardware configuration _bOLED_WriteCmd(pdrv, 0x12); _bOLED_WriteCmd(pdrv, 0xdb); ///--set vcomh _bOLED_WriteCmd(pdrv, 0x20); /// 0x20,0.77xVcc _bOLED_WriteCmd(pdrv, 0x8d); ///--set DC-DC enable _bOLED_WriteCmd(pdrv, 0x14); /// _bOLED_WriteCmd(pdrv, 0xaf); ///--turn on oled panel return 0; } #ifdef BSECTION_NEED_PRAGMA #pragma section driver_init #endif bDRIVER_REG_INIT(B_DRIVER_OLED, bOLED_Init); #ifdef BSECTION_NEED_PRAGMA #pragma section #endif /** * \} */ /** * \} */ /** * \} */ /** * \} */ /************************ Copyright (c) 2019 Bean *****END OF FILE****/