-
Notifications
You must be signed in to change notification settings - Fork 0
/
st7789_lcd.pio
71 lines (59 loc) · 2.23 KB
/
st7789_lcd.pio
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
;
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
;
; SPDX-License-Identifier: BSD-3-Clause
;
.program st7789_lcd
.side_set 1
; This is just a simple clocked serial TX. At 125 MHz system clock we can
; sustain up to 62.5 Mbps.
; Data on OUT pin 0
; Clock on side-set pin 0
.wrap_target
out pins, 1 side 0 ; stall here if no data (clock low)
nop side 1
.wrap
% c-sdk {
// Pixels are 16-bit so we autopull at 16 bits (this wastes half the DMA
// bandwidth but never mind)
static inline void st7789_lcd_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clk_pin, float clk_div) {
pio_gpio_init(pio, data_pin);
pio_gpio_init(pio, clk_pin);
pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true);
pio_sm_set_consecutive_pindirs(pio, sm, clk_pin, 1, true);
pio_sm_config c = st7789_lcd_program_get_default_config(offset);
sm_config_set_sideset_pins(&c, clk_pin);
sm_config_set_out_pins(&c, data_pin, 1);
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
sm_config_set_clkdiv(&c, clk_div);
sm_config_set_out_shift(&c, false, true, 8);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
// Switch between 8 and 16-bit modes
static inline void st7789_set_pixel_mode(PIO pio, uint sm, bool pixel_mode) {
uint32_t shiftctrl = pio->sm[sm].shiftctrl;
shiftctrl &= ~PIO_SM0_SHIFTCTRL_PULL_THRESH_BITS;
shiftctrl |= (pixel_mode ? 16u : 8u) << PIO_SM0_SHIFTCTRL_PULL_THRESH_LSB;
pio->sm[sm].shiftctrl = shiftctrl;
}
// Making use of the narrow store replication behaviour on RP2040 to get the
// data left-justified (as we are using shift-to-left to get MSB-first serial)
static inline void st7789_lcd_put(PIO pio, uint sm, uint8_t x) {
while (pio_sm_is_tx_fifo_full(pio, sm))
;
*(volatile uint8_t*)&pio->txf[sm] = x;
}
static inline void st7789_lcd_put_pixel(PIO pio, uint sm, uint16_t x) {
while (pio_sm_is_tx_fifo_full(pio, sm))
;
*(volatile uint16_t*)&pio->txf[sm] = x;
}
// SM is done when it stalls on an empty FIFO
static inline void st7789_lcd_wait_idle(PIO pio, uint sm) {
uint32_t sm_stall_mask = 1u << (sm + PIO_FDEBUG_TXSTALL_LSB);
pio->fdebug = sm_stall_mask;
while (!(pio->fdebug & sm_stall_mask))
;
}
%}