mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[ion] Clean the display init code
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#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; i<length; i++) {
|
||||
perform_instruction(c, instructions+i);
|
||||
perform_instruction(c, instructions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void st7586_initialize(st7586_t * controller) {
|
||||
// Falling edge on CSX
|
||||
controller->chip_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);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define PLATFORM_ST7586_H 1
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
*/
|
||||
|
||||
#include <ion.h>
|
||||
|
||||
#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<size; i++) {
|
||||
SPI_DR(SPI2) = data[i];
|
||||
while (!(SPI_SR(SPI2) & SPI_TXE)) {
|
||||
}
|
||||
}
|
||||
while (SPI_SR(SPI2) & SPI_BSY) {
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_b10_write(bool pin_state) {
|
||||
REGISTER_SET_VALUE(GPIO_ODR(GPIOB), ODR(10), pin_state);
|
||||
}
|
||||
|
||||
void gpio_b12_write(bool pin_state) {
|
||||
REGISTER_SET_VALUE(GPIO_ODR(GPIOB), ODR(12), pin_state);
|
||||
}
|
||||
|
||||
void gpio_b14_write(bool pin_state) {
|
||||
REGISTER_SET_VALUE(GPIO_ODR(GPIOB), ODR(14), pin_state);
|
||||
st7586_set_display_area(controller, 0, FRAMEBUFFER_WIDTH, 0, FRAMEBUFFER_HEIGHT);
|
||||
|
||||
display_dma_init();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
extern char _framebuffer_start, _framebuffer_end;
|
||||
|
||||
void display_configure_dma() {
|
||||
void display_dma_init() {
|
||||
// 0 - ENable DMA clock!
|
||||
RCC_AHB1ENR |= DMA1EN;
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
void display_configure_dma();
|
||||
void display_dma_init();
|
||||
|
||||
49
ion/platform/device/display/gpio.c
Normal file
49
ion/platform/device/display/gpio.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* The LCD panel is connected via an SPI interface. The SPI interface is used to
|
||||
* configure the panel and to stream the bitmap data.
|
||||
*
|
||||
* Here is the connection this file assumes:
|
||||
*
|
||||
* LCD | STM32 | Role
|
||||
* --------------+-------+-----
|
||||
* LCD_CS | PB10 | Chip-select for LCD panel (panel selected when low)
|
||||
* LCD_RST | PB12 | Reset the LCD panel (panel active when high)
|
||||
* LCD_DAT_INS | PB14 | Select "command" or "data" mode
|
||||
* LCD_SPI_CLK | PB13 | SPI clock
|
||||
* LCD_SPI_MOSI | PB15 | SPI data
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../registers/registers.h"
|
||||
#include "gpio.h"
|
||||
|
||||
void display_gpio_init() {
|
||||
// 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);
|
||||
}
|
||||
|
||||
void gpio_b10_write(bool pin_state) {
|
||||
REGISTER_SET_VALUE(GPIO_ODR(GPIOB), ODR(10), pin_state);
|
||||
}
|
||||
|
||||
void gpio_b12_write(bool pin_state) {
|
||||
REGISTER_SET_VALUE(GPIO_ODR(GPIOB), ODR(12), pin_state);
|
||||
}
|
||||
|
||||
void gpio_b14_write(bool pin_state) {
|
||||
REGISTER_SET_VALUE(GPIO_ODR(GPIOB), ODR(14), pin_state);
|
||||
}
|
||||
6
ion/platform/device/display/gpio.h
Normal file
6
ion/platform/device/display/gpio.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
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);
|
||||
25
ion/platform/device/display/spi.c
Normal file
25
ion/platform/device/display/spi.c
Normal file
@@ -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<size; i++) {
|
||||
SPI_DR(SPI2) = data[i];
|
||||
while (!(SPI_SR(SPI2) & SPI_TXE)) {
|
||||
}
|
||||
}
|
||||
while (SPI_SR(SPI2) & SPI_BSY) {
|
||||
}
|
||||
}
|
||||
4
ion/platform/device/display/spi.h
Normal file
4
ion/platform/device/display/spi.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#include <string.h>
|
||||
|
||||
void display_spi_init();
|
||||
void spi_2_write(char * data, size_t size);
|
||||
@@ -1,19 +0,0 @@
|
||||
#include "init_lcd.h"
|
||||
#include <private/memconfig.h>
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
void init_heap();
|
||||
Reference in New Issue
Block a user