[refactor][mcu_lcd] standardize mcu lcd driver

This commit is contained in:
jzlv 2021-08-25 17:01:22 +08:00
parent dea22ca51a
commit 5db2f4abd8
17 changed files with 2908 additions and 679 deletions

View file

@ -11,10 +11,9 @@
*********************/
#include "lvgl.h"
#include "lv_port_disp.h"
#include "bsp_il9341.h"
#include "hal_spi.h"
#include "hal_dma.h"
#include "../mcu_lcd/mcu_lcd.h"
/*********************
* DEFINES
@ -27,7 +26,6 @@
/**********************
* STATIC PROTOTYPES
**********************/
void LCD_Init(void);
static void disp_init(void);
static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p);
@ -48,7 +46,7 @@ static void gpu_fill(lv_disp_drv_t *disp_drv, lv_color_t *dest_buf, lv_coord_t d
/**********************
* GLOBAL FUNCTIONS
**********************/
static lv_disp_drv_t Disp_Drv; /*Descriptor of a display driver*/
lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
static lv_disp_drv_t *p_disp_drv_cb;
void lv_port_disp_init(void)
@ -89,9 +87,9 @@ void lv_port_disp_init(void)
// /* Example for 2) */
static lv_disp_buf_t draw_buf_dsc_2;
static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * 20]; /*A buffer for 10 rows*/
static lv_color_t draw_buf_2_2[LV_HOR_RES_MAX * 20]; /*An other buffer for 10 rows*/
lv_disp_buf_init(&draw_buf_dsc_2, draw_buf_2_1, draw_buf_2_2, LV_HOR_RES_MAX * 20); /*Initialize the display buffer*/
static lv_color_t draw_buf_2_1[LCD_W * 20]; /*A buffer for 10 rows*/
static lv_color_t draw_buf_2_2[LCD_W * 20]; /*An other buffer for 10 rows*/
lv_disp_buf_init(&draw_buf_dsc_2, draw_buf_2_1, draw_buf_2_2, LCD_W * 20); /*Initialize the display buffer*/
// /* Example for 3) *
// static lv_disp_buf_t draw_buf_dsc_3;
@ -103,23 +101,23 @@ void lv_port_disp_init(void)
* Register the display in LVGL
*----------------------------------*/
lv_disp_drv_init(&Disp_Drv); /*Basic initialization*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
/*Set up the functions to access to your display*/
/*Set the resolution of the display*/
Disp_Drv.hor_res = 240;
Disp_Drv.ver_res = 320;
disp_drv.hor_res = LCD_W;
disp_drv.ver_res = LCD_H;
/* hardware rotation */
Disp_Drv.sw_rotate = 0;
disp_drv.sw_rotate = 0;
/* rotation */
Disp_Drv.rotated = LV_DISP_ROT_NONE;
disp_drv.rotated = LV_DISP_ROT_NONE;
/*Used to copy the buffer's content to the display*/
Disp_Drv.flush_cb = disp_flush;
disp_drv.flush_cb = disp_flush;
/*Set a display buffer*/
Disp_Drv.buffer = &draw_buf_dsc_2;
disp_drv.buffer = &draw_buf_dsc_2;
#if LV_USE_GPU
/*Optionally add functions to access the GPU. (Only in buffered mode, LV_VDB_SIZE != 0)*/
@ -132,32 +130,29 @@ void lv_port_disp_init(void)
#endif
/*Finally register the driver*/
lv_disp_drv_register(&Disp_Drv);
lv_disp_drv_register(&disp_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
struct device *lcd_spi;
struct device *lcd_dma_tx;
struct device *lcd_dma_rx;
void flush_callback(struct device *dev, void *args, uint32_t size, uint32_t event)
{
device_control(lcd_spi, DEVICE_CTRL_TX_DMA_SUSPEND, NULL);
while (lcd_draw_is_busy())
;
lv_disp_flush_ready(p_disp_drv_cb);
CS1_HIGH;
}
/* Initialize your display and the required peripherals. */
void disp_init(void)
{
/*You code here*/
LCD_Init();
lcd_spi = device_find("spi0");
lcd_dma_tx = device_find("dma0_ch3");
lcd_dma_rx = device_find("dma0_ch4");
device_set_callback(lcd_dma_tx, flush_callback);
lcd_init();
lcd_auto_swap_set(0);
device_set_callback(SPI_DEV(lcd_dev_ifs)->tx_dma, flush_callback);
device_control(SPI_DEV(lcd_dev_ifs)->tx_dma, DEVICE_CTRL_SET_INT, NULL);
}
/* Flush the content of the internal buffer the specific area on the display
@ -167,28 +162,18 @@ static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_
{
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
static uint8_t rotated_dir = 0;
uint32_t length = (area->y2 - area->y1 + 1) * (area->x2 - area->x1 + 1);
if (rotated_dir != disp_drv->rotated) {
rotated_dir = disp_drv->rotated;
LCD_Set_Dir(rotated_dir);
lcd_set_dir(rotated_dir, 0);
}
LCD_Set_Addr(area->x1, area->y1, area->x2, area->y2);
device_control(lcd_spi, DEVICE_CTRL_TX_DMA_RESUME, NULL);
device_control(lcd_dma_tx, DEVICE_CTRL_SET_INT, NULL);
CS1_LOW;
DC_HIGH;
dma_reload(lcd_dma_tx, (uint32_t)color_p, (uint32_t)DMA_ADDR_SPI_TDR, length * 2);
dma_channel_start(lcd_dma_tx);
lcd_draw_picture_nonblocking(area->x1, area->y1, area->x2, area->y2, (lcd_color_t *)color_p);
p_disp_drv_cb = disp_drv;
return;
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
//lv_disp_flush_ready(disp_drv);
// lv_disp_flush_ready(disp_drv);
}
/*OPTIONAL: GPU INTERFACE*/

View file

@ -29,11 +29,13 @@ extern "C" {
/**********************
* GLOBAL PROTOTYPES
**********************/
extern lv_disp_drv_t disp_drv;
void lv_port_disp_init(void);
/**********************
* MACROS
**********************/
void lv_port_disp_init(void);
#ifdef __cplusplus
} /* extern "C" */

View file

@ -255,7 +255,7 @@ static lv_fs_res_t fs_read(lv_fs_drv_t *drv, void *file_p, void *buf, uint32_t b
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/* Add your code here*/
res = f_read((file_t *)file_p, buf, btr, br);
res = f_read((file_t *)file_p, buf, btr, (UINT *)br);
res = res_fatfs_to_lv(res);
return res;
@ -275,7 +275,7 @@ static lv_fs_res_t fs_write(lv_fs_drv_t *drv, void *file_p, const void *buf, uin
lv_fs_res_t res = LV_FS_RES_NOT_IMP;
/* Add your code here*/
res = f_write((file_t *)file_p, buf, btw, bw);
res = f_write((file_t *)file_p, buf, btw, (UINT *)bw);
res = res_fatfs_to_lv(res);
return res;

View file

@ -11,6 +11,8 @@
*********************/
#include "lv_port_indev.h"
#include "bflb_platform.h"
#include "hal_gpio.h"
#include "hal_dma.h"
/*********************
* DEFINES
@ -95,6 +97,10 @@ void lv_port_indev_init(void)
indev_drv.read_cb = touchpad_read;
indev_touchpad = lv_indev_drv_register(&indev_drv);
lv_obj_t *touchpad_cursor = lv_img_create(lv_disp_get_scr_act(NULL), NULL);
lv_img_set_src(touchpad_cursor, LV_SYMBOL_USB);
lv_indev_set_cursor(indev_touchpad, touchpad_cursor);
/*------------------
* Mouse
* -----------------*/
@ -184,7 +190,13 @@ void lv_port_indev_init(void)
static void touchpad_init(void)
{
/*Your code comes here*/
if (device_find("lcd_dev_ifs") == NULL) {
xpt2046_init();
} else {
gpio_set_mode(TOUCH_PIN_CS, GPIO_OUTPUT_MODE);
gpio_write(TOUCH_PIN_CS, 1);
touch_spi = device_find("lcd_dev_ifs");
}
}
/* Will be called by the library to read the touchpad */
@ -230,9 +242,11 @@ static lv_coord_t touchpad_get_xy(lv_coord_t *x, lv_coord_t *y)
while (p_disp_drv_cb->driver.buffer->flushing)
;
device_control(touch_spi, DEVICE_CTRL_SPI_CONFIG_CLOCK, (void *)3600000);
uint32_t spi_clock = SPI_DEV(touch_spi)->clk;
device_control(touch_spi, DEVICE_CTRL_SPI_CONFIG_CLOCK, (void *)360000);
res = touch_read(x, y);
device_control(touch_spi, DEVICE_CTRL_SPI_CONFIG_CLOCK, (void *)36000000);
device_control(touch_spi, DEVICE_CTRL_SPI_CONFIG_CLOCK, (void *)spi_clock);
return res;
}

View file

@ -1,296 +1,305 @@
#include "ssd1306.h"
#include "hal_spi.h"
#include "hal_gpio.h"
/**
* @file font.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
*/
static struct device *spi0;
#include "font.h"
uint8_t OLED_GRAM[128][8];
// clang-format off
static void spi0_init(void)
{
gpio_set_mode(OLED_CS_PIN, GPIO_OUTPUT_MODE);
gpio_set_mode(OLED_DC_PIN, GPIO_OUTPUT_MODE);
gpio_set_mode(OLED_RES_PIN, GPIO_OUTPUT_MODE);
gpio_write(OLED_CS_PIN, 1); //CS1
gpio_write(OLED_DC_PIN, 1); //DC
#if FONT_ASCII_16X8
spi0 = device_find("spi0");
const unsigned char font_ascii_16x8[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //" "
0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00, //"!"
0x00,0x00,0x6C,0x6C,0x24,0x24,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00, //"""
0x00,0x24,0x24,0x24,0x24,0xFE,0x48,0x48,0x48,0x48,0xFC,0x90,0x90,0x90,0x90,0x00, //"#"
0x00,0x10,0x3C,0x54,0x92,0x90,0x50,0x38,0x14,0x12,0x12,0x92,0x54,0x78,0x10,0x00, //"$"
0x00,0x00,0x22,0x5C,0x94,0xA8,0x48,0x10,0x10,0x24,0x2A,0x52,0x54,0x88,0x00,0x00, //"%"
0x00,0x00,0x30,0x48,0x48,0x50,0x20,0x6E,0x54,0x94,0x8C,0x88,0x8A,0x74,0x00,0x00, //"&"
0x00,0x00,0x30,0x30,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //"'"
0x00,0x04,0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x04,0x00, //"("
0x00,0x80,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40,0x80,0x00, //")"
0x00,0x00,0x00,0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00, //"*"
0x00,0x00,0x00,0x10,0x10,0x10,0x10,0xFE,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00, //"+"
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x20,0x00, //","
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //"-"
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00, //"."
0x00,0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00,0x00, //"/"
0x00,0x00,0x38,0x44,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x44,0x38,0x00,0x00, //"0"
0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00, //"1"
0x00,0x00,0x38,0x44,0x82,0x82,0x04,0x08,0x10,0x20,0x40,0x82,0x84,0xFC,0x00,0x00, //"2"
0x00,0x00,0x38,0x44,0x82,0x02,0x04,0x38,0x04,0x02,0x02,0x82,0x44,0x38,0x00,0x00, //"3"
0x00,0x00,0x04,0x0C,0x14,0x14,0x24,0x24,0x44,0x44,0xFE,0x04,0x04,0x0E,0x00,0x00, //"4"
0x00,0x00,0xFC,0x80,0x80,0x80,0xB8,0xC4,0x82,0x02,0x02,0x82,0x84,0x78,0x00,0x00, //"5"
0x00,0x00,0x3C,0x42,0x82,0x80,0xB8,0xC4,0x82,0x82,0x82,0x82,0x44,0x38,0x00,0x00, //"6"
0x00,0x00,0x7E,0x42,0x82,0x04,0x04,0x08,0x08,0x08,0x10,0x10,0x10,0x10,0x00,0x00, //"7"
0x00,0x00,0x38,0x44,0x82,0x82,0x44,0x38,0x44,0x82,0x82,0x82,0x44,0x38,0x00,0x00, //"8"
0x00,0x00,0x38,0x44,0x82,0x82,0x82,0x82,0x46,0x3A,0x02,0x82,0x44,0x38,0x00,0x00, //"9"
0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00, //":"
0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x20,0x00,0x00, //";"
0x00,0x00,0x00,0x00,0x06,0x18,0x60,0x80,0x60,0x18,0x06,0x00,0x00,0x00,0x00,0x00, //"<"
0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, //"="
0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x02,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00, //">"
0x00,0x38,0x44,0x82,0x82,0x02,0x04,0x08,0x10,0x10,0x10,0x00,0x10,0x10,0x00,0x00, //"?"
0x00,0x00,0x38,0x44,0x82,0x9A,0xAA,0xAA,0xAA,0xAA,0xAA,0x96,0x80,0x42,0x3C,0x00, //"@"
0x00,0x00,0x10,0x10,0x10,0x28,0x28,0x28,0x44,0x44,0x7C,0x44,0x44,0xEE,0x00,0x00, //"A"
0x00,0x00,0xFC,0x42,0x42,0x42,0x42,0x7C,0x42,0x42,0x42,0x42,0x42,0xFC,0x00,0x00, //"B"
0x00,0x00,0x3C,0x44,0x82,0x80,0x80,0x80,0x80,0x80,0x82,0x82,0x44,0x38,0x00,0x00, //"C"
0x00,0x00,0xF8,0x44,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x44,0xF8,0x00,0x00, //"D"
0x00,0x00,0xFC,0x44,0x42,0x40,0x44,0x7C,0x44,0x40,0x40,0x42,0x44,0xFC,0x00,0x00, //"E"
0x00,0x00,0xFC,0x44,0x42,0x40,0x44,0x7C,0x44,0x40,0x40,0x40,0x40,0xF0,0x00,0x00, //"F"
0x00,0x00,0x34,0x4C,0x82,0x80,0x80,0x80,0x8E,0x84,0x84,0x84,0x4C,0x34,0x00,0x00, //"G"
0x00,0x00,0xEE,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x44,0xEE,0x00,0x00, //"H"
0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00, //"I"
0x00,0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x88,0x88,0x70,0x00,0x00, //"J"
0x00,0x00,0xEE,0x44,0x48,0x48,0x50,0x60,0x50,0x48,0x48,0x44,0x44,0xEE,0x00,0x00, //"K"
0x00,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x42,0x44,0xFC,0x00,0x00, //"L"
0x00,0x00,0xC6,0x44,0x6C,0x6C,0x6C,0x54,0x54,0x54,0x44,0x44,0x44,0xEE,0x00,0x00, //"M"
0x00,0x00,0xCE,0x44,0x64,0x64,0x64,0x54,0x54,0x4C,0x4C,0x4C,0x44,0xE4,0x00,0x00, //"N"
0x00,0x00,0x38,0x44,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x44,0x38,0x00,0x00, //"O"
0x00,0x00,0xF8,0x44,0x42,0x42,0x42,0x44,0x78,0x40,0x40,0x40,0x40,0xE0,0x00,0x00, //"P"
0x00,0x00,0x38,0x44,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xBA,0x44,0x3C,0x02,0x00, //"Q"
0x00,0x00,0xF0,0x48,0x44,0x44,0x44,0x48,0x70,0x48,0x44,0x44,0x44,0xE6,0x00,0x00, //"R"
0x00,0x00,0x3C,0x44,0x82,0x80,0x40,0x30,0x0C,0x02,0x02,0x82,0x44,0x78,0x00,0x00, //"S"
0x00,0x00,0x7C,0x54,0x92,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, //"T"
0x00,0x00,0xEE,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, //"U"
0x00,0x00,0xEE,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x28,0x10,0x10,0x10,0x00,0x00, //"V"
0x00,0x00,0xEE,0x44,0x54,0x54,0x54,0x54,0x54,0x54,0x28,0x28,0x28,0x28,0x00,0x00, //"W"
0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x10,0x10,0x28,0x28,0x44,0x44,0xEE,0x00,0x00, //"X"
0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, //"Y"
0x00,0x00,0x7E,0x44,0x84,0x08,0x08,0x10,0x20,0x20,0x40,0x82,0x84,0xFC,0x00,0x00, //"Z"
0x00,0x1C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1C,0x00, //"["
0x00,0x00,0xEE,0x44,0x54,0x54,0xFE,0x54,0x54,0x54,0x28,0x28,0x28,0x28,0x00,0x00, //"\"
0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, //"]"
0x00,0x30,0x48,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //"^"
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00, //"_"
0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //"`"
0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x84,0x04,0x7C,0x84,0x84,0x8C,0x76,0x00,0x00, //"a"
0x00,0x00,0xC0,0x40,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x42,0x64,0x58,0x00,0x00, //"b"
0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x80,0x80,0x80,0x80,0x44,0x38,0x00,0x00, //"c"
0x00,0x00,0x0C,0x04,0x04,0x04,0x34,0x4C,0x84,0x84,0x84,0x84,0x4C,0x36,0x00,0x00, //"d"
0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x84,0x84,0xFC,0x80,0x80,0x84,0x78,0x00,0x00, //"e"
0x00,0x00,0x18,0x24,0x20,0x20,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, //"f"
0x00,0x00,0x00,0x00,0x00,0x00,0x3A,0x44,0x44,0x78,0x80,0x7C,0x82,0x82,0x7C,0x00, //"g"
0x00,0x00,0xC0,0x40,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0xEE,0x00,0x00, //"h"
0x00,0x00,0x10,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, //"i"
0x00,0x00,0x10,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00, //"j"
0x00,0x00,0xC0,0x40,0x40,0x40,0x5C,0x48,0x50,0x60,0x50,0x48,0x44,0xEE,0x00,0x00, //"k"
0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x11,0x10,0x10,0x10,0x10,0x10,0x39,0x00,0x00, //"l"
0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0xD2,0x92,0x92,0x92,0x92,0x92,0xD6,0x00,0x00, //"m"
0x00,0x00,0x00,0x00,0x00,0x00,0x58,0xE4,0x44,0x44,0x44,0x44,0x44,0xEE,0x00,0x00, //"n"
0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x82,0x82,0x82,0x82,0x44,0x38,0x00,0x00, //"o"
0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x64,0x42,0x42,0x42,0x64,0x58,0x40,0xE0,0x00, //"p"
0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x4C,0x84,0x84,0x84,0x4C,0x34,0x04,0x0E,0x00, //"q"
0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x30,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, //"r"
0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x88,0x84,0x60,0x18,0x84,0x44,0x78,0x00,0x00, //"s"
0x00,0x00,0x00,0x20,0x20,0x20,0xF8,0x20,0x20,0x20,0x20,0x20,0x24,0x18,0x00,0x00, //"t"
0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x42,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00, //"u"
0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, //"v"
0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x44,0x44,0x54,0x54,0x28,0x28,0x28,0x00,0x00, //"w"
0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x44,0x28,0x10,0x10,0x28,0x44,0xEE,0x00,0x00, //"x"
0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x10,0x10,0xA0,0xC0,0x00, //"y"
0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x44,0x88,0x10,0x20,0x42,0x84,0xFC,0x00,0x00, //"z"
0x00,0x0C,0x10,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x10,0x10,0x0C,0x00, //"{"
0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, //"|"
0x00,0xC0,0x20,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0x20,0x20,0xC0,0x00, //"}"
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x72,0x8C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //"~"
0x00,
};
#endif
if (spi0) {
device_close(spi0);
} else {
spi_register(SPI0_INDEX, "spi0");
spi0 = device_find("spi0");
}
#if FONT_ASCII_64X32
const unsigned char ascii_64x32[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xF8,0x00,
0x00,0x1F,0xFE,0x00,0x00,0x7F,0xFF,0x80,0x00,0xFF,0x1F,0xC0,0x00,0xFC,0x0F,0xE0,
0x01,0xF8,0x07,0xE0,0x03,0xF8,0x03,0xF0,0x03,0xF0,0x03,0xF0,0x07,0xF0,0x01,0xF8,
0x07,0xE0,0x01,0xF8,0x07,0xE0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,
0x0F,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,
0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,
0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,
0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,
0x0F,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,
0x0F,0xE0,0x00,0xFC,0x07,0xE0,0x01,0xF8,0x07,0xE0,0x01,0xF8,0x03,0xF0,0x03,0xF0,
0x03,0xF8,0x03,0xF0,0x01,0xF8,0x07,0xE0,0x00,0xFC,0x0F,0xC0,0x00,0xFF,0x1F,0xC0,
0x00,0x3F,0xFF,0x80,0x00,0x1F,0xFE,0x00,0x00,0x07,0xF8,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"0",0*/
if (spi0) {
device_open(spi0, DEVICE_OFLAG_STREAM_TX | DEVICE_OFLAG_STREAM_RX);
}
}
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,
0x00,0x00,0xF0,0x00,0x00,0x01,0xF0,0x00,0x00,0x07,0xF0,0x00,0x01,0xFF,0xF0,0x00,
0x01,0xFF,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xF8,0x00,
0x00,0x0F,0xFC,0x00,0x01,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"1",1*/
void oled_wr_cmd(uint8_t command)
{
CS1_LOW;
DC_LOW;
spi_transmit(spi0, &command, 1, SPI_TRANSFER_TYPE_8BIT);
CS1_HIGH;
DC_HIGH;
}
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFC,0x00,
0x00,0x3F,0xFF,0x80,0x00,0xFF,0xFF,0xE0,0x01,0xFC,0x1F,0xF0,0x03,0xF0,0x07,0xF0,
0x07,0xE0,0x03,0xF8,0x07,0xE0,0x01,0xF8,0x0F,0xC0,0x01,0xFC,0x0F,0xC0,0x00,0xFC,
0x0F,0xE0,0x00,0xFC,0x0F,0xF0,0x00,0xFC,0x0F,0xF0,0x00,0xFC,0x0F,0xF0,0x00,0xFC,
0x0F,0xF0,0x00,0xFC,0x07,0xE0,0x01,0xFC,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,
0x00,0x00,0x03,0xF8,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xE0,
0x00,0x00,0x1F,0xC0,0x00,0x00,0x3F,0x80,0x00,0x00,0x7F,0x00,0x00,0x00,0xFE,0x00,
0x00,0x01,0xFC,0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,0x00,
0x00,0x1F,0x80,0x00,0x00,0x3F,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0xFC,0x00,0x3C,
0x01,0xF8,0x00,0x3C,0x03,0xF0,0x00,0x3C,0x03,0xE0,0x00,0x3C,0x07,0xE0,0x00,0x7C,
0x0F,0xC0,0x00,0xF8,0x1F,0x80,0x01,0xF8,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,
0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"2",2*/
void oled_wr_data(uint8_t data)
{
CS1_LOW;
DC_HIGH;
spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_8BIT);
CS1_HIGH;
DC_HIGH;
}
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,
0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFF,0x80,0x01,0xF8,0x7F,0xC0,0x03,0xE0,0x1F,0xC0,
0x03,0xC0,0x0F,0xE0,0x07,0xC0,0x07,0xE0,0x07,0xC0,0x07,0xF0,0x07,0xE0,0x03,0xF0,
0x07,0xE0,0x03,0xF0,0x07,0xE0,0x03,0xF0,0x07,0xE0,0x03,0xF0,0x03,0xC0,0x03,0xF0,
0x00,0x00,0x03,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,0x00,0x0F,0xC0,
0x00,0x00,0x1F,0xC0,0x00,0x00,0xFF,0x00,0x00,0x0F,0xFE,0x00,0x00,0x0F,0xFE,0x00,
0x00,0x0F,0xFF,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x07,0xF0,
0x00,0x00,0x03,0xF0,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0xFC,
0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x03,0xE0,0x00,0xFC,0x07,0xF0,0x00,0xFC,
0x0F,0xF0,0x00,0xFC,0x0F,0xF0,0x00,0xFC,0x0F,0xF0,0x01,0xFC,0x0F,0xF0,0x01,0xF8,
0x0F,0xE0,0x03,0xF8,0x07,0xE0,0x03,0xF0,0x07,0xF0,0x07,0xE0,0x03,0xFC,0x1F,0xC0,
0x01,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0x00,0x00,0x1F,0xF8,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"3",3*/
void oled_display_on(void)
{
oled_wr_cmd(0X8D);
oled_wr_cmd(0X14);
oled_wr_cmd(0XAF);
}
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,
0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x3F,0x80,0x00,0x00,0x3F,0x80,
0x00,0x00,0x7F,0x80,0x00,0x00,0xFF,0x80,0x00,0x00,0xFF,0x80,0x00,0x01,0xFF,0x80,
0x00,0x03,0xFF,0x80,0x00,0x03,0xFF,0x80,0x00,0x07,0xDF,0x80,0x00,0x0F,0x9F,0x80,
0x00,0x0F,0x9F,0x80,0x00,0x1F,0x1F,0x80,0x00,0x3E,0x1F,0x80,0x00,0x3E,0x1F,0x80,
0x00,0x7C,0x1F,0x80,0x00,0xF8,0x1F,0x80,0x00,0xF8,0x1F,0x80,0x01,0xF0,0x1F,0x80,
0x03,0xE0,0x1F,0x80,0x03,0xE0,0x1F,0x80,0x07,0xC0,0x1F,0x80,0x0F,0x80,0x1F,0x80,
0x0F,0x80,0x1F,0x80,0x1F,0x00,0x1F,0x80,0x3E,0x00,0x1F,0x80,0x3F,0xFF,0xFF,0xFF,
0x3F,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,
0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,
0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,0x00,0x00,0x1F,0x80,
0x00,0x00,0x3F,0xC0,0x00,0x07,0xFF,0xFE,0x00,0x07,0xFF,0xFE,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"4",4*/
void oled_display_off(void)
{
oled_wr_cmd(0X8D);
oled_wr_cmd(0X10);
oled_wr_cmd(0XAE);
}
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xF8,
0x01,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xF0,
0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,
0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xE0,0x00,0x00,0x01,0xC0,0x00,0x00,
0x03,0xC0,0x00,0x00,0x03,0xC0,0x00,0x00,0x03,0xC7,0xFE,0x00,0x03,0xDF,0xFF,0x80,
0x03,0xFF,0xFF,0xC0,0x03,0xFE,0x1F,0xE0,0x03,0xF8,0x07,0xF0,0x03,0xF0,0x03,0xF0,
0x03,0xE0,0x03,0xF8,0x03,0xE0,0x01,0xF8,0x03,0x80,0x01,0xF8,0x00,0x00,0x01,0xFC,
0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,
0x00,0x00,0x00,0xFC,0x03,0xE0,0x00,0xFC,0x07,0xF0,0x00,0xFC,0x0F,0xF0,0x00,0xFC,
0x0F,0xF0,0x00,0xFC,0x0F,0xF0,0x01,0xF8,0x0F,0xF0,0x01,0xF8,0x0F,0xE0,0x01,0xF8,
0x0F,0xE0,0x03,0xF0,0x07,0xE0,0x07,0xF0,0x03,0xF0,0x0F,0xE0,0x01,0xFC,0x1F,0xC0,
0x00,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0x00,0x00,0x0F,0xFC,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"5",5*/
void oled_show(void)
{
uint8_t i, j;
for (i = 0; i < 8; i++) {
oled_wr_cmd(0xB0 + i);
oled_wr_cmd(0x00);
oled_wr_cmd(0x10);
for (j = 0; j < 128; j++) {
oled_wr_data(OLED_GRAM[j][i]);
}
}
}
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x00,
0x00,0x0F,0xFF,0xC0,0x00,0x1F,0xFF,0xF0,0x00,0x3F,0x87,0xF0,0x00,0x7E,0x03,0xF8,
0x00,0xFC,0x03,0xF8,0x01,0xF8,0x03,0xF8,0x03,0xF0,0x03,0xF8,0x03,0xE0,0x01,0xF0,
0x07,0xE0,0x00,0x00,0x07,0xC0,0x00,0x00,0x07,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,
0x0F,0xC0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x0F,0x80,0x00,0x00,0x1F,0x83,0xFE,0x00,
0x1F,0x9F,0xFF,0xC0,0x1F,0xBF,0xFF,0xE0,0x1F,0xFF,0x0F,0xF0,0x1F,0xFC,0x03,0xF8,
0x1F,0xF8,0x01,0xF8,0x1F,0xF0,0x01,0xFC,0x1F,0xE0,0x00,0xFC,0x1F,0xC0,0x00,0xFC,
0x1F,0xC0,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,
0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x0F,0xC0,0x00,0x7E,0x0F,0xC0,0x00,0x7E,
0x0F,0xC0,0x00,0x7E,0x0F,0xC0,0x00,0xFE,0x07,0xE0,0x00,0xFC,0x07,0xF0,0x00,0xFC,
0x03,0xF0,0x01,0xF8,0x03,0xF8,0x01,0xF8,0x01,0xFC,0x03,0xF0,0x00,0xFF,0x0F,0xE0,
0x00,0x7F,0xFF,0xC0,0x00,0x3F,0xFF,0x80,0x00,0x07,0xFC,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"6",6*/
void oled_clear(void)
{
uint8_t i, j;
for (i = 0; i < 8; i++)
for (j = 0; j < 128; j++)
OLED_GRAM[j][i] = 0x00;
oled_show();
}
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFC,
0x07,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xF8,
0x07,0xF0,0x00,0xF0,0x07,0xC0,0x01,0xF0,0x07,0x80,0x01,0xE0,0x0F,0x80,0x03,0xE0,
0x0F,0x00,0x03,0xC0,0x0F,0x00,0x07,0xC0,0x0F,0x00,0x0F,0x80,0x00,0x00,0x0F,0x80,
0x00,0x00,0x1F,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3E,0x00,
0x00,0x00,0x7E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xF8,0x00,
0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF0,0x00,0x00,0x03,0xF0,0x00,
0x00,0x03,0xF0,0x00,0x00,0x07,0xF0,0x00,0x00,0x07,0xE0,0x00,0x00,0x07,0xE0,0x00,
0x00,0x07,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,0x00,0x0F,0xE0,0x00,
0x00,0x0F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,
0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,
0x00,0x1F,0xE0,0x00,0x00,0x1F,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"7",7*/
void oled_init(void)
{
spi0_init();
CS1_HIGH;
DC_HIGH;
RES_LOW;
bflb_platform_delay_ms(100);
RES_HIGH;
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xFC,0x00,
0x00,0x7F,0xFF,0x80,0x00,0xFF,0xFF,0xC0,0x01,0xFE,0x1F,0xE0,0x03,0xF8,0x07,0xF0,
0x07,0xF0,0x03,0xF8,0x07,0xE0,0x01,0xF8,0x0F,0xE0,0x01,0xFC,0x0F,0xC0,0x00,0xFC,
0x0F,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,0x0F,0xC0,0x00,0xFC,0x0F,0xE0,0x00,0xFC,
0x0F,0xF0,0x00,0xFC,0x07,0xF0,0x01,0xF8,0x07,0xFC,0x01,0xF8,0x03,0xFE,0x03,0xF0,
0x03,0xFF,0x87,0xE0,0x01,0xFF,0xEF,0xC0,0x00,0xFF,0xFF,0x80,0x00,0x3F,0xFE,0x00,
0x00,0x7F,0xFF,0x00,0x00,0xFF,0xFF,0x80,0x01,0xF8,0xFF,0xC0,0x03,0xF0,0x7F,0xE0,
0x07,0xE0,0x1F,0xF0,0x0F,0xE0,0x0F,0xF8,0x0F,0xC0,0x07,0xF8,0x0F,0xC0,0x03,0xF8,
0x1F,0xC0,0x01,0xFC,0x1F,0x80,0x01,0xFC,0x1F,0x80,0x00,0xFC,0x1F,0x80,0x00,0xFC,
0x1F,0x80,0x00,0xFC,0x1F,0x80,0x00,0xFC,0x1F,0xC0,0x00,0xFC,0x0F,0xC0,0x01,0xF8,
0x0F,0xE0,0x01,0xF8,0x07,0xE0,0x03,0xF0,0x07,0xF8,0x07,0xF0,0x03,0xFC,0x1F,0xE0,
0x00,0xFF,0xFF,0xC0,0x00,0x7F,0xFF,0x00,0x00,0x0F,0xFC,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"8",8*/
oled_wr_cmd(0xAE);
oled_wr_cmd(0xD5);
oled_wr_cmd(80);
oled_wr_cmd(0xA8);
oled_wr_cmd(0x3F);
oled_wr_cmd(0xD3);
oled_wr_cmd(0x00);
oled_wr_cmd(0x40);
oled_wr_cmd(0x8D);
oled_wr_cmd(0x14);
oled_wr_cmd(0x20);
oled_wr_cmd(0x02);
oled_wr_cmd(0xA1);
oled_wr_cmd(0xC0);
oled_wr_cmd(0xDA);
oled_wr_cmd(0x12);
oled_wr_cmd(0x81);
oled_wr_cmd(0xEF);
oled_wr_cmd(0xD9);
oled_wr_cmd(0xF1);
oled_wr_cmd(0xDB);
oled_wr_cmd(0x30);
oled_wr_cmd(0xA4);
oled_wr_cmd(0xA6);
oled_wr_cmd(0xAF);
oled_clear();
}
void oled_draw_point(uint8_t x, uint8_t y, uint8_t mode)
{
uint8_t i, j, temp;
if (x > 127 || y > 63)
return;
i = 7 - y / 8;
j = y % 8;
temp = 0x01 << (7 - j);
if (mode == 0)
OLED_GRAM[x][i] &= ~temp;
else
OLED_GRAM[x][i] |= temp;
}
void oled_draw_char(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode)
{
uint8_t temp, t, t1;
uint8_t y0 = y;
uint8_t csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2);
chr = chr - ' ';
for (t = 0; t < csize; t++) {
switch (size) {
case 12:
temp = asc2_1206[chr][t];
break;
case 16:
temp = asc2_1608[chr][t];
break;
case 24:
temp = asc2_2412[chr][t];
break;
default:
return;
}
for (t1 = 0; t1 < 8; t1++) {
if (temp & 0x80)
oled_draw_point(x, y, mode);
else
oled_draw_point(x, y, !mode);
temp <<= 1;
y++;
if ((y - y0) == size) {
y = y0;
x++;
break;
}
}
}
}
void oled_draw_string(uint8_t x, uint8_t y, const uint8_t *p, uint8_t size, uint8_t mode)
{
while ((*p <= '~') && (*p >= ' ')) {
if (x > (128 - (size / 2))) {
x = 0;
y = y + size;
}
if (y > (64 - size)) {
x = y = 0;
oled_clear();
}
oled_draw_char(x, y, *p, size, mode);
x = x + size / 2;
p++;
}
}
void oled_draw_chinese(uint8_t x, uint8_t y, uint8_t no, uint8_t mode)
{
uint8_t temp1;
uint8_t temp2;
uint8_t t1, t2;
uint8_t x0 = x, y0 = y;
for (t1 = 0; t1 < 16; t1++) {
temp1 = Hzk[2 * no][t1];
for (t2 = 0; t2 < 8; t2++) {
if (temp1 & 0x01)
oled_draw_point(x, y, mode);
else
oled_draw_point(x, y, !mode);
temp1 >>= 1;
y++;
}
y = y0;
x++;
}
x = x0;
y = y0 + 8;
y0 = y;
for (t1 = 0; t1 < 16; t1++) {
temp2 = Hzk[2 * no + 1][t1];
for (t2 = 0; t2 < 8; t2++) {
if (temp2 & 0x01)
oled_draw_point(x, y, mode);
else
oled_draw_point(x, y, !mode);
temp2 >>= 1;
y++;
}
y = y0;
x++;
}
}
void oled_draw_bmp(uint8_t x, uint8_t y, const unsigned char *image, uint8_t index, uint8_t mode)
{
uint8_t temp, t1;
uint16_t i;
uint8_t y0 = y;
for (i = 0; i < 1024; i++) {
temp = image[1024 * index + i];
for (t1 = 0; t1 < 8; t1++) {
if (temp & 0x80)
oled_draw_point(x, y, mode);
else
oled_draw_point(x, y, !mode);
temp <<= 1;
y++;
if ((y - y0) == 64) {
y = y0;
x++;
break;
}
}
}
}
void oled_draw_alpha(uint8_t x, uint8_t y, const unsigned char *image, uint8_t index, uint8_t mode)
{
uint8_t temp, t1;
uint16_t i;
uint8_t y0 = y;
for (i = 0; i < 1024; i++) {
temp = image[1024 * index + i];
for (t1 = 0; t1 < 8; t1++) {
if (temp & 0x80)
oled_draw_point(x, y, mode);
temp <<= 1;
y++;
if ((y - y0) == 64) {
y = y0;
x++;
break;
}
}
}
}
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,
0x00,0x7F,0xFF,0x00,0x00,0xFF,0xFF,0x80,0x01,0xFE,0x1F,0xC0,0x03,0xF8,0x07,0xE0,
0x07,0xF0,0x03,0xF0,0x07,0xE0,0x01,0xF0,0x0F,0xC0,0x01,0xF8,0x0F,0xC0,0x00,0xF8,
0x0F,0xC0,0x00,0xFC,0x1F,0x80,0x00,0xFC,0x1F,0x80,0x00,0x7C,0x1F,0x80,0x00,0x7C,
0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,0x1F,0x80,0x00,0x7E,
0x1F,0x80,0x00,0x7E,0x1F,0xC0,0x00,0xFE,0x1F,0xC0,0x00,0xFE,0x0F,0xC0,0x01,0xFE,
0x0F,0xE0,0x03,0xFE,0x0F,0xF0,0x07,0xFE,0x07,0xF8,0x0F,0xFE,0x03,0xFC,0x3F,0xFE,
0x01,0xFF,0xFF,0x7E,0x00,0xFF,0xFC,0xFE,0x00,0x1F,0xF0,0xFC,0x00,0x00,0x00,0xFC,
0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0xFC,0x00,0x00,0x01,0xF8,0x00,0x00,0x01,0xF8,
0x00,0x00,0x01,0xF8,0x00,0x00,0x03,0xF0,0x03,0xE0,0x03,0xF0,0x07,0xF0,0x07,0xE0,
0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xC0,0x07,0xF0,0x3F,0x80,0x07,0xF8,0xFF,0x00,
0x03,0xFF,0xFE,0x00,0x01,0xFF,0xF8,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"9",9*/
};
#endif
const unsigned char asc2_1206[95][12] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /*" ",0*/
@ -599,3 +608,5 @@ const unsigned char Hzk[][32] = {
{ 0x08, 0xCC, 0x4A, 0x49, 0x48, 0x4A, 0xCC, 0x18, 0x00, 0x7F, 0x88, 0x88, 0x84, 0x82, 0xE0, 0x00 },
{ 0x00, 0xFF, 0x12, 0x12, 0x52, 0x92, 0x7F, 0x00, 0x00, 0x7E, 0x88, 0x88, 0x84, 0x82, 0xE0, 0x00 }, /*"能",3*/
};
// clang-format on

View file

@ -0,0 +1,45 @@
/**
* @file font.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 __FONT_FONT_ASCII_16X8_H__
#define __FONT_FONT_ASCII_16X8_H__
#define FONT_ASCII_16X8 1
#define FONT_ASCII_32X16 0
#define FONT_ASCII_64X32 0
#if FONT_ASCII_16X8
extern const unsigned char font_ascii_16x8[];
#endif
#if FONT_ASCII_64X32
extern const unsigned char ascii_64x32[];
#endif
extern const unsigned char asc2_1206[95][12];
extern const unsigned char asc2_1608[95][16];
extern const unsigned char asc2_2412[95][36];
extern const unsigned char Hzk[][32];
extern const unsigned char c_chFont1608[95][16];
#endif

View file

@ -0,0 +1,389 @@
/**
* @file ili9341.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 "ili9341.h"
#include "mcu_lcd.h"
#include "hal_spi.h"
#include "hal_dma.h"
#include "hal_gpio.h"
static struct device *spi0;
static struct device *dma_ch3;
const ili9341_init_cmd_t ili9341_init_cmds[] = {
{ 0x11, "\x00", 0x80 }, /* Exit sleep */
{ 0xCF, "\x00\xd9\x30", 3 },
{ 0xED, "\x64\x03\x12\x81", 4 },
{ 0xE8, "\x85\x01\x78", 3 },
{ 0xCB, "\x39\x2C\x00\x34\x02", 5 },
{ 0xF7, "\x20", 1 },
{ 0xEA, "\x00\x00", 2 },
{ 0xC0, "\x23", 1 }, /*Power control*/
{ 0xC1, "\x12", 1 }, /*Power control */
{ 0xC2, "\x11", 1 },
{ 0xC5, "\x40\x30", 2 }, /*VCOM control 1*/
{ 0xC7, "\xa9", 1 }, /*VCOM control 2*/
{ 0x36, "\x08", 1 }, /*Memory Access Control*/
{ 0x3A, "\x55", 1 }, /*Pixel Format Set*/
{ 0xB1, "\x00\x18", 2 }, /* Frame Rate Control */
{ 0xB6, "\x0a\xa2", 2 }, /* Display Function Control */
{ 0x0C, "\xd5", 1 }, /* display pixel format,RGB 16bits,MCU 16bits */
{ 0xF2, "\x00", 1 }, /* 3Gamma Function Disable */
{ 0xF7, "\x20", 1 },
{ 0x26, "\x01", 1 }, /* Gamma curve selected */
{ 0xE0, "\x1F\x1A\x18\x0A\x0F\x06\x45\x87\x32\x0A\x07\x02\x07\x05\x00", 15 }, /* Set Gamma */
{ 0XE1, "\x00\x25\x27\x05\x10\x09\x3A\x78\x4D\x05\x18\x0D\x38\x3A\x1F", 15 }, /* Set Gamma */
{ 0xB7, "\x07", 1 },
{ 0x29, "\x00", 0x80 }, /* Display on */
};
/**
* @brief ili9341_spi_init
*
* @return int 0:succes 1:error
*/
static int ili9341_spi_init(void)
{
gpio_set_mode(ILI9341_CS_PIN, GPIO_OUTPUT_MODE);
gpio_set_mode(ILI9341_DC_PIN, GPIO_OUTPUT_MODE);
ILI9341_CS_HIGH;
ILI9341_DC_HIGH;
spi0 = device_find("lcd_dev_ifs");
if (spi0) {
device_close(spi0);
} else {
spi_register(SPI0_INDEX, "lcd_dev_ifs");
spi0 = device_find("lcd_dev_ifs");
}
if (spi0) {
SPI_DEV(spi0)->mode = SPI_MASTER_MODE;
SPI_DEV(spi0)->clk = (36 * 1000 * 1000);
SPI_DEV(spi0)->direction = SPI_MSB_BYTE0_DIRECTION_FIRST;
SPI_DEV(spi0)->clk_polaraity = SPI_POLARITY_LOW;
SPI_DEV(spi0)->datasize = SPI_DATASIZE_8BIT;
SPI_DEV(spi0)->clk_phase = SPI_PHASE_1EDGE;
SPI_DEV(spi0)->fifo_threshold = 1;
device_open(spi0, DEVICE_OFLAG_STREAM_TX);
} else {
return 1;
}
dma_ch3 = device_find("lcd_dev_ifs_dma");
if (dma_ch3) {
device_close(dma_ch3);
} else {
dma_register(DMA0_CH3_INDEX, "lcd_dev_ifs_dma");
dma_ch3 = device_find("lcd_dev_ifs_dma");
}
if (dma_ch3) {
DMA_DEV(dma_ch3)->direction = DMA_MEMORY_TO_PERIPH;
DMA_DEV(dma_ch3)->transfer_mode = DMA_LLI_ONCE_MODE;
DMA_DEV(dma_ch3)->src_req = DMA_REQUEST_NONE;
DMA_DEV(dma_ch3)->dst_req = DMA_REQUEST_SPI0_TX;
DMA_DEV(dma_ch3)->src_width = DMA_TRANSFER_WIDTH_8BIT;
DMA_DEV(dma_ch3)->dst_width = DMA_TRANSFER_WIDTH_8BIT;
DMA_DEV(dma_ch3)->src_burst_size = DMA_BURST_1BYTE;
DMA_DEV(dma_ch3)->dst_burst_size = DMA_BURST_1BYTE;
device_open(dma_ch3, 0);
device_set_callback(dma_ch3, NULL);
device_control(spi0, DEVICE_CTRL_ATTACH_TX_DMA, dma_ch3);
device_control(dma_ch3, DEVICE_CTRL_SET_INT, NULL);
} else {
return 1;
}
device_control(spi0, DEVICE_CTRL_TX_DMA_SUSPEND, NULL);
return 0;
}
/**
* @brief ili9341_write_cmd
*
* @param cmd
* @return int 0:succes 1:error
*/
static int ili9341_write_cmd(uint8_t cmd)
{
ILI9341_DC_LOW;
ILI9341_CS_LOW;
int res = spi_transmit(spi0, &cmd, 1, SPI_TRANSFER_TYPE_8BIT);
ILI9341_CS_HIGH;
return res;
}
/**
* @brief ili9341_write_data_1byte
*
* @param data
* @return int 0:succes 1:error
*/
static int ili9341_write_data_1byte(uint8_t data)
{
ILI9341_DC_HIGH;
ILI9341_CS_LOW;
int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_8BIT);
ILI9341_CS_HIGH;
return res;
}
/**
* @brief ili9341_write_data_2byte
*
* @param data
* @return int 0:succes 1:error
*/
// static int ili9341_write_data_2byte(uint16_t data)
// {
// data = ((data >> 8) & 0xFF) | data << 8;
// ILI9341_DC_HIGH;
// ILI9341_CS_LOW;
// int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_16BIT);
// ILI9341_CS_HIGH;
// return res;
// }
/**
* @brief ili9341_write_data_4byte
*
* @param data
* @return int 0:succes 1:error
*/
static int ili9341_write_data_4byte(uint32_t data)
{
data = ((data >> 24) & 0xFF) | ((data >> 8) & 0xFF00) | ((data << 8) & 0xFF0000) | ((data << 24));
ILI9341_DC_HIGH;
ILI9341_CS_LOW;
int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_32BIT);
ILI9341_CS_HIGH;
return res;
}
/**
* @brief ili9341_draw_is_busy, After the call ili9341_draw_picture_dma must check this,
* if ili9341_draw_is_busy() == 1, Don't allow other draw !!
* can run in the DMA interrupt callback function.
*
* @return int 0:draw end; 1:Being draw
*/
int ili9341_draw_is_busy(void)
{
if (device_control(SPI_DEV(spi0)->tx_dma, DMA_CHANNEL_GET_STATUS, NULL)) {
return 1;
} else {
device_control(spi0, DEVICE_CTRL_TX_DMA_SUSPEND, NULL);
ILI9341_CS_HIGH;
return 0;
}
}
/**
* @brief ili9341_init
*
* @return int
*/
int ili9341_init()
{
int res = ili9341_spi_init();
if (res) {
return res;
}
for (uint16_t i = 0; i < (sizeof(ili9341_init_cmds) / sizeof(ili9341_init_cmd_t)); i++) {
/* send register address */
res |= ili9341_write_cmd(ili9341_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (ili9341_init_cmds[i].databytes & 0x7F); j++) {
res |= ili9341_write_data_1byte(ili9341_init_cmds[i].data[j]);
}
if (res) {
return res;
}
/* delay */
if (ili9341_init_cmds[i].databytes & 0x80) {
bflb_platform_delay_ms(100);
}
}
ili9341_set_draw_window(0, 0, ILI9341_H, ILI9341_W);
return res;
}
/**
* @brief
*
* @param dir
* @param mir_flag
*/
int ili9341_set_dir(uint8_t dir, uint8_t mir_flag)
{
ili9341_write_cmd(0x36);
switch (dir) {
case 0:
if (!mir_flag)
ili9341_write_data_1byte(0x08);
else
ili9341_write_data_1byte(0x48);
break;
case 1:
if (!mir_flag)
ili9341_write_data_1byte(0xA8);
else
ili9341_write_data_1byte(0x28);
break;
case 2:
if (!mir_flag)
ili9341_write_data_1byte(0xC8);
else
ili9341_write_data_1byte(0x88);
break;
case 3:
if (!mir_flag)
ili9341_write_data_1byte(0x68);
else
ili9341_write_data_1byte(0xE8);
break;
default:
return -1;
break;
}
return dir;
}
/**
* @brief ili9341_set_draw_window
*
* @param x1
* @param y1
* @param x2
* @param y2
*/
void ili9341_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
{
#if ILI9341_OFFSET_X
x1 += ILI9341_OFFSET_X;
x2 += ILI9341_OFFSET_X;
#endif
#if ILI9341_OFFSET_Y
y1 += ILI9341_OFFSET_Y;
y2 += ILI9341_OFFSET_Y;
#endif
ili9341_write_cmd(0x2a);
ili9341_write_data_4byte(x1 << 16 | (x2 & 0xFFFF));
ili9341_write_cmd(0x2b);
ili9341_write_data_4byte(y1 << 16 | (y2 & 0xFFFF));
ili9341_write_cmd(0x2c);
}
/**
* @brief ili9341_draw_point
*
* @param x
* @param y
* @param color
*/
void ili9341_draw_point(uint16_t x, uint16_t y, uint16_t color)
{
if (lcd_auto_swap_flag) {
color = ((color >> 8) & 0xFF) | color << 8;
}
ili9341_set_draw_window(x, y, x, y);
ILI9341_DC_HIGH;
ILI9341_CS_LOW;
spi_transmit(spi0, &color, 1, SPI_TRANSFER_TYPE_16BIT);
ILI9341_CS_HIGH;
}
/**
* @brief ili9341_draw_area
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param color
*/
void ili9341_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
if (lcd_auto_swap_flag) {
color = ((color >> 8) & 0xFF) | color << 8;
}
ili9341_set_draw_window(x1, y1, x2, y2);
ILI9341_DC_HIGH;
ILI9341_CS_LOW;
for (uint16_t i = y1; i <= y2; i++) {
for (uint16_t j = x1; j <= x2; j++)
spi_transmit(spi0, &color, 1, SPI_TRANSFER_TYPE_16BIT);
}
ILI9341_CS_HIGH;
}
/**
* @brief ili9341_draw_picture_dma, Non-blocking! Using DMA acceleration, Not waiting for the draw end
* After the call, No other operations are allowed until (ili9341_draw_is_busy()==0)
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void ili9341_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture)
{
size_t picture_size = (x2 - x1 + 1) * (y2 - y1 + 1);
/* 数据高低位切换 */
if (lcd_auto_swap_flag) {
lcd_swap_color_data16(picture, picture, picture_size);
}
ili9341_set_draw_window(x1, y1, x2, y2);
ILI9341_DC_HIGH;
ILI9341_CS_LOW;
device_control(spi0, DEVICE_CTRL_TX_DMA_RESUME, NULL);
device_write(spi0, 0, picture, picture_size * 2);
}
/**
* @brief ili9341_draw_picture,BlockingUsing DMA acceleration,Waiting for the draw end
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void ili9341_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture)
{
ili9341_draw_picture_nonblocking(x1, y1, x2, y2, picture);
while (ili9341_draw_is_busy()) {
};
}

View file

@ -0,0 +1,58 @@
/**
* @file ili9341.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 _ILI9341_H_
#define _ILI9341_H_
#include "bflb_platform.h"
#define ILI9341_CS_PIN GPIO_PIN_10
#define ILI9341_DC_PIN GPIO_PIN_22
#define ILI9341_CS_HIGH gpio_write(ILI9341_CS_PIN, 1)
#define ILI9341_CS_LOW gpio_write(ILI9341_CS_PIN, 0)
#define ILI9341_DC_HIGH gpio_write(ILI9341_DC_PIN, 1)
#define ILI9341_DC_LOW gpio_write(ILI9341_DC_PIN, 0)
#define ILI9341_W 240 /* ILI9341 LCD width */
#define ILI9341_H 320 /* ILI9341 LCD height */
#define ILI9341_OFFSET_X 0
#define ILI9341_OFFSET_Y 0
typedef struct {
uint8_t cmd;
const char *data;
uint8_t databytes; /* Num of data in data; bit 7 = delay after set */
} ili9341_init_cmd_t;
int ili9341_init();
int ili9341_set_dir(uint8_t dir, uint8_t mir_flag);
void ili9341_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2);
void ili9341_draw_point(uint16_t x, uint16_t y, uint16_t color);
void ili9341_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void ili9341_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture);
void ili9341_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture);
int ili9341_draw_is_busy(void);
#endif

View file

@ -0,0 +1,407 @@
/**
* @file mcu_lcd.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 "mcu_lcd.h"
#include "font.h"
#include "bflb_platform.h"
#include "drv_device.h"
struct device *lcd_dev_ifs = NULL;
uint8_t lcd_dir = 0;
uint8_t lcd_auto_swap_flag = 1;
uint16_t lcd_max_x = LCD_W, lcd_max_y = LCD_H;
/**
* @brief ,
*
* @param flag 0:off 1:on
* @return int
*/
int lcd_auto_swap_set(uint8_t flag)
{
lcd_auto_swap_flag = flag ? 1 : 0;
return lcd_auto_swap_flag;
}
/**
* @brief lcd_auto_swap_flag == 1
*
* @param dst destination
* @param src source
* @param color_num color num
* @return int
*/
int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, size_t color_num)
{
for (size_t i = 0; i < color_num; i++) {
dst[i] = (src[i] << 8) | (src[i] >> 8);
}
return 0;
}
/**
* @brief LCD init
*
* @return int
*/
int lcd_init(void)
{
int res;
#if defined(MCU_LCD_ILI9341)
res = ili9341_init();
#elif defined(MCU_LCD_ST7735S)
res = st7735s_init();
#elif defined(MCU_LCD_ST7789V)
res = st7789v_init();
#endif
lcd_dev_ifs = device_find("lcd_dev_ifs");
return res;
}
/**
* @brief Set display direction and mir
*
* @param dir 0~3 : 0~270 Angle
* @param mir_flag 0:normal 1:Horizontal Mirroring(if support)
* @return int
*/
int lcd_set_dir(uint8_t dir, uint8_t mir_flag)
{
dir %= 4;
lcd_dir = dir;
if (dir == 0 || dir == 2) {
lcd_max_x = LCD_W;
lcd_max_y = LCD_H;
} else {
lcd_max_x = LCD_H;
lcd_max_y = LCD_W;
}
#if defined(MCU_LCD_ILI9341)
ili9341_set_dir(dir, mir_flag);
return 0;
#elif defined(MCU_LCD_ST7735S)
st7735s_set_dir(dir);
return 0;
#elif defined(MCU_LCD_ST7789V)
st7789v_set_dir(dir);
return 0;
#endif
}
/**
* @brief Draws a point at the specified position
*
* @param x X coordinate
* @param y Y coordinate
* @param color
* @return int
*/
int lcd_draw_point(uint16_t x, uint16_t y, lcd_color_t color)
{
#if defined(MCU_LCD_ILI9341)
ili9341_draw_point(x, y, color);
return 0;
#elif defined(MCU_LCD_ST7735S)
st7735s_draw_point(x, y, color);
return 0;
#elif defined(MCU_LCD_ST7789V)
st7789v_draw_point(x, y, color);
return 0;
#endif
}
/**
* @brief Draw a monochrome rectangle (May be less efficient)
*
* @param x1 start coordinate
* @param y1 start coordinate
* @param x2 end coordinate
* @param y2 end coordinate
* @param color
* @return int
*/
int lcd_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t color)
{
#if defined(MCU_LCD_ILI9341)
ili9341_draw_area(x1, y1, x2, y2, color);
return 0;
#elif defined(MCU_LCD_ST7735S)
st7735s_draw_area(x1, y1, x2, y2, color);
return 0;
#elif defined(MCU_LCD_ST7789V)
st7789v_draw_area(x1, y1, x2, y2, color);
return 0;
#endif
}
/**
* @brief Draw a picture in the designated area(blocking),Will wait for the drawing to finish
*
* @param x1 start coordinate
* @param y1 start coordinate
* @param x2 end coordinate
* @param y2 end coordinate
* @param picture
* @return int
*/
int lcd_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t *picture)
{
#if defined(MCU_LCD_ILI9341)
ili9341_draw_picture_blocking(x1, y1, x2, y2, picture);
return 0;
#elif defined(MCU_LCD_ST7735S)
st7735s_draw_picture_blocking(x1, y1, x2, y2, picture);
return 0;
#elif defined(MCU_LCD_ST7789V)
st7789v_draw_picture_blocking(x1, y1, x2, y2, picture);
return 0;
#endif
}
/**
* @brief Draw a picture in the designated area(nonblocking,if it supports),
* Must be calle lcd_draw_is_busy! and (lcd_draw_is_busyd()==1) before performing other drawing and changing picture data!
*
* @param x1 start coordinate
* @param y1 start coordinate
* @param x2 end coordinate
* @param y2 end coordinate
* @param picture
* @return int
*/
int lcd_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t *picture)
{
#if defined(MCU_LCD_ILI9341)
ili9341_draw_picture_nonblocking(x1, y1, x2, y2, picture);
return 0;
#elif defined(MCU_LCD_ST7735S)
st7735s_draw_picture_nonblocking(x1, y1, x2, y2, picture);
return 0;
#elif defined(MCU_LCD_ST7789V)
st7789v_draw_picture_nonblocking(x1, y1, x2, y2, picture);
return 0;
#endif
}
/**
* @brief Check if it is drawing, must call it After call lcd_draw_picture_nonblocking
*
* @return int 1:lcd Drawing,Prohibit other operations! 0:Drawing is over
*/
int lcd_draw_is_busy(void)
{
#if defined(MCU_LCD_ILI9341)
return ili9341_draw_is_busy();
#elif defined(MCU_LCD_ST7735S)
return st7735s_draw_is_busy();
#elif defined(MCU_LCD_ST7789V)
return st7789v_draw_is_busy();
#endif
}
/**
* @brief clear lcd
*
* @param color
* @return int
*/
int lcd_clear(uint16_t color)
{
if (lcd_dir == 0 || lcd_dir == 2) {
lcd_draw_area(0, 0, LCD_W, LCD_H, color);
} else {
lcd_draw_area(0, 0, LCD_H, LCD_W, color);
}
return 0;
}
/**
* @brief
*
* @param x1 start coordinate
* @param y1 start coordinate
* @param x2 end coordinate
* @param y2 end coordinate
* @param color
* @return int
*/
int lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t color)
{
int xVariation, yVariation, temp;
int absX, absY, i;
xVariation = x2 - x1;
yVariation = y2 - y1;
absX = ABS(xVariation);
absY = ABS(yVariation);
if (absX > absY) {
for (i = 0; i < absX + 1; i++) {
temp = yVariation * 100 / absX * i / 100;
if (xVariation > 0) {
lcd_draw_point(x1 + i, y1 + temp, color);
} else {
lcd_draw_point(x1 - i, y1 + temp, color);
}
}
} else {
for (i = 0; i < absY + 1; i++) {
temp = xVariation * 100 / absY * i / 100;
if (yVariation > 0) {
lcd_draw_point(x1 + temp, y1 + i, color);
} else {
lcd_draw_point(x1 + temp, y1 - i, color);
}
}
}
return 0;
}
/**
* @brief
*
* @param x1 start coordinate
* @param y1 start coordinate
* @param x2 end coordinate
* @param y2 end coordinate
* @param color
* @return int
*/
int lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t color)
{
lcd_draw_line(x1, y1, x2, y1, color);
lcd_draw_line(x2, y1, x2, y2, color);
lcd_draw_line(x2, y2, x1, y2, color);
lcd_draw_line(x1, y2, x1, y1, color);
return 0;
}
/**
* @brief draw a circle
*
* @param x coordinate
* @param y coordinate
* @param r
* @param color
* @return int
*/
int lcd_draw_circle(uint16_t x, uint16_t y, uint16_t r, lcd_color_t color)
{
int a = 0, b;
int di;
b = r;
di = 3 - (r << 1);
while (a <= b) {
lcd_draw_point(x - b, y - a, color);
lcd_draw_point(x + b, y - a, color);
lcd_draw_point(x - a, y + b, color);
lcd_draw_point(x - b, y - a, color);
lcd_draw_point(x - a, y - b, color);
lcd_draw_point(x + b, y + a, color);
lcd_draw_point(x + a, y - b, color);
lcd_draw_point(x + a, y + b, color);
lcd_draw_point(x - b, y + a, color);
a++;
if (di < 0) {
di += 4 * a + 6;
} else {
di += 10 + 4 * (a - b);
b--;
}
lcd_draw_point(x + a, y + b, color);
}
return 0;
}
#if FONT_ASCII_16X8
/**
* @brief Draw font(16*8) ,Use double buffer to speed up drawing
*
* @param x start coordinate
* @param y start coordinate
* @param color font color
* @param bk_color Background color
* @param str The string to be displayed
* @param num number of characters displayed
* @return int
*/
int lcd_draw_str_ascii16(uint16_t x, uint16_t y, lcd_color_t color, lcd_color_t bk_color, uint8_t *str, uint8_t num)
{
lcd_color_t draw_buff[2][16 * 8];
uint16_t buff_color_num;
uint8_t buff_using_num = 0;
uint8_t ch, temp;
uint16_t x0 = x;
for (uint16_t i = 0; i < num && str[i]; i++) {
if (str[i] < 128) {
if (x > LCD_W - 8) {
x = x0;
y += 16;
}
if (x > LCD_W - 8 || y > LCD_H - 16)
break;
ch = str[i];
if (ch >= ' ') {
ch = ch - ' ';
} else if (ch == '\n') {
x = x0;
y += 16;
continue;
} else {
continue;
}
buff_color_num = 0;
for (uint8_t j = 0; j < 16; j++) {
temp = font_ascii_16x8[ch * 16 + j];
for (uint8_t k = 0; k < 8; k++) {
if (temp & (0x80 >> k))
draw_buff[buff_using_num][buff_color_num++] = color;
else
draw_buff[buff_using_num][buff_color_num++] = bk_color;
}
}
while (lcd_draw_is_busy()) {
};
lcd_draw_picture_nonblocking(x, y, x + 7, y + 15, draw_buff[buff_using_num]);
buff_using_num = !buff_using_num;
x += 8;
} else {
continue;
}
}
while (lcd_draw_is_busy()) {
};
return 0;
}
#endif

View file

@ -0,0 +1,80 @@
/**
* @file mcu_lcd.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 _MCU_LCD_H_
#define _MCU_LCD_H_
#include "font.h"
#define MCU_LCD_ILI9341
// #define MCU_LCD_ST7735S /* 未验证 */
// #define MCU_LCD_ST7789V
extern struct device *lcd_dev_ifs;
#if defined MCU_LCD_ILI9341
#include "ili9341.h"
#define LCD_W ILI9341_W
#define LCD_H ILI9341_H
typedef uint16_t lcd_color_t;
#elif defined MCU_LCD_ST7735S
#include "st7735s.h"
#define LCD_W ST7735S_W
#define LCD_H ST7735S_H
typedef uint16_t lcd_color_t;
#elif defined MCU_LCD_ST7789V
#include "st7789v.h"
#define LCD_W ST7789V_W
#define LCD_H ST7789V_H
typedef uint16_t lcd_color_t;
#endif
#define ABS(x) ((x) > 0 ? (x) : -(x))
extern struct device *lcd_dev_ifs;
extern uint8_t lcd_auto_swap_flag;
int lcd_auto_swap_set(uint8_t flag);
int lcd_swap_color_data16(uint16_t *dst, uint16_t *src, size_t num);
int lcd_init(void);
int lcd_set_dir(uint8_t dir, uint8_t mir_flag);
int lcd_get_dir();
int lcd_draw_point(uint16_t x, uint16_t y, lcd_color_t color);
int lcd_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t color);
int lcd_clear(uint16_t color);
int lcd_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t *picture);
int lcd_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t *picture);
int lcd_draw_is_busy(void);
int lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t color);
int lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, lcd_color_t color);
int lcd_draw_circle(uint16_t x, uint16_t y, uint16_t r, lcd_color_t color);
#if FONT_ASCII_16X8
int lcd_draw_str_ascii16(uint16_t x, uint16_t y, lcd_color_t color, lcd_color_t bk_color, uint8_t *str, uint8_t num);
#endif
#endif

View file

@ -0,0 +1,388 @@
#include "ssd1306.h"
#include "hal_i2c.h"
#include "hal_spi.h"
#include "hal_gpio.h"
#include "font.h"
#define SSD1306_USING_I2C 0
#define SSD1306_USING_SPI 1
#define INTERFACE_SELECT SSD1306_USING_SPI
static uint8_t OLED_GRAM[128][8];
struct device *ssd_1306;
static void ssd1306_write_byte(uint8_t data, uint8_t cmd)
{
#if INTERFACE_SELECT == SSD1306_USING_I2C
i2c_msg_t msg;
if (cmd) {
msg.subaddr = 0x40;
} else {
msg.subaddr = 0x00;
}
msg.buf = &data;
msg.flags = SUB_ADDR_1BYTE | I2C_WR;
msg.len = 1;
msg.slaveaddr = 0x3c;
i2c_transfer(ssd_1306, &msg, 1);
#else
if (cmd) {
CS1_LOW;
DC_HIGH;
} else {
CS1_LOW;
DC_LOW;
}
spi_transmit(ssd_1306, &data, 1, SPI_TRANSFER_TYPE_8BIT);
CS1_HIGH;
DC_HIGH;
#endif
}
void ssd1306_init(void)
{
#if INTERFACE_SELECT == SSD1306_USING_I2C
i2c_register(I2C0_INDEX, "lcd_dev_ifs");
ssd_1306 = device_find("lcd_dev_ifs");
if (ssd_1306) {
device_open(ssd_1306, 0);
}
ssd1306_write_byte(0xAE, SSD1306_CMD); //--turn off oled panel
ssd1306_write_byte(0x00, SSD1306_CMD); //---set low column address
ssd1306_write_byte(0x10, SSD1306_CMD); //---set high column address
ssd1306_write_byte(0x40, SSD1306_CMD); //--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
ssd1306_write_byte(0x81, SSD1306_CMD); //--set contrast control register
ssd1306_write_byte(0xCF, SSD1306_CMD); // Set SEG Output Current Brightness
ssd1306_write_byte(0xA1, SSD1306_CMD); //--Set SEG/Column Mapping
ssd1306_write_byte(0xC0, SSD1306_CMD); //Set COM/Row Scan Direction
ssd1306_write_byte(0xA6, SSD1306_CMD); //--set normal display
ssd1306_write_byte(0xA8, SSD1306_CMD); //--set multiplex ratio(1 to 64)
ssd1306_write_byte(0x3f, SSD1306_CMD); //--1/64 duty
ssd1306_write_byte(0xD3, SSD1306_CMD); //-set display offset Shift Mapping RAM Counter (0x00~0x3F)
ssd1306_write_byte(0x00, SSD1306_CMD); //-not offset
ssd1306_write_byte(0xd5, SSD1306_CMD); //--set display clock divide ratio/oscillator frequency
ssd1306_write_byte(0x80, SSD1306_CMD); //--set divide ratio, Set Clock as 100 Frames/Sec
ssd1306_write_byte(0xD9, SSD1306_CMD); //--set pre-charge period
ssd1306_write_byte(0xF1, SSD1306_CMD); //Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
ssd1306_write_byte(0xDA, SSD1306_CMD); //--set com pins hardware configuration
ssd1306_write_byte(0x12, SSD1306_CMD);
ssd1306_write_byte(0xDB, SSD1306_CMD); //--set vcomh
ssd1306_write_byte(0x40, SSD1306_CMD); //Set VCOM Deselect Level
ssd1306_write_byte(0x20, SSD1306_CMD); //-Set Page Addressing Mode (0x00/0x01/0x02)
ssd1306_write_byte(0x02, SSD1306_CMD); //
ssd1306_write_byte(0x8D, SSD1306_CMD); //--set Charge Pump enable/disable
ssd1306_write_byte(0x14, SSD1306_CMD); //--set(0x10) disable
ssd1306_write_byte(0xA4, SSD1306_CMD); // Disable Entire Display On (0xa4/0xa5)
ssd1306_write_byte(0xA6, SSD1306_CMD); // Disable Inverse Display On (0xa6/a7)
ssd1306_write_byte(0xAF, SSD1306_CMD); //--turn on oled panel
ssd1306_display_on();
ssd1306_clear_screen(0xff);
#else
gpio_set_mode(OLED_CS_PIN, GPIO_OUTPUT_MODE);
gpio_set_mode(OLED_DC_PIN, GPIO_OUTPUT_MODE);
gpio_set_mode(OLED_RES_PIN, GPIO_OUTPUT_MODE);
gpio_write(OLED_CS_PIN, 1); //CS1
gpio_write(OLED_DC_PIN, 1); //DC
spi_register(SPI0_INDEX, "lcd_dev_ifs");
ssd_1306 = device_find("lcd_dev_ifs");
if (ssd_1306) {
device_open(ssd_1306, DEVICE_OFLAG_STREAM_TX | DEVICE_OFLAG_STREAM_RX);
}
CS1_HIGH;
DC_HIGH;
RES_LOW;
bflb_platform_delay_ms(100);
RES_HIGH;
ssd1306_write_byte(0xAE, SSD1306_CMD);
ssd1306_write_byte(0xD5, SSD1306_CMD);
ssd1306_write_byte(0x50, SSD1306_CMD);
ssd1306_write_byte(0xA8, SSD1306_CMD);
ssd1306_write_byte(0x3F, SSD1306_CMD);
ssd1306_write_byte(0xD3, SSD1306_CMD);
ssd1306_write_byte(0x00, SSD1306_CMD);
ssd1306_write_byte(0x40, SSD1306_CMD);
ssd1306_write_byte(0x8D, SSD1306_CMD);
ssd1306_write_byte(0x14, SSD1306_CMD);
ssd1306_write_byte(0x20, SSD1306_CMD);
ssd1306_write_byte(0x02, SSD1306_CMD);
ssd1306_write_byte(0xA1, SSD1306_CMD);
ssd1306_write_byte(0xC0, SSD1306_CMD);
ssd1306_write_byte(0xDA, SSD1306_CMD);
ssd1306_write_byte(0x12, SSD1306_CMD);
ssd1306_write_byte(0x81, SSD1306_CMD);
ssd1306_write_byte(0xEF, SSD1306_CMD);
ssd1306_write_byte(0xD9, SSD1306_CMD);
ssd1306_write_byte(0xF1, SSD1306_CMD);
ssd1306_write_byte(0xDB, SSD1306_CMD);
ssd1306_write_byte(0x30, SSD1306_CMD);
ssd1306_write_byte(0xA4, SSD1306_CMD);
ssd1306_write_byte(0xA6, SSD1306_CMD);
ssd1306_write_byte(0xAF, SSD1306_CMD);
ssd1306_clear_screen(0);
#endif
}
void ssd1306_display_on(void)
{
ssd1306_write_byte(0x8D, SSD1306_CMD);
ssd1306_write_byte(0x14, SSD1306_CMD);
ssd1306_write_byte(0xAF, SSD1306_CMD);
}
/**
* @brief OLED turns off
*
* @param None
*
* @retval None
**/
void ssd1306_display_off(void)
{
ssd1306_write_byte(0x8D, SSD1306_CMD);
ssd1306_write_byte(0x10, SSD1306_CMD);
ssd1306_write_byte(0xAE, SSD1306_CMD);
}
void ssd1306_refresh_gram(void)
{
uint8_t i, j;
for (i = 0; i < 8; i++) {
ssd1306_write_byte(0xB0 + i, SSD1306_CMD);
ssd1306_write_byte(0x02, SSD1306_CMD);
ssd1306_write_byte(0x10, SSD1306_CMD);
for (j = 0; j < 128; j++) {
ssd1306_write_byte(OLED_GRAM[j][i], SSD1306_DAT);
}
}
}
void ssd1306_clear_screen(uint8_t fill)
{
memset(OLED_GRAM, fill, sizeof(OLED_GRAM));
ssd1306_refresh_gram();
}
/**
* @brief Draws a piont on the screen
*
* @param x: Specifies the X position
* @param y: Specifies the Y position
* @param mode: 0: the point turns off 1: the piont turns on
*
* @retval None
**/
void ssd1306_draw_point(uint8_t x, uint8_t y, uint8_t mode)
{
uint8_t i, j, temp;
if (x > 127 || y > 63)
return;
i = 7 - y / 8;
j = y % 8;
temp = 0x01 << (7 - j);
if (mode == 0)
OLED_GRAM[x][i] &= ~temp;
else
OLED_GRAM[x][i] |= temp;
}
/**
* @brief Displays one character at the specified position
*
* @param x: Specifies the X position
* @param y: Specifies the Y position
* @param size:
* @param mode
* @retval
**/
void ssd1306_display_char(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode)
{
uint8_t temp, t, t1;
uint8_t y0 = y;
uint8_t csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2);
chr = chr - ' ';
for (t = 0; t < csize; t++) {
switch (size) {
case 12:
temp = asc2_1206[chr][t];
break;
case 16:
temp = asc2_1608[chr][t];
break;
case 24:
temp = asc2_2412[chr][t];
break;
default:
return;
}
for (t1 = 0; t1 < 8; t1++) {
if (temp & 0x80)
ssd1306_draw_point(x, y, mode);
else
ssd1306_draw_point(x, y, !mode);
temp <<= 1;
y++;
if ((y - y0) == size) {
y = y0;
x++;
break;
}
}
}
}
/**
* @brief Displays a string on the screen
*
* @param x: Specifies the X position
* @param y: Specifies the Y position
* @param string: Pointer to a string to display on the screen
*
* @retval None
**/
void ssd1306_display_string(uint8_t x, uint8_t y, const char *string, uint8_t size, uint8_t mode)
{
while (*string != '\0') {
if (x > (SSD1306_WIDTH - size / 2)) {
x = 0;
y += size;
if (y > (SSD1306_HEIGHT - size)) {
y = x = 0;
ssd1306_clear_screen(0x00);
}
}
ssd1306_display_char(x, y, *string, size, mode);
x += size / 2;
string++;
}
}
void ssd1306_display_chinese(uint8_t x, uint8_t y, uint8_t no, uint8_t mode)
{
uint8_t temp1;
uint8_t temp2;
uint8_t t1, t2;
uint8_t x0 = x, y0 = y;
for (t1 = 0; t1 < 16; t1++) {
temp1 = Hzk[2 * no][t1];
for (t2 = 0; t2 < 8; t2++) {
if (temp1 & 0x01)
ssd1306_draw_point(x, y, mode);
else
ssd1306_draw_point(x, y, !mode);
temp1 >>= 1;
y++;
}
y = y0;
x++;
}
x = x0;
y = y0 + 8;
y0 = y;
for (t1 = 0; t1 < 16; t1++) {
temp2 = Hzk[2 * no + 1][t1];
for (t2 = 0; t2 < 8; t2++) {
if (temp2 & 0x01)
ssd1306_draw_point(x, y, mode);
else
ssd1306_draw_point(x, y, !mode);
temp2 >>= 1;
y++;
}
y = y0;
x++;
}
}
void ssd1306_draw_bmp(uint8_t x, uint8_t y, const unsigned char *image, uint8_t index, uint8_t mode)
{
uint8_t temp, t1;
uint16_t i;
uint8_t y0 = y;
for (i = 0; i < 1024; i++) {
temp = image[1024 * index + i];
for (t1 = 0; t1 < 8; t1++) {
if (temp & 0x80)
ssd1306_draw_point(x, y, mode);
else
ssd1306_draw_point(x, y, !mode);
temp <<= 1;
y++;
if ((y - y0) == 64) {
y = y0;
x++;
break;
}
}
}
}
void ssd1306_draw_alpha(uint8_t x, uint8_t y, const unsigned char *image, uint8_t index, uint8_t mode)
{
uint8_t temp, t1;
uint16_t i;
uint8_t y0 = y;
for (i = 0; i < 1024; i++) {
temp = image[1024 * index + i];
for (t1 = 0; t1 < 8; t1++) {
if (temp & 0x80)
ssd1306_draw_point(x, y, mode);
temp <<= 1;
y++;
if ((y - y0) == 64) {
y = y0;
x++;
break;
}
}
}
}
/**
* @brief Fills a rectangle
*
* @param x1: Specifies the X position 1 (X top left position)
* @param y1: Specifies the Y position 1 (Y top left position)
* @param x2: Specifies the X position 2 (X bottom right position)
* @param y3: Specifies the Y position 2 (Y bottom right position)
*
* @retval
**/
void ssd1306_fill_screen(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t chDot)
{
uint8_t x, y;
for (x = x1; x <= x2; x++) {
for (y = y1; y <= y2; y++) {
ssd1306_draw_point(x, y, chDot);
}
}
ssd1306_refresh_gram();
}

View file

@ -0,0 +1,34 @@
#ifndef _SSD1306_H_
#define _SSD1306_H_
#include "stdint.h"
#define SSD1306_CMD 0
#define SSD1306_DAT 1
#define SSD1306_WIDTH 128
#define SSD1306_HEIGHT 64
#define OLED_CS_PIN GPIO_PIN_10
#define OLED_DC_PIN GPIO_PIN_22
#define OLED_RES_PIN GPIO_PIN_11
#define CS1_HIGH gpio_write(OLED_CS_PIN, 1)
#define CS1_LOW gpio_write(OLED_CS_PIN, 0)
#define DC_HIGH gpio_write(OLED_DC_PIN, 1)
#define DC_LOW gpio_write(OLED_DC_PIN, 0)
#define RES_HIGH gpio_write(OLED_RES_PIN, 1)
#define RES_LOW gpio_write(OLED_RES_PIN, 0)
void ssd1306_init(void);
void ssd1306_display_on(void);
void ssd1306_display_off(void);
void ssd1306_refresh_gram(void);
void ssd1306_clear_screen(uint8_t fill);
void ssd1306_draw_point(uint8_t x, uint8_t y, uint8_t mode);
void ssd1306_display_char(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode);
void ssd1306_display_string(uint8_t x, uint8_t y, const char *string, uint8_t size, uint8_t mode);
void ssd1306_display_chinese(uint8_t x, uint8_t y, uint8_t no, uint8_t mode);
void ssd1306_draw_bmp(uint8_t x, uint8_t y, const unsigned char *image, uint8_t index, uint8_t mode);
void ssd1306_draw_alpha(uint8_t x, uint8_t y, const unsigned char *image, uint8_t index, uint8_t mode);
#endif

View file

@ -0,0 +1,366 @@
/**
* @file st7735s.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 "st7735s.h"
#include "mcu_lcd.h"
#include "hal_spi.h"
#include "hal_dma.h"
#include "hal_gpio.h"
static struct device *spi0;
static struct device *dma_ch3;
const st7735s_init_cmd_t st7735s_init_cmds[] = {
{ 0x01, NULL, 0x80 }, /* Software reset */
{ 0x11, NULL, 0x80 }, /* Exit sleep */
{ 0xB1, "\x01\x2C\x2D", 3 }, /* Frame rate ctrl - normal mode, Rate = fosc/(1x2+40) * (LINE+2C+2D) */
{ 0xB2, "\x01\x2C\x2D", 3 }, /* Frame rate control - idle mode, Rate = fosc/(1x2+40) * (LINE+2C+2D) */
{ 0xB3, "\x01\x2C\x2D\x01\x2C\x2D", 6 }, /* Frame rate ctrl - partial mode, Dot inversion mode. Line inversion mode */
{ 0xB4, "\x07", 1 }, /* Display inversion ctrl, No inversion */
{ 0xC0, "\xa2\x02\x84", 3 }, /* Power control, -4.6V AUTO mode */
{ 0xC1, "\xc5", 1 }, /* Power control, VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD */
{ 0xC2, "\x0a\x00", 2 }, /* Power control, Opamp current small, Boost frequency */
{ 0xC3, "\x8a\x2a", 2 }, /* Power control, BCLK/2, Opamp current small & Medium low */
{ 0xC4, "\x8a\xee", 2 }, /* Power control */
{ 0xC5, "\x0e", 1 }, /* Power control */
{ 0x20, "\x00", 1 }, /* set non-inverted mode, 16-bit color */
//{ 0x21, "\x00", 1 }, /* set inverted mode */
{ 0x3A, "\x05", 1 }, /* set color mode */
{ 0x36, "\xC0", 1 }, /* set MX, MY, RGB mode */
{ 0xE0, "\x02\x1c\x07\x12\x37\x32\x29\x2d\x29\x25\x2B\x39\x00\x01\x03\x10", 16 }, /* set Gamma Sequence */
{ 0xE1, "\x03\x1d\x07\x06\x2E\x2C\x29\x2D\x2E\x2E\x37\x3F\x00\x00\x02\x10", 16 }, /* set Gamma Sequence */
{ 0x13, NULL, 0x80 }, /* Normal display on */
{ 0x20, NULL, 0x80 }, /* Display on */
};
/**
* @brief st7735s_spi_init
*
* @return int 0:succes 1:error
*/
static int st7735s_spi_init(void)
{
gpio_set_mode(ST7735S_CS_PIN, GPIO_OUTPUT_MODE);
gpio_set_mode(ST7735S_DC_PIN, GPIO_OUTPUT_MODE);
ST7735S_CS_HIGH;
ST7735S_DC_HIGH;
spi0 = device_find("lcd_dev_ifs");
if (spi0) {
device_close(spi0);
} else {
spi_register(SPI0_INDEX, "lcd_dev_ifs");
spi0 = device_find("lcd_dev_ifs");
}
if (spi0) {
SPI_DEV(spi0)->mode = SPI_MASTER_MODE;
SPI_DEV(spi0)->clk = (36 * 1000 * 1000);
SPI_DEV(spi0)->direction = SPI_MSB_BYTE0_DIRECTION_FIRST;
SPI_DEV(spi0)->clk_polaraity = SPI_POLARITY_LOW;
SPI_DEV(spi0)->datasize = SPI_DATASIZE_8BIT;
SPI_DEV(spi0)->clk_phase = SPI_PHASE_1EDGE;
SPI_DEV(spi0)->fifo_threshold = 0;
device_open(spi0, DEVICE_OFLAG_STREAM_TX | DEVICE_OFLAG_STREAM_RX);
} else {
return 1;
}
dma_ch3 = device_find("lcd_dev_ifs_dma");
if (dma_ch3) {
device_close(dma_ch3);
} else {
dma_register(DMA0_CH3_INDEX, "lcd_dev_ifs_dma");
dma_ch3 = device_find("lcd_dev_ifs_dma");
}
if (dma_ch3) {
DMA_DEV(dma_ch3)->direction = DMA_MEMORY_TO_PERIPH;
DMA_DEV(dma_ch3)->transfer_mode = DMA_LLI_ONCE_MODE;
DMA_DEV(dma_ch3)->src_req = DMA_REQUEST_NONE;
DMA_DEV(dma_ch3)->dst_req = DMA_REQUEST_SPI0_TX;
DMA_DEV(dma_ch3)->src_width = DMA_TRANSFER_WIDTH_8BIT;
DMA_DEV(dma_ch3)->dst_width = DMA_TRANSFER_WIDTH_8BIT;
DMA_DEV(dma_ch3)->src_burst_size = DMA_BURST_1BYTE;
DMA_DEV(dma_ch3)->dst_burst_size = DMA_BURST_1BYTE;
device_open(dma_ch3, 0);
device_set_callback(dma_ch3, NULL);
device_control(spi0, DEVICE_CTRL_ATTACH_TX_DMA, dma_ch3);
device_control(dma_ch3, DEVICE_CTRL_CLR_INT, NULL);
} else {
return 1;
}
device_control(spi0, DEVICE_CTRL_TX_DMA_SUSPEND, NULL);
return 0;
}
/**
* @brief st7735s_write_cmd
*
* @param cmd
* @return int 0:succes 1:error
*/
static int st7735s_write_cmd(uint8_t cmd)
{
ST7735S_DC_LOW;
ST7735S_CS_LOW;
int res = spi_transmit(spi0, &cmd, 1, SPI_TRANSFER_TYPE_8BIT);
ST7735S_CS_HIGH;
return res;
}
/**
* @brief st7735s_write_data_1byte
*
* @param data
* @return int 0:succes 1:error
*/
static int st7735s_write_data_1byte(uint8_t data)
{
ST7735S_DC_HIGH;
ST7735S_CS_LOW;
int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_8BIT);
ST7735S_CS_HIGH;
return res;
}
/**
* @brief st7735s_write_data_2byte
*
* @param data
* @return int 0:succes 1:error
*/
// static int st7735s_write_data_2byte(uint16_t data)
// {
// data = ((data >> 8) & 0xFF) | data << 8;
// ST7735S_DC_HIGH;
// ST7735S_CS_LOW;
// int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_16BIT);
// ST7735S_CS_HIGH;
// return res;
// }
/**
* @brief st7735s_write_data_4byte
*
* @param data
* @return int 0:succes 1:error
*/
static int st7735s_write_data_4byte(uint32_t data)
{
data = ((data >> 24) & 0xFF) | ((data >> 8) & 0xFF00) | ((data << 8) & 0xFF0000) | ((data << 24));
ST7735S_DC_HIGH;
ST7735S_CS_LOW;
int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_32BIT);
ST7735S_CS_HIGH;
return res;
}
/**
* @brief st7735s_draw_is_busy, After the call st7735s_draw_picture_dma must check this,
* if st7735s_draw_is_busy() == 1, Don't allow other draw !!
* can run in the DMA interrupt callback function.
*
* @return int 0:draw end; 1:Being draw
*/
int st7735s_draw_is_busy(void)
{
if (device_control(SPI_DEV(spi0)->tx_dma, DMA_CHANNEL_GET_STATUS, NULL)) {
return 1;
} else {
device_control(spi0, DEVICE_CTRL_TX_DMA_SUSPEND, NULL);
ST7735S_CS_HIGH;
return 0;
}
}
/**
* @brief st7735s_init
*
* @return int
*/
int st7735s_init()
{
int res = st7735s_spi_init();
if (res) {
return res;
}
for (uint16_t i = 0; i < (sizeof(st7735s_init_cmds) / sizeof(st7735s_init_cmd_t)); i++) {
/* send register address */
res |= st7735s_write_cmd(st7735s_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (st7735s_init_cmds[i].databytes & 0x7F); j++) {
res |= st7735s_write_data_1byte(st7735s_init_cmds[i].data[j]);
}
if (res) {
return res;
}
/* delay */
if (st7735s_init_cmds[i].databytes & 0x80) {
bflb_platform_delay_ms(100);
}
}
st7735s_set_draw_window(0, 0, ST7735S_W, ST7735S_H);
return res;
}
/**
* @brief st7735s_set_dir
*
* @param dir
*/
void st7735s_set_dir(uint8_t dir)
{
st7735s_write_cmd(0x36);
switch (dir) {
case 0:
st7735s_write_data_1byte(0x08);
break;
case 1:
st7735s_write_data_1byte(0xA8);
break;
case 2:
st7735s_write_data_1byte(0xC8);
break;
case 3:
st7735s_write_data_1byte(0x68);
break;
default:
break;
}
}
void st7735s_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
{
#if ST7735S_OFFSET_X
x1 += ST7735S_OFFSET_X;
x2 += ST7735S_OFFSET_X;
#endif
#if ST7735S_OFFSET_Y
y1 += ST7735S_OFFSET_Y;
y2 += ST7735S_OFFSET_Y;
#endif
st7735s_write_cmd(0x2a);
st7735s_write_data_4byte(x1 << 16 | (x2 & 0xFFFF));
st7735s_write_cmd(0x2b);
st7735s_write_data_4byte(y1 << 16 | (y2 & 0xFFFF));
st7735s_write_cmd(0x2c);
}
/**
* @brief st7735s_draw_point
*
* @param x
* @param y
* @param color
*/
void st7735s_draw_point(uint16_t x, uint16_t y, uint16_t color)
{
if (lcd_auto_swap_flag) {
color = ((color >> 8) & 0xFF) | color << 8;
}
st7735s_set_draw_window(x, y, x, y);
ST7735S_DC_HIGH;
ST7735S_CS_LOW;
spi_transmit(spi0, &color, 1, SPI_TRANSFER_TYPE_16BIT);
ST7735S_CS_HIGH;
}
/**
* @brief st7735s_draw_area
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param color
*/
void st7735s_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
if (lcd_auto_swap_flag) {
color = ((color >> 8) & 0xFF) | color << 8;
}
st7735s_set_draw_window(x1, y1, x2, y2);
ST7735S_DC_HIGH;
ST7735S_CS_LOW;
for (uint16_t i = y1; i <= y2; i++) {
for (uint16_t j = x1; j <= x2; j++)
spi_transmit(spi0, &color, 1, SPI_TRANSFER_TYPE_16BIT);
}
ST7735S_CS_HIGH;
}
/**
* @brief st7735s_draw_picture_dma, Non-blocking! Using DMA acceleration, Not waiting for the draw end
* After the call, No other operations are allowed until (st7735s_draw_is_busy()==0)
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void st7735s_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture)
{
size_t picture_size = (x2 - x1 + 1) * (y2 - y1 + 1);
/* 数据高低位切换 */
if (lcd_auto_swap_flag) {
lcd_swap_color_data16(picture, picture, picture_size);
}
st7735s_set_draw_window(x1, y1, x2, y2);
ST7735S_DC_HIGH;
ST7735S_CS_LOW;
device_control(spi0, DEVICE_CTRL_TX_DMA_RESUME, NULL);
device_write(spi0, 0, picture, picture_size * 2);
}
/**
* @brief st7735s_draw_picture,BlockingUsing DMA acceleration,Waiting for the draw end
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void st7735s_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture)
{
st7735s_draw_picture_nonblocking(x1, y1, x2, y2, picture);
while (st7735s_draw_is_busy()) {
BL_DRV_DUMMY;
};
}

View file

@ -0,0 +1,58 @@
/**
* @file st7735s.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 _ST7735S_H_
#define _ST7735S_H_
#include "bflb_platform.h"
#define ST7735S_CS_PIN GPIO_PIN_10
#define ST7735S_DC_PIN GPIO_PIN_22
#define ST7735S_CS_HIGH gpio_write(ST7735S_CS_PIN, 1)
#define ST7735S_CS_LOW gpio_write(ST7735S_CS_PIN, 0)
#define ST7735S_DC_HIGH gpio_write(ST7735S_DC_PIN, 1)
#define ST7735S_DC_LOW gpio_write(ST7735S_DC_PIN, 0)
#define ST7735S_W 128 /* ST7735S LCD width */
#define ST7735S_H 160 /* ST7735S LCD height */
#define ST7735S_OFFSET_X 0
#define ST7735S_OFFSET_Y 0
typedef struct {
uint8_t cmd;
const char *data;
uint8_t databytes; /* Num of data in data; bit 7 = delay after set */
} st7735s_init_cmd_t;
int st7735s_init();
void st7735s_set_dir(uint8_t dir);
void st7735s_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2);
void st7735s_draw_point(uint16_t x, uint16_t y, uint16_t color);
void st7735s_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void st7735s_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture);
void st7735s_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture);
int st7735s_draw_is_busy(void);
#endif

View file

@ -0,0 +1,368 @@
/**
* @file st7789v.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 "st7789v.h"
#include "mcu_lcd.h"
#include "hal_spi.h"
#include "hal_dma.h"
#include "hal_gpio.h"
static struct device *spi0;
static struct device *dma_ch3;
const st7789v_init_cmd_t st7789v_init_cmds[] = {
{ 0x01, NULL, 0x80 }, /* Software reset */
{ 0x11, NULL, 0x80 }, /* Exit sleep */
{ 0xB2, "\x05\x05\x00\x33\x33", 5 },
{ 0xB7, "\x74", 1 },
{ 0xBB, "\x2a", 1 },
{ 0xC0, "\x2c", 1 },
{ 0xC2, "\x01", 1 },
{ 0xC3, "\x13", 1 },
{ 0xC4, "\x20", 1 },
{ 0xC6, "\x0F", 1 },
{ 0xD0, "\xA4\xA1", 2 },
{ 0xD6, "\xA1", 1 },
// { 0x20, "\x00", 1 }, /* set non-inverted mode, 16-bit color */
{ 0x21, "\x00", 1 }, /* set inverted mode */
{ 0x3A, "\x05", 1 }, /* set color mode */
{ 0x36, "\xC0", 1 }, /* set MX, MY, RGB mode */
{ 0xE0, "\x70\x0b\x10\x0b\x0a\x26\x35\x44\x4c\x38\x17\x17\x2f\x2f", 14 }, /* set Gamma Sequence */
{ 0xE1, "\x70\x03\x08\x09\x08\x04\x2e\x22\x47\x39\x18\x19\x2d\x30", 14 }, /* set Gamma Sequence */
{ 0xD6, "\xA1", 1 },
{ 0x29, NULL, 0x80 }, /* Display on */
};
/**
* @brief st7789v_spi_init
*
* @return int 0:succes 1:error
*/
static int st7789v_spi_init(void)
{
gpio_set_mode(ST7789V_CS_PIN, GPIO_OUTPUT_MODE);
gpio_set_mode(ST7789V_DC_PIN, GPIO_OUTPUT_MODE);
ST7789V_CS_HIGH;
ST7789V_DC_HIGH;
spi0 = device_find("lcd_dev_ifs");
if (spi0) {
device_close(spi0);
} else {
spi_register(SPI0_INDEX, "lcd_dev_ifs");
spi0 = device_find("lcd_dev_ifs");
}
if (spi0) {
SPI_DEV(spi0)->mode = SPI_MASTER_MODE;
SPI_DEV(spi0)->clk = (36 * 1000 * 1000);
SPI_DEV(spi0)->direction = SPI_MSB_BYTE0_DIRECTION_FIRST;
SPI_DEV(spi0)->clk_polaraity = SPI_POLARITY_LOW;
SPI_DEV(spi0)->datasize = SPI_DATASIZE_8BIT;
SPI_DEV(spi0)->clk_phase = SPI_PHASE_1EDGE;
SPI_DEV(spi0)->fifo_threshold = 0;
device_open(spi0, DEVICE_OFLAG_STREAM_TX | DEVICE_OFLAG_STREAM_RX);
} else {
return 1;
}
dma_ch3 = device_find("lcd_dev_ifs_dma");
if (dma_ch3) {
device_close(dma_ch3);
} else {
dma_register(DMA0_CH3_INDEX, "lcd_dev_ifs_dma");
dma_ch3 = device_find("lcd_dev_ifs_dma");
}
if (dma_ch3) {
DMA_DEV(dma_ch3)->direction = DMA_MEMORY_TO_PERIPH;
DMA_DEV(dma_ch3)->transfer_mode = DMA_LLI_ONCE_MODE;
DMA_DEV(dma_ch3)->src_req = DMA_REQUEST_NONE;
DMA_DEV(dma_ch3)->dst_req = DMA_REQUEST_SPI0_TX;
DMA_DEV(dma_ch3)->src_width = DMA_TRANSFER_WIDTH_8BIT;
DMA_DEV(dma_ch3)->dst_width = DMA_TRANSFER_WIDTH_8BIT;
DMA_DEV(dma_ch3)->src_burst_size = DMA_BURST_1BYTE;
DMA_DEV(dma_ch3)->dst_burst_size = DMA_BURST_1BYTE;
device_open(dma_ch3, 0);
device_set_callback(dma_ch3, NULL);
device_control(spi0, DEVICE_CTRL_ATTACH_TX_DMA, dma_ch3);
// device_control(dma_ch3, DEVICE_CTRL_CLR_INT, NULL);
} else {
return 1;
}
device_control(spi0, DEVICE_CTRL_TX_DMA_SUSPEND, NULL);
return 0;
}
/**
* @brief st7789v_write_cmd
*
* @param cmd
* @return int 0:succes 1:error
*/
static int st7789v_write_cmd(uint8_t cmd)
{
ST7789V_DC_LOW;
ST7789V_CS_LOW;
int res = spi_transmit(spi0, &cmd, 1, SPI_TRANSFER_TYPE_8BIT);
ST7789V_CS_HIGH;
return res;
}
/**
* @brief st7789v_write_data_1byte
*
* @param data
* @return int 0:succes 1:error
*/
static int st7789v_write_data_1byte(uint8_t data)
{
ST7789V_DC_HIGH;
ST7789V_CS_LOW;
int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_8BIT);
ST7789V_CS_HIGH;
return res;
}
/**
* @brief st7789v_write_data_2byte
*
* @param data
* @return int 0:succes 1:error
*/
// static int st7789v_write_data_2byte(uint16_t data)
// {
// data = ((data >> 8) & 0xFF) | data << 8;
// ST7789V_DC_HIGH;
// ST7789V_CS_LOW;
// int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_16BIT);
// ST7789V_CS_HIGH;
// return res;
// }
/**
* @brief st7789v_write_data_4byte
*
* @param data
* @return int 0:succes 1:error
*/
static int st7789v_write_data_4byte(uint32_t data)
{
data = ((data >> 24) & 0xFF) | ((data >> 8) & 0xFF00) | ((data << 8) & 0xFF0000) | ((data << 24));
ST7789V_DC_HIGH;
ST7789V_CS_LOW;
int res = spi_transmit(spi0, &data, 1, SPI_TRANSFER_TYPE_32BIT);
ST7789V_CS_HIGH;
return res;
}
/**
* @brief st7789v_draw_is_busy, After the call st7789v_draw_picture_dma must check this,
* if st7789v_draw_is_busy() == 1, Don't allow other draw !!
* can run in the DMA interrupt callback function.
*
* @return int 0:draw end; 1:Being draw
*/
int st7789v_draw_is_busy(void)
{
if (device_control(SPI_DEV(spi0)->tx_dma, DMA_CHANNEL_GET_STATUS, NULL)) {
return 1;
} else {
device_control(spi0, DEVICE_CTRL_TX_DMA_SUSPEND, NULL);
ST7789V_CS_HIGH;
return 0;
}
}
/**
* @brief st7789v_init
*
* @return int
*/
int st7789v_init()
{
int res = st7789v_spi_init();
if (res) {
return res;
}
for (uint16_t i = 0; i < (sizeof(st7789v_init_cmds) / sizeof(st7789v_init_cmd_t)); i++) {
/* send register address */
res |= st7789v_write_cmd(st7789v_init_cmds[i].cmd);
/* send register data */
for (uint8_t j = 0; j < (st7789v_init_cmds[i].databytes & 0x7F); j++) {
res |= st7789v_write_data_1byte(st7789v_init_cmds[i].data[j]);
}
if (res) {
return res;
}
/* delay */
if (st7789v_init_cmds[i].databytes & 0x80) {
bflb_platform_delay_ms(100);
}
}
st7789v_set_draw_window(0, 0, ST7789V_W, ST7789V_H);
return res;
}
/**
* @brief st7789v_set_dir
*
* @param dir
*/
void st7789v_set_dir(uint8_t dir)
{
st7789v_write_cmd(0x36);
switch (dir) {
case 0:
st7789v_write_data_1byte(0x00);
break;
case 1:
st7789v_write_data_1byte(0xA0);
break;
case 2:
st7789v_write_data_1byte(0xC0);
break;
case 3:
st7789v_write_data_1byte(0x60);
break;
default:
break;
}
}
void st7789v_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
{
#if ST7789V_OFFSET_X
x1 += ST7789V_OFFSET_X;
x2 += ST7789V_OFFSET_X;
#endif
#if ST7789V_OFFSET_Y
y1 += ST7789V_OFFSET_Y;
y2 += ST7789V_OFFSET_Y;
#endif
st7789v_write_cmd(0x2a);
st7789v_write_data_4byte(x1 << 16 | (x2 & 0xFFFF));
st7789v_write_cmd(0x2b);
st7789v_write_data_4byte(y1 << 16 | (y2 & 0xFFFF));
st7789v_write_cmd(0x2c);
}
/**
* @brief st7789v_draw_point
*
* @param x
* @param y
* @param color
*/
void st7789v_draw_point(uint16_t x, uint16_t y, uint16_t color)
{
if (lcd_auto_swap_flag) {
color = ((color >> 8) & 0xFF) | color << 8;
}
st7789v_set_draw_window(x, y, x, y);
ST7789V_DC_HIGH;
ST7789V_CS_LOW;
spi_transmit(spi0, &color, 1, SPI_TRANSFER_TYPE_16BIT);
ST7789V_CS_HIGH;
}
/**
* @brief st7789v_draw_area
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param color
*/
void st7789v_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
if (lcd_auto_swap_flag) {
color = ((color >> 8) & 0xFF) | color << 8;
}
st7789v_set_draw_window(x1, y1, x2, y2);
ST7789V_DC_HIGH;
ST7789V_CS_LOW;
for (uint16_t i = y1; i <= y2; i++) {
for (uint16_t j = x1; j <= x2; j++)
spi_transmit(spi0, &color, 1, SPI_TRANSFER_TYPE_16BIT);
}
ST7789V_CS_HIGH;
}
/**
* @brief st7789v_draw_picture_dma, Non-blocking! Using DMA acceleration, Not waiting for the draw end
* After the call, No other operations are allowed until (st7789v_draw_is_busy()==0)
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void st7789v_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture)
{
size_t picture_size = (x2 - x1 + 1) * (y2 - y1 + 1);
/* 数据高低位切换 */
if (lcd_auto_swap_flag) {
lcd_swap_color_data16(picture, picture, picture_size);
}
st7789v_set_draw_window(x1, y1, x2, y2);
ST7789V_DC_HIGH;
ST7789V_CS_LOW;
device_control(spi0, DEVICE_CTRL_TX_DMA_RESUME, NULL);
device_write(spi0, 0, picture, picture_size * 2);
}
/**
* @brief st7789v_draw_picture,BlockingUsing DMA acceleration,Waiting for the draw end
*
* @param x1
* @param y1
* @param x2
* @param y2
* @param picture
*/
void st7789v_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture)
{
st7789v_draw_picture_nonblocking(x1, y1, x2, y2, picture);
while (st7789v_draw_is_busy()) {
BL_DRV_DUMMY;
};
}

View file

@ -0,0 +1,58 @@
/**
* @file st7789v.h
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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 _ST7789V_H_
#define _ST7789V_H_
#include "bflb_platform.h"
#define ST7789V_CS_PIN GPIO_PIN_10
#define ST7789V_DC_PIN GPIO_PIN_22
#define ST7789V_CS_HIGH gpio_write(ST7789V_CS_PIN, 1)
#define ST7789V_CS_LOW gpio_write(ST7789V_CS_PIN, 0)
#define ST7789V_DC_HIGH gpio_write(ST7789V_DC_PIN, 1)
#define ST7789V_DC_LOW gpio_write(ST7789V_DC_PIN, 0)
#define ST7789V_W 135 /* ST7789V LCD width */
#define ST7789V_H 240 /* ST7789V LCD height */
#define ST7789V_OFFSET_X 53
#define ST7789V_OFFSET_Y 40
typedef struct {
uint8_t cmd;
const char *data;
uint8_t databytes; /* Num of data in data; bit 7 = delay after set */
} st7789v_init_cmd_t;
int st7789v_init();
void st7789v_set_dir(uint8_t dir);
void st7789v_set_draw_window(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2);
void st7789v_draw_point(uint16_t x, uint16_t y, uint16_t color);
void st7789v_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void st7789v_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture);
void st7789v_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *picture);
int st7789v_draw_is_busy(void);
#endif

View file

@ -1,34 +0,0 @@
#ifndef __SSD1306_h__
#define __SSD1306_h__
#include "drv_device.h"
#define OLED_CS_PIN GPIO_PIN_10
#define OLED_DC_PIN GPIO_PIN_22
#define OLED_RES_PIN GPIO_PIN_11
#define CS1_HIGH gpio_write(OLED_CS_PIN, 1)
#define CS1_LOW gpio_write(OLED_CS_PIN, 0)
#define DC_HIGH gpio_write(OLED_DC_PIN, 1)
#define DC_LOW gpio_write(OLED_DC_PIN, 0)
#define RES_HIGH gpio_write(OLED_RES_PIN, 1)
#define RES_LOW gpio_write(OLED_RES_PIN, 0)
extern const unsigned char asc2_1206[95][12];
extern const unsigned char asc2_1608[95][16];
extern const unsigned char asc2_2412[95][36];
extern const unsigned char Hzk[][32];
void oled_init(void);
void oled_display_on(void);
void oled_display_off(void);
void oled_clear(void);
void oled_show(void);
void oled_draw_point(uint8_t x, uint8_t y, uint8_t mode);
void oled_draw_char(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode);
void oled_draw_string(uint8_t x, uint8_t y, const uint8_t *p, uint8_t size, uint8_t mode);
void oled_draw_chinese(uint8_t x, uint8_t y, uint8_t no, uint8_t mode);
void oled_draw_bmp(uint8_t x, uint8_t y, const unsigned char *image, uint8_t index, uint8_t mode);
void oled_draw_alpha(uint8_t x, uint8_t y, const unsigned char *image, uint8_t index, uint8_t mode);
#endif