forked from raspberrypi/pico-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hub75.c
78 lines (65 loc) · 2.53 KB
/
hub75.c
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
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/pio.h"
#include "hub75.pio.h"
#include "mountains_128x64_rgb565.h"
#define DATA_BASE_PIN 0
#define DATA_N_PINS 6
#define ROWSEL_BASE_PIN 6
#define ROWSEL_N_PINS 5
#define CLK_PIN 11
#define STROBE_PIN 12
#define OEN_PIN 13
#define WIDTH 128
#define HEIGHT 64
static inline uint32_t gamma_correct_565_888(uint16_t pix) {
uint32_t r_gamma = pix & 0xf800u;
r_gamma *= r_gamma;
uint32_t g_gamma = pix & 0x07e0u;
g_gamma *= g_gamma;
uint32_t b_gamma = pix & 0x001fu;
b_gamma *= b_gamma;
return (b_gamma >> 2 << 16) | (g_gamma >> 14 << 8) | (r_gamma >> 24 << 0);
}
int main() {
stdio_init_all();
PIO pio = pio0;
uint sm_data = 0;
uint sm_row = 1;
uint data_prog_offs = pio_add_program(pio, &hub75_data_rgb888_program);
uint row_prog_offs = pio_add_program(pio, &hub75_row_program);
hub75_data_rgb888_program_init(pio, sm_data, data_prog_offs, DATA_BASE_PIN, CLK_PIN);
hub75_row_program_init(pio, sm_row, row_prog_offs, ROWSEL_BASE_PIN, ROWSEL_N_PINS, STROBE_PIN);
static uint32_t gc_row[2][WIDTH];
const uint16_t *img = (const uint16_t*)mountains_128x64;
while (1) {
for (int rowsel = 0; rowsel < (1 << ROWSEL_N_PINS); ++rowsel) {
for (int x = 0; x < WIDTH; ++x) {
gc_row[0][x] = gamma_correct_565_888(img[rowsel * WIDTH + x]);
gc_row[1][x] = gamma_correct_565_888(img[((1u << ROWSEL_N_PINS) + rowsel) * WIDTH + x]);
}
for (int bit = 0; bit < 8; ++bit) {
hub75_data_rgb888_set_shift(pio, sm_data, data_prog_offs, bit);
for (int x = 0; x < WIDTH; ++x) {
pio_sm_put_blocking(pio, sm_data, gc_row[0][x]);
pio_sm_put_blocking(pio, sm_data, gc_row[1][x]);
}
// Dummy pixel per lane
pio_sm_put_blocking(pio, sm_data, 0);
pio_sm_put_blocking(pio, sm_data, 0);
// SM is finished when it stalls on empty TX FIFO
hub75_wait_tx_stall(pio, sm_data);
// Also check that previous OEn pulse is finished, else things can get out of sequence
hub75_wait_tx_stall(pio, sm_row);
// Latch row data, pulse output enable for new row.
pio_sm_put_blocking(pio, sm_row, rowsel | (100u * (1u << bit) << 5));
}
}
}
}