From a46612e2c3945d583fa37def8a8540d79edf5cf7 Mon Sep 17 00:00:00 2001 From: IOsetting Date: Sun, 2 Jan 2022 17:46:54 +0800 Subject: [PATCH] feat: demo of spi - st7567 12864 lcd --- demo/spi/{ => max7219}/max7219_8x8led.c | 0 demo/spi/{ => max7219}/max7219_8x8led_4in1.c | 0 .../max7219_8x8led_4in1_stc8g1k08.c | 0 .../{ => max7219}/max7219_8x8led_stc8g1k08.c | 0 demo/spi/st7567/st7567.c | 540 ++++++++++++++++++ demo/spi/st7567/st7567.h | 274 +++++++++ demo/spi/st7567/st7567_stc8h3k.c | 147 +++++ 7 files changed, 961 insertions(+) rename demo/spi/{ => max7219}/max7219_8x8led.c (100%) rename demo/spi/{ => max7219}/max7219_8x8led_4in1.c (100%) rename demo/spi/{ => max7219}/max7219_8x8led_4in1_stc8g1k08.c (100%) rename demo/spi/{ => max7219}/max7219_8x8led_stc8g1k08.c (100%) create mode 100644 demo/spi/st7567/st7567.c create mode 100644 demo/spi/st7567/st7567.h create mode 100644 demo/spi/st7567/st7567_stc8h3k.c diff --git a/demo/spi/max7219_8x8led.c b/demo/spi/max7219/max7219_8x8led.c similarity index 100% rename from demo/spi/max7219_8x8led.c rename to demo/spi/max7219/max7219_8x8led.c diff --git a/demo/spi/max7219_8x8led_4in1.c b/demo/spi/max7219/max7219_8x8led_4in1.c similarity index 100% rename from demo/spi/max7219_8x8led_4in1.c rename to demo/spi/max7219/max7219_8x8led_4in1.c diff --git a/demo/spi/max7219_8x8led_4in1_stc8g1k08.c b/demo/spi/max7219/max7219_8x8led_4in1_stc8g1k08.c similarity index 100% rename from demo/spi/max7219_8x8led_4in1_stc8g1k08.c rename to demo/spi/max7219/max7219_8x8led_4in1_stc8g1k08.c diff --git a/demo/spi/max7219_8x8led_stc8g1k08.c b/demo/spi/max7219/max7219_8x8led_stc8g1k08.c similarity index 100% rename from demo/spi/max7219_8x8led_stc8g1k08.c rename to demo/spi/max7219/max7219_8x8led_stc8g1k08.c diff --git a/demo/spi/st7567/st7567.c b/demo/spi/st7567/st7567.c new file mode 100644 index 0000000..657efaa --- /dev/null +++ b/demo/spi/st7567/st7567.c @@ -0,0 +1,540 @@ +// 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 "st7567.h" +#include + +/* Absolute value */ +#define ABS(x) ((x) > 0 ? (x) : -(x)) + +/* ST7567 data buffer */ +static __XDATA uint8_t ST7567_Buffer_all[(ST7567_WIDTH + ST7567_SEG_EXPAND) * ST7567_HEIGHT / 8]; + +/* Private ST7567 structure */ +typedef struct { + uint16_t CurrentX; + uint16_t CurrentY; + uint8_t Inverted; + uint8_t Initialized; +} ST7567_t; + +/* Private variable */ +static __XDATA ST7567_t ST7567; + + +static void ST7567_TransmitByte(uint8_t dat) +{ + ST7567_CS = 0; + SPI_TxRx(dat); + ST7567_CS = 1; +} + +static void ST7567_Transmit(const uint8_t *pData, uint32_t Size) +{ + ST7567_CS = 0; + while (Size--) + { + SPI_TxRx(*pData++); + } + ST7567_CS = 1; +} + +void ST7567_WriteCommand(uint8_t command) +{ + ST7567_DC = 0; + ST7567_TransmitByte(command); + ST7567_DC = 1; +} + +void ST7567_WriteData(uint8_t dat) +{ + ST7567_TransmitByte(dat); +} + +void ST7567_Init(void) +{ + ST7567_Reset(); + ST7567_BackLight_On(); + + ST7567_WriteCommand(ST7567_RESET); + // adjust contrast + ST7567_WriteCommand(ST7567_SET_EV); + ST7567_WriteCommand(ST7567_SET_EV_MASK & 0x20); + // adjust regular voltage. LCD may fail to display if it is set too low. + ST7567_WriteCommand(ST7567_REGULATION_RATIO | ST7567_REGULATION_RATIO_5_0); + ST7567_WriteCommand(ST7567_BIAS_1_9); + ST7567_WriteCommand(ST7567_X_ORIENT); + ST7567_WriteCommand(ST7567_Y_ORIENT); + ST7567_WriteCommand(ST7567_INVERSE_DISPLAY_OFF); + // Start from line 0 + ST7567_WriteCommand(ST7567_SET_START_LINE | (0x00 & ST7567_SET_START_LINE_MASK)); + // Start from page 0 + ST7567_WriteCommand(ST7567_SET_PAGE_ADDRESS | (0x00 & ST7567_SET_PAGE_ADDRESS_MASK)); + // Start from column 0 + ST7567_WriteCommand(ST7567_SET_COLUMN_ADDRESS_MSB | (0x00 & ST7567_SET_COLUMN_ADDRESS_MSB_MASK)); + ST7567_WriteCommand(ST7567_SET_COLUMN_ADDRESS_LSB | (0x00 & ST7567_SET_COLUMN_ADDRESS_LSB_MASK)); + // power control, LCD may fail to display if it is not properly set. + // recommend to set them all + ST7567_WriteCommand(ST7567_POWER_CONTROL + |ST7567_POWER_CONTROL_VB + |ST7567_POWER_CONTROL_VR + |ST7567_POWER_CONTROL_VF); + ST7567_WriteCommand(ST7567_DISPLAY_ON); + ST7567_WriteCommand(ST7567_ALL_PIXEL_NORMAL); +} + +void ST7567_Reset(void) +{ + ST7567_RES = 0; + SYS_Delay(5); + ST7567_RES = 1; +} + +void ST7567_BackLight_On(void) +{ + ST7567_BL = 1; +} + +void ST7567_BackLight_Off(void) +{ + ST7567_BL = 0; +} + +void ST7567_SetContrast(uint8_t val) +{ + ST7567_WriteCommand(ST7567_SET_EV); + ST7567_WriteCommand(ST7567_SET_EV_MASK & val); +} + +void ST7567_UpdateScreen(void) +{ + ST7567_WriteCommand(ST7567_SET_PAGE_ADDRESS | (0x00 & ST7567_SET_PAGE_ADDRESS_MASK)); + ST7567_WriteCommand(ST7567_SET_COLUMN_ADDRESS_MSB); + ST7567_WriteCommand(ST7567_SET_COLUMN_ADDRESS_LSB); + ST7567_Transmit(ST7567_Buffer_all, sizeof(ST7567_Buffer_all)); +} + +void ST7567_ToggleInvert(void) +{ + /* Toggle invert */ + ST7567.Inverted = !ST7567.Inverted; + if (ST7567.Inverted) + { + ST7567_WriteCommand(ST7567_INVERSE_DISPLAY_ON); + } + else + { + ST7567_WriteCommand(ST7567_INVERSE_DISPLAY_OFF); + } +} + +void ST7567_Fill(uint8_t color) +{ + /* Set memory */ + memset(ST7567_Buffer_all, (color == ST7567_COLOR_BACK) ? 0x00 : 0xFF, sizeof(ST7567_Buffer_all)); +} + +void ST7567_DrawPixel(uint16_t x, uint16_t y, uint8_t color) +{ + if (x >= ST7567_WIDTH || y >= ST7567_HEIGHT) + { + /* Error */ + return; + } + + if (color == ST7567_COLOR_FRONT) + { + ST7567_Buffer_all[ST7567_X_OFFSET + x + (y / 8) * (ST7567_WIDTH + ST7567_SEG_EXPAND)] |= 1 << (y % 8); + } + else + { + ST7567_Buffer_all[ST7567_X_OFFSET + x + (y / 8) * (ST7567_WIDTH + ST7567_SEG_EXPAND)] &= ~(1 << (y % 8)); + } +} + +void ST7567_GotoXY(uint16_t x, uint16_t y) +{ + /* Set write pointers */ + ST7567.CurrentX = x; + ST7567.CurrentY = y; +} + +char ST7567_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) + { + ST7567_DrawPixel(ST7567.CurrentX + (j * 8) + k, (ST7567.CurrentY + i), (uint8_t) color); + } + else + { + ST7567_DrawPixel(ST7567.CurrentX + (j * 8) + k, (ST7567.CurrentY + i), (uint8_t) !color); + } + } + } + else + { + for (k = 0; k < 8 && k < font->width - j * 8; k++) + { + if (b & (0x0001 << k)) + { + ST7567_DrawPixel(ST7567.CurrentX + (j * 8) + k, (ST7567.CurrentY + i), (uint8_t) color); + } + else + { + ST7567_DrawPixel(ST7567.CurrentX + (j * 8) + k, (ST7567.CurrentY + i), (uint8_t) !color); + } + } + } + } + } + + /* Increase pointer */ + ST7567.CurrentX += font->width + 1; + + /* Return character written */ + return ch; +} + +char ST7567_Puts(char* str, FontDef_t* Font, uint8_t color) +{ + /* Write characters */ + while (*str) + { + /* Write character by character */ + if (ST7567_Putc(*str, Font, color) != *str) + { + /* Return error */ + return *str; + } + + /* Increase string pointer */ + str++; + } + + /* Everything OK, zero should be returned */ + return *str; +} + +void ST7567_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t c) +{ + int16_t dx, dy, sx, sy, err, e2, i, tmp; + + /* Check for overflow */ + if (x0 >= ST7567_WIDTH) + { + x0 = ST7567_WIDTH - 1; + } + if (x1 >= ST7567_WIDTH) + { + x1 = ST7567_WIDTH - 1; + } + if (y0 >= ST7567_HEIGHT) + { + y0 = ST7567_HEIGHT - 1; + } + if (y1 >= ST7567_HEIGHT) + { + y1 = ST7567_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++) + { + ST7567_DrawPixel(x0, i, c); + } + + /* Return from function */ + 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++) + { + ST7567_DrawPixel(i, y0, c); + } + + /* Return from function */ + return; + } + + while (1) + { + ST7567_DrawPixel(x0, y0, c); + if (x0 == x1 && y0 == y1) + { + break; + } + e2 = err; + if (e2 > -dx) + { + err -= dy; + x0 += sx; + } + if (e2 < dy) + { + err += dx; + y0 += sy; + } + } +} + +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}; diff --git a/demo/spi/st7567/st7567.h b/demo/spi/st7567/st7567.h new file mode 100644 index 0000000..63ea89a --- /dev/null +++ b/demo/spi/st7567/st7567.h @@ -0,0 +1,274 @@ +// 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 __ST7567_H_ +#define __ST7567_H_ + +#include "fw_hal.h" + + +#define ST7567_CS P35 +#define ST7567_MOSI P34 +#define ST7567_SCK P32 +#define ST7567_RES P37 +#define ST7567_DC P36 +#define ST7567_BL P12 + +// X width +#define ST7567_WIDTH 128 +// Y height +#define ST7567_HEIGHT 64 +// Additional bytes in each row +#define ST7567_SEG_EXPAND 4 +// X orientation +#define ST7567_X_ORIENT ST7567_SEG_DIRECTION_NORMAL +// Y orientation +#define ST7567_Y_ORIENT ST7567_COM_DIRECTION_REVERSE + + +/* ST7567 commands definitions */ +#define ST7567_DISPLAY_OFF 0xAE /* 0xae: Display OFF (sleep mode) */ +#define ST7567_DISPLAY_ON 0xAF /* 0xaf: Display ON in normal mode */ + +#define ST7567_SET_START_LINE 0x40 /* 0x40-7f: Set display start line */ +#define ST7567_SET_START_LINE_MASK 0x3f + +#define ST7567_SET_PAGE_ADDRESS 0xB0 /* 0xb0-b7: Set page start address, 0 - 7 */ +#define ST7567_SET_PAGE_ADDRESS_MASK 0x07 + +#define ST7567_SET_COLUMN_ADDRESS_MSB 0x10 /* 0x10-0x1f: Set 8bit column address - high 4 bits */ +#define ST7567_SET_COLUMN_ADDRESS_MSB_MASK 0x0f + +#define ST7567_SET_COLUMN_ADDRESS_LSB 0x00 /* 0x00-0x0f: Set 8bit column address - low 4 bits */ +#define ST7567_SET_COLUMN_ADDRESS_LSB_MASK 0x0F + +/** + * SEG: 0 - 131 +*/ +#define ST7567_SEG_DIRECTION_NORMAL 0xA0 /* 0xa0: Column address 0 is mapped to SEG0 */ +#define ST7567_SEG_DIRECTION_REVERSE 0xA1 /* 0xa1: Column address 128 is mapped to SEG0 */ + +/** + * COM: 0 - 63 +*/ +#define ST7567_COM_DIRECTION_NORMAL 0xC0 /* 0xc0: Set COM output direction, normal mode */ +#define ST7567_COM_DIRECTION_REVERSE 0xC8 /* 0xc8: Set COM output direction, reverse mode */ + +#define ST7567_INVERSE_DISPLAY_OFF 0xA6 /* 0xa6: Normal display */ +#define ST7567_INVERSE_DISPLAY_ON 0xA7 /* 0xa7: Inverse display */ + +#define ST7567_ALL_PIXEL_ON 0xA5 /* 0xa5: Entire display ON */ +#define ST7567_ALL_PIXEL_NORMAL 0xA4 /* 0xa4: Resume to RAM content display */ + +#define ST7567_BIAS_1_9 0xA2 /* 0xa2: Select BIAS setting 1/9 */ +#define ST7567_BIAS_1_7 0xA3 /* 0xa3: Select BIAS setting 1/7 */ + +#define ST7567_READ_MODIFY_WRITE_START 0xE0 /* 0xe0: Enter the Read Modify Write mode */ +#define ST7567_READ_MODIFY_WRITE_END 0xEE /* 0xee: Leave the Read Modify Write mode */ +#define ST7567_RESET 0xE2 /* 0xe2: Software RESET */ + +/** + * This instruction controls the built-in power circuits. + * Typically, these 3 flags are turned ON at the same time. +*/ +#define ST7567_POWER_CONTROL 0x28 +#define ST7567_POWER_CONTROL_VF 0x01 +#define ST7567_POWER_CONTROL_VR 0x02 +#define ST7567_POWER_CONTROL_VB 0x04 + +/** + * The operation voltage (V0) calculation formula is shown below: + * (RR comes from Regulation Ratio, EV comes from EV[5:0]) + * V0 = RR X [ 1 – (63 – EV) / 162 ] X 2.1, or + * V0 = RR X [ ( 99 + EV ) / 162 ] X 2.1 +*/ +#define ST7567_REGULATION_RATIO 0x20 +#define ST7567_REGULATION_RATIO_3_0 0x00 +#define ST7567_REGULATION_RATIO_3_5 0x01 +#define ST7567_REGULATION_RATIO_4_0 0x02 +#define ST7567_REGULATION_RATIO_4_5 0x03 +#define ST7567_REGULATION_RATIO_5_0 0x04 /* Default */ +#define ST7567_REGULATION_RATIO_5_5 0x05 +#define ST7567_REGULATION_RATIO_6_0 0x06 +#define ST7567_REGULATION_RATIO_6_5 0x07 + +/** + * This is double byte instruction. The first byte set ST7567 into EV + * adjust mode and the following instruction will change the EV setting. + * That means these 2 bytes must be used together. They control the electronic + * volume to adjust a suitable V0 voltage for the LCD. +*/ +#define ST7567_SET_EV 0x81 +#define ST7567_SET_EV_MASK 0x3F + +#define ST7567_SET_BOOSTER 0xF8 /* Set booster level */ +#define ST7567_SET_BOOSTER_4X 0x00 +#define ST7567_SET_BOOSTER_5X 0x01 + +#define ST7567_NOP 0xE3 +#define ST7567_TEST 0xFE + +#ifndef ST7567_TIMEOUT +#define ST7567_TIMEOUT 20000 +#endif + +#if ST7567_X_ORIENT == ST7567_SEG_DIRECTION_REVERSE + #define ST7567_X_OFFSET ST7567_SEG_EXPAND +#else + #define ST7567_X_OFFSET 0 +#endif + + +/** Background color */ +#define ST7567_COLOR_BACK 0x00 +/** Front color */ +#define ST7567_COLOR_FRONT 0x01 + +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 Initializes ST7567 LCD + * @param None + * @retval None + */ +void ST7567_Init(void); + +/** + * @brief Hardware reset ST7567 LCD + * @param None + * @retval None + */ +void ST7567_Reset(void); + +/** + * @brief Turn ST7567 LCD backlight on + * @param None + * @retval None + */ +void ST7567_BackLight_On(void); + +/** + * @brief Turn ST7567 LCD backlight off + * @param None + * @retval None + */ +void ST7567_BackLight_Off(void); + +/** + * @brief Turn ST7567 LCD backlight off + * @param val: value between 0x00 ~ 0x3F + * @retval None + */ +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 + * @param None + * @retval None + */ +void ST7567_UpdateScreen(void); + +/** + * @brief Toggles pixels invertion inside internal RAM + * @note @ref ST7567_UpdateScreen() must be called after that in order to see updated LCD screen + * @param None + * @retval None + */ +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 + * @param Color: Color to be used for screen fill. This parameter can be a value of @ref ST7567_COLOR_t enumeration + * @retval None + */ +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 + * @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 + * @retval None + */ +void ST7567_DrawPixel(uint16_t x, uint16_t y, uint8_t color); + +/** + * @brief Sets cursor pointer to desired location for strings + * @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 + * @retval None + */ +void ST7567_GotoXY(uint16_t x, uint16_t y); + +/** + * @brief Puts character to internal RAM + * @note @ref ST7567_UpdateScreen() must be called after that in order to see updated LCD screen + * @param ch: Character to be written + * @param *Font: Pointer to @ref FontDef_t structure with used font + * @param color: Color used for drawing. This parameter can be a value of @ref ST7567_COLOR_t enumeration + * @retval Character written + */ +char ST7567_Putc(char ch, FontDef_t* Font, uint8_t color); + +/** + * @brief Puts string to internal RAM + * @note @ref ST7567_UpdateScreen() must be called after that in order to see updated LCD screen + * @param *str: String to be written + * @param *Font: Pointer to @ref FontDef_t structure with used font + * @param color: Color used for drawing. This parameter can be a value of @ref ST7567_COLOR_t enumeration + * @retval Zero on success or character value when function failed + */ +char ST7567_Puts(char* str, FontDef_t* Font, uint8_t color); + +/** + * @brief Draws line on LCD + * @note @ref ST7567_UpdateScreen() must be called after that in order to see updated LCD screen + * @param x0: Line X start point. Valid input is 0 to ST7567_WIDTH - 1 + * @param y0: Line Y start point. Valid input is 0 to ST7567_HEIGHT - 1 + * @param x1: Line X end point. Valid input is 0 to ST7567_WIDTH - 1 + * @param y1: Line Y end point. Valid input is 0 to ST7567_HEIGHT - 1 + * @param c: Color to be used. This parameter can be a value of @ref ST7567_COLOR_t enumeration + * @retval None + */ +void ST7567_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint8_t c); + +/** + * @brief Writes single byte command to slave + * @param command: command to be written + * @retval None + */ +void ST7567_WriteCommand(uint8_t command); + +/** + * @brief Writes single byte data to slave + * @param data: data to be written + * @retval None + */ +void ST7567_WriteData(uint8_t data); + + +#endif // __ST7567_H_ diff --git a/demo/spi/st7567/st7567_stc8h3k.c b/demo/spi/st7567/st7567_stc8h3k.c new file mode 100644 index 0000000..b6237d5 --- /dev/null +++ b/demo/spi/st7567/st7567_stc8h3k.c @@ -0,0 +1,147 @@ +// 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: ST7567 12864 LCD + * Board: STC8H3K32 + * + * P37 -> RES, RESET 7 - 18 + * P36 -> DC, A0 8 - 17 + * P35 -> CSB, Chip Select 6 - 16 + * P32 -> SCK, SCL, CLK, Clock 9 - 13 + * P12 -> LED-A, Backlight 3 - 19 + * P34 -> MOSI, SDA 10 - 15 + * GND -> GND + * 3.3V -> VCC + */ + +#include "fw_hal.h" +#include "st7567.h" + + +void SPI_Init(void) +{ + // ST7567 doesn't work if SPI frequency is too high + SPI_SetClockPrescaler(SPI_ClockPreScaler_16); + // Clock idles low + 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_SetEnableState(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) +{ + int y1, y2; + uint8_t d1, d2; + + SYS_SetClock(); + GPIO_Init(); + SPI_Init(); + ST7567_Init(); + + while(1) + { + ST7567_DrawLine(0, 0, 127, 0, 1); + ST7567_DrawLine(0, 0, 0, 63, 1); + ST7567_DrawLine(127, 0, 127, 63, 1); + ST7567_DrawLine(0, 63, 127, 63, 1); + + ST7567_GotoXY(3, 5); + ST7567_Puts("LCD:ST7567", &Font_5x7, 1); + ST7567_GotoXY(3, 13); + ST7567_Puts("STC8 FwLib Demo", &Font_5x7, 1); + ST7567_GotoXY(3, 21); + ST7567_Puts("It's a demo of ST7567 12864 LCD", &Font_3x5, 1); + ST7567_GotoXY(3, 27); + ST7567_Puts("Font size 3x5, nums:01234567890", &Font_3x5, 1); + ST7567_GotoXY(5, 52); + ST7567_Puts("Font size: 5x7", &Font_5x7, 1); + ST7567_UpdateScreen(); + SYS_Delay(2000); + + y1 = 10; + while (y1 <= 0x30) + { + ST7567_SetContrast(y1++); + SYS_Delay(100); + } + while (y1 >= 10) + { + ST7567_SetContrast(y1--); + SYS_Delay(100); + } + while (y1 <= 0x20) + { + ST7567_SetContrast(y1++); + SYS_Delay(100); + } + SYS_Delay(2000); + + ST7567_ToggleInvert(); + ST7567_UpdateScreen(); + SYS_Delay(2000); + + ST7567_ToggleInvert(); + ST7567_UpdateScreen(); + SYS_Delay(2000); + + ST7567_Fill(0); + y1 = 64, y2 = 0; + while (y1 > 0) + { + ST7567_DrawLine(0, y1, 127, y2, 1); + ST7567_UpdateScreen(); + y1 -= 2; + y2 += 2; + SYS_Delay(100); + } + SYS_Delay(1000); + + ST7567_Fill(0); + y1 = 127, y2 = 0; + while (y1 > 0) + { + ST7567_DrawLine(y1, 0, y2, 63, 1); + ST7567_UpdateScreen(); + y1 -= 2; + y2 += 2; + SYS_Delay(100); + } + SYS_Delay(1000); + + ST7567_Fill(0); + ST7567_UpdateScreen(); + SYS_Delay(2000); + } +}