290 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| /**
 | |
|  * @file ST7565.c
 | |
|  *
 | |
|  */
 | |
| 
 | |
| /*********************
 | |
|  *      INCLUDES
 | |
|  *********************/
 | |
| #include "ST7565.h"
 | |
| #if USE_ST7565
 | |
| 
 | |
| #include <stdbool.h>
 | |
| #include <stddef.h>
 | |
| #include <string.h>
 | |
| #include "lvgl/lv_core/lv_vdb.h"
 | |
| #include LV_DRV_DISP_INCLUDE
 | |
| #include LV_DRV_DELAY_INCLUDE
 | |
| 
 | |
| /*********************
 | |
|  *      DEFINES
 | |
|  *********************/
 | |
| #define ST7565_BAUD      2000000    /*< 2,5 MHz (400 ns)*/
 | |
| 
 | |
| #define ST7565_CMD_MODE  0
 | |
| #define ST7565_DATA_MODE 1
 | |
| 
 | |
| #define ST7565_HOR_RES  128
 | |
| #define ST7565_VER_RES  64
 | |
| 
 | |
| #define CMD_DISPLAY_OFF         0xAE
 | |
| #define CMD_DISPLAY_ON          0xAF
 | |
| 
 | |
| #define CMD_SET_DISP_START_LINE 0x40
 | |
| #define CMD_SET_PAGE            0xB0
 | |
| 
 | |
| #define CMD_SET_COLUMN_UPPER    0x10
 | |
| #define CMD_SET_COLUMN_LOWER    0x00
 | |
| 
 | |
| #define CMD_SET_ADC_NORMAL      0xA0
 | |
| #define CMD_SET_ADC_REVERSE     0xA1
 | |
| 
 | |
| #define CMD_SET_DISP_NORMAL     0xA6
 | |
| #define CMD_SET_DISP_REVERSE    0xA7
 | |
| 
 | |
| #define CMD_SET_ALLPTS_NORMAL   0xA4
 | |
| #define CMD_SET_ALLPTS_ON       0xA5
 | |
| #define CMD_SET_BIAS_9          0xA2
 | |
| #define CMD_SET_BIAS_7          0xA3
 | |
| 
 | |
| #define CMD_RMW                 0xE0
 | |
| #define CMD_RMW_CLEAR           0xEE
 | |
| #define CMD_INTERNAL_RESET      0xE2
 | |
| #define CMD_SET_COM_NORMAL      0xC0
 | |
| #define CMD_SET_COM_REVERSE     0xC8
 | |
| #define CMD_SET_POWER_CONTROL   0x28
 | |
| #define CMD_SET_RESISTOR_RATIO  0x20
 | |
| #define CMD_SET_VOLUME_FIRST    0x81
 | |
| #define CMD_SET_VOLUME_SECOND   0x00
 | |
| #define CMD_SET_STATIC_OFF      0xAC
 | |
| #define CMD_SET_STATIC_ON       0xAD
 | |
| #define CMD_SET_STATIC_REG      0x00
 | |
| #define CMD_SET_BOOSTER_FIRST   0xF8
 | |
| #define CMD_SET_BOOSTER_234     0x00
 | |
| #define CMD_SET_BOOSTER_5       0x01
 | |
| #define CMD_SET_BOOSTER_6       0x03
 | |
| #define CMD_NOP                 0xE3
 | |
| #define CMD_TEST                0xF0
 | |
| 
 | |
| /**********************
 | |
|  *      TYPEDEFS
 | |
|  **********************/
 | |
| 
 | |
| /**********************
 | |
|  *  STATIC PROTOTYPES
 | |
|  **********************/
 | |
| static void st7565_sync(int32_t x1, int32_t y1, int32_t x2, int32_t y2);
 | |
| static void st7565_command(uint8_t cmd);
 | |
| static void st7565_data(uint8_t data);
 | |
| 
 | |
| /**********************
 | |
|  *  STATIC VARIABLES
 | |
|  **********************/
 | |
| static uint8_t lcd_fb[ST7565_HOR_RES * ST7565_VER_RES / 8] = {0xAA, 0xAA};
 | |
| static uint8_t pagemap[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
 | |
| 
 | |
| /**********************
 | |
|  *      MACROS
 | |
|  **********************/
 | |
| 
 | |
| /**********************
 | |
|  *   GLOBAL FUNCTIONS
 | |
|  **********************/
 | |
| 
 | |
| /**
 | |
|  * Initialize the ST7565
 | |
|  */
 | |
| void st7565_init(void)
 | |
| {
 | |
|     LV_DRV_DISP_RST(1);
 | |
|     LV_DRV_DELAY_MS(10);
 | |
|     LV_DRV_DISP_RST(0);
 | |
|     LV_DRV_DELAY_MS(10);
 | |
|     LV_DRV_DISP_RST(1);
 | |
|     LV_DRV_DELAY_MS(10);
 | |
| 
 | |
|     LV_DRV_DISP_SPI_CS(0);
 | |
| 
 | |
|     st7565_command(CMD_SET_BIAS_7);
 | |
|     st7565_command(CMD_SET_ADC_NORMAL);
 | |
|     st7565_command(CMD_SET_COM_NORMAL);
 | |
|     st7565_command(CMD_SET_DISP_START_LINE);
 | |
|     st7565_command(CMD_SET_POWER_CONTROL | 0x4);
 | |
|     LV_DRV_DELAY_MS(50);
 | |
| 
 | |
|     st7565_command(CMD_SET_POWER_CONTROL | 0x6);
 | |
|     LV_DRV_DELAY_MS(50);
 | |
| 
 | |
|     st7565_command(CMD_SET_POWER_CONTROL | 0x7);
 | |
|     LV_DRV_DELAY_MS(10);
 | |
| 
 | |
|     st7565_command(CMD_SET_RESISTOR_RATIO | 0x6); // Defaulted to 0x26 (but could also be between 0x20-0x27 based on display's specs)
 | |
| 
 | |
|     st7565_command(CMD_DISPLAY_ON);
 | |
|     st7565_command(CMD_SET_ALLPTS_NORMAL);
 | |
| 
 | |
|     /*Set brightness*/
 | |
|     st7565_command(CMD_SET_VOLUME_FIRST);
 | |
|     st7565_command(CMD_SET_VOLUME_SECOND | (0x18 & 0x3f));
 | |
| 
 | |
|     LV_DRV_DISP_SPI_CS(1);
 | |
| 
 | |
|     memset(lcd_fb, 0x00, sizeof(lcd_fb));
 | |
| }
 | |
| 
 | |
| 
 | |
| void st7565_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p)
 | |
| {
 | |
|     /*Return if the area is out the screen*/
 | |
|     if(x2 < 0) return;
 | |
|     if(y2 < 0) return;
 | |
|     if(x1 > ST7565_HOR_RES - 1) return;
 | |
|     if(y1 > ST7565_VER_RES - 1) return;
 | |
| 
 | |
|     /*Truncate the area to the screen*/
 | |
|     int32_t act_x1 = x1 < 0 ? 0 : x1;
 | |
|     int32_t act_y1 = y1 < 0 ? 0 : y1;
 | |
|     int32_t act_x2 = x2 > ST7565_HOR_RES - 1 ? ST7565_HOR_RES - 1 : x2;
 | |
|     int32_t act_y2 = y2 > ST7565_VER_RES - 1 ? ST7565_VER_RES - 1 : y2;
 | |
| 
 | |
|     int32_t x, y;
 | |
| 
 | |
|     /*Set the first row in */
 | |
| 
 | |
|     /*Refresh frame buffer*/
 | |
|     for(y = act_y1; y <= act_y2; y++) {
 | |
|         for(x = act_x1; x <= act_x2; x++) {
 | |
|             if(lv_color_to1(*color_p) != 0) {
 | |
|                 lcd_fb[x + (y / 8)*ST7565_HOR_RES] &= ~(1 << (7 - (y % 8)));
 | |
|             } else {
 | |
|                 lcd_fb[x + (y / 8)*ST7565_HOR_RES] |= (1 << (7 - (y % 8)));
 | |
|             }
 | |
|             color_p ++;
 | |
|         }
 | |
| 
 | |
|         color_p += x2 - act_x2; /*Next row*/
 | |
|     }
 | |
| 
 | |
|     st7565_sync(act_x1, act_y1, act_x2, act_y2);
 | |
|     lv_flush_ready();
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void st7565_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color)
 | |
| {
 | |
|     /*Return if the area is out the screen*/
 | |
|     if(x2 < 0) return;
 | |
|     if(y2 < 0) return;
 | |
|     if(x1 > ST7565_HOR_RES - 1) return;
 | |
|     if(y1 > ST7565_VER_RES - 1) return;
 | |
| 
 | |
|     /*Truncate the area to the screen*/
 | |
|     int32_t act_x1 = x1 < 0 ? 0 : x1;
 | |
|     int32_t act_y1 = y1 < 0 ? 0 : y1;
 | |
|     int32_t act_x2 = x2 > ST7565_HOR_RES - 1 ? ST7565_HOR_RES - 1 : x2;
 | |
|     int32_t act_y2 = y2 > ST7565_VER_RES - 1 ? ST7565_VER_RES - 1 : y2;
 | |
| 
 | |
|     int32_t x, y;
 | |
|     uint8_t white = lv_color_to1(color);
 | |
| 
 | |
|     /*Refresh frame buffer*/
 | |
|     for(y = act_y1; y <= act_y2; y++) {
 | |
|         for(x = act_x1; x <= act_x2; x++) {
 | |
|             if(white != 0) {
 | |
|                 lcd_fb[x + (y / 8)*ST7565_HOR_RES] |= (1 << (7 - (y % 8)));
 | |
|             } else {
 | |
|                 lcd_fb[x + (y / 8)*ST7565_HOR_RES] &= ~(1 << (7 - (y % 8)));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     st7565_sync(act_x1, act_y1, act_x2, act_y2);
 | |
| }
 | |
| 
 | |
| void st7565_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p)
 | |
| {
 | |
|     /*Return if the area is out the screen*/
 | |
|     if(x2 < 0) return;
 | |
|     if(y2 < 0) return;
 | |
|     if(x1 > ST7565_HOR_RES - 1) return;
 | |
|     if(y1 > ST7565_VER_RES - 1) return;
 | |
| 
 | |
|     /*Truncate the area to the screen*/
 | |
|     int32_t act_x1 = x1 < 0 ? 0 : x1;
 | |
|     int32_t act_y1 = y1 < 0 ? 0 : y1;
 | |
|     int32_t act_x2 = x2 > ST7565_HOR_RES - 1 ? ST7565_HOR_RES - 1 : x2;
 | |
|     int32_t act_y2 = y2 > ST7565_VER_RES - 1 ? ST7565_VER_RES - 1 : y2;
 | |
| 
 | |
|     int32_t x, y;
 | |
| 
 | |
|     /*Set the first row in */
 | |
| 
 | |
|     /*Refresh frame buffer*/
 | |
|     for(y = act_y1; y <= act_y2; y++) {
 | |
|         for(x = act_x1; x <= act_x2; x++) {
 | |
|             if(lv_color_to1(*color_p) != 0) {
 | |
|                 lcd_fb[x + (y / 8)*ST7565_HOR_RES] &= ~(1 << (7 - (y % 8)));
 | |
|             } else {
 | |
|                 lcd_fb[x + (y / 8)*ST7565_HOR_RES] |= (1 << (7 - (y % 8)));
 | |
|             }
 | |
|             color_p ++;
 | |
|         }
 | |
| 
 | |
|         color_p += x2 - act_x2; /*Next row*/
 | |
|     }
 | |
| 
 | |
|     st7565_sync(act_x1, act_y1, act_x2, act_y2);
 | |
| }
 | |
| /**********************
 | |
|  *   STATIC FUNCTIONS
 | |
|  **********************/
 | |
| /**
 | |
|  * Flush a specific part of the buffer to the display
 | |
|  * @param x1 left coordinate of the area to flush
 | |
|  * @param y1 top coordinate of the area to flush
 | |
|  * @param x2 right coordinate of the area to flush
 | |
|  * @param y2 bottom coordinate of the area to flush
 | |
|  */
 | |
| static void st7565_sync(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
 | |
| {
 | |
| 
 | |
|     LV_DRV_DISP_SPI_CS(0);
 | |
| 
 | |
|     uint8_t c, p;
 | |
|     for(p = y1 / 8; p <= y2 / 8; p++) {
 | |
|         st7565_command(CMD_SET_PAGE | pagemap[p]);
 | |
|         st7565_command(CMD_SET_COLUMN_LOWER | (x1 & 0xf));
 | |
|         st7565_command(CMD_SET_COLUMN_UPPER | ((x1 >> 4) & 0xf));
 | |
|         st7565_command(CMD_RMW);
 | |
| 
 | |
|         for(c = x1; c <= x2; c++) {
 | |
|             st7565_data(lcd_fb[(ST7565_HOR_RES * p) + c]);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     LV_DRV_DISP_SPI_CS(1);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Write a command to the ST7565
 | |
|  * @param cmd the command
 | |
|  */
 | |
| static void st7565_command(uint8_t cmd)
 | |
| {
 | |
|     LV_DRV_DISP_CMD_DATA(ST7565_CMD_MODE);
 | |
|     LV_DRV_DISP_SPI_WR_BYTE(cmd);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Write data to the ST7565
 | |
|  * @param data the data
 | |
|  */
 | |
| static void st7565_data(uint8_t data)
 | |
| {
 | |
|     LV_DRV_DISP_CMD_DATA(ST7565_DATA_MODE);
 | |
|     LV_DRV_DISP_SPI_WR_BYTE(data);
 | |
| }
 | |
| 
 | |
| #endif
 | 
