diff --git a/demo/spi/pcd8544_nokia5110_lcd/pcd8544.c b/demo/spi/pcd8544_nokia5110_lcd/pcd8544.c new file mode 100644 index 0000000..6461822 --- /dev/null +++ b/demo/spi/pcd8544_nokia5110_lcd/pcd8544.c @@ -0,0 +1,548 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "pcd8544.h" +#include + +/* PCD8544 data buffer */ +uint8_t PCD8544_currentX = 0; +uint8_t PCD8544_currentY = 0; +static __XDATA uint8_t PCD8544_Buffer[PCD8544_WIDTH * PCD8544_HEIGHT / 8]; + +void PCD8544_WriteData(uint8_t dat) +{ + PCD8544_CS = 0; + SPI_TxRx(dat); + PCD8544_CS = 1; +} + +void PCD8544_WriteSameData(uint8_t dat, uint32_t size) +{ + PCD8544_CS = 0; + do + { + SPI_TxRx(dat); + } while (--size); + PCD8544_CS = 1; +} + +void PCD8544_WriteCommand(uint8_t command) +{ + PCD8544_DC = 0; + PCD8544_WriteData(command); + PCD8544_DC = 1; +} + +static void PCD8544_Transmit(const uint8_t *pDat, uint32_t size) +{ + PCD8544_CS = 0; + do + { + SPI_TxRx(*pDat++); + } while (--size); + PCD8544_CS = 1; +} + +void PCD8544_Reset(void) +{ + PCD8544_RES = 0; + SYS_Delay(5); + PCD8544_RES = 1; +} + +void PCD8544_SetPowerDownMode(HAL_State_t state) +{ + if (state == HAL_State_ON) + PCD8544_WriteCommand(PCD8544_FUNCTIONSET | PCD8544_POWERDOWN); + else + PCD8544_WriteCommand(PCD8544_FUNCTIONSET); +} + +void PCD8544_clear(void) +{ + PCD8544_WriteCommand(0x0c); + PCD8544_WriteCommand(0x80); + PCD8544_WriteSameData(0x00, PCD8544_WIDTH * PCD8544_HEIGHT); +} + +void PCD8544_SetBias(uint8_t val) +{ + val = val & 0x07; + PCD8544_WriteCommand(PCD8544_FUNCTIONSET | PCD8544_EXT_INSTRUCTION); + PCD8544_WriteCommand(PCD8544_SET_BIAS | val); + PCD8544_WriteCommand(PCD8544_FUNCTIONSET); +} + +void PCD8544_SetContrast(uint8_t bias, uint8_t val) +{ + bias = bias & 0x07; + val = val & 0x7F; + // Extended instruction set + PCD8544_WriteCommand(PCD8544_FUNCTIONSET | PCD8544_EXT_INSTRUCTION); + // Set Bias System, value can be [0x03, 0x07] + PCD8544_WriteCommand(PCD8544_SET_BIAS | bias); + // Set Vop, value can be [0x01, 0x7F] + PCD8544_WriteCommand(PCD8544_SET_VOP | val); + // Change back to basic instruction set + PCD8544_WriteCommand(PCD8544_FUNCTIONSET); +} + +void PCD8544_SetTemperatureCoef(uint8_t val) +{ + val = val & 0x03; + PCD8544_WriteCommand(PCD8544_FUNCTIONSET | PCD8544_EXT_INSTRUCTION); + PCD8544_WriteCommand(PCD8544_SET_TEMP | val); + PCD8544_WriteCommand(PCD8544_FUNCTIONSET); +} + +void PCD8544_SetDisplayAllOn(void) +{ + PCD8544_WriteCommand(PCD8544_DISPLAY_CONTROL | PCD8544_DISPLAY_ALLON); +} + +void PCD8544_SetDisplayInverted(void) +{ + PCD8544_WriteCommand(PCD8544_DISPLAY_CONTROL | PCD8544_DISPLAY_INVERTED); +} + +void PCD8544_SetDisplayBlank(void) +{ + PCD8544_WriteCommand(PCD8544_DISPLAY_CONTROL | PCD8544_DISPLAY_BLANK); +} + +void PCD8544_SetDisplayNormal(void) +{ + PCD8544_WriteCommand(PCD8544_DISPLAY_CONTROL | PCD8544_DISPLAY_NORMAL); +} + +void PCD8544_Init(void) +{ + PCD8544_Reset(); + PCD8544_SetContrast(0x06, 0x3F); + PCD8544_SetDisplayNormal(); +} + +void PCD8544_SetBackLightState(HAL_State_t state) +{ + PCD8544_BL = (state == HAL_State_ON)? SET : RESET; +} + +void PCD8544_Fill(uint8_t color) +{ + /* Set memory */ + memset((uint8_t *)PCD8544_Buffer, (color == 0x00) ? 0x00 : 0xFF, sizeof(PCD8544_Buffer)); +} + +void PCD8544_UpdateScreen(void) +{ + uint8_t i = 0, *pt = PCD8544_Buffer; + for (i = 0; i < PCD8544_PAGES; i++) + { + PCD8544_WriteCommand(PCD8544_SET_YADDR | i); + PCD8544_WriteCommand(PCD8544_SET_XADDR); + PCD8544_Transmit(pt + (PCD8544_WIDTH * i), PCD8544_WIDTH); + } + PCD8544_WriteCommand(PCD8544_SET_YADDR); +} + +void PCD8544_DrawPixel(uint8_t x, uint8_t y, uint8_t color) +{ + if (x >= PCD8544_WIDTH || y >= PCD8544_HEIGHT) + { + /* Error */ + return; + } + + if (color == 0x01) + { + PCD8544_Buffer[x + (y / 8) * PCD8544_WIDTH] |= 1 << (y % 8); + } + else + { + PCD8544_Buffer[x + (y / 8) * PCD8544_WIDTH] &= ~(1 << (y % 8)); + } +} + +void PCD8544_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t color) +{ + int16_t dx, dy, sx, sy, err, e2, i, tmp; + + /* Check for overflow */ + if (x0 >= PCD8544_WIDTH) + { + x0 = PCD8544_WIDTH - 1; + } + if (x1 >= PCD8544_WIDTH) + { + x1 = PCD8544_WIDTH - 1; + } + if (y0 >= PCD8544_HEIGHT) + { + y0 = PCD8544_HEIGHT - 1; + } + if (y1 >= PCD8544_HEIGHT) + { + y1 = PCD8544_HEIGHT - 1; + } + + dx = (x0 < x1) ? (x1 - x0) : (x0 - x1); + dy = (y0 < y1) ? (y1 - y0) : (y0 - y1); + sx = (x0 < x1) ? 1 : -1; + sy = (y0 < y1) ? 1 : -1; + err = ((dx > dy) ? dx : -dy) / 2; + + if (dx == 0) + { + if (y1 < y0) + { + tmp = y1; + y1 = y0; + y0 = tmp; + } + + if (x1 < x0) + { + tmp = x1; + x1 = x0; + x0 = tmp; + } + + /* Vertical line */ + for (i = y0; i <= y1; i++) + { + PCD8544_DrawPixel(x0, i, color); + } + return; + } + + if (dy == 0) + { + if (y1 < y0) + { + tmp = y1; + y1 = y0; + y0 = tmp; + } + + if (x1 < x0) + { + tmp = x1; + x1 = x0; + x0 = tmp; + } + + /* Horizontal line */ + for (i = x0; i <= x1; i++) + { + PCD8544_DrawPixel(i, y0, color); + } + return; + } + + while (1) + { + PCD8544_DrawPixel(x0, y0, color); + if (x0 == x1 && y0 == y1) + { + break; + } + e2 = err; + if (e2 > -dx) + { + err -= dy; + x0 += sx; + } + if (e2 < dy) + { + err += dx; + y0 += sy; + } + } +} + +void PCD8544_GotoXY(uint8_t x, uint8_t y) +{ + /* Set write pointers */ + PCD8544_currentX = x; + PCD8544_currentY = y; +} + +char PCD8544_Putc(char ch, FontDef_t* font, uint8_t color) +{ + uint32_t i, b, j, k; + + for (i = 0; i < font->height; i++) + { + for (j = 0; j < font->bytes; j++) + { + b = font->dat[((ch - 32) * font->height + i) * font->bytes + j]; + if (font->order == 0) + { + for (k = 0; k < 8 && k < font->width - j * 8; k++) + { + if ((b << k) & 0x80) + { + PCD8544_DrawPixel(PCD8544_currentX + (j * 8) + k, (PCD8544_currentY + i), (uint8_t) color); + } + else + { + PCD8544_DrawPixel(PCD8544_currentX + (j * 8) + k, (PCD8544_currentY + i), (uint8_t) !color); + } + } + } + else + { + for (k = 0; k < 8 && k < font->width - j * 8; k++) + { + if (b & (0x0001 << k)) + { + PCD8544_DrawPixel(PCD8544_currentX + (j * 8) + k, (PCD8544_currentY + i), (uint8_t) color); + } + else + { + PCD8544_DrawPixel(PCD8544_currentX + (j * 8) + k, (PCD8544_currentY + i), (uint8_t) !color); + } + } + } + } + } + + /* Increase pointer */ + PCD8544_currentX += font->width + 1; + + /* Return character written */ + return ch; +} + +char PCD8544_Puts(char* str, FontDef_t* Font, uint8_t color) +{ + /* Write characters */ + while (*str) + { + /* Write character by character */ + if (PCD8544_Putc(*str, Font, color) != *str) + { + /* Return error */ + return *str; + } + + /* Increase string pointer */ + str++; + } + + /* Everything OK, zero should be returned */ + return *str; +} + + +static __CODE uint8_t Font3x5 [] = { +0x00, 0x00, 0x00, 0x00, 0x00, // SP +0x02, 0x02, 0x02, 0x00, 0x02, // ! +0x05, 0x05, 0x00, 0x00, 0x00, // " +0x05, 0x07, 0x05, 0x07, 0x05, // # +0x06, 0x03, 0x06, 0x03, 0x02, // $ +0x01, 0x04, 0x02, 0x01, 0x04, // % +0x03, 0x03, 0x07, 0x05, 0x06, // & +0x02, 0x02, 0x00, 0x00, 0x00, // ' +0x04, 0x02, 0x02, 0x02, 0x04, // ( +0x01, 0x02, 0x02, 0x02, 0x01, // ) +0x05, 0x02, 0x05, 0x00, 0x00, // * +0x00, 0x02, 0x07, 0x02, 0x00, // + +0x00, 0x00, 0x00, 0x02, 0x01, // , +0x00, 0x00, 0x07, 0x00, 0x00, // - +0x00, 0x00, 0x00, 0x00, 0x02, // . +0x00, 0x04, 0x02, 0x01, 0x00, // / +0x07, 0x05, 0x05, 0x05, 0x07, // 0 +0x02, 0x03, 0x02, 0x02, 0x07, // 1 +0x07, 0x04, 0x07, 0x01, 0x07, // 2 +0x07, 0x04, 0x06, 0x04, 0x07, // 3 +0x05, 0x05, 0x07, 0x04, 0x04, // 4 +0x07, 0x01, 0x07, 0x04, 0x07, // 5 +0x07, 0x01, 0x07, 0x05, 0x07, // 6 +0x07, 0x04, 0x04, 0x04, 0x04, // 7 +0x07, 0x05, 0x07, 0x05, 0x07, // 8 +0x07, 0x05, 0x07, 0x04, 0x07, // 9 +0x00, 0x02, 0x00, 0x02, 0x00, // : +0x00, 0x02, 0x00, 0x02, 0x01, // ; +0x04, 0x02, 0x01, 0x02, 0x04, // < +0x00, 0x07, 0x00, 0x07, 0x00, // = +0x01, 0x02, 0x04, 0x02, 0x01, // > +0x07, 0x04, 0x02, 0x00, 0x02, // ? +0x02, 0x05, 0x07, 0x01, 0x06, // @ +0x02, 0x05, 0x07, 0x05, 0x05, // A +0x03, 0x05, 0x03, 0x05, 0x03, // B +0x06, 0x01, 0x01, 0x01, 0x06, // C +0x03, 0x05, 0x05, 0x05, 0x03, // D +0x07, 0x01, 0x07, 0x01, 0x07, // E +0x07, 0x01, 0x07, 0x01, 0x01, // F +0x06, 0x01, 0x07, 0x05, 0x06, // G +0x05, 0x05, 0x07, 0x05, 0x05, // H +0x07, 0x02, 0x02, 0x02, 0x07, // I +0x04, 0x04, 0x04, 0x05, 0x02, // J +0x05, 0x05, 0x03, 0x05, 0x05, // K +0x01, 0x01, 0x01, 0x01, 0x07, // L +0x05, 0x07, 0x07, 0x05, 0x05, // M +0x05, 0x07, 0x07, 0x07, 0x05, // N +0x02, 0x05, 0x05, 0x05, 0x02, // O +0x03, 0x05, 0x03, 0x01, 0x01, // P +0x02, 0x05, 0x05, 0x05, 0x06, // Q +0x03, 0x05, 0x07, 0x03, 0x05, // R +0x06, 0x01, 0x02, 0x04, 0x03, // S +0x07, 0x02, 0x02, 0x02, 0x02, // T +0x05, 0x05, 0x05, 0x05, 0x02, // U +0x05, 0x05, 0x05, 0x02, 0x02, // V +0x05, 0x05, 0x07, 0x07, 0x05, // W +0x05, 0x05, 0x02, 0x05, 0x05, // X +0x05, 0x05, 0x02, 0x02, 0x02, // Y +0x07, 0x04, 0x02, 0x01, 0x07, // Z +0x03, 0x01, 0x01, 0x01, 0x03, // [ +0x00, 0x01, 0x02, 0x04, 0x00, /* \ */ +0x06, 0x04, 0x04, 0x04, 0x06, // ] +0x02, 0x05, 0x00, 0x00, 0x00, // ^ +0x00, 0x00, 0x00, 0x00, 0x07, // _ +0x01, 0x02, 0x00, 0x00, 0x00, // ` +0x00, 0x03, 0x06, 0x05, 0x07, // a +0x01, 0x03, 0x05, 0x05, 0x03, // b +0x00, 0x06, 0x01, 0x01, 0x06, // c +0x04, 0x06, 0x05, 0x05, 0x06, // d +0x00, 0x06, 0x05, 0x03, 0x06, // e +0x04, 0x02, 0x07, 0x02, 0x02, // f +0x06, 0x05, 0x07, 0x04, 0x02, // g +0x01, 0x03, 0x05, 0x05, 0x05, // h +0x02, 0x00, 0x02, 0x02, 0x02, // i +0x04, 0x00, 0x04, 0x04, 0x03, // j +0x01, 0x05, 0x03, 0x03, 0x05, // k +0x03, 0x02, 0x02, 0x02, 0x07, // l +0x00, 0x07, 0x07, 0x07, 0x05, // m +0x00, 0x03, 0x05, 0x05, 0x05, // n +0x00, 0x02, 0x05, 0x05, 0x02, // o +0x00, 0x03, 0x05, 0x03, 0x01, // p +0x00, 0x06, 0x05, 0x06, 0x04, // q +0x00, 0x06, 0x01, 0x01, 0x01, // r +0x00, 0x06, 0x03, 0x06, 0x03, // s +0x02, 0x07, 0x02, 0x02, 0x06, // t +0x00, 0x05, 0x05, 0x05, 0x06, // u +0x00, 0x05, 0x05, 0x05, 0x02, // v +0x00, 0x05, 0x07, 0x07, 0x07, // w +0x00, 0x05, 0x02, 0x02, 0x05, // x +0x00, 0x05, 0x06, 0x04, 0x06, // y +0x00, 0x07, 0x06, 0x03, 0x07, // z +0x06, 0x02, 0x01, 0x02, 0x06, // { +0x02, 0x02, 0x02, 0x02, 0x02, // | +0x03, 0x02, 0x04, 0x02, 0x03, // } +0x00, 0x06, 0x03, 0x00, 0x00, // ~ +0x07, 0x07, 0x07, 0x07, 0x07, // DEL +}; + +static __CODE uint8_t Font5x7 [] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // +0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, // ! +0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, // " +0x0a, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x0a, // # +0x04, 0x1e, 0x05, 0x0e, 0x14, 0x0f, 0x04, // $ +0x00, 0x19, 0x1a, 0x04, 0x0b, 0x13, 0x00, // % +0x06, 0x09, 0x05, 0x02, 0x15, 0x09, 0x16, // & +0x06, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, // ' +0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, // ( +0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02, // ) +0x00, 0x04, 0x15, 0x0e, 0x15, 0x04, 0x00, // * +0x00, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x00, // + +0x00, 0x00, 0x00, 0x00, 0x0c, 0x08, 0x04, // , +0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, // - +0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, // . +0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, // / +0x0e, 0x11, 0x19, 0x15, 0x13, 0x11, 0x0e, // 0 +0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x0e, // 1 +0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x1f, // 2 +0x1f, 0x08, 0x04, 0x08, 0x10, 0x11, 0x0e, // 3 +0x08, 0x0c, 0x0a, 0x09, 0x1f, 0x08, 0x08, // 4 +0x1f, 0x01, 0x0f, 0x10, 0x10, 0x11, 0x0e, // 5 +0x0c, 0x02, 0x01, 0x0f, 0x11, 0x11, 0x0e, // 6 +0x1f, 0x10, 0x08, 0x04, 0x02, 0x02, 0x02, // 7 +0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e, // 8 +0x0e, 0x11, 0x11, 0x1e, 0x10, 0x08, 0x06, // 9 +0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, // : +0x00, 0x06, 0x06, 0x00, 0x06, 0x04, 0x02, // ; +0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, // < +0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, // = +0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, // > +0x0e, 0x11, 0x10, 0x08, 0x04, 0x00, 0x04, // ? +0x0e, 0x11, 0x10, 0x16, 0x1d, 0x11, 0x0e, // @ +0x0e, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, // A +0x0f, 0x11, 0x11, 0x0f, 0x11, 0x11, 0x0f, // B +0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e, // C +0x07, 0x09, 0x11, 0x11, 0x11, 0x09, 0x07, // D +0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x1f, // E +0x1f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x01, // F +0x0e, 0x11, 0x01, 0x1d, 0x11, 0x11, 0x1e, // G +0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11, // H +0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e, // I +0x1c, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06, // J +0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11, // K +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f, // L +0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11, // M +0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11, // N +0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e, // O +0x0f, 0x11, 0x11, 0x0f, 0x01, 0x01, 0x01, // P +0x0e, 0x11, 0x11, 0x11, 0x15, 0x09, 0x16, // Q +0x0f, 0x11, 0x11, 0x0f, 0x05, 0x09, 0x11, // R +0x1e, 0x01, 0x01, 0x0e, 0x10, 0x10, 0x0f, // S +0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, // T +0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e, // U +0x11, 0x11, 0x11, 0x11, 0x11, 0x0a, 0x04, // V +0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0a, // W +0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11, // X +0x11, 0x11, 0x11, 0x0a, 0x04, 0x04, 0x04, // Y +0x1f, 0x10, 0x08, 0x04, 0x02, 0x01, 0x1f, // Z +0x0e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0e, // [ +0x15, 0x0a, 0x15, 0x0a, 0x15, 0x0a, 0x15, /* \ */ +0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, // ] +0x04, 0x0a, 0x11, 0x00, 0x00, 0x00, 0x00, // ^ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, // _ +0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, // ` +0x00, 0x00, 0x0e, 0x10, 0x1e, 0x11, 0x1e, // a +0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x0f, // b +0x00, 0x00, 0x0e, 0x01, 0x01, 0x11, 0x0e, // c +0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1e, // d +0x00, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x0e, // e +0x0c, 0x12, 0x02, 0x07, 0x02, 0x02, 0x02, // f +0x00, 0x1e, 0x11, 0x11, 0x1e, 0x10, 0x0e, // g +0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, // h +0x04, 0x00, 0x06, 0x04, 0x04, 0x04, 0x0e, // i +0x08, 0x00, 0x0c, 0x08, 0x08, 0x09, 0x06, // j +0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, // k +0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e, // l +0x00, 0x00, 0x0b, 0x15, 0x15, 0x11, 0x11, // m +0x00, 0x00, 0x0d, 0x13, 0x11, 0x11, 0x11, // n +0x00, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e, // o +0x00, 0x00, 0x0f, 0x11, 0x0f, 0x01, 0x01, // p +0x00, 0x00, 0x16, 0x19, 0x1e, 0x10, 0x10, // q +0x00, 0x00, 0x0d, 0x13, 0x01, 0x01, 0x01, // r +0x00, 0x00, 0x0e, 0x01, 0x0e, 0x10, 0x0f, // s +0x02, 0x02, 0x07, 0x02, 0x02, 0x12, 0x0c, // t +0x00, 0x00, 0x11, 0x11, 0x11, 0x19, 0x16, // u +0x00, 0x00, 0x11, 0x11, 0x11, 0x0a, 0x04, // v +0x00, 0x00, 0x11, 0x11, 0x15, 0x15, 0x0a, // w +0x00, 0x00, 0x11, 0x0a, 0x04, 0x0a, 0x11, // x +0x00, 0x00, 0x11, 0x11, 0x1e, 0x10, 0x0e, // y +0x00, 0x00, 0x1f, 0x08, 0x04, 0x02, 0x1f, // z +0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, // { +0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, // | +0x02, 0x04, 0x04, 0x08, 0x04, 0x04, 0x02, // } +0x00, 0x00, 0x02, 0x15, 0x08, 0x00, 0x00, // ~ +0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00, // +}; + +__CODE FontDef_t Font_3x5 = {3, 5, 1, 1, Font3x5}; +__CODE FontDef_t Font_5x7 = {5, 7, 1, 1, Font5x7}; \ No newline at end of file diff --git a/demo/spi/pcd8544_nokia5110_lcd/pcd8544.h b/demo/spi/pcd8544_nokia5110_lcd/pcd8544.h new file mode 100644 index 0000000..af5e24c --- /dev/null +++ b/demo/spi/pcd8544_nokia5110_lcd/pcd8544.h @@ -0,0 +1,232 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __FW_PCD8544__ +#define __FW_PCD8544__ + +#include "fw_hal.h" + +/** + * PCD8544 + * + * Philips – PCD8544 is a single-chip low-power CMOS LCD driver controller + * The chip is designed to drive a graphic display of 84×48 pixels with SPI interface. + * Display Data RAM = 6 banks x 84 segments x 8 bits = 4032 bits = 504 bytes + * Each bank contains 84 columns/segments (from 0 to 83) + * Each column can store 8 bits of data (from 0 to 7) +*/ + +#define PCD8544_CS P35 +#define PCD8544_MOSI P34 +#define PCD8544_SCK P32 +#define PCD8544_RES P37 +#define PCD8544_DC P36 +#define PCD8544_BL P12 + +// X width +#define PCD8544_WIDTH 84 +// Y height +#define PCD8544_HEIGHT 48 +// Display RAM Pages +#define PCD8544_PAGES 6 + +#define PCD8544_FUNCTIONSET 0x20 // Function set +#define PCD8544_POWERDOWN 0x04 // Function set, power down mode +#define PCD8544_ENTRYMODE 0x02 // Function set, entry mode (vertical addressing) +#define PCD8544_EXT_INSTRUCTION 0x01 // Function set, extended instruction set control + +#define PCD8544_DISPLAY_CONTROL 0x08 // Basic instruction set - Set display configuration +#define PCD8544_DISPLAY_BLANK 0x00 // Display control, blank +#define PCD8544_DISPLAY_NORMAL 0x04 // Display control, normal mode +#define PCD8544_DISPLAY_ALLON 0x01 // Display control, all segments on +#define PCD8544_DISPLAY_INVERTED 0x05 // Display control, inverse mode + +#define PCD8544_SET_YADDR 0x40 // Basic instruction set - Set Y address of RAM, 0 <= Y <= 5 +#define PCD8544_SET_XADDR 0x80 // Basic instruction set - Set X address of RAM, 0 <= X <= 83 + +#define PCD8544_SET_TEMP 0x04 // Extended instruction set - Set temperature coefficient +#define PCD8544_SET_BIAS 0x10 // Extended instruction set - Set bias system +#define PCD8544_SET_VOP 0x80 // Extended instruction set - Write Vop to register + +typedef struct { + uint8_t width; + uint8_t height; + uint8_t order; + uint8_t bytes; + const uint8_t *dat; +} FontDef_t; + +extern __CODE FontDef_t Font_3x5; +extern __CODE FontDef_t Font_5x7; + +/** + * @brief Turn PCD8544 LCD backlight on or off + * @param state HAL_State_ON:on, HAL_State_OFF:off + * @retval None + */ +void PCD8544_SetBackLightState(HAL_State_t state); + +/** + * @brief Writes single byte data to PCD8544 + * @param dat: data to be written + * @retval None + */ +void PCD8544_WriteData(uint8_t dat); +void PCD8544_WriteSameData(uint8_t dat, uint32_t size); + +/** + * @brief Write a single byte command to PCD8544 + * @param command: command to be written + * @retval None + */ +void PCD8544_WriteCommand(uint8_t command); + +/** + * @brief Hardware reset PCD8544 LCD + * @param None + * @retval None + */ +void PCD8544_Reset(void); + +/** + * @brief Powerdown mode control + * @param state HAL_State_ON:powerdown mode, HAL_State_OFF:work mode + * @retval None + */ +void PCD8544_SetPowerDownMode(HAL_State_t state); + +/** + * @brief Set bias system level + * @param val bias value, [0x00,0x07], small value may lead to totally blank display + * @retval None + */ +void PCD8544_SetBias(uint8_t val); + +/** + * @brief Set TCx (temperature coefficient) + * @param val TCx value, [0x00, 0x03] + * @retval None + */ +void PCD8544_SetTemperatureCoef(uint8_t val); + +/** + * @brief Set the contrast level by adjusting Vlcd + * @param bias, bias value, [0x00,0x07], small value may lead to totally blank display + * @param val contrast level, [0x00, 0x7F] + * @retval None + */ +void PCD8544_SetContrast(uint8_t bias, uint8_t val); + +/** + * @brief Set PCD8544 To Turn On All Segments + * @param None + * @retval None + */ +void PCD8544_SetDisplayAllOn(void); + +/** + * @brief Set PCD8544 Display Mode to Inverted + * @param None + * @retval None + */ +void PCD8544_SetDisplayInverted(void); + +/** + * @brief Set PCD8544 Display Mode to Blank + * @param None + * @retval None + */ +void PCD8544_SetDisplayBlank(void); + +/** + * @brief Set PCD8544 Display Mode to Normal + * @param None + * @retval None + */ +void PCD8544_SetDisplayNormal(void); + +/** + * @brief Initializes PCD8544 Display + * @param None + * @retval None + */ +void PCD8544_Init(void); + +/** + * @brief Fills entire LCD with specified color + * @note @ref PCD8544_UpdateScreen() must be called after that in order to see updates + * @param Color: Color to be used for screen fill, 0x00 or 0x01 + * @retval None + */ +void PCD8544_Fill(uint8_t color); + +/** + * @brief Update LCD display with changes + * @note Call this function each time when display is changed + * @param None + * @retval None + */ +void PCD8544_UpdateScreen(void); + +/** + * @brief Draws pixel at desired location + * @note @ref PCD8544_UpdateScreen() must called after that in order to show updates + * @param x: X location, value between [0, PCD8544_WIDTH) + * @param y: Y location, value between [0, PCD8544_HEIGHT) + * @param color: Color to be used for screen fill, 0x00 or 0x01 + * @retval None + */ +void PCD8544_DrawPixel(uint8_t x, uint8_t y, uint8_t color); + +/** + * @brief Draws line on LCD + * @note @ref PCD8544_UpdateScreen() must be called after that in order to show updates + * @param x0: Line X start point, value between [0, PCD8544_WIDTH) + * @param y0: Line Y start point, value between [0, PCD8544_HEIGHT) + * @param x1: Line X end point, value between [0, PCD8544_WIDTH) + * @param y1: Line Y end point, value between [0, PCD8544_HEIGHT) + * @param color: Color to be used. 0x00 or 0x01 + * @retval None + */ +void PCD8544_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t color); + +/** + * @brief Sets cursor pointer to desired location for strings + * @param x: X location, value between [0, PCD8544_WIDTH) + * @param y: Y location, value between [0, PCD8544_HEIGHT) + * @retval None + */ +void PCD8544_GotoXY(uint8_t x, uint8_t y); + +/** + * @brief Put one character to internal RAM + * @note @ref PCD8544_UpdateScreen() must be called after that in order to show updates + * @param ch: Character to be written + * @param *Font: Pointer to @ref FontDef_t structure with used font + * @param color: Color used for drawing. 0x00 or 0x01 + * @retval value of ch + */ +char PCD8544_Putc(char ch, FontDef_t* font, uint8_t color); + +/** + * @brief Puts string to internal RAM + * @note @ref PCD8544_UpdateScreen() must be called after that in order to show updates + * @param *str: String to be written + * @param *Font: Pointer to @ref FontDef_t structure with used font + * @param color: Color used for drawing. 0x00 or 0x01 + * @retval Zero on success or character value when function failed + */ +char PCD8544_Puts(char* str, FontDef_t* Font, uint8_t color); + +#endif // __PCD8544_H_ diff --git a/demo/spi/pcd8544_nokia5110_lcd/pcd8544_stc8h3k.c b/demo/spi/pcd8544_nokia5110_lcd/pcd8544_stc8h3k.c new file mode 100644 index 0000000..d7fc919 --- /dev/null +++ b/demo/spi/pcd8544_nokia5110_lcd/pcd8544_stc8h3k.c @@ -0,0 +1,159 @@ +// Copyright 2021 IOsetting +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*** + * Demo: PCD8544 - Nokia5110 84x48 LCD + * Board: STC8H3K32 + * + * P37 -> RES, RESET + * P36 -> DC, A0 + * P35 -> CE, Chip Select + * P32 -> SCK, SCL, CLK, Clock + * P12 -> BL, Backlight + * P34 -> MOSI, Din + * GND -> GND + * 3.3V -> VCC + */ + +#include "fw_hal.h" +#include "pcd8544.h" + + +void SPI_Init(void) +{ + SPI_SetClockPrescaler(SPI_ClockPreScaler_16); + // Clock is low when idle + SPI_SetClockPolarity(HAL_State_OFF); + // Data transfer is driven by lower SS pin + SPI_SetClockPhase(SPI_ClockPhase_LeadingEdge); + // MSB first + SPI_SetDataOrder(SPI_DataOrder_MSB); + // Define the output pins + SPI_SetPort(SPI_AlterPort_P35_P34_P33_P32); + // Ignore SS pin, use MSTR to swith between master/slave mode + SPI_IgnoreSlaveSelect(HAL_State_ON); + // Master mode + SPI_SetMasterMode(HAL_State_ON); + // Start SPI + SPI_SetEnabled(HAL_State_ON); +} + +void GPIO_Init(void) +{ + // Configure GPIO pins before SPI and device + // DIN(P34) + GPIO_P3_SetMode(GPIO_Pin_4, GPIO_Mode_InOut_QBD); + // SCLK(P32) + GPIO_P3_SetMode(GPIO_Pin_2|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7, GPIO_Mode_Output_PP); + GPIO_P1_SetMode(GPIO_Pin_2, GPIO_Mode_Output_PP); +} + +int main(void) +{ + uint8_t y1, y2; + + SYS_SetClock(); + GPIO_Init(); + SPI_Init(); + PCD8544_Init(); + + while(1) + { + PCD8544_SetBackLightState(HAL_State_ON); + SYS_Delay(500); + PCD8544_SetDisplayAllOn(); + SYS_Delay(200); + PCD8544_SetDisplayInverted(); + SYS_Delay(200); + PCD8544_SetDisplayBlank(); + SYS_Delay(200); + PCD8544_SetDisplayNormal(); + SYS_Delay(200); + PCD8544_Fill(0); + + PCD8544_DrawLine(0, 0, 83, 0, 1); + PCD8544_DrawLine(0, 0, 0, 47, 1); + PCD8544_DrawLine(83, 0, 83, 47, 1); + PCD8544_DrawLine(0, 47, 83, 47, 1); + PCD8544_UpdateScreen(); + + PCD8544_GotoXY(3, 3); + PCD8544_Puts("LCD:PCD8544", &Font_5x7, 1); + PCD8544_GotoXY(3, 11); + PCD8544_Puts("STC8 FwLib", &Font_5x7, 1); + PCD8544_GotoXY(3, 19); + PCD8544_Puts("A demo of PCD8544", &Font_3x5, 1); + PCD8544_GotoXY(3, 25); + PCD8544_Puts("Font 3x5: 01234567890", &Font_3x5, 1); + PCD8544_UpdateScreen(); + SYS_Delay(500); + PCD8544_SetPowerDownMode(HAL_State_ON); + SYS_Delay(1000); + PCD8544_SetPowerDownMode(HAL_State_OFF); + SYS_Delay(2000); + + PCD8544_SetDisplayInverted(); + SYS_Delay(1000); + PCD8544_SetDisplayNormal(); + SYS_Delay(1000); + + for (y1 = 0x05; y1 < 0x08; y1++) + { + for (y2 = 0x00; y2 < 0x60; y2+=2) + { + PCD8544_GotoXY(3, 32); + PCD8544_Putc(HEX_TABLE[y1 >> 4], &Font_5x7, 1); + PCD8544_Putc(HEX_TABLE[y1 & 0x0F], &Font_5x7, 1); + PCD8544_Putc(' ', &Font_5x7, 1); + PCD8544_Putc(HEX_TABLE[y2 >> 4], &Font_5x7, 1); + PCD8544_Putc(HEX_TABLE[y2 & 0x0F], &Font_5x7, 1); + PCD8544_UpdateScreen(); + PCD8544_SetContrast(y1, y2); + SYS_Delay(100); + } + SYS_Delay(1000); + } + PCD8544_SetContrast(0x06, 0x3F); + PCD8544_Fill(0); + + y1 = 47, y2 = 0; + while (y1 < 0xF0) + { + PCD8544_DrawLine(0, y1, 83, y2, 1); + PCD8544_UpdateScreen(); + y1 -= 2; + y2 += 2; + SYS_Delay(100); + } + SYS_Delay(1000); + PCD8544_Fill(0); + + y1 = 83, y2 = 0; + while (y1 < 0xF0) + { + PCD8544_DrawLine(y1, 0, y2, 47, 1); + PCD8544_UpdateScreen(); + y1 -= 2; + y2 += 2; + SYS_Delay(100); + } + SYS_Delay(1000); + + PCD8544_Fill(0); + PCD8544_UpdateScreen(); + SYS_Delay(1000); + PCD8544_SetBackLightState(HAL_State_OFF); + SYS_Delay(1000); + } +} diff --git a/demo/spi/st7567/st7567.h b/demo/spi/st7567/st7567.h index 628c4f0..bdc66bb 100644 --- a/demo/spi/st7567/st7567.h +++ b/demo/spi/st7567/st7567.h @@ -157,16 +157,16 @@ extern __CODE FontDef_t Font_3x5; extern __CODE FontDef_t Font_5x7; /** - * @brief Writes single byte data to ST7567 - * @param dat: data to be written + * @brief Write a single byte data to ST7567 + * @param dat: data * @retval None */ void ST7567_WriteData(uint8_t dat); void ST7567_WriteSameData(uint8_t dat, uint32_t size); /** - * @brief Writes single byte command to ST7567 - * @param command: command to be written + * @brief Write a single byte command to ST7567 + * @param command: command * @retval None */ void ST7567_WriteCommand(uint8_t command); @@ -208,8 +208,8 @@ void ST7567_SetBackLightState(HAL_State_t state); void ST7567_SetContrast(uint8_t val); /** - * @brief Updates buffer from internal RAM to LCD - * @note This function must be called each time you do some changes to LCD, to update buffer from RAM to LCD + * @brief Update LCD display with buffer changes + * @note Call this function each time when display is changed * @param None * @retval None */ @@ -224,8 +224,8 @@ void ST7567_UpdateScreen(void); void ST7567_ToggleInvert(void); /** - * @brief Fills entire LCD with desired color - * @note @ref ST7567_UpdateScreen() must be called after that in order to see updated LCD screen + * @brief Fills entire LCD with specified color + * @note @ref ST7567_UpdateScreen() must be called after that in order to see updates * @param Color: Color to be used for screen fill, ST7567_COLOR_FRONT or ST7567_COLOR_BACK * @retval None */ @@ -233,7 +233,7 @@ void ST7567_Fill(uint8_t Color); /** * @brief Draws pixel at desired location - * @note @ref ST7567_UpdateScreen() must called after that in order to see updated LCD screen + * @note @ref ST7567_UpdateScreen() must called after that in order to see updates * @param x: X location. This parameter can be a value between 0 and ST7567_WIDTH - 1 * @param y: Y location. This parameter can be a value between 0 and ST7567_HEIGHT - 1 * @param color: Color to be used for screen fill. This parameter can be a value of @ref ST7567_COLOR_t enumeration diff --git a/include/fw_uart.h b/include/fw_uart.h index 81b3caf..168b570 100644 --- a/include/fw_uart.h +++ b/include/fw_uart.h @@ -21,6 +21,8 @@ #define UART_RX_BUFF_SIZE 0x20 +extern __CODE char HEX_TABLE[16]; + int16_t UART_Timer_InitValueCalculate(uint32_t sysclk, HAL_State_t _1TMode, uint32_t baudrate); diff --git a/src/fw_uart.c b/src/fw_uart.c index 98e8595..ad63951 100644 --- a/src/fw_uart.c +++ b/src/fw_uart.c @@ -16,7 +16,6 @@ #include "fw_tim.h" #include "fw_sys.h" -__CODE char hexTable[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; __IDATA char wptr, rptr, UART1_RxBuffer[UART_RX_BUFF_SIZE]; __BIT busy; @@ -100,8 +99,8 @@ void UART1_IntTxChar(char dat) void UART1_IntTxHex(uint8_t hex) { - UART1_IntTxChar(hexTable[hex >> 4]); - UART1_IntTxChar(hexTable[hex & 0xF]); + UART1_IntTxChar(HEX_TABLE[hex >> 4]); + UART1_IntTxChar(HEX_TABLE[hex & 0xF]); } void UART1_IntTxString(uint8_t *str) @@ -118,8 +117,8 @@ void UART1_TxChar(char dat) void UART1_TxHex(uint8_t hex) { - UART1_TxChar(hexTable[hex >> 4]); - UART1_TxChar(hexTable[hex & 0xF]); + UART1_TxChar(HEX_TABLE[hex >> 4]); + UART1_TxChar(HEX_TABLE[hex & 0xF]); } void UART1_TxString(uint8_t *str) @@ -160,8 +159,8 @@ void UART2_TxChar(char dat) void UART2_TxHex(uint8_t hex) { - UART2_TxChar(hexTable[hex >> 4]); - UART2_TxChar(hexTable[hex & 0xF]); + UART2_TxChar(HEX_TABLE[hex >> 4]); + UART2_TxChar(HEX_TABLE[hex & 0xF]); } void UART2_TxString(uint8_t *str) diff --git a/src/fw_util.c b/src/fw_util.c index b1eec9b..113ff07 100644 --- a/src/fw_util.c +++ b/src/fw_util.c @@ -15,6 +15,7 @@ #include "fw_util.h" #include "fw_sys.h" +__CODE char HEX_TABLE[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; void UTIL_Uart1_24M_9600_Init(void) {