Skip to content

Commit 37a1b65

Browse files
committed
ST7789: Add pixel doubling for Badger 2350.
1 parent 04b4a99 commit 37a1b65

File tree

6 files changed

+120
-17
lines changed

6 files changed

+120
-17
lines changed

drivers/st7789/st7789.cpp

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ namespace pimoroni {
9494
command(reg::GMCTRN1, 14, "\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23");
9595
}
9696

97-
if(width == 320 && height == 240) {
97+
if((width == 320 && height == 240) || (width == 160 && height == 120)) {
9898
command(reg::GCTRL, 1, "\x35");
9999
command(reg::VCOMS, 1, "\x1f");
100100
command(reg::GMCTRP1, 14, "\xD0\x08\x11\x08\x0C\x15\x39\x33\x50\x36\x13\x14\x29\x2D");
@@ -128,12 +128,23 @@ namespace pimoroni {
128128
dma_channel_abort(st_dma);
129129
dma_channel_unclaim(st_dma);
130130
}
131+
if(dma_channel_is_claimed(pd_st_dma)) {
132+
dma_channel_abort(pd_st_dma);
133+
dma_channel_unclaim(pd_st_dma);
134+
}
131135
if(spi) return; // SPI mode needs no further tear down
132136

133137
if(pio_sm_is_claimed(parallel_pio, parallel_sm)) {
134138
pio_sm_set_enabled(parallel_pio, parallel_sm, false);
135139
pio_sm_drain_tx_fifo(parallel_pio, parallel_sm);
136-
pio_sm_unclaim(parallel_pio, parallel_sm);
140+
//pio_sm_unclaim(parallel_pio, parallel_sm);
141+
pio_remove_program_and_unclaim_sm(&st7789_parallel_program, parallel_pio, parallel_sm, parallel_offset);
142+
}
143+
if(pio_sm_is_claimed(parallel_pio, parallel_pd_sm)) {
144+
pio_sm_set_enabled(parallel_pio, parallel_pd_sm, false);
145+
pio_sm_drain_tx_fifo(parallel_pio, parallel_pd_sm);
146+
//pio_sm_unclaim(parallel_pio, parallel_pd_sm);
147+
pio_remove_program_and_unclaim_sm(&st7789_parallel_pd_program, parallel_pio, parallel_pd_sm, parallel_pd_offset);
137148
}
138149
}
139150

@@ -147,7 +158,7 @@ namespace pimoroni {
147158
if(width == 240 && height == 240) {
148159
int row_offset = round ? 40 : 80;
149160
int col_offset = 0;
150-
161+
151162
switch(rotate) {
152163
case ROTATE_90:
153164
if (!round) row_offset = 0;
@@ -216,7 +227,7 @@ namespace pimoroni {
216227
}
217228

218229
// Pico Display 2.0
219-
if(width == 320 && height == 240) {
230+
if((width == 320 && height == 240) || (width == 160 && height == 120)) {
220231
caset[0] = 0;
221232
caset[1] = 319;
222233
raset[0] = 0;
@@ -262,11 +273,24 @@ namespace pimoroni {
262273
;
263274
}
264275

276+
void ST7789::write_blocking_parallel_pixel_doubled(const uint8_t *src, size_t len) {
277+
while (dma_channel_is_busy(pd_st_dma))
278+
;
279+
dma_channel_set_trans_count(pd_st_dma, len, false);
280+
dma_channel_set_read_addr(pd_st_dma, src, true);
281+
dma_channel_wait_for_finish_blocking(pd_st_dma);
282+
283+
// This may cause a race between PIO and the
284+
// subsequent chipselect deassert for the last pixel
285+
while(!pio_sm_is_tx_fifo_empty(parallel_pio, parallel_pd_sm))
286+
;
287+
}
288+
265289
void ST7789::command(uint8_t command, size_t len, const char *data) {
266290
gpio_put(dc, 0); // command mode
267291

268292
gpio_put(cs, 0);
269-
293+
270294
if(spi) {
271295
spi_write_blocking(spi, &command, 1);
272296
} else {
@@ -284,12 +308,24 @@ namespace pimoroni {
284308

285309
gpio_put(cs, 1);
286310
}
287-
311+
288312
void ST7789::update(PicoGraphics *graphics) {
289313
uint8_t cmd = reg::RAMWR;
290314

291315
if(graphics->pen_type == PicoGraphics::PEN_RGB565 && graphics->layers == 1) { // Display buffer is screen native
292-
command(cmd, width * height * sizeof(uint16_t), (const char*)graphics->frame_buffer);
316+
if(width == 160 && height == 120) {
317+
gpio_put(dc, 0); // command mode
318+
gpio_put(cs, 0);
319+
write_blocking_parallel(&cmd, 1);
320+
gpio_put(dc, 1); // data mode
321+
for(int y = 0; y < height; y++) {
322+
write_blocking_parallel_pixel_doubled((const uint8_t*)(graphics->frame_buffer) + width * 2 * y, width); // Len is given in pixels not bytes
323+
write_blocking_parallel_pixel_doubled((const uint8_t*)(graphics->frame_buffer) + width * 2 * y, width);
324+
}
325+
gpio_put(cs, 1);
326+
} else {
327+
command(cmd, width * height * sizeof(uint16_t), (const char*)graphics->frame_buffer);
328+
}
293329
} else {
294330
gpio_put(dc, 0); // command mode
295331
gpio_put(cs, 0);

drivers/st7789/st7789.hpp

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace pimoroni {
2222

2323
class ST7789 : public DisplayDriver {
2424
spi_inst_t *spi = PIMORONI_SPI_DEFAULT_INSTANCE;
25-
25+
2626
public:
2727
bool round;
2828

@@ -41,8 +41,14 @@ namespace pimoroni {
4141
uint vsync = PIN_UNUSED; // only available on some products
4242
uint parallel_sm;
4343
PIO parallel_pio;
44-
uint parallel_offset;
44+
int parallel_offset;
4545
uint st_dma;
46+
47+
// Pixel double
48+
uint parallel_pd_sm;
49+
int parallel_pd_offset;
50+
uint pd_st_dma;
51+
4652
bool display_on = false;
4753
bool display_sleep = false;
4854

@@ -67,8 +73,18 @@ namespace pimoroni {
6773

6874
parallel_pio = pio1;
6975
pio_set_gpio_base(parallel_pio, d0 + 8 >= 32 ? 16 : 0);
76+
7077
parallel_sm = pio_claim_unused_sm(parallel_pio, true);
7178
parallel_offset = pio_add_program(parallel_pio, &st7789_parallel_program);
79+
if(parallel_offset == -1) {
80+
panic("Could not add parallel PIO program.");
81+
}
82+
83+
parallel_pd_sm = pio_claim_unused_sm(parallel_pio, true);
84+
parallel_pd_offset = pio_add_program(parallel_pio, &st7789_parallel_pd_program);
85+
if(parallel_offset == -1) {
86+
panic("Could not add parallel pixel-doubling PIO program.");
87+
}
7288

7389
//gpio_init(wr_sck);
7490
//gpio_set_dir(wr_sck, GPIO_OUT);
@@ -88,19 +104,33 @@ namespace pimoroni {
88104
pio_sm_set_consecutive_pindirs(parallel_pio, parallel_sm, d0, 8, true);
89105
pio_sm_set_consecutive_pindirs(parallel_pio, parallel_sm, wr_sck, 1, true);
90106

91-
pio_sm_config c = st7789_parallel_program_get_default_config(parallel_offset);
107+
// Is this needed?
108+
pio_sm_set_consecutive_pindirs(parallel_pio, parallel_pd_sm, d0, 8, true);
109+
pio_sm_set_consecutive_pindirs(parallel_pio, parallel_pd_sm, wr_sck, 1, true);
110+
111+
pio_sm_config pd_c = st7789_parallel_pd_program_get_default_config(parallel_pd_offset);
112+
sm_config_set_out_pins(&pd_c, d0, 8);
113+
sm_config_set_sideset_pins(&pd_c, wr_sck);
114+
sm_config_set_fifo_join(&pd_c, PIO_FIFO_JOIN_TX);
115+
sm_config_set_out_shift(&pd_c, false, false, 16);
92116

117+
pio_sm_config c = st7789_parallel_program_get_default_config(parallel_offset);
93118
sm_config_set_out_pins(&c, d0, 8);
94119
sm_config_set_sideset_pins(&c, wr_sck);
95120
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
96121
sm_config_set_out_shift(&c, false, true, 8);
97-
122+
98123
// Determine clock divider
99124
constexpr uint32_t max_pio_clk = 32 * MHZ;
100125
const uint32_t sys_clk_hz = clock_get_hz(clk_sys);
101126
const uint32_t clk_div = (sys_clk_hz + max_pio_clk - 1) / max_pio_clk;
127+
128+
sm_config_set_clkdiv(&pd_c, clk_div);
102129
sm_config_set_clkdiv(&c, clk_div);
103-
130+
131+
pio_sm_init(parallel_pio, parallel_pd_sm, parallel_pd_offset, &pd_c);
132+
pio_sm_set_enabled(parallel_pio, parallel_pd_sm, true);
133+
104134
pio_sm_init(parallel_pio, parallel_sm, parallel_offset, &c);
105135
pio_sm_set_enabled(parallel_pio, parallel_sm, true);
106136

@@ -111,7 +141,14 @@ namespace pimoroni {
111141
channel_config_set_bswap(&config, false);
112142
channel_config_set_dreq(&config, pio_get_dreq(parallel_pio, parallel_sm, true));
113143
dma_channel_configure(st_dma, &config, &parallel_pio->txf[parallel_sm], NULL, 0, false);
114-
144+
145+
pd_st_dma = dma_claim_unused_channel(true);
146+
dma_channel_config pd_config = dma_channel_get_default_config(pd_st_dma);
147+
channel_config_set_transfer_data_size(&pd_config, DMA_SIZE_16);
148+
channel_config_set_bswap(&pd_config, true);
149+
channel_config_set_dreq(&pd_config, pio_get_dreq(parallel_pio, parallel_pd_sm, true));
150+
dma_channel_configure(pd_st_dma, &pd_config, &parallel_pio->txf[parallel_pd_sm], NULL, 0, false);
151+
115152
gpio_put(rd_sck, 1);
116153

117154
common_init();
@@ -135,7 +172,7 @@ namespace pimoroni {
135172
channel_config_set_bswap(&config, false);
136173
channel_config_set_dreq(&config, spi_get_dreq(spi, true));
137174
dma_channel_configure(st_dma, &config, &spi_get_hw(spi)->dr, NULL, 0, false);
138-
175+
139176
common_init();
140177
}
141178

@@ -148,6 +185,7 @@ namespace pimoroni {
148185
void configure_display(Rotation rotate);
149186
void write_blocking_dma(const uint8_t *src, size_t len);
150187
void write_blocking_parallel(const uint8_t *src, size_t len);
188+
void write_blocking_parallel_pixel_doubled(const uint8_t *src, size_t len);
151189
void command(uint8_t command, size_t len = 0, const char *data = NULL);
152190
};
153191

drivers/st7789/st7789_parallel.pio

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,23 @@
44
.wrap_target
55
out pins, 8 side 0
66
nop side 1
7+
.wrap
8+
9+
.program st7789_parallel_pd
10+
.side_set 1
11+
12+
.wrap_target
13+
pull side 0
14+
mov x osr side 0 ; Store the OSR in scratch X
15+
16+
out pins, 8 side 0
17+
nop side 1
18+
out pins, 8 side 0
19+
nop side 1
20+
21+
mov osr x side 0 ; Retrieve the OSR from scratch X
22+
out pins, 8 side 0
23+
nop side 1
24+
out pins, 8 side 0
25+
nop side 1
726
.wrap

micropython/modules/picographics/picographics.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ static const mp_map_elem_t picographics_globals_table[] = {
176176
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_PRESTO_FULL_RES), MP_ROM_INT(DISPLAY_PRESTO_FULL_RES) },
177177
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_GENERIC), MP_ROM_INT(DISPLAY_GENERIC) },
178178
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_INKY_FRAME_SPECTRA_7), MP_ROM_INT(DISPLAY_INKY_FRAME_SPECTRA_7) },
179+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_TUFTY_2350), MP_ROM_INT(DISPLAY_TUFTY_2350) },
179180

180181
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_BADGER_2350), MP_ROM_INT(DISPLAY_BADGER_2350) },
181182

micropython/modules/picographics/picographics.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,13 @@ bool get_display_settings(PicoGraphicsDisplay display, int &width, int &height,
288288
if(rotate == -1) rotate = (int)Rotation::ROTATE_0;
289289
if(pen_type == -1) pen_type = PEN_2BIT;
290290
break;
291+
case DISPLAY_TUFTY_2350:
292+
width = 160;
293+
height = 120;
294+
bus_type = BUS_PARALLEL;
295+
if(rotate == -1) rotate = (int)Rotation::ROTATE_180;
296+
if(pen_type == -1) pen_type = PEN_RGB565;
297+
break;
291298
default:
292299
return false;
293300
}
@@ -391,7 +398,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
391398
spi_bus = {PIMORONI_SPI_DEFAULT_INSTANCE, 17, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, PIN_UNUSED, 20, PIN_UNUSED};
392399
}
393400
} else if (bus_type == BUS_PARALLEL) {
394-
if (display == DISPLAY_EXPLORER) {
401+
if (display == DISPLAY_EXPLORER || display == DISPLAY_TUFTY_2350) {
395402
parallel_bus = {27, 28, 30, 31, 32, 26};
396403
}
397404
}
@@ -409,7 +416,8 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
409416
self->display = m_new_class(Inky73, width, height, (Rotation)rotate, spi_bus);
410417

411418
} else if (display == DISPLAY_TUFTY_2040
412-
|| display == DISPLAY_EXPLORER) {
419+
|| display == DISPLAY_EXPLORER
420+
|| display == DISPLAY_TUFTY_2350) {
413421
self->display = m_new_class(ST7789, width, height, (Rotation)rotate, parallel_bus);
414422

415423
} else if (display == DISPLAY_LCD_160X80) {

micropython/modules/picographics/picographics.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ enum PicoGraphicsDisplay {
3737
DISPLAY_PRESTO_FULL_RES,
3838
DISPLAY_GENERIC,
3939
DISPLAY_INKY_FRAME_SPECTRA_7,
40-
DISPLAY_BADGER_2350
40+
DISPLAY_BADGER_2350,
41+
DISPLAY_TUFTY_2350
4142
};
4243

4344
enum PicoGraphicsPenType {

0 commit comments

Comments
 (0)