633 lines
20 KiB
C
633 lines
20 KiB
C
/**
|
|
* @file gc9a01.c
|
|
* @brief Implémentation du driver pour écran TFT rond GC9A01 240x240
|
|
*/
|
|
|
|
#include "gc9a01.h"
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
//==============================================================================
|
|
// Variables privées
|
|
//==============================================================================
|
|
static SPI_HandleTypeDef *hspi_gc9a01 = NULL;
|
|
|
|
// Police simple 8x8 (bitmap)
|
|
static const uint8_t font8x8_basic[128][8] = {
|
|
// A partir du caractère ' ' (32)
|
|
[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // space
|
|
[33] = { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, // !
|
|
[34] = { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // "
|
|
[35] = { 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00}, // #
|
|
[36] = { 0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00}, // $
|
|
[37] = { 0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00}, // %
|
|
[38] = { 0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00}, // &
|
|
[39] = { 0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // '
|
|
[40] = { 0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00}, // (
|
|
[41] = { 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00}, // )
|
|
[42] = { 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // *
|
|
[43] = { 0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00}, // +
|
|
[44] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x06, 0x00}, // ,
|
|
[45] = { 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00}, // -
|
|
[46] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // .
|
|
[47] = { 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // /
|
|
[48] = { 0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00}, // 0
|
|
[49] = { 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00}, // 1
|
|
[50] = { 0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00}, // 2
|
|
[51] = { 0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00}, // 3
|
|
[52] = { 0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00}, // 4
|
|
[53] = { 0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00}, // 5
|
|
[54] = { 0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00}, // 6
|
|
[55] = { 0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00}, // 7
|
|
[56] = { 0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00}, // 8
|
|
[57] = { 0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00}, // 9
|
|
[58] = { 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00}, // :
|
|
[65] = { 0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00}, // A
|
|
[66] = { 0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00}, // B
|
|
[67] = { 0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00}, // C
|
|
[68] = { 0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00}, // D
|
|
[69] = { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00}, // E
|
|
[70] = { 0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00}, // F
|
|
[71] = { 0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00}, // G
|
|
[72] = { 0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00}, // H
|
|
[73] = { 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // I
|
|
[74] = { 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00}, // J
|
|
[75] = { 0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00}, // K
|
|
[76] = { 0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00}, // L
|
|
[77] = { 0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00}, // M
|
|
[78] = { 0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00}, // N
|
|
[79] = { 0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00}, // O
|
|
[80] = { 0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00}, // P
|
|
[81] = { 0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00}, // Q
|
|
[82] = { 0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00}, // R
|
|
[83] = { 0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00}, // S
|
|
[84] = { 0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00}, // T
|
|
[85] = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00}, // U
|
|
[86] = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00}, // V
|
|
[87] = { 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // W
|
|
[88] = { 0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00}, // X
|
|
[89] = { 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00}, // Y
|
|
[90] = { 0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00}, // Z
|
|
};
|
|
|
|
//==============================================================================
|
|
// Fonctions privées
|
|
//==============================================================================
|
|
|
|
static void GC9A01_WriteCommand(uint8_t cmd) {
|
|
HAL_GPIO_WritePin(GC9A01_DC_GPIO_Port, GC9A01_DC_Pin, GPIO_PIN_RESET);
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_RESET);
|
|
HAL_SPI_Transmit(hspi_gc9a01, &cmd, 1, HAL_MAX_DELAY);
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_SET);
|
|
}
|
|
|
|
static void GC9A01_WriteData(uint8_t data) {
|
|
HAL_GPIO_WritePin(GC9A01_DC_GPIO_Port, GC9A01_DC_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_RESET);
|
|
HAL_SPI_Transmit(hspi_gc9a01, &data, 1, HAL_MAX_DELAY);
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_SET);
|
|
}
|
|
|
|
static void GC9A01_WriteDataBuffer(uint8_t *buffer, uint16_t len) {
|
|
HAL_GPIO_WritePin(GC9A01_DC_GPIO_Port, GC9A01_DC_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_RESET);
|
|
HAL_SPI_Transmit(hspi_gc9a01, buffer, len, HAL_MAX_DELAY);
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_SET);
|
|
}
|
|
|
|
static void GC9A01_SetAddressWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
|
// Column address set
|
|
GC9A01_WriteCommand(GC9A01_CASET);
|
|
GC9A01_WriteData(x0 >> 8);
|
|
GC9A01_WriteData(x0 & 0xFF);
|
|
GC9A01_WriteData(x1 >> 8);
|
|
GC9A01_WriteData(x1 & 0xFF);
|
|
|
|
// Row address set
|
|
GC9A01_WriteCommand(GC9A01_RASET);
|
|
GC9A01_WriteData(y0 >> 8);
|
|
GC9A01_WriteData(y0 & 0xFF);
|
|
GC9A01_WriteData(y1 >> 8);
|
|
GC9A01_WriteData(y1 & 0xFF);
|
|
|
|
// Write to RAM
|
|
GC9A01_WriteCommand(GC9A01_RAMWR);
|
|
}
|
|
|
|
//==============================================================================
|
|
// Fonctions publiques
|
|
//==============================================================================
|
|
|
|
bool GC9A01_Init(SPI_HandleTypeDef *hspi) {
|
|
hspi_gc9a01 = hspi;
|
|
|
|
// Reset de l'écran
|
|
GC9A01_Reset();
|
|
HAL_Delay(100);
|
|
|
|
// Séquence d'initialisation GC9A01
|
|
GC9A01_WriteCommand(GC9A01_INREGEN2);
|
|
|
|
GC9A01_WriteCommand(GC9A01_SPI2DATA);
|
|
|
|
GC9A01_WriteCommand(0xEB);
|
|
GC9A01_WriteData(0x14);
|
|
|
|
GC9A01_WriteCommand(GC9A01_INREGEN2);
|
|
|
|
GC9A01_WriteCommand(GC9A01_SPI2DATA);
|
|
|
|
GC9A01_WriteCommand(0x84);
|
|
GC9A01_WriteData(0x40);
|
|
|
|
GC9A01_WriteCommand(0x85);
|
|
GC9A01_WriteData(0xFF);
|
|
|
|
GC9A01_WriteCommand(0x86);
|
|
GC9A01_WriteData(0xFF);
|
|
|
|
GC9A01_WriteCommand(0x87);
|
|
GC9A01_WriteData(0xFF);
|
|
|
|
GC9A01_WriteCommand(0x88);
|
|
GC9A01_WriteData(0x0A);
|
|
|
|
GC9A01_WriteCommand(0x89);
|
|
GC9A01_WriteData(0x21);
|
|
|
|
GC9A01_WriteCommand(0x8A);
|
|
GC9A01_WriteData(0x00);
|
|
|
|
GC9A01_WriteCommand(0x8B);
|
|
GC9A01_WriteData(0x80);
|
|
|
|
GC9A01_WriteCommand(0x8C);
|
|
GC9A01_WriteData(0x01);
|
|
|
|
GC9A01_WriteCommand(0x8D);
|
|
GC9A01_WriteData(0x01);
|
|
|
|
GC9A01_WriteCommand(0x8E);
|
|
GC9A01_WriteData(0xFF);
|
|
|
|
GC9A01_WriteCommand(0x8F);
|
|
GC9A01_WriteData(0xFF);
|
|
|
|
GC9A01_WriteCommand(GC9A01_DFUNCTR);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x20);
|
|
|
|
GC9A01_WriteCommand(GC9A01_MADCTL);
|
|
GC9A01_WriteData(0x08);
|
|
|
|
GC9A01_WriteCommand(GC9A01_COLMOD);
|
|
GC9A01_WriteData(0x05);
|
|
|
|
GC9A01_WriteCommand(0x90);
|
|
GC9A01_WriteData(0x08);
|
|
GC9A01_WriteData(0x08);
|
|
GC9A01_WriteData(0x08);
|
|
GC9A01_WriteData(0x08);
|
|
|
|
GC9A01_WriteCommand(0xBD);
|
|
GC9A01_WriteData(0x06);
|
|
|
|
GC9A01_WriteCommand(0xBC);
|
|
GC9A01_WriteData(0x00);
|
|
|
|
GC9A01_WriteCommand(0xFF);
|
|
GC9A01_WriteData(0x60);
|
|
GC9A01_WriteData(0x01);
|
|
GC9A01_WriteData(0x04);
|
|
|
|
GC9A01_WriteCommand(GC9A01_PWCTR2);
|
|
GC9A01_WriteData(0x13);
|
|
GC9A01_WriteCommand(GC9A01_PWCTR3);
|
|
GC9A01_WriteData(0x13);
|
|
|
|
GC9A01_WriteCommand(GC9A01_PWCTR4);
|
|
GC9A01_WriteData(0x22);
|
|
|
|
GC9A01_WriteCommand(0xBE);
|
|
GC9A01_WriteData(0x11);
|
|
|
|
GC9A01_WriteCommand(0xE1);
|
|
GC9A01_WriteData(0x10);
|
|
GC9A01_WriteData(0x0E);
|
|
|
|
GC9A01_WriteCommand(0xDF);
|
|
GC9A01_WriteData(0x21);
|
|
GC9A01_WriteData(0x0c);
|
|
GC9A01_WriteData(0x02);
|
|
|
|
GC9A01_WriteCommand(GC9A01_GAMMA1);
|
|
GC9A01_WriteData(0x45);
|
|
GC9A01_WriteData(0x09);
|
|
GC9A01_WriteData(0x08);
|
|
GC9A01_WriteData(0x08);
|
|
GC9A01_WriteData(0x26);
|
|
GC9A01_WriteData(0x2A);
|
|
|
|
GC9A01_WriteCommand(GC9A01_GAMMA2);
|
|
GC9A01_WriteData(0x43);
|
|
GC9A01_WriteData(0x70);
|
|
GC9A01_WriteData(0x72);
|
|
GC9A01_WriteData(0x36);
|
|
GC9A01_WriteData(0x37);
|
|
GC9A01_WriteData(0x6F);
|
|
|
|
GC9A01_WriteCommand(GC9A01_GAMMA3);
|
|
GC9A01_WriteData(0x45);
|
|
GC9A01_WriteData(0x09);
|
|
GC9A01_WriteData(0x08);
|
|
GC9A01_WriteData(0x08);
|
|
GC9A01_WriteData(0x26);
|
|
GC9A01_WriteData(0x2A);
|
|
|
|
GC9A01_WriteCommand(GC9A01_GAMMA4);
|
|
GC9A01_WriteData(0x43);
|
|
GC9A01_WriteData(0x70);
|
|
GC9A01_WriteData(0x72);
|
|
GC9A01_WriteData(0x36);
|
|
GC9A01_WriteData(0x37);
|
|
GC9A01_WriteData(0x6F);
|
|
|
|
GC9A01_WriteCommand(0xED);
|
|
GC9A01_WriteData(0x1B);
|
|
GC9A01_WriteData(0x0B);
|
|
|
|
GC9A01_WriteCommand(0xAE);
|
|
GC9A01_WriteData(0x77);
|
|
|
|
GC9A01_WriteCommand(0xCD);
|
|
GC9A01_WriteData(0x63);
|
|
|
|
GC9A01_WriteCommand(0x70);
|
|
GC9A01_WriteData(0x07);
|
|
GC9A01_WriteData(0x07);
|
|
GC9A01_WriteData(0x04);
|
|
GC9A01_WriteData(0x0E);
|
|
GC9A01_WriteData(0x0F);
|
|
GC9A01_WriteData(0x71);
|
|
GC9A01_WriteData(0xEF);
|
|
GC9A01_WriteData(0x70);
|
|
GC9A01_WriteData(0x70);
|
|
|
|
GC9A01_WriteCommand(0x63);
|
|
GC9A01_WriteData(0x18);
|
|
GC9A01_WriteData(0x11);
|
|
GC9A01_WriteData(0x71);
|
|
GC9A01_WriteData(0xF1);
|
|
GC9A01_WriteData(0x70);
|
|
GC9A01_WriteData(0x70);
|
|
GC9A01_WriteData(0x18);
|
|
GC9A01_WriteData(0x13);
|
|
GC9A01_WriteData(0x71);
|
|
GC9A01_WriteData(0xF3);
|
|
GC9A01_WriteData(0x70);
|
|
GC9A01_WriteData(0x70);
|
|
|
|
GC9A01_WriteCommand(0x64);
|
|
GC9A01_WriteData(0x28);
|
|
GC9A01_WriteData(0x29);
|
|
GC9A01_WriteData(0xF1);
|
|
GC9A01_WriteData(0x01);
|
|
GC9A01_WriteData(0xF1);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x07);
|
|
|
|
GC9A01_WriteCommand(0x66);
|
|
GC9A01_WriteData(0x3C);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0xCD);
|
|
GC9A01_WriteData(0x67);
|
|
GC9A01_WriteData(0x45);
|
|
GC9A01_WriteData(0x45);
|
|
GC9A01_WriteData(0x10);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x00);
|
|
|
|
GC9A01_WriteCommand(0x67);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x3C);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x01);
|
|
GC9A01_WriteData(0x54);
|
|
GC9A01_WriteData(0x10);
|
|
GC9A01_WriteData(0x32);
|
|
GC9A01_WriteData(0x98);
|
|
|
|
GC9A01_WriteCommand(0x74);
|
|
GC9A01_WriteData(0x10);
|
|
GC9A01_WriteData(0x85);
|
|
GC9A01_WriteData(0x80);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x00);
|
|
GC9A01_WriteData(0x4E);
|
|
GC9A01_WriteData(0x00);
|
|
|
|
GC9A01_WriteCommand(0x98);
|
|
GC9A01_WriteData(0x3e);
|
|
GC9A01_WriteData(0x07);
|
|
|
|
GC9A01_WriteCommand(GC9A01_SLPOUT);
|
|
HAL_Delay(120);
|
|
|
|
GC9A01_WriteCommand(GC9A01_DISPON);
|
|
HAL_Delay(20);
|
|
|
|
return true;
|
|
}
|
|
|
|
void GC9A01_Reset(void) {
|
|
HAL_GPIO_WritePin(GC9A01_RST_GPIO_Port, GC9A01_RST_Pin, GPIO_PIN_RESET);
|
|
HAL_Delay(10);
|
|
HAL_GPIO_WritePin(GC9A01_RST_GPIO_Port, GC9A01_RST_Pin, GPIO_PIN_SET);
|
|
HAL_Delay(10);
|
|
}
|
|
|
|
void GC9A01_DisplayOn(void) {
|
|
GC9A01_WriteCommand(GC9A01_DISPON);
|
|
}
|
|
|
|
void GC9A01_DisplayOff(void) {
|
|
GC9A01_WriteCommand(GC9A01_DISPOFF);
|
|
}
|
|
|
|
void GC9A01_SetRotation(uint8_t rotation) {
|
|
GC9A01_WriteCommand(GC9A01_MADCTL);
|
|
switch (rotation) {
|
|
case 0:
|
|
GC9A01_WriteData(0x08);
|
|
break;
|
|
case 1:
|
|
GC9A01_WriteData(0x68);
|
|
break;
|
|
case 2:
|
|
GC9A01_WriteData(0xC8);
|
|
break;
|
|
case 3:
|
|
GC9A01_WriteData(0xA8);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GC9A01_FillScreen(uint16_t color) {
|
|
GC9A01_SetAddressWindow(0, 0, GC9A01_WIDTH-1, GC9A01_HEIGHT-1);
|
|
|
|
uint8_t color_high = color >> 8;
|
|
uint8_t color_low = color & 0xFF;
|
|
|
|
HAL_GPIO_WritePin(GC9A01_DC_GPIO_Port, GC9A01_DC_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_RESET);
|
|
|
|
for (uint32_t i = 0; i < GC9A01_WIDTH * GC9A01_HEIGHT; i++) {
|
|
uint8_t data[2] = {color_high, color_low};
|
|
HAL_SPI_Transmit(hspi_gc9a01, data, 2, HAL_MAX_DELAY);
|
|
}
|
|
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_SET);
|
|
}
|
|
|
|
void GC9A01_SetPixel(uint16_t x, uint16_t y, uint16_t color) {
|
|
if (x >= GC9A01_WIDTH || y >= GC9A01_HEIGHT) return;
|
|
|
|
GC9A01_SetAddressWindow(x, y, x, y);
|
|
uint8_t data[2] = {color >> 8, color & 0xFF};
|
|
GC9A01_WriteDataBuffer(data, 2);
|
|
}
|
|
|
|
void GC9A01_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color) {
|
|
int16_t dx = abs(x1 - x0);
|
|
int16_t dy = abs(y1 - y0);
|
|
int16_t sx = (x0 < x1) ? 1 : -1;
|
|
int16_t sy = (y0 < y1) ? 1 : -1;
|
|
int16_t err = dx - dy;
|
|
|
|
while (1) {
|
|
GC9A01_SetPixel(x0, y0, color);
|
|
|
|
if (x0 == x1 && y0 == y1) break;
|
|
|
|
int16_t e2 = 2 * err;
|
|
if (e2 > -dy) {
|
|
err -= dy;
|
|
x0 += sx;
|
|
}
|
|
if (e2 < dx) {
|
|
err += dx;
|
|
y0 += sy;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GC9A01_DrawRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) {
|
|
GC9A01_DrawLine(x, y, x + width - 1, y, color);
|
|
GC9A01_DrawLine(x + width - 1, y, x + width - 1, y + height - 1, color);
|
|
GC9A01_DrawLine(x + width - 1, y + height - 1, x, y + height - 1, color);
|
|
GC9A01_DrawLine(x, y + height - 1, x, y, color);
|
|
}
|
|
|
|
void GC9A01_FillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) {
|
|
if (x >= GC9A01_WIDTH || y >= GC9A01_HEIGHT) return;
|
|
if (x + width > GC9A01_WIDTH) width = GC9A01_WIDTH - x;
|
|
if (y + height > GC9A01_HEIGHT) height = GC9A01_HEIGHT - y;
|
|
|
|
GC9A01_SetAddressWindow(x, y, x + width - 1, y + height - 1);
|
|
|
|
uint8_t color_high = color >> 8;
|
|
uint8_t color_low = color & 0xFF;
|
|
|
|
HAL_GPIO_WritePin(GC9A01_DC_GPIO_Port, GC9A01_DC_Pin, GPIO_PIN_SET);
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_RESET);
|
|
|
|
for (uint32_t i = 0; i < width * height; i++) {
|
|
uint8_t data[2] = {color_high, color_low};
|
|
HAL_SPI_Transmit(hspi_gc9a01, data, 2, HAL_MAX_DELAY);
|
|
}
|
|
|
|
HAL_GPIO_WritePin(GC9A01_CS_GPIO_Port, GC9A01_CS_Pin, GPIO_PIN_SET);
|
|
}
|
|
|
|
void GC9A01_DrawCircle(uint16_t x, uint16_t y, uint8_t radius, uint16_t color) {
|
|
int16_t f = 1 - radius;
|
|
int16_t ddF_x = 1;
|
|
int16_t ddF_y = -2 * radius;
|
|
int16_t x1 = 0;
|
|
int16_t y1 = radius;
|
|
|
|
GC9A01_SetPixel(x, y + radius, color);
|
|
GC9A01_SetPixel(x, y - radius, color);
|
|
GC9A01_SetPixel(x + radius, y, color);
|
|
GC9A01_SetPixel(x - radius, y, color);
|
|
|
|
while (x1 < y1) {
|
|
if (f >= 0) {
|
|
y1--;
|
|
ddF_y += 2;
|
|
f += ddF_y;
|
|
}
|
|
x1++;
|
|
ddF_x += 2;
|
|
f += ddF_x;
|
|
|
|
GC9A01_SetPixel(x + x1, y + y1, color);
|
|
GC9A01_SetPixel(x - x1, y + y1, color);
|
|
GC9A01_SetPixel(x + x1, y - y1, color);
|
|
GC9A01_SetPixel(x - x1, y - y1, color);
|
|
GC9A01_SetPixel(x + y1, y + x1, color);
|
|
GC9A01_SetPixel(x - y1, y + x1, color);
|
|
GC9A01_SetPixel(x + y1, y - x1, color);
|
|
GC9A01_SetPixel(x - y1, y - x1, color);
|
|
}
|
|
}
|
|
|
|
void GC9A01_FillCircle(uint16_t x, uint16_t y, uint8_t radius, uint16_t color) {
|
|
for (int16_t dy = -radius; dy <= radius; dy++) {
|
|
for (int16_t dx = -radius; dx <= radius; dx++) {
|
|
if (dx*dx + dy*dy <= radius*radius) {
|
|
GC9A01_SetPixel(x + dx, y + dy, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GC9A01_DrawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg_color, uint8_t size) {
|
|
if (c < 32 || c > 127) c = '?';
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
uint8_t line = font8x8_basic[c][i];
|
|
for (int j = 0; j < 8; j++) {
|
|
if (line & (1 << j)) {
|
|
if (size == 1) {
|
|
GC9A01_SetPixel(x + j, y + i, color);
|
|
} else {
|
|
GC9A01_FillRect(x + j * size, y + i * size, size, size, color);
|
|
}
|
|
} else if (bg_color != color) {
|
|
if (size == 1) {
|
|
GC9A01_SetPixel(x + j, y + i, bg_color);
|
|
} else {
|
|
GC9A01_FillRect(x + j * size, y + i * size, size, size, bg_color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GC9A01_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bg_color, uint8_t size) {
|
|
while (*str) {
|
|
GC9A01_DrawChar(x, y, *str, color, bg_color, size);
|
|
x += 8 * size;
|
|
str++;
|
|
}
|
|
}
|
|
|
|
uint16_t GC9A01_RGB565(uint8_t r, uint8_t g, uint8_t b) {
|
|
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
|
}
|
|
|
|
bool GC9A01_IsInCircle(uint16_t x, uint16_t y) {
|
|
int16_t dx = x - GC9A01_RADIUS;
|
|
int16_t dy = y - GC9A01_RADIUS;
|
|
return (dx*dx + dy*dy) <= (GC9A01_RADIUS * GC9A01_RADIUS);
|
|
}
|
|
|
|
// Fonctions spécifiques pour interface moto
|
|
void GC9A01_DrawGauge(uint16_t center_x, uint16_t center_y, uint8_t radius,
|
|
float value, float min_val, float max_val,
|
|
uint16_t color, const char* label) {
|
|
|
|
// Dessiner le cercle extérieur
|
|
GC9A01_DrawCircle(center_x, center_y, radius, GC9A01_WHITE);
|
|
|
|
// Calculer l'angle (de -90° à +90°, soit 180° total)
|
|
float normalized = (value - min_val) / (max_val - min_val);
|
|
if (normalized < 0) normalized = 0;
|
|
if (normalized > 1) normalized = 1;
|
|
|
|
float angle = -90.0f + (normalized * 180.0f); // -90° à +90°
|
|
float rad = angle * M_PI / 180.0f;
|
|
|
|
// Dessiner l'aiguille
|
|
int16_t needle_x = center_x + (radius - 5) * cos(rad);
|
|
int16_t needle_y = center_y + (radius - 5) * sin(rad);
|
|
GC9A01_DrawLine(center_x, center_y, needle_x, needle_y, color);
|
|
|
|
// Dessiner le centre
|
|
GC9A01_FillCircle(center_x, center_y, 3, color);
|
|
|
|
// Afficher la valeur
|
|
char value_str[10];
|
|
snprintf(value_str, sizeof(value_str), "%.1f", value);
|
|
GC9A01_DrawString(center_x - 20, center_y + radius + 10, value_str, color, GC9A01_BLACK, 1);
|
|
|
|
// Afficher le label
|
|
if (label) {
|
|
GC9A01_DrawString(center_x - strlen(label) * 4, center_y - radius - 20, label, GC9A01_WHITE, GC9A01_BLACK, 1);
|
|
}
|
|
}
|
|
|
|
void GC9A01_DrawAngleIndicator(float roll, float pitch) {
|
|
uint16_t center_x = GC9A01_WIDTH / 2;
|
|
uint16_t center_y = GC9A01_HEIGHT / 2;
|
|
|
|
// Effacer la zone central
|
|
GC9A01_FillCircle(center_x, center_y, 50, GC9A01_BLACK);
|
|
|
|
// Dessiner l'horizon artificiel
|
|
GC9A01_DrawCircle(center_x, center_y, 50, GC9A01_WHITE);
|
|
|
|
// Ligne d'horizon (basée sur le pitch)
|
|
int16_t horizon_offset = (int16_t)(pitch * 2); // Facteur d'échelle
|
|
GC9A01_DrawLine(center_x - 40, center_y + horizon_offset,
|
|
center_x + 40, center_y + horizon_offset, GC9A01_CYAN);
|
|
|
|
// Indicateur de roulis (triangle au centre)
|
|
float roll_rad = roll * M_PI / 180.0f;
|
|
int16_t tri_x = center_x + 20 * sin(roll_rad);
|
|
int16_t tri_y = center_y - 20 * cos(roll_rad);
|
|
|
|
GC9A01_DrawLine(center_x, center_y, tri_x, tri_y, GC9A01_RED);
|
|
GC9A01_FillCircle(tri_x, tri_y, 3, GC9A01_RED);
|
|
|
|
// Afficher les valeurs numériques
|
|
char roll_str[10], pitch_str[10];
|
|
snprintf(roll_str, sizeof(roll_str), "R:%.1f", roll);
|
|
snprintf(pitch_str, sizeof(pitch_str), "P:%.1f", pitch);
|
|
|
|
GC9A01_DrawString(10, 10, roll_str, GC9A01_WHITE, GC9A01_BLACK, 1);
|
|
GC9A01_DrawString(10, 25, pitch_str, GC9A01_WHITE, GC9A01_BLACK, 1);
|
|
}
|
|
|
|
void GC9A01_DrawStateIndicator(const char* state, uint16_t color) {
|
|
// Effacer la zone du bas
|
|
GC9A01_FillRect(0, GC9A01_HEIGHT - 30, GC9A01_WIDTH, 30, GC9A01_BLACK);
|
|
|
|
// Centrer le texte
|
|
uint16_t text_width = strlen(state) * 8;
|
|
uint16_t start_x = (GC9A01_WIDTH - text_width) / 2;
|
|
|
|
GC9A01_DrawString(start_x, GC9A01_HEIGHT - 20, state, color, GC9A01_BLACK, 1);
|
|
}A01_WriteData(0x09);
|
|
GC9A01_WriteData(0x07);
|
|
GC9A01_WriteData(0x08);
|
|
GC9A01_WriteData(0x03);
|
|
|
|
GC9A01_WriteCommand(GC9A01_FRAMERATE);
|
|
GC9A01_WriteData(0x34);
|
|
|
|
GC9A01_WriteCommand(0x62);
|
|
GC9A01_WriteData(0x18);
|
|
GC9A01_WriteData(0x0D);
|
|
GC9A01_WriteData(0x71);
|
|
GC9A01_WriteData(0xED);
|
|
GC9A01_WriteData(0x70);
|
|
GC9A01_WriteData(0x70);
|
|
GC9A01_WriteData(0x18);
|
|
GC9A01_WriteData(0x0F);
|
|
GC9
|