-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathbar-graph-on-unicornhathd.c
149 lines (139 loc) · 4.82 KB
/
bar-graph-on-unicornhathd.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
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
//
// A simulated (random) bar graph displayed on the Unicorn Hat HD from
// pimoroni (https://shop.pimoroni.com/products/unicorn-hat-hd)
// http://forums.pimoroni.com/t/c-example-for-unicorn-hat-hd/5149/5
//
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <wiringPiSPI.h>
#define SPI_CHANNEL 0
#define SPI_SPEED 9000000
#define PACKET_SIZE (1 + ( 16 * 16 * 3 ))
unsigned char buffer[PACKET_SIZE];
// With the exception of red, green and blue the color names are
// best guesses I could come up with. I was shooting for a reasonable
// gradient where each color was discernable from the next.
int colors[16][3] = {
{255,153,255}, // light-pink
{255,102,255}, // pink
{255,0,255}, // fuschia
{153,0,255}, // violet
{102,0,255}, // indigo
{0,0,255}, // blue
{0,102,255}, // cyan
{0,153,255}, // baby-blue
{0,255,255}, // teal
{0,255,102}, // seafoam
{0,255,0}, // green
{153,255,0}, // pale-green
{255,255,0}, // yellow
{255,153,0}, // orange
{255,102,0}, // red-orange
{255,0,0} // red
};
// It took me a little while to work out how to properly address each
// pixel. Once I had the the (x,y) to array index formula worked out
// I used the following python script to generate a table to confirm.
//
// print('| {0:>2s} | {1:>2s} | {2:>3s} | {3:>3s} | {4:>3s} |'.format(
// 'x', 'y', 'r', 'g', 'b'))
// print('=============================')
// for x in range(16):
// for y in range(16):
// r = 1 + ((y * 16) + x) * 3
// g = r + 1
// b = r + 2
// print('| {0:2d} | {1:2d} | {2:3d} | {3:3d} | {4:3d} |'.format(
//
// | Coords | Color Indices |
// | x | y | r | g | b |
// =============================
// | 0 | 0 | 1 | 2 | 3 |
// | 0 | 1 | 49 | 50 | 51 |
// | 0 | 2 | 97 | 98 | 99 |
// | 0 | 3 | 145 | 146 | 147 |
// | 0 | 4 | 193 | 194 | 195 |
// | 0 | 5 | 241 | 242 | 243 |
// .
// .
// .
// | 15 | 10 | 526 | 527 | 528 |
// | 15 | 11 | 574 | 575 | 576 |
// | 15 | 12 | 622 | 623 | 624 |
// | 15 | 13 | 670 | 671 | 672 |
// | 15 | 14 | 718 | 719 | 720 |
// | 15 | 15 | 766 | 767 | 768 |
//
// All this the bottom of the matrix along the GPIO edge of the RPi.
// If you swap x and y in the offset equation it will rotate the display
// 90 degrees widdershins (counter-clockwise) so the bottm of the graph
// is now along the Micro SD card edge.
//
// print('| {0:7s} | {1:15s} |'.format('Coords', 'Color Indices'))
// print('| {0:>2s} | {1:>2s} | {2:>3s} | {3:>3s} | {4:>3s} |'.format(
// 'x', 'y', 'r', 'g', 'b'))
// print('=============================')
// for x in range(16):
// for y in range(16):
// r = 1 + ((x * 16) + y) * 3
// g = r + 1
// b = r + 2
// print('| {0:2d} | {1:2d} | {2:3d} | {3:3d} | {4:3d} |'.format(
// x, y, r, g, b))
// | Coords | Color Indices |
// | x | y | r | g | b |
// =============================
// | 0 | 0 | 1 | 2 | 3 |
// | 0 | 1 | 4 | 5 | 6 |
// | 0 | 2 | 7 | 8 | 9 |
// .
// .
// .
// | 15 | 13 | 760 | 761 | 762 |
// | 15 | 14 | 763 | 764 | 765 |
// | 15 | 15 | 766 | 767 | 768 |
void set_pixel(int x, int y, int r, int g, int b) {
// Sets specified pixel with an RGB value.
// Find the starting position in the array.
int offset = 1 + ((y * 16) + x) * 3;
buffer[offset + 0] = r; // led red value
buffer[offset + 1] = g; // led green value
buffer[offset + 2] = b; // led blue value
}
int main( int argc, char *argv[] )
{
srand(time(0));
if( wiringPiSPISetup( SPI_CHANNEL, SPI_SPEED ) == -1 )
{
printf("Could not initialise SPI\n");
return( 1 );
}
// setup the buffer and set the Start of Frame byte.
buffer[0] = 0x72; // SOF byte
// Set buffer to zero so we start out with a blank matrix.
for (size_t i = 1; i < 770; i++) {
buffer[i] = 0;
}
// What follows just iterates over each column of LEDs (x) and
// then picks a row height (y) for that column. Each x,y value is
// then set to the appropriate color.
while (1) {
for (size_t x = 0; x < 16; x++) {
buffer[0] = 0x72; // SOF byte
int y_height = rand() / (RAND_MAX / 15) + 1;
for (size_t y = 0; y < y_height; y++) {
set_pixel(x, y, colors[x][0], colors[x][1], colors[x][2]);
}
}
// Write the buffer to the Unicorn Hat HD via SPI.
wiringPiSPIDataRW( SPI_CHANNEL, buffer, PACKET_SIZE );
// Based on experimentation without sleeping updates to the
// Unicorn Hat HD seem to happen too often for it to display
// anything.
usleep( (int)(1000) );
}
}