forked from hzeller/rpi-rgb-led-matrix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
text-example.cc
173 lines (152 loc) · 4.92 KB
/
text-example.cc
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
// Small example how write text.
//
// This code is public domain
// (but note, that the led-matrix library this depends on is GPL v2)
#include "led-matrix.h"
#include "graphics.h"
#include "transformer.h"
#include "ak-transformer.h"
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
using namespace rgb_matrix;
static int usage(const char *progname) {
fprintf(stderr, "usage: %s [options]\n", progname);
fprintf(stderr, "Reads text from stdin and displays it. "
"Empty string: clear screen\n");
fprintf(stderr, "Options:\n"
"\t-f <font-file>: Use given font.\n"
"\t-r <rows> : Display rows. 16 for 16x32, 32 for 32x32. "
"Default: 32\n"
"\t-P <parallel> : For Plus-models or RPi2: parallel chains. 1..3. "
"Default: 1\n"
"\t-c <chained> : Daisy-chained boards. Default: 1.\n"
"\t-L : Large display (alternate layout)\n"
"\t-b <brightness>: Sets brightness percent. Default: 100.\n"
"\t-x <x-origin> : X-Origin of displaying text (Default: 0)\n"
"\t-y <y-origin> : Y-Origin of displaying text (Default: 0)\n"
"\t-C <r,g,b> : Color. Default 255,255,0\n");
return 1;
}
static bool parseColor(Color *c, const char *str) {
return sscanf(str, "%hhu,%hhu,%hhu", &c->r, &c->g, &c->b) == 3;
}
int main(int argc, char *argv[]) {
Color color(255, 255, 0);
const char *bdf_font_file = NULL;
int rows = 32;
int chain = 1;
int parallel = 1;
int x_orig = 0;
int y_orig = -1;
int brightness = 100;
bool large_display = false;
int opt;
while ((opt = getopt(argc, argv, "r:P:c:x:y:Lf:C:b:")) != -1) {
switch (opt) {
case 'r': rows = atoi(optarg); break;
case 'P': parallel = atoi(optarg); break;
case 'c': chain = atoi(optarg); break;
case 'b': brightness = atoi(optarg); break;
case 'x': x_orig = atoi(optarg); break;
case 'y': y_orig = atoi(optarg); break;
case 'L':
// The 'large' display assumes a chain of four displays with 32x32
chain = 4;
rows = 16;
large_display = true;
break;
case 'f': bdf_font_file = strdup(optarg); break;
case 'C':
if (!parseColor(&color, optarg)) {
fprintf(stderr, "Invalid color spec.\n");
return usage(argv[0]);
}
break;
default:
return usage(argv[0]);
}
}
if (bdf_font_file == NULL) {
fprintf(stderr, "Need to specify BDF font-file with -f\n");
return usage(argv[0]);
}
/*
* Load font. This needs to be a filename with a bdf bitmap font.
*/
rgb_matrix::Font font;
if (!font.LoadFont(bdf_font_file)) {
fprintf(stderr, "Couldn't load font '%s'\n", bdf_font_file);
return usage(argv[0]);
}
if (rows != 16 && rows != 32) {
fprintf(stderr, "Rows can either be 16 or 32\n");
return 1;
}
if (chain < 1) {
fprintf(stderr, "Chain outside usable range\n");
return 1;
}
if (chain > 8) {
fprintf(stderr, "That is a long chain. Expect some flicker.\n");
}
if (parallel < 1 || parallel > 3) {
fprintf(stderr, "Parallel outside usable range.\n");
return 1;
}
if (brightness < 1 || brightness > 100) {
fprintf(stderr, "Brightness is outside usable range.\n");
return 1;
}
/*
* Set up GPIO pins. This fails when not running as root.
*/
GPIO io;
if (!io.Init())
return 1;
/*
* Set up the RGBMatrix. It implements a 'Canvas' interface.
*/
RGBMatrix *canvas = new RGBMatrix(&io, rows, chain, parallel);
canvas->SetBrightness(brightness);
LinkedTransformer *transformer = new LinkedTransformer();
canvas->SetTransformer(transformer);
if (large_display) {
// Mapping the coordinates of a 32x128 display mapped to a square of 64x64
transformer->AddTransformer(new Rect64x32Transformer());
}
bool all_extreme_colors = brightness == 100;
all_extreme_colors &= color.r == 0 || color.r == 255;
all_extreme_colors &= color.g == 0 || color.g == 255;
all_extreme_colors &= color.b == 0 || color.b == 255;
if (all_extreme_colors)
canvas->SetPWMBits(1);
const int x = x_orig;
int y = y_orig;
if (isatty(STDIN_FILENO)) {
// Only give a message if we are interactive. If connected via pipe, be quiet
printf("Enter lines. Full screen or empty line clears screen.\n"
"Supports UTF-8. CTRL-D for exit.\n");
}
char line[1024];
while (fgets(line, sizeof(line), stdin)) {
const size_t last = strlen(line);
if (last > 0) line[last - 1] = '\0'; // remove newline.
bool line_empty = strlen(line) == 0;
if ((y + font.height() > canvas->height()) || line_empty) {
canvas->Clear();
y = y_orig;
}
if (line_empty)
continue;
rgb_matrix::DrawText(canvas, font, x, y + font.baseline(), color, line);
y += font.height();
}
// Finished. Shut down the RGB matrix.
canvas->Clear();
delete canvas;
return 0;
}