diff --git a/ion/drivers/st7586/st7586.c b/ion/drivers/st7586/st7586.c index 46f80c5f6..a4c65af58 100644 --- a/ion/drivers/st7586/st7586.c +++ b/ion/drivers/st7586/st7586.c @@ -1,4 +1,3 @@ -#include #include #include "st7586.h" @@ -9,8 +8,8 @@ enum { }; enum { - NOP = 0x00, // No operation - RESET = 0x01, // Software reset + NOP = 0x00, + RESET = 0x01, SLEEP_IN = 0x10, SLEEP_OUT = 0x11, DISPLAY_OFF = 0x28, @@ -19,34 +18,7 @@ enum { SET_ROW_ADDRESS = 0x2B, WRITE_DISPLAY_DATA = 0x2C, ENABLE_DDRAM = 0x3A, - /* - RAMWR = 0x2C, // Memory write - MADCTL = 0x36, // Memory access control - PIXSET = 0x3A, // Pixel format set - IFMODE = 0xB0, // RGB interface signal control - FRMCTR1 = 0xB1, // Frame rate control in normal/full-color mode - IFCTL = 0xF6 // Interface control - */ }; -/* -#define IFMODE_EPL (1<<0) -#define IFMODE_DPL (1<<1) -#define IFMODE_HSPL (1<<2) -#define IFMODE_VSPL (1<<3) -#define IFMODE_RCM_DE (2<<5) -// DE mode: Valid data is determined by the DE signal -#define IFMODE_RCM_SYNC (3<<5) -// Sync mode: In sync mode, DE signal is ignored -#define IFMODE_BYPASS (1<<7) - - -#define MADCTL_MH (1<<2) -#define MADCTL_BGR (1<<3) -#define MADCTL_ML (1<<4) -#define MADCTL_MV (1<<5) -#define MADCTL_MX (1<<6) -#define MADCTL_MY (1<<7) -*/ typedef struct { char mode; @@ -57,97 +29,101 @@ typedef struct { #define DATA(d) (instruction_t){.mode = (char)DATA_MODE, .payload = (char)d} #define DELAY(m) (instruction_t){.mode = (char)DELAY_MODE, .payload = (char)m} -#define USE_MANUFACTURER_INIT 0 -#if USE_MANUFACTURER_INIT -static instruction_t init_sequence[] = { - COMMAND(0x01), // ADDED BY ME - DELAY(220), - COMMAND(0x11), // Sleep Out - COMMAND(0x28), // Display OFF - DELAY(50), - COMMAND(0xC0), // Vop = B9h - DATA(0x45), - DATA(0x01), - COMMAND(0xC3), // BIAS = 1/14 - DATA(0x00), - COMMAND(0xC4), // Booster = x8 - DATA(0x07), - COMMAND(0xD0), // Enable Analog Circuit - DATA(0x1D), - COMMAND(0xB5), // N-Line = 0 - DATA(0x00), - //COMMAND(0x39), // Monochrome Mode - COMMAND(0x38), // Grey Mode - COMMAND(0x3A), // Enable DDRAM Interface - DATA(0x02), - COMMAND(0x36), // Scan Direction Setting - DATA(0xc0), //COM:C160--C1 SEG: SEG384-SEG1 - COMMAND(0xB0), // Duty Setting - DATA(0x9F), - - COMMAND(0x20), // Display Inversion OFF - COMMAND(0x2A), // Column Address Setting - DATA(0x00), // SEG0 -> SEG384 - DATA(0x00), - DATA(0x00), - DATA(0x7F), - COMMAND(0x2B), // Row Address Setting - DATA(0x00), // COM0 -> COM160 - DATA(0x00), - DATA(0x00), - DATA(0x9F), - COMMAND(0x29) // Display ON -}; -#else -static instruction_t init_sequence[] = { - COMMAND(RESET), DELAY(50), // Software reset, then wait 5ms - COMMAND(DISPLAY_OFF), - - // Sleep out, requires a 100ms delay - COMMAND(SLEEP_OUT), DELAY(100), - - // Display on, requires a 20ms delay - COMMAND(DISPLAY_ON), DELAY(20), - - // Enable DDRAM interface - // The "DATA" makes no real sense but is mandatory according to the spec - COMMAND(ENABLE_DDRAM), DATA(0x2), - - - // This has been copy-pasted from the manufacturer. - // FIXME: Understand what it does, and maybe fix it! - COMMAND(0xC0), // Vop = B9h - DATA(0x45), - DATA(0x01), - COMMAND(0xC3), // BIAS = 1/14 - DATA(0x00), - COMMAND(0xC4), // Booster = x8 - DATA(0x07), - COMMAND(0xD0), // Enable Analog Circuit - DATA(0x1D), - COMMAND(0xB5), // N-Line = 0 - DATA(0x00), - -}; -#endif - -static void perform_instruction(st7586_t * c, instruction_t * instruction) { - if (instruction->mode == DELAY_MODE) { +static void perform_instruction(st7586_t * c, instruction_t instruction) { + if (instruction.mode == DELAY_MODE) { // FIXME: Should sleep instruction->payload miliseconds - for (int i = 0; i < 800*instruction->payload; i++) { + for (int i = 0; i < 800*instruction.payload; i++) { } } else { - c->data_command_pin_write(instruction->mode); - c->spi_write(&instruction->payload, 1); + c->data_command_pin_write(instruction.mode); + c->spi_write(&instruction.payload, 1); } } -static void perform_instructions(st7586_t * c, instruction_t * instructions, size_t length) { +static void perform_instructions(st7586_t * c, const instruction_t * instructions, size_t length) { for (size_t i=0; ichip_select_pin_write(0); + + const instruction_t init_sequence[] = { +#define USE_MANUFACTURER_INIT 0 +#if USE_MANUFACTURER_INIT + COMMAND(0x01), // ADDED BY ME + DELAY(220), + COMMAND(0x11), // Sleep Out + COMMAND(0x28), // Display OFF + DELAY(50), + COMMAND(0xC0), // Vop = B9h + DATA(0x45), + DATA(0x01), + COMMAND(0xC3), // BIAS = 1/14 + DATA(0x00), + COMMAND(0xC4), // Booster = x8 + DATA(0x07), + COMMAND(0xD0), // Enable Analog Circuit + DATA(0x1D), + COMMAND(0xB5), // N-Line = 0 + DATA(0x00), + //COMMAND(0x39), // Monochrome Mode + COMMAND(0x38), // Grey Mode + COMMAND(0x3A), // Enable DDRAM Interface + DATA(0x02), + COMMAND(0x36), // Scan Direction Setting + DATA(0xc0), //COM:C160--C1 SEG: SEG384-SEG1 + COMMAND(0xB0), // Duty Setting + DATA(0x9F), + COMMAND(0x20), // Display Inversion OFF + COMMAND(0x2A), // Column Address Setting + DATA(0x00), // SEG0 -> SEG384 + DATA(0x00), + DATA(0x00), + DATA(0x7F), + COMMAND(0x2B), // Row Address Setting + DATA(0x00), // COM0 -> COM160 + DATA(0x00), + DATA(0x00), + DATA(0x9F), + COMMAND(0x29) // Display ON +#else + COMMAND(RESET), DELAY(50), // Software reset, then wait 5ms + COMMAND(DISPLAY_OFF), + + // Sleep out, requires a 100ms delay + COMMAND(SLEEP_OUT), DELAY(100), + + // Display on, requires a 20ms delay + COMMAND(DISPLAY_ON), DELAY(20), + + // Enable DDRAM interface + // The "DATA" makes no real sense but is mandatory according to the spec + COMMAND(ENABLE_DDRAM), DATA(0x2), + + + // This has been copy-pasted from the manufacturer. + // FIXME: Understand what it does, and maybe fix it! + COMMAND(0xC0), // Vop = B9h + DATA(0x45), + DATA(0x01), + COMMAND(0xC3), // BIAS = 1/14 + DATA(0x00), + COMMAND(0xC4), // Booster = x8 + DATA(0x07), + COMMAND(0xD0), // Enable Analog Circuit + DATA(0x1D), + COMMAND(0xB5), // N-Line = 0 + DATA(0x00), +#endif + }; + + // Send all the initialisation_sequence + perform_instructions(controller, init_sequence, sizeof(init_sequence)/sizeof(init_sequence[0])); +} + void st7586_set_display_area(st7586_t * controller, uint16_t x_start, uint16_t x_length, uint16_t y_start, uint16_t y_length) { /* The datasheet says the panel counts in "columns", groups of 3 pixels. * It says 3, but from my understanding pixels are grouped by 2, not by 3. So @@ -160,7 +136,7 @@ void st7586_set_display_area(st7586_t * controller, uint16_t x_start, uint16_t x assert(y_end >= y_start); assert(y_end <= 0x9F); - instruction_t sequence[] = { + const instruction_t sequence[] = { COMMAND(SET_COLUMN_ADDRESS), DATA(x_start >> 8), DATA(x_start), @@ -176,79 +152,8 @@ void st7586_set_display_area(st7586_t * controller, uint16_t x_start, uint16_t x perform_instructions(controller, sequence, sizeof(sequence)/sizeof(sequence[0])); } -// p1 = 0, 1, 2, or 3 -// p2 = 0, 1, 2, or 3 -char two_pixels(int p1, int p2) { - return (p1<<6 | p2 << 3); -} - -void st7586_initialize(st7586_t * c) { - // Falling edge on CSX - c->chip_select_pin_write(0); - - // Send all the initialisation_sequence - perform_instructions(c, init_sequence, sizeof(init_sequence)/sizeof(init_sequence[0])); - - st7586_set_display_area(c, 0, 160, 0, 160); - +void st7586_prepare_frame_upload(st7586_t * controller) { // Put the screen in "receive frame data" - - perform_instruction(c, &COMMAND(WRITE_DISPLAY_DATA)); - c->data_command_pin_write(DATA_MODE); - - char pixels[3] = { - two_pixels(0x0,0x3), - two_pixels(0x0,0x3), - two_pixels(0x0,0x3) - }; - c->spi_write(&pixels, 3); - -#define FILL_SCREEN_UPON_INIT 0 -#if FILL_SCREEN_UPON_INIT - - /* FIGURED OUT THE PIXEL FORMAT!!! - * 1 byte = 2 pixels - * Pixel 0 : bit 6,7 - * Pixel 1 : bit 3,4 - */ - // 4byte data 8 dot (B B X - A A X - X X X) - - /* Obesrvations - * - One byte = 2 pixels - * - 64 pixels for a "gradient" on pixel0, and constant on pixel1 - * - that means 32 bytes, so values from 0 to 31 - * BITMASKS! - * pixel 2 : 0x18 - */ - - perform_instruction(c, &COMMAND(WRITE_DISPLAY_DATA)); - c->data_command_pin_write(DATA_MODE); - - char pixels[] = { - two_pixels(0, 3), - two_pixels(1, 1), - two_pixels(2, 2), - two_pixels(0, 3) - }; - for (int i = 0; i<256; i++) { - //char p = ((i%256) & 0x18); - //c->spi_write(&p, 1); - c->spi_write(pixels, sizeof(pixels)); - } - //char pixel = 0; - for (int i=0;i<1024; i++) { - c->spi_write(&pixel, 1); - } - for (int i = 0; i<256; i++) { - char p = (i%256); - c->spi_write(&p, 1); - } -#endif -} - -void st7586_display_buffer(st7586_t * controller, char * buffer, size_t length) { - perform_instruction(controller, &COMMAND(WRITE_DISPLAY_DATA)); + perform_instruction(controller, COMMAND(WRITE_DISPLAY_DATA)); controller->data_command_pin_write(DATA_MODE); - controller->spi_write(buffer, length); } - diff --git a/ion/drivers/st7586/st7586.h b/ion/drivers/st7586/st7586.h index 2373e98dd..9002a3253 100644 --- a/ion/drivers/st7586/st7586.h +++ b/ion/drivers/st7586/st7586.h @@ -2,6 +2,7 @@ #define PLATFORM_ST7586_H 1 #include +#include #include /* This is the ST7586 driver @@ -16,7 +17,5 @@ typedef struct { void st7586_initialize(st7586_t * controller); void st7586_set_display_area(st7586_t * controller, uint16_t x_start, uint16_t x_length, uint16_t y_start, uint16_t y_length); - - - +void st7586_prepare_frame_upload(st7586_t * controller); #endif diff --git a/ion/platform/device/Makefile b/ion/platform/device/Makefile index 7ec65619a..a2fdd0e18 100644 --- a/ion/platform/device/Makefile +++ b/ion/platform/device/Makefile @@ -1,2 +1,2 @@ -objs += $(addprefix ion/platform/device/, platform.o init.o display.o framebuffer.o init_kbd.o display/dma.o) +objs += $(addprefix ion/platform/device/, platform.o init.o display.o framebuffer.o init_kbd.o display/dma.o display/gpio.o display/spi.o) objs += $(addprefix ion/drivers/, st7586/st7586.o fx92kbd/fx92kbd.o) diff --git a/ion/platform/device/display.c b/ion/platform/device/display.c index 4ced05161..5ada99c52 100644 --- a/ion/platform/device/display.c +++ b/ion/platform/device/display.c @@ -17,6 +17,11 @@ */ #include + +#include "display/gpio.h" +#include "display/spi.h" +#include "display/dma.h" + #include "platform.h" #include "framebuffer.h" #include "registers/registers.h" @@ -33,98 +38,19 @@ void ion_display_off() { // Turn off panel } -static void init_spi_pins(); -static void init_spi_port(); -static void init_panel(); - void init_display() { - /* This routine is responsible for initializing the LCD panel. - * Its interface with the outer world is the framebuffer: after execution of - * this routine, everyone can expect to write to the LCD by writing to the - * framebuffer. */ - init_spi_pins(); - init_spi_port(); + display_gpio_init(); + display_spi_init(); - init_panel(); - - - - display_configure_dma(); -} - -static void init_spi_pins() { - // We are using GPIO B, which live on the AHB1 bus. Let's enable its clock. - RCC_AHB1ENR |= GPIOBEN; - - // LCD_CS(PB10, LCD_RST(PB12) and LCD_DAT_INS(PB14)are controlled directly - REGISTER_SET_VALUE(GPIO_MODER(GPIOB), MODER(10), GPIO_MODE_OUTPUT); - REGISTER_SET_VALUE(GPIO_MODER(GPIOB), MODER(12), GPIO_MODE_OUTPUT); - REGISTER_SET_VALUE(GPIO_MODER(GPIOB), MODER(14), GPIO_MODE_OUTPUT); - - /* LCD_SPI_CLK(PB13) and LCD_SPI_MOSI(PB15) are used for SPI, which is an - * alternate function. */ - REGISTER_SET_VALUE(GPIO_MODER(GPIOB), MODER(13), GPIO_MODE_ALTERNATE_FUNCTION); - REGISTER_SET_VALUE(GPIO_MODER(GPIOB), MODER(15), GPIO_MODE_ALTERNATE_FUNCTION); - - /* More precisely, we will use AF05, which maps PB15 to SPI2_MOSI and PB13 to - * SPI2_SCK. */ - REGISTER_SET_VALUE(GPIO_AFR(GPIOB, 13), AFR(13), 5); - REGISTER_SET_VALUE(GPIO_AFR(GPIOB, 15), AFR(15), 5); -} - -static void init_spi_port() { - // Enable the SPI2 clock (SPI2 lives on the APB1 bus) - RCC_APB1ENR |= SPI2EN; - - // Configure the SPI port - SPI_CR1(SPI2) = (SPI_BIDIMODE | SPI_BIDIOE | SPI_MSTR | SPI_DFF_8_BITS | SPI_BR(SPI_BR_DIV_2) | SPI_SSM | SPI_SSI | SPI_SPE); -} - -// Panel - -static void spi_2_write(char * data, size_t size); -static void gpio_b10_write(bool pin_state); -static void gpio_b12_write(bool pin_state); -static void gpio_b14_write(bool pin_state); - -static void init_panel() { + st7586_t * controller = &(Platform.display); gpio_b12_write(1); // LCD-RST high - Platform.display.chip_select_pin_write = gpio_b10_write; - Platform.display.data_command_pin_write = gpio_b14_write; - Platform.display.spi_write = spi_2_write; - st7586_initialize(&(Platform.display)); + controller->chip_select_pin_write = gpio_b10_write; + controller->data_command_pin_write = gpio_b14_write; + controller->spi_write = spi_2_write; - st7586_set_display_area(0, FRAMEBUFFER_WIDTH, 0, FRAMEBUFFER_HEIGHT); - st7586_display_buffer + st7586_initialize(controller); - //for(int i=0;i<10;i++) { - // ion_set_pixel(i,i,i%4); - //} - //framebuffer[0] = 0xD8; - //st7586_display_buffer(&(Platform.display), &_framebuffer_start, &_framebuffer_end-&_framebuffer_start); - //st7586_display_buffer(&(Platform.display), &_framebuffer_start, 1000); -} - -static void spi_2_write(char * data, size_t size) { - while (SPI_SR(SPI2) & SPI_BSY) { - } - for (size_t i=0; i + +void display_gpio_init(); +void gpio_b10_write(bool pin_state); +void gpio_b12_write(bool pin_state); +void gpio_b14_write(bool pin_state); diff --git a/ion/platform/device/display/spi.c b/ion/platform/device/display/spi.c new file mode 100644 index 000000000..201b802fc --- /dev/null +++ b/ion/platform/device/display/spi.c @@ -0,0 +1,25 @@ +/* The LCD panel is connected via the SPI2 port. + * This file configures the port. */ + +#include "../registers/registers.h" +#include "spi.h" + +void display_spi_init() { + // Enable the SPI2 clock (SPI2 lives on the APB1 bus) + RCC_APB1ENR |= SPI2EN; + + // Configure the SPI port + SPI_CR1(SPI2) = (SPI_BIDIMODE | SPI_BIDIOE | SPI_MSTR | SPI_DFF_8_BITS | SPI_BR(SPI_BR_DIV_2) | SPI_SSM | SPI_SSI | SPI_SPE); +} + +void spi_2_write(char * data, size_t size) { + while (SPI_SR(SPI2) & SPI_BSY) { + } + for (size_t i=0; i + +void display_spi_init(); +void spi_2_write(char * data, size_t size); diff --git a/ion/platform/device/init_heap.c b/ion/platform/device/init_heap.c deleted file mode 100644 index 93da1a2a3..000000000 --- a/ion/platform/device/init_heap.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "init_lcd.h" -#include - -extern char _ccm_heap_start; -extern char _ccm_heap_end; - -heap_config_t HeapConfig; - -int memsys5Init(void *NotUsed); - -void init_heap() { - HeapConfig.nHeap = (&_ccm_heap_end - &_ccm_heap_start); - HeapConfig.pHeap = &_ccm_heap_start; - HeapConfig.mnReq = 1; - HeapConfig.bMemstat = 0; - HeapConfig.xLog = 0; - - memsys5Init(0); -} diff --git a/ion/platform/device/init_heap.h b/ion/platform/device/init_heap.h deleted file mode 100644 index 5b3b62268..000000000 --- a/ion/platform/device/init_heap.h +++ /dev/null @@ -1 +0,0 @@ -void init_heap();