main.c
Go to the documentation of this file.
1 /*
2  * newtest.c
3  *
4  * Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without modification, are permitted
9  * provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this list of
12  * conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
14  * of conditions and the following disclaimer in the documentation and/or other materials
15  * provided with the distribution.
16  * 3. Neither the name of the owner nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 
31 static char VERSION[] = "XX.YY.ZZ";
32 
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <sys/mman.h>
42 #include <signal.h>
43 #include <stdarg.h>
44 #include <getopt.h>
45 
46 
47 #include "clk.h"
48 #include "gpio.h"
49 #include "dma.h"
50 #include "pwm.h"
51 #include "version.h"
52 
53 #include "ws2811.h"
54 
55 
56 #define ARRAY_SIZE(stuff) (sizeof(stuff) / sizeof(stuff[0]))
57 
58 // defaults for cmdline options
59 #define TARGET_FREQ WS2811_TARGET_FREQ
60 #define GPIO_PIN 18
61 #define DMA 10
62 //#define STRIP_TYPE WS2811_STRIP_RGB // WS2812/SK6812RGB integrated chip+leds
63 #define STRIP_TYPE WS2811_STRIP_GBR // WS2812/SK6812RGB integrated chip+leds
64 //#define STRIP_TYPE SK6812_STRIP_RGBW // SK6812RGBW (NOT SK6812RGB)
65 
66 #define WIDTH 8
67 #define HEIGHT 8
68 #define LED_COUNT (WIDTH * HEIGHT)
69 
70 int width = WIDTH;
71 int height = HEIGHT;
73 
74 int clear_on_exit = 0;
75 
77 {
78  .freq = TARGET_FREQ,
79  .dmanum = DMA,
80  .channel =
81  {
82  [0] =
83  {
84  .gpionum = GPIO_PIN,
85  .count = LED_COUNT,
86  .invert = 0,
87  .brightness = 255,
88  .strip_type = STRIP_TYPE,
89  },
90  [1] =
91  {
92  .gpionum = 0,
93  .count = 0,
94  .invert = 0,
95  .brightness = 0,
96  },
97  },
98 };
99 
101 
102 static uint8_t running = 1;
103 
104 void matrix_render(void)
105 {
106  int x, y;
107 
108  for (x = 0; x < width; x++)
109  {
110  for (y = 0; y < height; y++)
111  {
112  ledstring.channel[0].leds[(y * width) + x] = matrix[y * width + x];
113  }
114  }
115 }
116 
117 void matrix_raise(void)
118 {
119  int x, y;
120 
121  for (y = 0; y < (height - 1); y++)
122  {
123  for (x = 0; x < width; x++)
124  {
125  // This is for the 8x8 Pimoroni Unicorn-HAT where the LEDS in subsequent
126  // rows are arranged in opposite directions
127  matrix[y * width + x] = matrix[(y + 1)*width + width - x - 1];
128  }
129  }
130 }
131 
132 void matrix_clear(void)
133 {
134  int x, y;
135 
136  for (y = 0; y < (height ); y++)
137  {
138  for (x = 0; x < width; x++)
139  {
140  matrix[y * width + x] = 0;
141  }
142  }
143 }
144 
145 int dotspos[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
147 {
148  0x00200000, // red
149  0x00201000, // orange
150  0x00202000, // yellow
151  0x00002000, // green
152  0x00002020, // lightblue
153  0x00000020, // blue
154  0x00100010, // purple
155  0x00200010, // pink
156 };
157 
159 {
160  0x00200000, // red
161  0x10200000, // red + W
162  0x00002000, // green
163  0x10002000, // green + W
164  0x00000020, // blue
165  0x10000020, // blue + W
166  0x00101010, // white
167  0x10101010, // white + W
168 
169 };
170 
171 void matrix_bottom(void)
172 {
173  int i;
174 
175  for (i = 0; i < (int)(ARRAY_SIZE(dotspos)); i++)
176  {
177  dotspos[i]++;
178  if (dotspos[i] > (width - 1))
179  {
180  dotspos[i] = 0;
181  }
182 
183  if (ledstring.channel[0].strip_type == SK6812_STRIP_RGBW) {
184  matrix[dotspos[i] + (height - 1) * width] = dotcolors_rgbw[i];
185  } else {
186  matrix[dotspos[i] + (height - 1) * width] = dotcolors[i];
187  }
188  }
189 }
190 
191 static void ctrl_c_handler(int signum)
192 {
193  (void)(signum);
194  running = 0;
195 }
196 
197 static void setup_handlers(void)
198 {
199  struct sigaction sa =
200  {
201  .sa_handler = ctrl_c_handler,
202  };
203 
204  sigaction(SIGINT, &sa, NULL);
205  sigaction(SIGTERM, &sa, NULL);
206 }
207 
208 
209 void parseargs(int argc, char **argv, ws2811_t *ws2811)
210 {
211  int index;
212  int c;
213 
214  static struct option longopts[] =
215  {
216  {"help", no_argument, 0, 'h'},
217  {"dma", required_argument, 0, 'd'},
218  {"gpio", required_argument, 0, 'g'},
219  {"invert", no_argument, 0, 'i'},
220  {"clear", no_argument, 0, 'c'},
221  {"strip", required_argument, 0, 's'},
222  {"height", required_argument, 0, 'y'},
223  {"width", required_argument, 0, 'x'},
224  {"version", no_argument, 0, 'v'},
225  {0, 0, 0, 0}
226  };
227 
228  while (1)
229  {
230 
231  index = 0;
232  c = getopt_long(argc, argv, "cd:g:his:vx:y:", longopts, &index);
233 
234  if (c == -1)
235  break;
236 
237  switch (c)
238  {
239  case 0:
240  /* handle flag options (array's 3rd field non-0) */
241  break;
242 
243  case 'h':
244  fprintf(stderr, "%s version %s\n", argv[0], VERSION);
245  fprintf(stderr, "Usage: %s \n"
246  "-h (--help) - this information\n"
247  "-s (--strip) - strip type - rgb, grb, gbr, rgbw\n"
248  "-x (--width) - matrix width (default 8)\n"
249  "-y (--height) - matrix height (default 8)\n"
250  "-d (--dma) - dma channel to use (default 10)\n"
251  "-g (--gpio) - GPIO to use\n"
252  " If omitted, default is 18 (PWM0)\n"
253  "-i (--invert) - invert pin output (pulse LOW)\n"
254  "-c (--clear) - clear matrix on exit.\n"
255  "-v (--version) - version information\n"
256  , argv[0]);
257  exit(-1);
258 
259  case 'D':
260  break;
261 
262  case 'g':
263  if (optarg) {
264  int gpio = atoi(optarg);
265 /*
266  PWM0, which can be set to use GPIOs 12, 18, 40, and 52.
267  Only 12 (pin 32) and 18 (pin 12) are available on the B+/2B/3B
268  PWM1 which can be set to use GPIOs 13, 19, 41, 45 and 53.
269  Only 13 is available on the B+/2B/PiZero/3B, on pin 33
270  PCM_DOUT, which can be set to use GPIOs 21 and 31.
271  Only 21 is available on the B+/2B/PiZero/3B, on pin 40.
272  SPI0-MOSI is available on GPIOs 10 and 38.
273  Only GPIO 10 is available on all models.
274 
275  The library checks if the specified gpio is available
276  on the specific model (from model B rev 1 till 3B)
277 
278 */
279  ws2811->channel[0].gpionum = gpio;
280  }
281  break;
282 
283  case 'i':
284  ws2811->channel[0].invert=1;
285  break;
286 
287  case 'c':
288  clear_on_exit=1;
289  break;
290 
291  case 'd':
292  if (optarg) {
293  int dma = atoi(optarg);
294  if (dma < 14) {
295  ws2811->dmanum = dma;
296  } else {
297  printf ("invalid dma %d\n", dma);
298  exit (-1);
299  }
300  }
301  break;
302 
303  case 'y':
304  if (optarg) {
305  height = atoi(optarg);
306  if (height > 0) {
307  ws2811->channel[0].count = height * width;
308  } else {
309  printf ("invalid height %d\n", height);
310  exit (-1);
311  }
312  }
313  break;
314 
315  case 'x':
316  if (optarg) {
317  width = atoi(optarg);
318  if (width > 0) {
319  ws2811->channel[0].count = height * width;
320  } else {
321  printf ("invalid width %d\n", width);
322  exit (-1);
323  }
324  }
325  break;
326 
327  case 's':
328  if (optarg) {
329  if (!strncasecmp("rgb", optarg, 4)) {
330  ws2811->channel[0].strip_type = WS2811_STRIP_RGB;
331  }
332  else if (!strncasecmp("rbg", optarg, 4)) {
333  ws2811->channel[0].strip_type = WS2811_STRIP_RBG;
334  }
335  else if (!strncasecmp("grb", optarg, 4)) {
336  ws2811->channel[0].strip_type = WS2811_STRIP_GRB;
337  }
338  else if (!strncasecmp("gbr", optarg, 4)) {
339  ws2811->channel[0].strip_type = WS2811_STRIP_GBR;
340  }
341  else if (!strncasecmp("brg", optarg, 4)) {
342  ws2811->channel[0].strip_type = WS2811_STRIP_BRG;
343  }
344  else if (!strncasecmp("bgr", optarg, 4)) {
345  ws2811->channel[0].strip_type = WS2811_STRIP_BGR;
346  }
347  else if (!strncasecmp("rgbw", optarg, 4)) {
348  ws2811->channel[0].strip_type = SK6812_STRIP_RGBW;
349  }
350  else if (!strncasecmp("grbw", optarg, 4)) {
351  ws2811->channel[0].strip_type = SK6812_STRIP_GRBW;
352  }
353  else {
354  printf ("invalid strip %s\n", optarg);
355  exit (-1);
356  }
357  }
358  break;
359 
360  case 'v':
361  fprintf(stderr, "%s version %s\n", argv[0], VERSION);
362  exit(-1);
363 
364  case '?':
365  /* getopt_long already reported error? */
366  exit(-1);
367 
368  default:
369  exit(-1);
370  }
371  }
372 }
373 
374 
375 int main(int argc, char *argv[])
376 {
377  ws2811_return_t ret;
378 
379  sprintf(VERSION, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO);
380 
381  parseargs(argc, argv, &ledstring);
382 
383  matrix = malloc(sizeof(ws2811_led_t) * width * height);
384 
385  setup_handlers();
386 
387  if ((ret = ws2811_init(&ledstring)) != WS2811_SUCCESS)
388  {
389  fprintf(stderr, "ws2811_init failed: %s\n", ws2811_get_return_t_str(ret));
390  return ret;
391  }
392 
393  while (running)
394  {
395  matrix_raise();
396  matrix_bottom();
397  matrix_render();
398 
399  if ((ret = ws2811_render(&ledstring)) != WS2811_SUCCESS)
400  {
401  fprintf(stderr, "ws2811_render failed: %s\n", ws2811_get_return_t_str(ret));
402  break;
403  }
404 
405  // 15 frames /sec
406  usleep(1000000 / 15);
407  }
408 
409  if (clear_on_exit) {
410  matrix_clear();
411  matrix_render();
412  ws2811_render(&ledstring);
413  }
414 
415  ws2811_fini(&ledstring);
416 
417  printf ("\n");
418  return ret;
419 }
#define WS2811_STRIP_BRG
Definition: ws2811.h:60
int height
Definition: main.c:71
int main(int argc, char *argv[])
Definition: main.c:375
#define WS2811_STRIP_BGR
Definition: ws2811.h:61
#define TARGET_FREQ
Definition: main.c:59
#define WS2811_STRIP_RBG
Definition: ws2811.h:57
uint32_t ws2811_led_t
Definition: ws2811.h:68
#define WS2811_STRIP_GRB
Definition: ws2811.h:58
#define DMA
Definition: main.c:61
ws2811_channel_t channel[RPI_PWM_CHANNELS]
Definition: ws2811.h:93
int clear_on_exit
Definition: main.c:74
#define LED_COUNT
Definition: main.c:68
ws2811_return_t
Definition: ws2811.h:116
#define ARRAY_SIZE(stuff)
Definition: main.c:56
#define GPIO_PIN
Definition: main.c:60
void parseargs(int argc, char **argv, ws2811_t *ws2811)
Definition: main.c:209
void matrix_clear(void)
Definition: main.c:132
ws2811_led_t * matrix
Definition: main.c:100
ws2811_led_t dotcolors_rgbw[]
Definition: main.c:158
#define SK6812_STRIP_GRBW
Definition: ws2811.h:49
ws2811_led_t dotcolors[]
Definition: main.c:146
void matrix_render(void)
Definition: main.c:104
int dotspos[]
Definition: main.c:145
ws2811_led_t * leds
Definition: ws2811.h:77
static void setup_handlers(void)
Definition: main.c:197
ws2811_return_t ws2811_init(ws2811_t *ws2811)
Definition: ws2811.c:894
static char VERSION[]
Definition: main.c:31
void matrix_raise(void)
Definition: main.c:117
int led_count
Definition: main.c:72
ws2811_t ledstring
Definition: main.c:76
#define HEIGHT
Definition: main.c:67
ws2811_return_t ws2811_render(ws2811_t *ws2811)
Definition: ws2811.c:1138
uint32_t freq
Definition: ws2811.h:91
const char * ws2811_get_return_t_str(const ws2811_return_t state)
Definition: ws2811.c:1273
void ws2811_fini(ws2811_t *ws2811)
Definition: ws2811.c:1079
int strip_type
Definition: ws2811.h:76
#define WS2811_STRIP_GBR
Definition: ws2811.h:59
#define SK6812_STRIP_RGBW
Definition: ws2811.h:47
int dmanum
Definition: ws2811.h:92
#define STRIP_TYPE
Definition: main.c:63
#define WIDTH
Definition: main.c:66
static uint8_t running
Definition: main.c:102
#define WS2811_STRIP_RGB
Definition: ws2811.h:56
static void ctrl_c_handler(int signum)
Definition: main.c:191
void matrix_bottom(void)
Definition: main.c:171
int width
Definition: main.c:70


ws281x
Author(s): Alexey Rogachevskiy , Oleg Kalachev
autogenerated on Wed Jun 15 2022 02:46:00