mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
Proper st7586 driver
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include "st7586.h"
|
||||
|
||||
enum {
|
||||
@@ -13,6 +15,10 @@ enum {
|
||||
SLEEP_OUT = 0x11,
|
||||
DISPLAY_OFF = 0x28,
|
||||
DISPLAY_ON = 0x29,
|
||||
SET_COLUMN_ADDRESS = 0x2A,
|
||||
SET_ROW_ADDRESS = 0x2B,
|
||||
WRITE_DISPLAY_DATA = 0x2C,
|
||||
ENABLE_DDRAM = 0x3A,
|
||||
/*
|
||||
RAMWR = 0x2C, // Memory write
|
||||
MADCTL = 0x36, // Memory access control
|
||||
@@ -51,7 +57,49 @@ 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}
|
||||
|
||||
static instruction_t initialisation_sequence[] = {
|
||||
#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),
|
||||
|
||||
@@ -59,8 +107,29 @@ static instruction_t initialisation_sequence[] = {
|
||||
COMMAND(SLEEP_OUT), DELAY(100),
|
||||
|
||||
// Display on, requires a 20ms delay
|
||||
COMMAND(DISPLAY_ON), DELAY(20)
|
||||
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) {
|
||||
@@ -73,30 +142,102 @@ static void perform_instruction(st7586_t * c, instruction_t * instruction) {
|
||||
}
|
||||
}
|
||||
|
||||
static void perform_instructions(st7586_t * c, instruction_t * instructions, size_t length) {
|
||||
for (size_t i=0; i<length; i++) {
|
||||
perform_instruction(c, instructions+i);
|
||||
}
|
||||
}
|
||||
|
||||
void st7586_set_display_area(st7586_t * c, 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
|
||||
* so let's make this 2 instead of 3. Seems to be working fine! */
|
||||
uint16_t x_end = x_start + x_length/2 - 1;
|
||||
uint16_t y_end = y_start + y_length - 1;
|
||||
|
||||
assert(x_end >= x_start);
|
||||
assert(x_end <= 0x7F);
|
||||
assert(y_end >= y_start);
|
||||
assert(y_end <= 0x9F);
|
||||
|
||||
instruction_t sequence[] = {
|
||||
COMMAND(SET_COLUMN_ADDRESS),
|
||||
DATA(x_start >> 8),
|
||||
DATA(x_start),
|
||||
DATA(x_end >> 8),
|
||||
DATA(x_end),
|
||||
COMMAND(SET_ROW_ADDRESS),
|
||||
DATA(y_start >> 8),
|
||||
DATA(y_start),
|
||||
DATA(y_end >> 8),
|
||||
DATA(y_end),
|
||||
};
|
||||
perform_instructions(c, 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
|
||||
size_t init_sequence_length = sizeof(initialisation_sequence)/sizeof(initialisation_sequence[0]);
|
||||
for (int i=0; i<init_sequence_length;i++) {
|
||||
perform_instruction(c, initialisation_sequence+i);
|
||||
perform_instructions(c, init_sequence, sizeof(init_sequence)/sizeof(init_sequence[0]));
|
||||
|
||||
st7586_set_display_area(c, 0, 160, 0, 160);
|
||||
|
||||
perform_instruction(c, &COMMAND(WRITE_DISPLAY_DATA));
|
||||
c->data_command_pin_write(DATA_MODE);
|
||||
unsigned char pixel = two_pixels(0x0, 0x3);
|
||||
for (int i=0; i<160*160/2; i++) {
|
||||
c->spi_write(&pixel, 1);
|
||||
for (int i=0;i<1000;i++) {
|
||||
}
|
||||
}
|
||||
|
||||
#define FILL_SCREEN_UPON_INIT 0
|
||||
#if FILL_SCREEN_UPON_INIT
|
||||
// This would draw stuff on the screen
|
||||
|
||||
perform_instruction(c, &COMMAND(RAMWR));
|
||||
/* FIGURED OUT THE PIXEL FORMAT!!!
|
||||
* 1 byte = 2 pixels
|
||||
* Pixel 0 : bit 6,7,8
|
||||
* Pixel 1 : bit 3,4,5
|
||||
*/
|
||||
|
||||
/* 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 buffer[256];
|
||||
for (int i = 0;i<256;i++) {
|
||||
buffer[i] = i;
|
||||
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));
|
||||
}
|
||||
for (int i = 0; i<(320*240*2)/256; i++) {
|
||||
c->spi_write(buffer, 256);
|
||||
//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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user