-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathecx337a.h
158 lines (141 loc) · 3.72 KB
/
ecx337a.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* Basic SPI routines for Sony ECX337A OLED microdisplay
* Copyright (c) 2020-2021 Aedan Cullen <[email protected]>
*/
#ifndef ECX_H
#define ECX_H
int si;
int clk;
int xclr;
int xcs;
int pwrctl; // Use for powerdown on both 10V boost and LVDS TX (low = off)
uint8_t ECX337A_INIT_STANDARD[] = {
0x01, // First value following is at addr 0x01, and ascending from there
0x00, // T_SLOPE default, YCB_P default, CALSEL default, LVDS_MAP default, MCLKPOL default
0x00, // ORBIT_H default
0x80, // ORBIT_V default
0x03, // PN_POL A=P/B=N, PINSWP ascending/ascending, PRTSWP IF0,IF1, IFSW 4lane-x2
0x08, // FORMAT_SEL_DATA default, DITHEREN default
0x00, // VD_POL default, HD_POL default, OTPCALDAC_REGEN default, OTPDG_REGEN default
0xD0, // VD_FILTER 3MCLK, HD_FILTER 3MCLK, C_SLOPE default
};
void ecx_spi_begin() {
digitalWrite(xcs, LOW);
delayMicroseconds(200);
}
void ecx_spi_end() {
delayMicroseconds(200);
digitalWrite(xcs, HIGH);
delayMicroseconds(200); // don't want it to think we're bursting
}
void ecx_shift(uint8_t data) {
for (int i = 0; i < 8; i++) {
digitalWrite(si, !!(data & (1 << i)));
delayMicroseconds(5);
digitalWrite(clk, HIGH);
delayMicroseconds(5);
digitalWrite(clk, LOW);
}
}
/*
* Single burst-mode transaction
*/
void ecx_spi_write8_burst(uint8_t *data, int len) {
ecx_spi_begin();
for (int i = 0; i < len; i++) {
ecx_shift(data[i]);
}
ecx_spi_end();
}
/*
* Multiple single-register transactions
*/
void ecx_spi_write16_seq(uint16_t *data, int len) {
for (int i = 0; i < len; i++) {
ecx_spi_begin();
ecx_shift((uint8_t)(data[i] >> 8));
ecx_shift((uint8_t)(data[i] & 0x00FF));
ecx_spi_end();
}
}
/*
* Release XCLR and write to "Normal" and "Side A" registers
*/
void ecx_initialize(int si_pin, int clk_pin, int xclr_pin, int xcs_pin, int pwrctl_pin) {
si = si_pin;
clk = clk_pin;
xclr = xclr_pin;
xcs = xcs_pin;
pwrctl = pwrctl_pin;
digitalWrite(si, LOW);
digitalWrite(clk, LOW);
digitalWrite(xclr, LOW);
digitalWrite(xcs, HIGH);
digitalWrite(pwrctl, LOW);
delay(16); // arbitrary
digitalWrite(xclr, HIGH);
delay(16); // Spec 16ms from XCLR high to ready in powersave mode
// Debug: scope SO pin (1.8v) and watch for 0x56 LSB-first (01101010)
uint16_t seq[] = {
0x8001, // RD_ON enable
0x817F, // RD_ADDR 0x7F
0x8100, // read
0x8000, // RD_ON disable
};
ecx_spi_write16_seq(seq, 4);
// Write settings
ecx_spi_write8_burst(ECX337A_INIT_STANDARD, sizeof(ECX337A_INIT_STANDARD));
}
/*
* Disable PS0/PS1 powersave modes
*/
void ecx_panelon() {
digitalWrite(pwrctl, HIGH);
delay(16); // arbitrary
uint16_t seq[] = {
0x004D,
0x004F,
};
ecx_spi_write16_seq(seq, 2);
}
/*
* Enable PS0/PS1 powersave modes
*/
void ecx_paneloff(bool poweroff) {
uint16_t seq[] = {
0x004D,
0x004C,
};
ecx_spi_write16_seq(seq, 2);
if (poweroff) {
delay(16); // arbitrary
digitalWrite(pwrctl, LOW);
}
}
/*
* Set real panel luminance directly. nitsx10 is the brightness
* in multiples of 10 nits (cd/m^2). Default is 15 (150 nits).
*/
void ecx_luminance(uint8_t nitsx10) {
nitsx10 = max(nitsx10, (uint8_t)5);
nitsx10 = min(nitsx10, (uint8_t)100);
uint16_t seq[] = {
0x1107, // L_AT_CALEN, L_SEAMLESSEN, WB_CALEN all set
0x1300 | (uint16_t)nitsx10,
};
ecx_spi_write16_seq(seq, 2);
}
/*
* Set image orbit position; each axis has 10 pixels of orbit
* space in either direction (for alleviating image retention)
*/
void ecx_orbit(int8_t horiz, int8_t vert) {
horiz = min(max(horiz, (int8_t)-10), (int8_t)10);
vert = min(max(horiz, (int8_t)-10), (int8_t)10);
uint16_t seq[] = {
0x0200 | (uint16_t)horiz,
0x0380 | (uint16_t)vert,
};
ecx_spi_write16_seq(seq, 2);
}
#endif