Skip to content

Commit 93ac854

Browse files
authored
Merge pull request #663 from pimoroni/feature/inky73
Support for Inky Frame 7.3" (using direct pen into PSRAM framebuffer)
2 parents f06d7c2 + ab488a4 commit 93ac854

31 files changed

+919
-25
lines changed

drivers/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,7 @@ add_subdirectory(vl53l5cx)
3939
add_subdirectory(pcf85063a)
4040
add_subdirectory(pms5003)
4141
add_subdirectory(sh1107)
42-
add_subdirectory(st7567)
42+
add_subdirectory(st7567)
43+
add_subdirectory(psram_display)
44+
add_subdirectory(inky73)
45+
add_subdirectory(shiftregister)

drivers/inky73/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include(inky73.cmake)

drivers/inky73/inky73.cmake

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set(DRIVER_NAME inky73)
2+
add_library(${DRIVER_NAME} INTERFACE)
3+
4+
target_sources(${DRIVER_NAME} INTERFACE
5+
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp)
6+
7+
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
8+
9+
# Pull in pico libraries that we need
10+
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib hardware_spi shiftregister)

drivers/inky73/inky73.cpp

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#include "inky73.hpp"
2+
3+
#include <cstdlib>
4+
#include <math.h>
5+
#include <string.h>
6+
7+
namespace pimoroni {
8+
9+
enum reg {
10+
PSR = 0x00,
11+
PWR = 0x01,
12+
POF = 0x02,
13+
PFS = 0x03,
14+
PON = 0x04,
15+
BTST1 = 0x05,
16+
BTST2 = 0x06,
17+
DSLP = 0x07,
18+
BTST3 = 0x08,
19+
DTM1 = 0x10,
20+
DSP = 0x11,
21+
DRF = 0x12,
22+
IPC = 0x13,
23+
PLL = 0x30,
24+
TSC = 0x40,
25+
TSE = 0x41,
26+
TSW = 0x42,
27+
TSR = 0x43,
28+
CDI = 0x50,
29+
LPD = 0x51,
30+
TCON = 0x60,
31+
TRES = 0x61,
32+
DAM = 0x65,
33+
REV = 0x70,
34+
FLG = 0x71,
35+
AMV = 0x80,
36+
VV = 0x81,
37+
VDCS = 0x82,
38+
T_VDCS = 0x84,
39+
AGID = 0x86,
40+
CMDH = 0xAA,
41+
CCSET =0xE0,
42+
PWS = 0xE3,
43+
TSSET = 0xE6 // E5 or E6
44+
};
45+
46+
bool Inky73::is_busy() {
47+
return !(sr.read() & 128);
48+
}
49+
50+
void Inky73::busy_wait() {
51+
while(is_busy()) {
52+
tight_loop_contents();
53+
}
54+
}
55+
56+
void Inky73::reset() {
57+
gpio_put(RESET, 0); sleep_ms(10);
58+
gpio_put(RESET, 1); sleep_ms(10);
59+
busy_wait();
60+
}
61+
62+
void Inky73::init() {
63+
// configure spi interface and pins
64+
spi_init(spi, 20'000'000);
65+
66+
gpio_set_function(DC, GPIO_FUNC_SIO);
67+
gpio_set_dir(DC, GPIO_OUT);
68+
69+
gpio_set_function(CS, GPIO_FUNC_SIO);
70+
gpio_set_dir(CS, GPIO_OUT);
71+
gpio_put(CS, 1);
72+
73+
gpio_set_function(RESET, GPIO_FUNC_SIO);
74+
gpio_set_dir(RESET, GPIO_OUT);
75+
gpio_put(RESET, 1);
76+
77+
gpio_set_function(SCK, GPIO_FUNC_SPI);
78+
gpio_set_function(MOSI, GPIO_FUNC_SPI);
79+
};
80+
81+
void Inky73::setup() {
82+
reset();
83+
busy_wait();
84+
85+
command(CMDH, {0x49, 0x55, 0x20, 0x08, 0x09, 0x18});
86+
command(PWR, {0x3F, 0x00, 0x32, 0x2A, 0x0E, 0x2A});
87+
if (rotation == ROTATE_0) {
88+
command(PSR, {0x53, 0x69});
89+
} else {
90+
command(PSR, {0x5F, 0x69});
91+
}
92+
//command(PSR, {0x5F, 0x69});
93+
command(PFS, {0x00, 0x54, 0x00, 0x44});
94+
command(BTST1, {0x40, 0x1F, 0x1F, 0x2C});
95+
command(BTST2, {0x6F, 0x1F, 0x16, 0x25});
96+
command(BTST3, {0x6F, 0x1F, 0x1F, 0x22});
97+
command(IPC, {0x00, 0x04});
98+
command(PLL, {0x02});
99+
command(TSE, {0x00});
100+
command(CDI, {0x3F});
101+
command(TCON, {0x02, 0x00});
102+
command(TRES, {0x03, 0x20, 0x01, 0xE0});
103+
command(VDCS, {0x1E});
104+
command(T_VDCS, {0x00});
105+
command(AGID, {0x00});
106+
command(PWS, {0x2F});
107+
command(CCSET, {0x00});
108+
command(TSSET, {0x00});
109+
}
110+
111+
void Inky73::set_blocking(bool blocking) {
112+
this->blocking = blocking;
113+
}
114+
115+
void Inky73::power_off() {
116+
busy_wait();
117+
command(POF); // turn off
118+
}
119+
120+
void Inky73::command(uint8_t reg, size_t len, const uint8_t *data) {
121+
gpio_put(CS, 0);
122+
123+
gpio_put(DC, 0); // command mode
124+
spi_write_blocking(spi, &reg, 1);
125+
126+
if(len > 0) {
127+
gpio_put(DC, 1); // data mode
128+
spi_write_blocking(spi, (const uint8_t*)data, len);
129+
}
130+
131+
gpio_put(CS, 1);
132+
}
133+
134+
void Inky73::data(size_t len, const uint8_t *data) {
135+
gpio_put(CS, 0);
136+
gpio_put(DC, 1); // data mode
137+
spi_write_blocking(spi, (const uint8_t*)data, len);
138+
gpio_put(CS, 1);
139+
}
140+
141+
void Inky73::command(uint8_t reg, std::initializer_list<uint8_t> values) {
142+
command(reg, values.size(), (uint8_t *)values.begin());
143+
}
144+
145+
void Inky73::update(PicoGraphics *graphics) {
146+
if(graphics->pen_type != PicoGraphics::PEN_INKY7) return; // Incompatible buffer
147+
148+
if(blocking) {
149+
busy_wait();
150+
}
151+
152+
setup();
153+
154+
gpio_put(CS, 0);
155+
156+
uint8_t reg = DTM1;
157+
gpio_put(DC, 0); // command mode
158+
spi_write_blocking(spi, &reg, 1);
159+
160+
gpio_put(DC, 1); // data mode
161+
162+
uint totalLength = 0;
163+
gpio_put(CS, 1);
164+
graphics->frame_convert(PicoGraphics::PEN_INKY7, [this, &totalLength](void *buf, size_t length) {
165+
if (length > 0) {
166+
gpio_put(CS, 0);
167+
spi_write_blocking(spi, (const uint8_t*)buf, length);
168+
totalLength += length;
169+
gpio_put(CS, 1);
170+
}
171+
});
172+
173+
gpio_put(DC, 0); // data mode
174+
175+
gpio_put(CS, 1);
176+
177+
busy_wait();
178+
179+
command(PON, {0}); // turn on
180+
busy_wait();
181+
182+
command(DRF, {0}); // start display refresh
183+
busy_wait();
184+
185+
if(blocking) {
186+
busy_wait();
187+
188+
command(POF); // turn off
189+
}
190+
}
191+
192+
bool Inky73::is_pressed(Button button) {
193+
return sr.read() & button;
194+
}
195+
196+
}

drivers/inky73/inky73.hpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#pragma once
2+
3+
#include <initializer_list>
4+
5+
#include "pico/stdlib.h"
6+
#include "hardware/spi.h"
7+
#include "hardware/gpio.h"
8+
#include "common/pimoroni_common.hpp"
9+
#include "common/pimoroni_bus.hpp"
10+
#include "libraries/pico_graphics/pico_graphics.hpp"
11+
#include "drivers/shiftregister/shiftregister.hpp"
12+
13+
namespace pimoroni {
14+
15+
class Inky73 : public DisplayDriver {
16+
//--------------------------------------------------
17+
// Variables
18+
//--------------------------------------------------
19+
private:
20+
spi_inst_t *spi = PIMORONI_SPI_DEFAULT_INSTANCE;
21+
22+
// interface pins with our standard defaults where appropriate
23+
uint CS = SPI_BG_FRONT_CS;
24+
uint DC = 28; // 27;
25+
uint SCK = SPI_DEFAULT_SCK;
26+
uint MOSI = SPI_DEFAULT_MOSI;
27+
uint RESET = 27; //25;
28+
29+
uint SR_CLOCK = 8;
30+
uint SR_LATCH = 9;
31+
uint SR_DATA = 10;
32+
33+
bool blocking = false;
34+
35+
ShiftRegister<uint8_t> sr = ShiftRegister<uint8_t>(SR_CLOCK, SR_LATCH, SR_DATA);
36+
37+
public:
38+
enum Button : uint8_t {
39+
BUTTON_A = 1,
40+
BUTTON_B = 2,
41+
BUTTON_C = 4,
42+
BUTTON_D = 8,
43+
BUTTON_E = 16
44+
};
45+
46+
enum colour : uint8_t {
47+
BLACK = 0,
48+
WHITE = 1,
49+
GREEN = 2,
50+
BLUE = 3,
51+
RED = 4,
52+
YELLOW = 5,
53+
ORANGE = 6,
54+
CLEAN = 7
55+
};
56+
57+
Inky73(uint16_t width, uint16_t height) : Inky73(width, height, ROTATE_0, {PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, PIN_UNUSED, 28, PIN_UNUSED}) {};
58+
59+
Inky73(uint16_t width, uint16_t height, SPIPins pins, uint reset=27) : Inky73(width, height, ROTATE_0, pins, reset) {};
60+
61+
Inky73(uint16_t width, uint16_t height, Rotation rotation, SPIPins pins, uint reset=27) :
62+
DisplayDriver(width, height, rotation),
63+
spi(pins.spi),
64+
CS(pins.cs), DC(pins.dc), SCK(pins.sck), MOSI(pins.mosi), RESET(reset) {
65+
init();
66+
}
67+
68+
69+
//--------------------------------------------------
70+
// Methods
71+
//--------------------------------------------------
72+
public:
73+
void busy_wait();
74+
void reset();
75+
void power_off();
76+
77+
bool is_busy() override;
78+
void update(PicoGraphics *graphics) override;
79+
80+
void set_blocking(bool blocking);
81+
82+
bool is_pressed(Button button);
83+
84+
private:
85+
void init();
86+
void setup();
87+
void command(uint8_t reg, size_t len, const uint8_t *data);
88+
void command(uint8_t reg, std::initializer_list<uint8_t> values);
89+
void command(uint8_t reg, const uint8_t data) {command(reg, 0, &data);};
90+
void command(uint8_t reg) {command(reg, 0, nullptr);};
91+
void data(size_t len, const uint8_t *data);
92+
};
93+
94+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include(psram_display.cmake)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set(DRIVER_NAME psram_display)
2+
add_library(${DRIVER_NAME} INTERFACE)
3+
4+
target_sources(${DRIVER_NAME} INTERFACE
5+
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp)
6+
7+
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
8+
9+
# Pull in pico libraries that we need
10+
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib hardware_spi)

0 commit comments

Comments
 (0)