led-matrix-c.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
  2. * Copyright (C) 2013 Henner Zeller <h.zeller@acm.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation version 2.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
  15. *
  16. * Controlling 16x32 or 32x32 RGB matrixes via GPIO. It allows daisy chaining
  17. * of a string of these, and also connecting a parallel string on newer
  18. * Raspberry Pis with more GPIO pins available.
  19. *
  20. * This is a C-binding (for the C++ library) to allow easy binding and
  21. * integration with other languages. The symbols are exported in librgbmatrix.a
  22. * and librgbmatrix.so. You still need to call the final link with
  23. *
  24. * See examples-api-use/c-example.c for a usage example.
  25. *
  26. */
  27. #ifndef RPI_RGBMATRIX_C_H
  28. #define RPI_RGBMATRIX_C_H
  29. #include <stdint.h>
  30. #include <stdio.h>
  31. #include <stdbool.h>
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35. struct RGBLedMatrix;
  36. struct LedCanvas;
  37. struct LedFont;
  38. /**
  39. * Parameters to create a new matrix.
  40. *
  41. * To get the defaults, non-set values have to be initialized to zero, so you
  42. * should zero out this struct before setting anything.
  43. */
  44. struct RGBLedMatrixOptions {
  45. /*
  46. * Name of the hardware mapping used. If passed NULL here, the default
  47. * is used.
  48. */
  49. const char *hardware_mapping;
  50. /* The "rows" are the number of rows supported by the display, so 32 or 16.
  51. * Default: 32.
  52. * Corresponding flag: --led-rows
  53. */
  54. int rows;
  55. /* The "cols" are the number of columns per panel. Typically something
  56. * like 32, but also 64 is possible. Sometimes even 40.
  57. * cols * chain_length is the total length of the display, so you can
  58. * represent a 64 wide display as cols=32, chain=2 or cols=64, chain=1;
  59. * same thing.
  60. * Flag: --led-cols
  61. */
  62. int cols;
  63. /* The chain_length is the number of displays daisy-chained together
  64. * (output of one connected to input of next). Default: 1
  65. * Corresponding flag: --led-chain
  66. */
  67. int chain_length;
  68. /* The number of parallel chains connected to the Pi; in old Pis with 26
  69. * GPIO pins, that is 1, in newer Pis with 40 interfaces pins, that can
  70. * also be 2 or 3. The effective number of pixels in vertical direction is
  71. * then thus rows * parallel. Default: 1
  72. * Corresponding flag: --led-parallel
  73. */
  74. int parallel;
  75. /* Set PWM bits used for output. Default is 11, but if you only deal with
  76. * limited comic-colors, 1 might be sufficient. Lower require less CPU and
  77. * increases refresh-rate.
  78. * Corresponding flag: --led-pwm-bits
  79. */
  80. int pwm_bits;
  81. /* Change the base time-unit for the on-time in the lowest
  82. * significant bit in nanoseconds.
  83. * Higher numbers provide better quality (more accurate color, less
  84. * ghosting), but have a negative impact on the frame rate.
  85. * Corresponding flag: --led-pwm-lsb-nanoseconds
  86. */
  87. int pwm_lsb_nanoseconds;
  88. /* The lower bits can be time-dithered for higher refresh rate.
  89. * Corresponding flag: --led-pwm-dither-bits
  90. */
  91. int pwm_dither_bits;
  92. /* The initial brightness of the panel in percent. Valid range is 1..100
  93. * Corresponding flag: --led-brightness
  94. */
  95. int brightness;
  96. /* Scan mode: 0=progressive, 1=interlaced
  97. * Corresponding flag: --led-scan-mode
  98. */
  99. int scan_mode;
  100. /* Default row address type is 0, corresponding to direct setting of the
  101. * row, while row address type 1 is used for panels that only have A/B,
  102. * typically some 64x64 panels
  103. */
  104. int row_address_type; /* Corresponding flag: --led-row-addr-type */
  105. /* Type of multiplexing. 0 = direct, 1 = stripe, 2 = checker (typical 1:8)
  106. */
  107. int multiplexing;
  108. /* In case the internal sequence of mapping is not "RGB", this contains the
  109. * real mapping. Some panels mix up these colors.
  110. */
  111. const char *led_rgb_sequence; /* Corresponding flag: --led-rgb-sequence */
  112. /* A string describing a sequence of pixel mappers that should be applied
  113. * to this matrix. A semicolon-separated list of pixel-mappers with optional
  114. * parameter.
  115. */
  116. const char *pixel_mapper_config; /* Corresponding flag: --led-pixel-mapper */
  117. /*
  118. * Panel type. Typically just NULL, but certain panels (FM6126) require
  119. * an initialization sequence
  120. */
  121. const char *panel_type; /* Corresponding flag: --led-panel-type */
  122. /** The following are boolean flags, all off by default **/
  123. /* Allow to use the hardware subsystem to create pulses. This won't do
  124. * anything if output enable is not connected to GPIO 18.
  125. * Corresponding flag: --led-hardware-pulse
  126. */
  127. char disable_hardware_pulsing;
  128. char show_refresh_rate; /* Corresponding flag: --led-show-refresh */
  129. char inverse_colors; /* Corresponding flag: --led-inverse */
  130. /* Limit refresh rate of LED panel. This will help on a loaded system
  131. * to keep a constant refresh rate. <= 0 for no limit.
  132. */
  133. int limit_refresh_rate_hz; /* Corresponding flag: --led-limit-refresh */
  134. };
  135. /**
  136. * Runtime options to simplify doing common things for many programs such as
  137. * dropping privileges and becoming a daemon.
  138. */
  139. struct RGBLedRuntimeOptions {
  140. int gpio_slowdown; // 0 = no slowdown. Flag: --led-slowdown-gpio
  141. // ----------
  142. // If the following options are set to disabled with -1, they are not
  143. // even offered via the command line flags.
  144. // ----------
  145. // Thre are three possible values here
  146. // -1 : don't leave choise of becoming daemon to the command line parsing.
  147. // If set to -1, the --led-daemon option is not offered.
  148. // 0 : do not becoma a daemon, run in forgreound (default value)
  149. // 1 : become a daemon, run in background.
  150. //
  151. // If daemon is disabled (= -1), the user has to call
  152. // RGBMatrix::StartRefresh() manually once the matrix is created, to leave
  153. // the decision to become a daemon
  154. // after the call (which requires that no threads have been started yet).
  155. // In the other cases (off or on), the choice is already made, so the thread
  156. // is conveniently already started for you.
  157. int daemon; // -1 disabled. 0=off, 1=on. Flag: --led-daemon
  158. // Drop privileges from 'root' to 'daemon' once the hardware is initialized.
  159. // This is usually a good idea unless you need to stay on elevated privs.
  160. int drop_privileges; // -1 disabled. 0=off, 1=on. flag: --led-drop-privs
  161. // By default, the gpio is initialized for you, but if you run on a platform
  162. // not the Raspberry Pi, this will fail. If you don't need to access GPIO
  163. // e.g. you want to just create a stream output (see content-streamer.h),
  164. // set this to false.
  165. bool do_gpio_init;
  166. };
  167. /**
  168. * Universal way to create and initialize a matrix.
  169. * The "options" struct (if not NULL) contains all default configuration values
  170. * chosen by the programmer to create the matrix.
  171. *
  172. * If "argc" and "argv" are provided, this function also reads command line
  173. * flags provided, that then can override any of the defaults given.
  174. * The arguments that have been used from the command line are removed from
  175. * the argv list (and argc is adjusted) - that way these don't mess with your
  176. * own command line handling.
  177. *
  178. * The actual options used are filled back into the "options" struct if not
  179. * NULL.
  180. *
  181. * Usage:
  182. * ----------------
  183. * int main(int argc, char **argv) {
  184. * struct RGBLedMatrixOptions options;
  185. * memset(&options, 0, sizeof(options));
  186. * options.rows = 32; // You can set defaults if you want.
  187. * options.chain_length = 1;
  188. * struct RGBLedMatrix *matrix = led_matrix_create_from_options(&options,
  189. * &argc, &argv);
  190. * if (matrix == NULL) {
  191. * led_matrix_print_flags(stderr);
  192. * return 1;
  193. * }
  194. * // do additional commandline handling; then use matrix...
  195. * }
  196. * ----------------
  197. */
  198. struct RGBLedMatrix *led_matrix_create_from_options(
  199. struct RGBLedMatrixOptions *options, int *argc, char ***argv);
  200. /* Same, but does not modify the argv array. */
  201. struct RGBLedMatrix *led_matrix_create_from_options_const_argv(
  202. struct RGBLedMatrixOptions *options, int argc, char **argv);
  203. /**
  204. * The way to completely initialize your matrix without using command line
  205. * flags to initialize some things.
  206. *
  207. * The actual options used are filled back into the "options" and "rt_options"
  208. * struct if not NULL. If they are null, the default value is used.
  209. *
  210. * Usage:
  211. * ----------------
  212. * int main(int argc, char **argv) {
  213. * struct RGBLedMatrixOptions options;
  214. * struct RGBLedRuntimeOptions rt_options;
  215. * memset(&options, 0, sizeof(options));
  216. * memset(&rt_options, 0, sizeof(rt_options));
  217. * options.rows = 32; // You can set defaults if you want.
  218. * options.chain_length = 1;
  219. * rt_options.gpio_slowdown = 4;
  220. * struct RGBLedMatrix *matrix = led_matrix_create_from_options_and_rt_options(&options, &rt_options);
  221. * if (matrix == NULL) {
  222. * return 1;
  223. * }
  224. * // do additional commandline handling; then use matrix...
  225. * }
  226. * ----------------
  227. */
  228. struct RGBLedMatrix *led_matrix_create_from_options_and_rt_options(
  229. struct RGBLedMatrixOptions *opts, struct RGBLedRuntimeOptions * rt_opts);
  230. /**
  231. * Print available LED matrix options.
  232. */
  233. void led_matrix_print_flags(FILE *out);
  234. /**
  235. * Simple form of led_matrix_create_from_options() with just the few
  236. * main options. Returns NULL if that was not possible.
  237. * The "rows" are the number of rows supported by the display, so 32, 16 or 8.
  238. *
  239. * Number of "chained_display"s tells many of these are daisy-chained together
  240. * (output of one connected to input of next).
  241. *
  242. * The "parallel_display" number determines if there is one or two displays
  243. * connected in parallel to the GPIO port - this only works with newer
  244. * Raspberry Pi that have 40 interface pins.
  245. *
  246. * This creates a realtime thread and requires root access to access the GPIO
  247. * pins.
  248. * So if you run this in a daemon, this should be called after becoming a
  249. * daemon (as fork/exec stops threads) and before dropping privileges.
  250. */
  251. struct RGBLedMatrix *led_matrix_create(int rows, int chained, int parallel);
  252. /**
  253. * Stop matrix and free memory.
  254. * Always call before the end of the program to properly reset the hardware
  255. */
  256. void led_matrix_delete(struct RGBLedMatrix *matrix);
  257. /**
  258. * Get active canvas from LED matrix for you to draw on.
  259. * Ownership of returned pointer stays with the matrix, don't free().
  260. */
  261. struct LedCanvas *led_matrix_get_canvas(struct RGBLedMatrix *matrix);
  262. /** Return size of canvas. */
  263. void led_canvas_get_size(const struct LedCanvas *canvas,
  264. int *width, int *height);
  265. /** Set pixel at (x, y) with color (r,g,b). */
  266. void led_canvas_set_pixel(struct LedCanvas *canvas, int x, int y,
  267. uint8_t r, uint8_t g, uint8_t b);
  268. /** Clear screen (black). */
  269. void led_canvas_clear(struct LedCanvas *canvas);
  270. /** Fill matrix with given color. */
  271. void led_canvas_fill(struct LedCanvas *canvas, uint8_t r, uint8_t g, uint8_t b);
  272. /*** API to provide double-buffering. ***/
  273. /**
  274. * Create a new canvas to be used with led_matrix_swap_on_vsync()
  275. * Ownership of returned pointer stays with the matrix, don't free().
  276. */
  277. struct LedCanvas *led_matrix_create_offscreen_canvas(struct RGBLedMatrix *matrix);
  278. /**
  279. * Swap the given canvas (created with create_offscreen_canvas) with the
  280. * currently active canvas on vsync (blocks until vsync is reached).
  281. * Returns the previously active canvas. So with that, you can create double
  282. * buffering:
  283. *
  284. * struct LedCanvas *offscreen = led_matrix_create_offscreen_canvas(...);
  285. * led_canvas_set_pixel(offscreen, ...); // not shown until swap-on-vsync
  286. * offscreen = led_matrix_swap_on_vsync(matrix, offscreen);
  287. * // The returned buffer, assigned to offscreen, is now the inactive buffer
  288. * // fill, then swap again.
  289. */
  290. struct LedCanvas *led_matrix_swap_on_vsync(struct RGBLedMatrix *matrix,
  291. struct LedCanvas *canvas);
  292. uint8_t led_matrix_get_brightness(struct RGBLedMatrix *matrix);
  293. void led_matrix_set_brightness(struct RGBLedMatrix *matrix, uint8_t brightness);
  294. // Utility function: set an image from the given buffer containting pixels.
  295. //
  296. // Draw image of size "image_width" and "image_height" from pixel at
  297. // canvas-offset "canvas_offset_x", "canvas_offset_y". Image will be shown
  298. // cropped on the edges if needed.
  299. //
  300. // The canvas offset can be negative, i.e. the image start can be shifted
  301. // outside the image frame on the left/top edge.
  302. //
  303. // The buffer needs to be organized as rows with columns of three bytes
  304. // organized as rgb or bgr. Thus the size of the buffer needs to be exactly
  305. // (3 * image_width * image_height) bytes.
  306. //
  307. // The "image_buffer" parameters contains the data, "buffer_size_bytes" the
  308. // size in bytes.
  309. //
  310. // If "is_bgr" is 1, the buffer is treated as BGR pixel arrangement instead
  311. // of RGB with is_bgr = 0.
  312. void set_image(struct LedCanvas *c, int canvas_offset_x, int canvas_offset_y,
  313. const uint8_t *image_buffer, size_t buffer_size_bytes,
  314. int image_width, int image_height,
  315. char is_bgr);
  316. // Load a font given a path to a font file containing a bdf font.
  317. struct LedFont *load_font(const char *bdf_font_file);
  318. // Read the baseline of a font
  319. int baseline_font(struct LedFont *font);
  320. // Read the height of a font
  321. int height_font(struct LedFont *font);
  322. // Creates an outline font based on an existing font instance
  323. struct LedFont *create_outline_font(struct LedFont *font);
  324. // Delete a font originally created from load_font.
  325. void delete_font(struct LedFont *font);
  326. int draw_text(struct LedCanvas *c, struct LedFont *font, int x, int y,
  327. uint8_t r, uint8_t g, uint8_t b,
  328. const char *utf8_text, int kerning_offset);
  329. int vertical_draw_text(struct LedCanvas *c, struct LedFont *font, int x, int y,
  330. uint8_t r, uint8_t g, uint8_t b,
  331. const char *utf8_text, int kerning_offset);
  332. void draw_circle(struct LedCanvas *c, int x, int y, int radius,
  333. uint8_t r, uint8_t g, uint8_t b);
  334. void draw_line(struct LedCanvas *c, int x0, int y0, int x1, int y1,
  335. uint8_t r, uint8_t g, uint8_t b);
  336. #ifdef __cplusplus
  337. } // extern C
  338. #endif
  339. #endif