Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for GC9A01 and WaveShare 1.28 inch GC9A01 240x240 ISP diplay module #267

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,12 @@ elseif(MPI3501)
if (USE_DMA_TRANSFERS)
message(FATAL_ERROR "DMA is unfortunately not possible with MPI3501. Please disable with -DUSE_DMA_TRANSFERS=OFF.")
endif()
elseif(WAVESHARE_GC9A01)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGC9A01 -DWAVESHARE_GC9A01")
message(STATUS "Targeting WaveShare 240x240 1.28inch IPS LCD Hat with GC9A01 controller")
elseif(GC9A01)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGC9A01")
message(STATUS "Targeting GC9A01")
else()
message(FATAL_ERROR "Please specify which display controller to use on command line to CMake!")
endif()
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ The following LCD displays have been tested:
- [WaveShare 128x128, 1.44inch LCD display HAT for Raspberry Pi](https://www.waveshare.com/1.44inch-lcd-hat.htm) with ST7735S controller
- [KeDei 3.5 inch SPI TFTLCD 480*320 16bit/18bit version 6.3 2018/4/9](https://github.com/juj/fbcp-ili9341/issues/40) with MPI3501 controller
- Unbranded 2.8" 320x240 display with ILI9340 controller
- [WaveShare 240×240, General 1.28inch Round LCD Display Module, 65K RGB](https://www.waveshare.com/product/1.28inch-lcd-module.htm) with GC9A01 controller

### Installation

Expand Down Expand Up @@ -120,6 +121,7 @@ When using one of the displays that stack on top of the Pi that are already reco
- `-DWAVESHARE_ST7789VW_HAT=ON`: If specified, targets a [240x240, 1.3inch IPS LCD display HAT for Raspberry Pi](https://www.waveshare.com/1.3inch-lcd-hat.htm) with ST7789VW display controller.
- `-DWAVESHARE_ST7735S_HAT=ON`: If specified, targets a [128x128, 1.44inch LCD display HAT for Raspberry Pi](https://www.waveshare.com/1.3inch-lcd-hat.htm) with ST7735S display controller.
- `-DKEDEI_V63_MPI3501=ON`: If specified, targets a [KeDei 3.5 inch SPI TFTLCD 480*320 16bit/18bit version 6.3 2018/4/9](https://github.com/juj/fbcp-ili9341/issues/40) display with MPI3501 display controller.
- `-DWAVESHARE_GC9A01=ON`: If specified, targets a [WaveShare 240×240, General 1.28inch Round LCD Display Module, 65K RGB](https://www.waveshare.com/product/1.28inch-lcd-module.htm) with GC9A01 display controller

###### If you wired the display to the Pi yourself

Expand All @@ -137,6 +139,7 @@ If you connected wires directly on the Pi instead of using a Hat from the above
- `-DILI9486L=ON`: If you have a ILI9486L display, pass this directive. Note that ILI9486 and ILI9486L are quite different, mutually incompatible controller chips, so be careful here identifying which one you have. (or just try both, should not break if you misidentified)
- `-DILI9488=ON`: If you have a ILI9488 display, pass this directive.
- `-DMPI3501=ON`: If specified, targets a display with MPI3501 display controller.
- `-DGC9A01=ON`: If you have a GC9A01 display, pass this directive.

And additionally, pass the following to customize the GPIO pin assignments you used:

Expand Down
2 changes: 2 additions & 0 deletions display.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "mz61581.h"
#elif defined(MPI3501)
#include "mpi3501.h"
#elif defined(GC9A01)
#include "gc9a01.h"
#else
#error Please reconfigure CMake with your display controller directive set!
#endif
Expand Down
180 changes: 180 additions & 0 deletions gc9a01.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#include "config.h"

#if defined(GC9A01)

#include "spi.h"

#include <memory.h>
#include <stdio.h>

void InitGC9A01()
{
// If a Reset pin is defined, toggle it briefly high->low->high to enable the device. Some devices do not have a reset pin, in which case compile with GPIO_TFT_RESET_PIN left undefined.
#if defined(GPIO_TFT_RESET_PIN) && GPIO_TFT_RESET_PIN >= 0
printf("Resetting display at reset GPIO pin %d\n", GPIO_TFT_RESET_PIN);
SET_GPIO_MODE(GPIO_TFT_RESET_PIN, 1);
SET_GPIO(GPIO_TFT_RESET_PIN);
usleep(120 * 1000);
CLEAR_GPIO(GPIO_TFT_RESET_PIN);
usleep(120 * 1000);
SET_GPIO(GPIO_TFT_RESET_PIN);
usleep(120 * 1000);
#endif

// Do the initialization with a very low SPI bus speed, so that it will succeed even if the bus speed chosen by the user is too high.
spi->clk = 34;
__sync_synchronize();

BEGIN_SPI_COMMUNICATION();
{
// The init sequence reference:
// https://www.waveshare.com/wiki/File:LCD_Module_code.zip
// File: RaspberryPi/c/lib/LCD/LCD_1in28.c
SPI_TRANSFER(0xEF);
SPI_TRANSFER(0xEB, 0x14);

SPI_TRANSFER(0xFE);
SPI_TRANSFER(0xEF);

SPI_TRANSFER(0xEB, 0x14);

SPI_TRANSFER(0x84, 0x40);

SPI_TRANSFER(0x85, 0xFF);

SPI_TRANSFER(0x86, 0xFF);

SPI_TRANSFER(0x87, 0xFF);

SPI_TRANSFER(0x88, 0x0A);

SPI_TRANSFER(0x89, 0x21);

SPI_TRANSFER(0x8A, 0x00);

SPI_TRANSFER(0x8B, 0x80);

SPI_TRANSFER(0x8C, 0x01);

SPI_TRANSFER(0x8D, 0x01);

SPI_TRANSFER(0x8E, 0xFF);

SPI_TRANSFER(0x8F, 0xFF);


SPI_TRANSFER(0xB6, 0x00, 0x20);

SPI_TRANSFER(0x36, 0x08);//Set as vertical screen

SPI_TRANSFER(0x3A, 0x05);


SPI_TRANSFER(0x90, 0x08, 0x08, 0x08, 0x08);

SPI_TRANSFER(0xBD, 0x06);

SPI_TRANSFER(0xBC, 0x00);

SPI_TRANSFER(0xFF, 0x60, 0x01, 0x04);

SPI_TRANSFER(0xC3, 0x13);

SPI_TRANSFER(0xC4, 0x13);

SPI_TRANSFER(0xC9, 0x22);

SPI_TRANSFER(0xBE, 0x11);

SPI_TRANSFER(0xE1, 0x10, 0x0E);

SPI_TRANSFER(0xDF, 0x21, 0x0c, 0x02);

SPI_TRANSFER(0xF0, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A);

SPI_TRANSFER(0xF1, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F);


SPI_TRANSFER(0xF2, 0x45, 0x09, 0x08, 0x08, 0x26, 0x2A);

SPI_TRANSFER(0xF3, 0x43, 0x70, 0x72, 0x36, 0x37, 0x6F);

SPI_TRANSFER(0xED, 0x1B, 0x0B);

SPI_TRANSFER(0xAE, 0x77);

SPI_TRANSFER(0xCD, 0x63);


SPI_TRANSFER(0x70, 0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0x08, 0x03);

SPI_TRANSFER(0xE8, 0x34);

SPI_TRANSFER(0x62, 0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0x0F, 0x71, 0xEF, 0x70, 0x70);

SPI_TRANSFER(0x63, 0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xF3, 0x70, 0x70);

SPI_TRANSFER(0x64, 0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07);

SPI_TRANSFER(0x66, 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00);

SPI_TRANSFER(0x67, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98);

SPI_TRANSFER(0x74, 0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00);

SPI_TRANSFER(0x98, 0x3e, 0x07);

SPI_TRANSFER(0x35);

SPI_TRANSFER(0x21);

SPI_TRANSFER(0x11);
usleep(120 * 1000);
SPI_TRANSFER(0x29);
usleep(20 * 1000);

ClearScreen();
}
#ifndef USE_DMA_TRANSFERS // For DMA transfers, keep SPI CS & TA active.
END_SPI_COMMUNICATION();
#endif

// And speed up to the desired operation speed finally after init is done.
usleep(10 * 1000); // Delay a bit before restoring CLK, or otherwise this has been observed to cause the display not init if done back to back after the clear operation above.
spi->clk = SPI_BUS_CLOCK_DIVISOR;
}

void TurnBacklightOn()
{
#if defined(GPIO_TFT_BACKLIGHT) && defined(BACKLIGHT_CONTROL)
SET_GPIO_MODE(GPIO_TFT_BACKLIGHT, 0x01); // Set backlight pin to digital 0/1 output mode (0x01) in case it had been PWM controlled
SET_GPIO(GPIO_TFT_BACKLIGHT); // And turn the backlight on.
#endif
}

void TurnBacklightOff()
{
#if defined(GPIO_TFT_BACKLIGHT) && defined(BACKLIGHT_CONTROL)
SET_GPIO_MODE(GPIO_TFT_BACKLIGHT, 0x01); // Set backlight pin to digital 0/1 output mode (0x01) in case it had been PWM controlled
CLEAR_GPIO(GPIO_TFT_BACKLIGHT); // And turn the backlight off.
#endif
}

void TurnDisplayOff()
{
TurnBacklightOff();
}

void TurnDisplayOn()
{
TurnBacklightOn();
}

void DeinitSPIDisplay()
{
ClearScreen();
SPI_TRANSFER(/*Display OFF*/ 0x28);
TurnBacklightOff();
}

#endif
27 changes: 27 additions & 0 deletions gc9a01.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#if defined(GC9A01)

// Data specific to the GC9A01 controller
#define DISPLAY_SET_CURSOR_X 0x2A
#define DISPLAY_SET_CURSOR_Y 0x2B
#define DISPLAY_WRITE_PIXELS 0x2C

#define MUST_SEND_FULL_CURSOR_WINDOW

#define DISPLAY_NATIVE_WIDTH 240
#define DISPLAY_NATIVE_HEIGHT 240

#define ALL_TASKS_SHOULD_DMA
#define UPDATE_FRAMES_WITHOUT_DIFFING
#undef SAVE_BATTERY_BY_SLEEPING_WHEN_IDLE // workaround for preventing crash in idle.

#ifdef WAVESHARE_GC9A01
#include "waveshare_gc9a01.h"
#endif

#define InitSPIDisplay InitGC9A01

void InitGC9A01(void);

#endif
19 changes: 19 additions & 0 deletions waveshare_gc9a01.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

// Data specific to WaveShare 240x240, 1.28 inch ISP LCD GC9A01, https://www.waveshare.net/w/upload/5/5e/GC9A01A.pdf
#ifdef WAVESHARE_GC9A01

#if !defined(GPIO_TFT_DATA_CONTROL)
#define GPIO_TFT_DATA_CONTROL 25
#endif

#if !defined(GPIO_TFT_BACKLIGHT)
#define GPIO_TFT_BACKLIGHT 18
#endif

#if !defined(GPIO_TFT_RESET_PIN)
#define GPIO_TFT_RESET_PIN 27
#endif

#undef DISPLAY_OUTPUT_LANDSCAPE
#endif