This commit is contained in:
52
depends/rpi-rgb-led-matrix/include/canvas.h
Normal file
52
depends/rpi-rgb-led-matrix/include/canvas.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
|
||||
|
||||
#ifndef RPI_CANVAS_H
|
||||
#define RPI_CANVAS_H
|
||||
#include <stdint.h>
|
||||
|
||||
namespace rgb_matrix {
|
||||
// An interface for things a Canvas can do. The RGBMatrix implements this
|
||||
// interface, so you can use it directly wherever a canvas is needed.
|
||||
//
|
||||
// This abstraction also allows you to e.g. create delegating
|
||||
// implementations that do a particular transformation, e.g. re-map
|
||||
// pixels (as you might lay out the physical RGB matrix in a different way),
|
||||
// compose images (OR, XOR, transparecy), scale, rotate, anti-alias or
|
||||
// translate coordinates in a funky way.
|
||||
//
|
||||
// It is a good idea to have your applications use the concept of
|
||||
// a Canvas to write the content to instead of directly using the RGBMatrix.
|
||||
class Canvas {
|
||||
public:
|
||||
virtual ~Canvas() {}
|
||||
virtual int width() const = 0; // Pixels available in x direction.
|
||||
virtual int height() const = 0; // Pixels available in y direction.
|
||||
|
||||
// Set pixel at coordinate (x,y) with given color. Pixel (0,0) is the
|
||||
// top left corner.
|
||||
// Each color is 8 bit (24bpp), 0 black, 255 brightest.
|
||||
virtual void SetPixel(int x, int y,
|
||||
uint8_t red, uint8_t green, uint8_t blue) = 0;
|
||||
|
||||
// Clear screen to be all black.
|
||||
virtual void Clear() = 0;
|
||||
|
||||
// Fill screen with given 24bpp color.
|
||||
virtual void Fill(uint8_t red, uint8_t green, uint8_t blue) = 0;
|
||||
};
|
||||
|
||||
} // namespace rgb_matrix
|
||||
#endif // RPI_CANVAS_H
|
||||
108
depends/rpi-rgb-led-matrix/include/content-streamer.h
Normal file
108
depends/rpi-rgb-led-matrix/include/content-streamer.h
Normal file
@@ -0,0 +1,108 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
//
|
||||
// Abstractions to read and write FrameCanvas objects to streams. This allows
|
||||
// you to create canned streams of content with minimal overhead at runtime
|
||||
// to play with extreme pixel-throughput which also minimizes overheads in
|
||||
// the Pi to avoid stuttering or brightness glitches.
|
||||
//
|
||||
// The disadvantage is, that this represents the full expanded internal
|
||||
// representation of a frame, so is very large memory wise.
|
||||
//
|
||||
// These abstractions are used in util/led-image-viewer.cc to read and
|
||||
// write such animations to disk. It is also used in util/video-viewer.cc
|
||||
// to write a version to disk that then can be played with the led-image-viewer.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace rgb_matrix {
|
||||
class FrameCanvas;
|
||||
|
||||
// An abstraction of a data stream.
|
||||
class StreamIO {
|
||||
public:
|
||||
virtual ~StreamIO() {}
|
||||
|
||||
// Rewind stream.
|
||||
virtual void Rewind() = 0;
|
||||
|
||||
// Read bytes into buffer. Similar to Posix behavior that allows short reads.
|
||||
virtual ssize_t Read(void *buf, size_t count) = 0;
|
||||
|
||||
// Write bytes from buffer. Similar to Posix behavior that allows short
|
||||
// writes.
|
||||
virtual ssize_t Append(const void *buf, size_t count) = 0;
|
||||
};
|
||||
|
||||
class FileStreamIO : public StreamIO {
|
||||
public:
|
||||
explicit FileStreamIO(int fd);
|
||||
~FileStreamIO();
|
||||
|
||||
virtual void Rewind();
|
||||
virtual ssize_t Read(void *buf, size_t count);
|
||||
virtual ssize_t Append(const void *buf, size_t count);
|
||||
|
||||
private:
|
||||
const int fd_;
|
||||
};
|
||||
|
||||
class MemStreamIO : public StreamIO {
|
||||
public:
|
||||
virtual void Rewind();
|
||||
virtual ssize_t Read(void *buf, size_t count);
|
||||
virtual ssize_t Append(const void *buf, size_t count);
|
||||
|
||||
private:
|
||||
std::string buffer_; // super simplistic.
|
||||
size_t pos_;
|
||||
};
|
||||
|
||||
class StreamWriter {
|
||||
public:
|
||||
// Does not take ownership of StreamIO
|
||||
StreamWriter(StreamIO *io);
|
||||
|
||||
// Stream out given canvas at the given time. "hold_time_us" indicates
|
||||
// for how long this frame is to be shown in microseconds.
|
||||
bool Stream(const FrameCanvas &frame, uint32_t hold_time_us);
|
||||
|
||||
private:
|
||||
void WriteFileHeader(const FrameCanvas &frame, size_t len);
|
||||
|
||||
StreamIO *const io_;
|
||||
bool header_written_;
|
||||
};
|
||||
|
||||
class StreamReader {
|
||||
public:
|
||||
// Does not take ownership of StreamIO
|
||||
StreamReader(StreamIO *io);
|
||||
~StreamReader();
|
||||
|
||||
// Go back to the beginning.
|
||||
void Rewind();
|
||||
|
||||
// Get next frame and its timestamp. Returns 'false' if there is an error
|
||||
// or end of stream reached..
|
||||
bool GetNext(FrameCanvas *frame, uint32_t* hold_time_us);
|
||||
|
||||
private:
|
||||
enum State {
|
||||
STREAM_AT_BEGIN,
|
||||
STREAM_READING,
|
||||
STREAM_ERROR,
|
||||
};
|
||||
bool ReadFileHeader(const FrameCanvas &frame);
|
||||
|
||||
StreamIO *io_;
|
||||
size_t frame_buf_size_;
|
||||
State state_;
|
||||
|
||||
char *header_frame_buffer_;
|
||||
};
|
||||
}
|
||||
144
depends/rpi-rgb-led-matrix/include/graphics.h
Normal file
144
depends/rpi-rgb-led-matrix/include/graphics.h
Normal file
@@ -0,0 +1,144 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Very simple graphics library to do simple things.
|
||||
//
|
||||
// Might be useful to consider using Cairo instead and just have an interface
|
||||
// between that and the Canvas. Well, this is a quick set of things to get
|
||||
// started (and nicely self-contained).
|
||||
#ifndef RPI_GRAPHICS_H
|
||||
#define RPI_GRAPHICS_H
|
||||
|
||||
#include "canvas.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace rgb_matrix {
|
||||
struct Color {
|
||||
Color() : r(0), g(0), b(0) {}
|
||||
Color(uint8_t rr, uint8_t gg, uint8_t bb) : r(rr), g(gg), b(bb) {}
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
|
||||
// Font loading bdf files. If this ever becomes more types, just make virtual
|
||||
// base class.
|
||||
class Font {
|
||||
public:
|
||||
// Initialize font, but it is only usable after LoadFont() has been called.
|
||||
Font();
|
||||
~Font();
|
||||
|
||||
bool LoadFont(const char *path);
|
||||
|
||||
// Return height of font in pixels. Returns -1 if font has not been loaded.
|
||||
int height() const { return font_height_; }
|
||||
|
||||
// Return baseline. Pixels from the topline to the baseline.
|
||||
int baseline() const { return base_line_; }
|
||||
|
||||
// Return width of given character, or -1 if font is not loaded or character
|
||||
// does not exist.
|
||||
int CharacterWidth(uint32_t unicode_codepoint) const;
|
||||
|
||||
// Draws the unicode character at position "x","y"
|
||||
// with "color" on "background_color" (background_color can be NULL for
|
||||
// transparency.
|
||||
// The "y" position is the baseline of the font.
|
||||
// If we don't have it in the font, draws the replacement character "<22>" if
|
||||
// available.
|
||||
// Returns how much we advance on the screen, which is the width of the
|
||||
// character or 0 if we didn't draw any chracter.
|
||||
int DrawGlyph(Canvas *c, int x, int y,
|
||||
const Color &color, const Color *background_color,
|
||||
uint32_t unicode_codepoint) const;
|
||||
|
||||
// Same without background. Deprecated, use the one above instead.
|
||||
int DrawGlyph(Canvas *c, int x, int y, const Color &color,
|
||||
uint32_t unicode_codepoint) const;
|
||||
|
||||
// Create a new font derived from this font, which represents an outline
|
||||
// of the original font, essentially pixels tracing around the original
|
||||
// letter.
|
||||
// This can be used in situations in which it is desirable to frame a letter
|
||||
// in a different color to increase contrast.
|
||||
// The ownership of the returned pointer is passed to the caller.
|
||||
Font *CreateOutlineFont() const;
|
||||
|
||||
private:
|
||||
Font(const Font& x); // No copy constructor. Use references or pointer instead.
|
||||
|
||||
struct Glyph;
|
||||
typedef std::map<uint32_t, Glyph*> CodepointGlyphMap;
|
||||
|
||||
const Glyph *FindGlyph(uint32_t codepoint) const;
|
||||
|
||||
int font_height_;
|
||||
int base_line_;
|
||||
CodepointGlyphMap glyphs_;
|
||||
};
|
||||
|
||||
// -- Some utility functions.
|
||||
|
||||
// Utility function: set an image from the given buffer containting pixels.
|
||||
//
|
||||
// Draw image of size "image_width" and "image_height" from pixel at
|
||||
// canvas-offset "canvas_offset_x", "canvas_offset_y". Image will be shown
|
||||
// cropped on the edges if needed.
|
||||
//
|
||||
// The canvas offset can be negative, i.e. the image start can be shifted
|
||||
// outside the image frame on the left/top edge.
|
||||
//
|
||||
// The buffer needs to be organized as rows with columns of three bytes
|
||||
// organized as rgb or bgr. Thus the size of the buffer needs to be exactly
|
||||
// (3 * image_width * image_height) bytes.
|
||||
//
|
||||
// The "image_buffer" parameters contains the data, "buffer_size_bytes" the
|
||||
// size in bytes.
|
||||
//
|
||||
// If "is_bgr" is true, the buffer is treated as BGR pixel arrangement instead
|
||||
// of RGB.
|
||||
// Returns 'true' if image was shown within canvas.
|
||||
bool SetImage(Canvas *c, int canvas_offset_x, int canvas_offset_y,
|
||||
const uint8_t *image_buffer, size_t buffer_size_bytes,
|
||||
int image_width, int image_height,
|
||||
bool is_bgr);
|
||||
|
||||
// Draw text, a standard NUL terminated C-string encoded in UTF-8,
|
||||
// with given "font" at "x","y" with "color".
|
||||
// "color" always needs to be set (hence it is a reference),
|
||||
// "background_color" is a pointer to optionally be NULL for transparency.
|
||||
// "kerning_offset" allows for additional spacing between characters (can be
|
||||
// negative)
|
||||
// Returns how many pixels we advanced on the screen.
|
||||
int DrawText(Canvas *c, const Font &font, int x, int y,
|
||||
const Color &color, const Color *background_color,
|
||||
const char *utf8_text, int kerning_offset = 0);
|
||||
|
||||
// Same without background. Deprecated, use the one above instead.
|
||||
int DrawText(Canvas *c, const Font &font, int x, int y, const Color &color,
|
||||
const char *utf8_text);
|
||||
|
||||
// Draw text, a standard NUL terminated C-string encoded in UTF-8,
|
||||
// with given "font" at "x","y" with "color".
|
||||
// Draw text as above, but vertically (top down).
|
||||
// The text is a standard NUL terminated C-string encoded in UTF-8.
|
||||
// "font, "x", "y", "color" and "background_color" are same as DrawText().
|
||||
// "kerning_offset" allows for additional spacing between characters (can be
|
||||
// negative).
|
||||
// Returns font height to advance up on the screen.
|
||||
int VerticalDrawText(Canvas *c, const Font &font, int x, int y,
|
||||
const Color &color, const Color *background_color,
|
||||
const char *utf8_text, int kerning_offset = 0);
|
||||
|
||||
// Draw a circle centered at "x", "y", with a radius of "radius" and with "color"
|
||||
void DrawCircle(Canvas *c, int x, int y, int radius, const Color &color);
|
||||
|
||||
// Draw a line from "x0", "y0" to "x1", "y1" and with "color"
|
||||
void DrawLine(Canvas *c, int x0, int y0, int x1, int y1, const Color &color);
|
||||
|
||||
} // namespace rgb_matrix
|
||||
|
||||
#endif // RPI_GRAPHICS_H
|
||||
412
depends/rpi-rgb-led-matrix/include/led-matrix-c.h
Normal file
412
depends/rpi-rgb-led-matrix/include/led-matrix-c.h
Normal file
@@ -0,0 +1,412 @@
|
||||
/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
* Copyright (C) 2013 Henner Zeller <h.zeller@acm.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
|
||||
*
|
||||
* Controlling 16x32 or 32x32 RGB matrixes via GPIO. It allows daisy chaining
|
||||
* of a string of these, and also connecting a parallel string on newer
|
||||
* Raspberry Pis with more GPIO pins available.
|
||||
*
|
||||
* This is a C-binding (for the C++ library) to allow easy binding and
|
||||
* integration with other languages. The symbols are exported in librgbmatrix.a
|
||||
* and librgbmatrix.so. You still need to call the final link with
|
||||
*
|
||||
* See examples-api-use/c-example.c for a usage example.
|
||||
*
|
||||
*/
|
||||
#ifndef RPI_RGBMATRIX_C_H
|
||||
#define RPI_RGBMATRIX_C_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct RGBLedMatrix;
|
||||
struct LedCanvas;
|
||||
struct LedFont;
|
||||
|
||||
/**
|
||||
* Parameters to create a new matrix.
|
||||
*
|
||||
* To get the defaults, non-set values have to be initialized to zero, so you
|
||||
* should zero out this struct before setting anything.
|
||||
*/
|
||||
struct RGBLedMatrixOptions {
|
||||
/*
|
||||
* Name of the hardware mapping used. If passed NULL here, the default
|
||||
* is used.
|
||||
*/
|
||||
const char *hardware_mapping;
|
||||
|
||||
/* The "rows" are the number of rows supported by the display, so 32 or 16.
|
||||
* Default: 32.
|
||||
* Corresponding flag: --led-rows
|
||||
*/
|
||||
int rows;
|
||||
|
||||
/* The "cols" are the number of columns per panel. Typically something
|
||||
* like 32, but also 64 is possible. Sometimes even 40.
|
||||
* cols * chain_length is the total length of the display, so you can
|
||||
* represent a 64 wide display as cols=32, chain=2 or cols=64, chain=1;
|
||||
* same thing.
|
||||
* Flag: --led-cols
|
||||
*/
|
||||
int cols;
|
||||
|
||||
/* The chain_length is the number of displays daisy-chained together
|
||||
* (output of one connected to input of next). Default: 1
|
||||
* Corresponding flag: --led-chain
|
||||
*/
|
||||
int chain_length;
|
||||
|
||||
/* The number of parallel chains connected to the Pi; in old Pis with 26
|
||||
* GPIO pins, that is 1, in newer Pis with 40 interfaces pins, that can
|
||||
* also be 2 or 3. The effective number of pixels in vertical direction is
|
||||
* then thus rows * parallel. Default: 1
|
||||
* Corresponding flag: --led-parallel
|
||||
*/
|
||||
int parallel;
|
||||
|
||||
/* Set PWM bits used for output. Default is 11, but if you only deal with
|
||||
* limited comic-colors, 1 might be sufficient. Lower require less CPU and
|
||||
* increases refresh-rate.
|
||||
* Corresponding flag: --led-pwm-bits
|
||||
*/
|
||||
int pwm_bits;
|
||||
|
||||
/* Change the base time-unit for the on-time in the lowest
|
||||
* significant bit in nanoseconds.
|
||||
* Higher numbers provide better quality (more accurate color, less
|
||||
* ghosting), but have a negative impact on the frame rate.
|
||||
* Corresponding flag: --led-pwm-lsb-nanoseconds
|
||||
*/
|
||||
int pwm_lsb_nanoseconds;
|
||||
|
||||
/* The lower bits can be time-dithered for higher refresh rate.
|
||||
* Corresponding flag: --led-pwm-dither-bits
|
||||
*/
|
||||
int pwm_dither_bits;
|
||||
|
||||
/* The initial brightness of the panel in percent. Valid range is 1..100
|
||||
* Corresponding flag: --led-brightness
|
||||
*/
|
||||
int brightness;
|
||||
|
||||
/* Scan mode: 0=progressive, 1=interlaced
|
||||
* Corresponding flag: --led-scan-mode
|
||||
*/
|
||||
int scan_mode;
|
||||
|
||||
/* Default row address type is 0, corresponding to direct setting of the
|
||||
* row, while row address type 1 is used for panels that only have A/B,
|
||||
* typically some 64x64 panels
|
||||
*/
|
||||
int row_address_type; /* Corresponding flag: --led-row-addr-type */
|
||||
|
||||
/* Type of multiplexing. 0 = direct, 1 = stripe, 2 = checker (typical 1:8)
|
||||
*/
|
||||
int multiplexing;
|
||||
|
||||
/** The following boolean flags are off by default **/
|
||||
|
||||
/* Allow to use the hardware subsystem to create pulses. This won't do
|
||||
* anything if output enable is not connected to GPIO 18.
|
||||
* Corresponding flag: --led-hardware-pulse
|
||||
*/
|
||||
bool disable_hardware_pulsing; /* Flag: --led-hardware-pulse */
|
||||
bool show_refresh_rate; /* Flag: --led-show-refresh */
|
||||
bool inverse_colors; /* Flag: --led-inverse */
|
||||
|
||||
/* In case the internal sequence of mapping is not "RGB", this contains the
|
||||
* real mapping. Some panels mix up these colors.
|
||||
*/
|
||||
const char *led_rgb_sequence; /* Corresponding flag: --led-rgb-sequence */
|
||||
|
||||
/* A string describing a sequence of pixel mappers that should be applied
|
||||
* to this matrix. A semicolon-separated list of pixel-mappers with optional
|
||||
* parameter.
|
||||
*/
|
||||
const char *pixel_mapper_config; /* Corresponding flag: --led-pixel-mapper */
|
||||
|
||||
/*
|
||||
* Panel type. Typically just NULL, but certain panels (FM6126) require
|
||||
* an initialization sequence
|
||||
*/
|
||||
const char *panel_type; /* Corresponding flag: --led-panel-type */
|
||||
|
||||
/* Limit refresh rate of LED panel. This will help on a loaded system
|
||||
* to keep a constant refresh rate. <= 0 for no limit.
|
||||
*/
|
||||
int limit_refresh_rate_hz; /* Corresponding flag: --led-limit-refresh */
|
||||
};
|
||||
|
||||
/**
|
||||
* Runtime options to simplify doing common things for many programs such as
|
||||
* dropping privileges and becoming a daemon.
|
||||
*/
|
||||
struct RGBLedRuntimeOptions {
|
||||
int gpio_slowdown; // 0 = no slowdown. Flag: --led-slowdown-gpio
|
||||
|
||||
// ----------
|
||||
// If the following options are set to disabled with -1, they are not
|
||||
// even offered via the command line flags.
|
||||
// ----------
|
||||
|
||||
// Thre are three possible values here
|
||||
// -1 : don't leave choise of becoming daemon to the command line parsing.
|
||||
// If set to -1, the --led-daemon option is not offered.
|
||||
// 0 : do not becoma a daemon, run in forgreound (default value)
|
||||
// 1 : become a daemon, run in background.
|
||||
//
|
||||
// If daemon is disabled (= -1), the user has to call
|
||||
// RGBMatrix::StartRefresh() manually once the matrix is created, to leave
|
||||
// the decision to become a daemon
|
||||
// after the call (which requires that no threads have been started yet).
|
||||
// In the other cases (off or on), the choice is already made, so the thread
|
||||
// is conveniently already started for you.
|
||||
int daemon; // -1 disabled. 0=off, 1=on. Flag: --led-daemon
|
||||
|
||||
// Drop privileges from 'root' to 'daemon' once the hardware is initialized.
|
||||
// This is usually a good idea unless you need to stay on elevated privs.
|
||||
int drop_privileges; // -1 disabled. 0=off, 1=on. flag: --led-drop-privs
|
||||
|
||||
// By default, the gpio is initialized for you, but if you run on a platform
|
||||
// not the Raspberry Pi, this will fail. If you don't need to access GPIO
|
||||
// e.g. you want to just create a stream output (see content-streamer.h),
|
||||
// set this to false.
|
||||
bool do_gpio_init;
|
||||
|
||||
// If drop privileges is enabled, this is the user/group we drop privileges
|
||||
// to. Unless chosen otherwise, the default is "daemon" for user and group.
|
||||
const char *drop_priv_user;
|
||||
const char *drop_priv_group;
|
||||
};
|
||||
|
||||
/**
|
||||
* 24-bit RGB color.
|
||||
*/
|
||||
struct Color {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
|
||||
/**
|
||||
* Universal way to create and initialize a matrix.
|
||||
* The "options" struct (if not NULL) contains all default configuration values
|
||||
* chosen by the programmer to create the matrix.
|
||||
*
|
||||
* If "argc" and "argv" are provided, this function also reads command line
|
||||
* flags provided, that then can override any of the defaults given.
|
||||
* The arguments that have been used from the command line are removed from
|
||||
* the argv list (and argc is adjusted) - that way these don't mess with your
|
||||
* own command line handling.
|
||||
*
|
||||
* The actual options used are filled back into the "options" struct if not
|
||||
* NULL.
|
||||
*
|
||||
* Usage:
|
||||
* ----------------
|
||||
* int main(int argc, char **argv) {
|
||||
* struct RGBLedMatrixOptions options;
|
||||
* memset(&options, 0, sizeof(options));
|
||||
* options.rows = 32; // You can set defaults if you want.
|
||||
* options.chain_length = 1;
|
||||
* struct RGBLedMatrix *matrix = led_matrix_create_from_options(&options,
|
||||
* &argc, &argv);
|
||||
* if (matrix == NULL) {
|
||||
* led_matrix_print_flags(stderr);
|
||||
* return 1;
|
||||
* }
|
||||
* // do additional commandline handling; then use matrix...
|
||||
* }
|
||||
* ----------------
|
||||
*/
|
||||
struct RGBLedMatrix *led_matrix_create_from_options(
|
||||
struct RGBLedMatrixOptions *options, int *argc, char ***argv);
|
||||
|
||||
/* Same, but does not modify the argv array. */
|
||||
struct RGBLedMatrix *led_matrix_create_from_options_const_argv(
|
||||
struct RGBLedMatrixOptions *options, int argc, char **argv);
|
||||
|
||||
/**
|
||||
* The way to completely initialize your matrix without using command line
|
||||
* flags to initialize some things.
|
||||
*
|
||||
* The actual options used are filled back into the "options" and "rt_options"
|
||||
* struct if not NULL. If they are null, the default value is used.
|
||||
*
|
||||
* Usage:
|
||||
* ----------------
|
||||
* int main(int argc, char **argv) {
|
||||
* struct RGBLedMatrixOptions options;
|
||||
* struct RGBLedRuntimeOptions rt_options;
|
||||
* memset(&options, 0, sizeof(options));
|
||||
* memset(&rt_options, 0, sizeof(rt_options));
|
||||
* options.rows = 32; // You can set defaults if you want.
|
||||
* options.chain_length = 1;
|
||||
* rt_options.gpio_slowdown = 4;
|
||||
* struct RGBLedMatrix *matrix = led_matrix_create_from_options_and_rt_options(&options, &rt_options);
|
||||
* if (matrix == NULL) {
|
||||
* return 1;
|
||||
* }
|
||||
* // do additional commandline handling; then use matrix...
|
||||
* }
|
||||
* ----------------
|
||||
*/
|
||||
struct RGBLedMatrix *led_matrix_create_from_options_and_rt_options(
|
||||
struct RGBLedMatrixOptions *opts, struct RGBLedRuntimeOptions * rt_opts);
|
||||
|
||||
/**
|
||||
* Print available LED matrix options.
|
||||
*/
|
||||
void led_matrix_print_flags(FILE *out);
|
||||
|
||||
/**
|
||||
* Simple form of led_matrix_create_from_options() with just the few
|
||||
* main options. Returns NULL if that was not possible.
|
||||
* The "rows" are the number of rows supported by the display, so 32, 16 or 8.
|
||||
*
|
||||
* Number of "chained_display"s tells many of these are daisy-chained together
|
||||
* (output of one connected to input of next).
|
||||
*
|
||||
* The "parallel_display" number determines if there is one or two displays
|
||||
* connected in parallel to the GPIO port - this only works with newer
|
||||
* Raspberry Pi that have 40 interface pins.
|
||||
*
|
||||
* This creates a realtime thread and requires root access to access the GPIO
|
||||
* pins.
|
||||
* So if you run this in a daemon, this should be called after becoming a
|
||||
* daemon (as fork/exec stops threads) and before dropping privileges.
|
||||
*/
|
||||
struct RGBLedMatrix *led_matrix_create(int rows, int chained, int parallel);
|
||||
|
||||
|
||||
/**
|
||||
* Stop matrix and free memory.
|
||||
* Always call before the end of the program to properly reset the hardware
|
||||
*/
|
||||
void led_matrix_delete(struct RGBLedMatrix *matrix);
|
||||
|
||||
|
||||
/**
|
||||
* Get active canvas from LED matrix for you to draw on.
|
||||
* Ownership of returned pointer stays with the matrix, don't free().
|
||||
*/
|
||||
struct LedCanvas *led_matrix_get_canvas(struct RGBLedMatrix *matrix);
|
||||
|
||||
/** Return size of canvas. */
|
||||
void led_canvas_get_size(const struct LedCanvas *canvas,
|
||||
int *width, int *height);
|
||||
|
||||
/** Set pixel at (x, y) with color (r,g,b). */
|
||||
void led_canvas_set_pixel(struct LedCanvas *canvas, int x, int y,
|
||||
uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
/** Copies pixels to rectangle at (x, y) with size (width, height). */
|
||||
void led_canvas_set_pixels(struct LedCanvas *canvas, int x, int y,
|
||||
int width, int height, struct Color *colors);
|
||||
|
||||
/** Clear screen (black). */
|
||||
void led_canvas_clear(struct LedCanvas *canvas);
|
||||
|
||||
/** Fill matrix with given color. */
|
||||
void led_canvas_fill(struct LedCanvas *canvas, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
/*** API to provide double-buffering. ***/
|
||||
|
||||
/**
|
||||
* Create a new canvas to be used with led_matrix_swap_on_vsync()
|
||||
* Ownership of returned pointer stays with the matrix, don't free().
|
||||
*/
|
||||
struct LedCanvas *led_matrix_create_offscreen_canvas(struct RGBLedMatrix *matrix);
|
||||
|
||||
/**
|
||||
* Swap the given canvas (created with create_offscreen_canvas) with the
|
||||
* currently active canvas on vsync (blocks until vsync is reached).
|
||||
* Returns the previously active canvas. So with that, you can create double
|
||||
* buffering:
|
||||
*
|
||||
* struct LedCanvas *offscreen = led_matrix_create_offscreen_canvas(...);
|
||||
* led_canvas_set_pixel(offscreen, ...); // not shown until swap-on-vsync
|
||||
* offscreen = led_matrix_swap_on_vsync(matrix, offscreen);
|
||||
* // The returned buffer, assigned to offscreen, is now the inactive buffer
|
||||
* // fill, then swap again.
|
||||
*/
|
||||
struct LedCanvas *led_matrix_swap_on_vsync(struct RGBLedMatrix *matrix,
|
||||
struct LedCanvas *canvas);
|
||||
|
||||
uint8_t led_matrix_get_brightness(struct RGBLedMatrix *matrix);
|
||||
void led_matrix_set_brightness(struct RGBLedMatrix *matrix, uint8_t brightness);
|
||||
|
||||
// Utility function: set an image from the given buffer containting pixels.
|
||||
//
|
||||
// Draw image of size "image_width" and "image_height" from pixel at
|
||||
// canvas-offset "canvas_offset_x", "canvas_offset_y". Image will be shown
|
||||
// cropped on the edges if needed.
|
||||
//
|
||||
// The canvas offset can be negative, i.e. the image start can be shifted
|
||||
// outside the image frame on the left/top edge.
|
||||
//
|
||||
// The buffer needs to be organized as rows with columns of three bytes
|
||||
// organized as rgb or bgr. Thus the size of the buffer needs to be exactly
|
||||
// (3 * image_width * image_height) bytes.
|
||||
//
|
||||
// The "image_buffer" parameters contains the data, "buffer_size_bytes" the
|
||||
// size in bytes.
|
||||
//
|
||||
// If "is_bgr" is 1, the buffer is treated as BGR pixel arrangement instead
|
||||
// of RGB with is_bgr = 0.
|
||||
void set_image(struct LedCanvas *c, int canvas_offset_x, int canvas_offset_y,
|
||||
const uint8_t *image_buffer, size_t buffer_size_bytes,
|
||||
int image_width, int image_height,
|
||||
char is_bgr);
|
||||
|
||||
// Load a font given a path to a font file containing a bdf font.
|
||||
struct LedFont *load_font(const char *bdf_font_file);
|
||||
|
||||
// Read the baseline of a font
|
||||
int baseline_font(struct LedFont *font);
|
||||
|
||||
// Read the height of a font
|
||||
int height_font(struct LedFont *font);
|
||||
|
||||
// Creates an outline font based on an existing font instance
|
||||
struct LedFont *create_outline_font(struct LedFont *font);
|
||||
|
||||
// Delete a font originally created from load_font.
|
||||
void delete_font(struct LedFont *font);
|
||||
|
||||
int draw_text(struct LedCanvas *c, struct LedFont *font, int x, int y,
|
||||
uint8_t r, uint8_t g, uint8_t b,
|
||||
const char *utf8_text, int kerning_offset);
|
||||
|
||||
int vertical_draw_text(struct LedCanvas *c, struct LedFont *font, int x, int y,
|
||||
uint8_t r, uint8_t g, uint8_t b,
|
||||
const char *utf8_text, int kerning_offset);
|
||||
|
||||
void draw_circle(struct LedCanvas *c, int x, int y, int radius,
|
||||
uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
void draw_line(struct LedCanvas *c, int x0, int y0, int x1, int y1,
|
||||
uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern C
|
||||
#endif
|
||||
|
||||
#endif
|
||||
514
depends/rpi-rgb-led-matrix/include/led-matrix.h
Normal file
514
depends/rpi-rgb-led-matrix/include/led-matrix.h
Normal file
@@ -0,0 +1,514 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Copyright (C) 2013 Henner Zeller <h.zeller@acm.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
|
||||
|
||||
// Controlling 16x32 or 32x32 RGB matrixes via GPIO. It allows daisy chaining
|
||||
// of a string of these, and also connecting a parallel string on newer
|
||||
// Raspberry Pis with more GPIO pins available.
|
||||
|
||||
#ifndef RPI_RGBMATRIX_H
|
||||
#define RPI_RGBMATRIX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "canvas.h"
|
||||
#include "thread.h"
|
||||
#include "pixel-mapper.h"
|
||||
#include "graphics.h"
|
||||
|
||||
namespace rgb_matrix {
|
||||
class RGBMatrix;
|
||||
class FrameCanvas; // Canvas for Double- and Multibuffering
|
||||
struct RuntimeOptions;
|
||||
|
||||
// The RGB matrix provides the framebuffer and the facilities to constantly
|
||||
// update the LED matrix.
|
||||
//
|
||||
// This implement the Canvas interface that represents the display with
|
||||
// (led_cols * chained_displays)x(rows * parallel_displays) pixels.
|
||||
//
|
||||
// If can do multi-buffering using the CreateFrameCanvas() and SwapOnVSync()
|
||||
// methods. This is useful for animations and to prevent tearing.
|
||||
//
|
||||
// If you arrange the panels in a different way in the physical space, write
|
||||
// a CanvasTransformer that does coordinate remapping and which should be added
|
||||
// to the transformers, like with UArrangementTransformer in demo-main.cc.
|
||||
class RGBMatrix : public Canvas {
|
||||
public:
|
||||
// Options to initialize the RGBMatrix. Also see the main README.md for
|
||||
// detailed descriptions of the command line flags.
|
||||
struct Options {
|
||||
Options(); // Creates a default option set.
|
||||
|
||||
// Validate the options and possibly output a message to string. If
|
||||
// "err" is NULL, outputs validation problems to stderr.
|
||||
// Returns 'true' if all options look good.
|
||||
bool Validate(std::string *err) const;
|
||||
|
||||
// Name of the hardware mapping. Something like "regular" or "adafruit-hat"
|
||||
const char *hardware_mapping;
|
||||
|
||||
// The "rows" are the number
|
||||
// of rows supported by the display, so 32 or 16. Default: 32.
|
||||
// Flag: --led-rows
|
||||
int rows;
|
||||
|
||||
// The "cols" are the number of columns per panel. Typically something
|
||||
// like 32, but also 64 is possible. Sometimes even 40.
|
||||
// cols * chain_length is the total length of the display, so you can
|
||||
// represent a 64 wide display as cols=32, chain=2 or cols=64, chain=1;
|
||||
// same thing, but more convenient to think of.
|
||||
// Flag: --led-cols
|
||||
int cols;
|
||||
|
||||
// The chain_length is the number of displays daisy-chained together
|
||||
// (output of one connected to input of next). Default: 1
|
||||
// Flag: --led-chain
|
||||
int chain_length;
|
||||
|
||||
// The number of parallel chains connected to the Pi; in old Pis with 26
|
||||
// GPIO pins, that is 1, in newer Pis with 40 interfaces pins, that can
|
||||
// also be 2 or 3. The effective number of pixels in vertical direction is
|
||||
// then thus rows * parallel. Default: 1
|
||||
// Flag: --led-parallel
|
||||
int parallel;
|
||||
|
||||
// Set PWM bits used for output. Default is 11, but if you only deal with
|
||||
// limited comic-colors, 1 might be sufficient. Lower require less CPU and
|
||||
// increases refresh-rate.
|
||||
// Flag: --led-pwm-bits
|
||||
int pwm_bits;
|
||||
|
||||
// Change the base time-unit for the on-time in the lowest
|
||||
// significant bit in nanoseconds.
|
||||
// Higher numbers provide better quality (more accurate color, less
|
||||
// ghosting), but have a negative impact on the frame rate.
|
||||
// Flag: --led-pwm-lsb-nanoseconds
|
||||
int pwm_lsb_nanoseconds;
|
||||
|
||||
// The lower bits can be time-dithered for higher refresh rate.
|
||||
// Flag: --led-pwm-dither-bits
|
||||
int pwm_dither_bits;
|
||||
|
||||
// The initial brightness of the panel in percent. Valid range is 1..100
|
||||
// Default: 100
|
||||
// Flag: --led-brightness
|
||||
int brightness;
|
||||
|
||||
// Scan mode: 0=progressive, 1=interlaced.
|
||||
// Flag: --led-scan-mode
|
||||
int scan_mode;
|
||||
|
||||
// Default row address type is 0, corresponding to direct setting of the
|
||||
// row, while row address type 1 is used for panels that only have A/B,
|
||||
// typically some 64x64 panels
|
||||
int row_address_type; // Flag --led-row-addr-type
|
||||
|
||||
// Type of multiplexing. 0 = direct, 1 = stripe, 2 = checker,...
|
||||
// Flag: --led-multiplexing
|
||||
int multiplexing;
|
||||
|
||||
// Disable the PWM hardware subsystem to create pulses.
|
||||
// Typically, you don't want to disable hardware pulsing, this is mostly
|
||||
// for debugging and figuring out if there is interference with the
|
||||
// sound system.
|
||||
// This won't do anything if output enable is not connected to GPIO 18 in
|
||||
// non-standard wirings.
|
||||
bool disable_hardware_pulsing; // Flag: --led-hardware-pulse
|
||||
|
||||
// Show refresh rate on the terminal for debugging and tweaking purposes.
|
||||
bool show_refresh_rate; // Flag: --led-show-refresh
|
||||
|
||||
// Some panels have inversed colors.
|
||||
bool inverse_colors; // Flag: --led-inverse
|
||||
|
||||
// In case the internal sequence of mapping is not "RGB", this contains the
|
||||
// real mapping. Some panels mix up these colors. String of length three
|
||||
// which has to contain all characters R, G and B.
|
||||
const char *led_rgb_sequence; // Flag: --led-rgb-sequence
|
||||
|
||||
// A string describing a sequence of pixel mappers that should be applied
|
||||
// to this matrix. A semicolon-separated list of pixel-mappers with optional
|
||||
// parameter.
|
||||
const char *pixel_mapper_config; // Flag: --led-pixel-mapper
|
||||
|
||||
// Panel type. Typically an empty string or NULL, but some panels need
|
||||
// a particular initialization sequence, so this is used for that.
|
||||
// This can be e.g. "FM6126A" for that particular panel type.
|
||||
const char *panel_type; // Flag: --led-panel-type
|
||||
|
||||
// Limit refresh rate of LED panel. This will help on a loaded system
|
||||
// to keep a constant refresh rate. <= 0 for no limit.
|
||||
int limit_refresh_rate_hz; // Flag: --led-limit-refresh
|
||||
};
|
||||
|
||||
// Factory to create a matrix. Additional functionality includes dropping
|
||||
// privileges and becoming a daemon.
|
||||
// Returns NULL, if there was a problem (a message then is written to stderr).
|
||||
static RGBMatrix *CreateFromOptions(const Options &options,
|
||||
const RuntimeOptions &runtime_options);
|
||||
|
||||
// A factory that parses your main() commandline flags to read options
|
||||
// meant to configure the the matrix and returns a freshly allocated matrix.
|
||||
//
|
||||
// Optionally, you can pass in option structs with a couple of defaults
|
||||
// which are used unless overwritten on the command line.
|
||||
// A matrix is created and returned; also the options structs are
|
||||
// updated to reflect the values that were used and set on the command line.
|
||||
//
|
||||
// If you allow the user to start a daemon with --led-daemon, make sure to
|
||||
// call this function before you have started any threads, so early on in
|
||||
// main() (see RuntimeOptions documentation).
|
||||
//
|
||||
// Note, the permissions are dropped by default from 'root' to 'daemon', so
|
||||
// if you are required to stay root after this, disable this option in
|
||||
// the default RuntimeOptions (set drop_privileges = -1).
|
||||
// Returns NULL, if there was a problem (a message then is written to stderr).
|
||||
static RGBMatrix *CreateFromFlags(int *argc, char ***argv,
|
||||
RGBMatrix::Options *default_options = NULL,
|
||||
RuntimeOptions *default_runtime_opts = NULL,
|
||||
bool remove_consumed_flags = true);
|
||||
|
||||
// Stop matrix, delete all resources.
|
||||
virtual ~RGBMatrix();
|
||||
|
||||
// -- Canvas interface. These write to the active FrameCanvas
|
||||
// (see documentation in canvas.h)
|
||||
//
|
||||
// Since this is updating the canvas that is currently displayed, this
|
||||
// might result in tearing.
|
||||
// Prefer using a FrameCanvas and do double-buffering, see section below.
|
||||
virtual int width() const;
|
||||
virtual int height() const;
|
||||
virtual void SetPixel(int x, int y,
|
||||
uint8_t red, uint8_t green, uint8_t blue);
|
||||
virtual void Clear();
|
||||
virtual void Fill(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
// -- Double- and Multibuffering.
|
||||
|
||||
// Create a new buffer to be used for multi-buffering. The returned new
|
||||
// Buffer implements a Canvas with the same size of thie RGBMatrix.
|
||||
// You can use it to draw off-screen on it, then swap it with the active
|
||||
// buffer using SwapOnVSync(). That would be classic double-buffering.
|
||||
//
|
||||
// You can also create as many FrameCanvas as you like and for instance use
|
||||
// them to pre-fill scenes of an animation for fast playback later.
|
||||
//
|
||||
// The ownership of the created Canvases remains with the RGBMatrix, so you
|
||||
// don't have to worry about deleting them (but you also don't want to create
|
||||
// more than needed as this will fill up your memory as they are only deleted
|
||||
// when the RGBMatrix is deleted).
|
||||
FrameCanvas *CreateFrameCanvas();
|
||||
|
||||
// This method waits to the next VSync and swaps the active buffer with the
|
||||
// supplied buffer. The formerly active buffer is returned.
|
||||
//
|
||||
// If you pass in NULL, the active buffer is returned, but it won't be
|
||||
// replaced with NULL. You can use the NULL-behavior to just wait on
|
||||
// VSync or to retrieve the initial buffer when preparing a multi-buffer
|
||||
// animation.
|
||||
//
|
||||
// The optional "framerate_fraction" parameter allows to choose which
|
||||
// multiple of the global frame-count to use. So it slows down your animation
|
||||
// to an exact integer fraction of the refresh rate.
|
||||
// Default is 1, so immediately next available frame.
|
||||
// (Say you have 140Hz refresh rate, then a value of 5 would give you an
|
||||
// 28Hz animation, nicely locked to the refresh-rate).
|
||||
// If you combine this with Options::limit_refresh_rate_hz you can create
|
||||
// time-correct animations.
|
||||
FrameCanvas *SwapOnVSync(FrameCanvas *other, unsigned framerate_fraction = 1);
|
||||
|
||||
// -- Setting shape and behavior of matrix.
|
||||
|
||||
// Apply a pixel mapper. This is used to re-map pixels according to some
|
||||
// scheme implemented by the PixelMapper. Does _not_ take ownership of the
|
||||
// mapper. Mapper can be NULL, in which case nothing happens.
|
||||
// Returns a boolean indicating if this was successful.
|
||||
bool ApplyPixelMapper(const PixelMapper *mapper);
|
||||
|
||||
// Note, there used to be ApplyStaticTransformer(), which has been deprecated
|
||||
// since 2018 and changed to a compile-time option, then finally removed
|
||||
// in 2020. Use PixelMapper instead, which is simpler and more intuitive.
|
||||
|
||||
// Set PWM bits used for output. Default is 11, but if you only deal with
|
||||
// limited comic-colors, 1 might be sufficient. Lower require less CPU and
|
||||
// increases refresh-rate.
|
||||
//
|
||||
// Returns boolean to signify if value was within range.
|
||||
//
|
||||
// This sets the PWM bits for the current active FrameCanvas and future
|
||||
// ones that are created with CreateFrameCanvas().
|
||||
bool SetPWMBits(uint8_t value);
|
||||
uint8_t pwmbits(); // return the pwm-bits of the currently active buffer.
|
||||
|
||||
// Map brightness of output linearly to input with CIE1931 profile.
|
||||
void set_luminance_correct(bool on);
|
||||
bool luminance_correct() const;
|
||||
|
||||
// Set brightness in percent for all created FrameCanvas. 1%..100%.
|
||||
// This will only affect newly set pixels.
|
||||
void SetBrightness(uint8_t brightness);
|
||||
uint8_t brightness();
|
||||
|
||||
//-- GPIO interaction.
|
||||
// This library uses the GPIO pins to drive the matrix; this is a safe way
|
||||
// to request the 'remaining' bits to be used for user purposes.
|
||||
|
||||
// Request user readable GPIO bits.
|
||||
// This function allows you to request pins you'd like to read with
|
||||
// AwaitInputChange().
|
||||
// Only bits that are not already in use for reading or wrtiting
|
||||
// by the matrix are allowed.
|
||||
// Input is a bitmap of all the GPIO bits you're interested in; returns all
|
||||
// the bits that are actually available.
|
||||
uint64_t RequestInputs(uint64_t all_interested_bits);
|
||||
|
||||
// This function will return whenever the GPIO input pins
|
||||
// change (pins that are not already in use for output, that is) or the
|
||||
// timeout is reached. You need to have reserved the inputs with
|
||||
// matrix->RequestInputs(...) first (e.g.
|
||||
// matrix->RequestInputs((1<<25)|(1<<24));
|
||||
//
|
||||
// A positive timeout waits the given amount of milliseconds for a change
|
||||
// (e.g. a button-press) to occur; if there is no change, it will just
|
||||
// return the last value.
|
||||
// If you just want to know how the pins are right now, call with zero
|
||||
// timeout.
|
||||
// A negative number waits forever and will only return if there is a change.
|
||||
//
|
||||
// This function only samples between display refreshes so polling some
|
||||
// input does not generate flicker and provide a convenient change interface.
|
||||
//
|
||||
// Returns the bitmap of all GPIO input pins.
|
||||
uint64_t AwaitInputChange(int timeout_ms);
|
||||
|
||||
// Request user writable GPIO bits.
|
||||
// This allows to request a bitmap of GPIO-bits to be used by the user for
|
||||
// writing.
|
||||
// Only bits that are not already in use for reading or wrtiting
|
||||
// by the matrix are allowed.
|
||||
// Returns the subset bits that are _actually_ available,
|
||||
uint64_t RequestOutputs(uint64_t output_bits);
|
||||
|
||||
// Set the user-settable bits according to output bits.
|
||||
void OutputGPIO(uint64_t output_bits);
|
||||
|
||||
// Legacy way to set gpio pins. We're not doing this anymore but need to
|
||||
// be source-compatible with old calls of the form
|
||||
// matrix->gpio()->RequestInputs(...)
|
||||
//
|
||||
// Don't use, use AwaitInputChange() directly.
|
||||
RGBMatrix *gpio() __attribute__((deprecated)) { return this; }
|
||||
|
||||
//-- Rarely needed
|
||||
// Start the refresh thread.
|
||||
// This is only needed if you chose RuntimeOptions::daemon = -1 (see below),
|
||||
// otherwise the refresh thread is already started.
|
||||
bool StartRefresh();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
RGBMatrix(Impl *impl) : impl_(impl) {}
|
||||
Impl *const impl_;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
class Framebuffer;
|
||||
}
|
||||
|
||||
class FrameCanvas : public Canvas {
|
||||
public:
|
||||
// Set PWM bits used for this Frame.
|
||||
// Simple comic-colors, 1 might be sufficient (111 RGB, i.e. 8 colors).
|
||||
// Lower require less CPU.
|
||||
// Returns boolean to signify if value was within range.
|
||||
bool SetPWMBits(uint8_t value);
|
||||
uint8_t pwmbits();
|
||||
|
||||
// Map brightness of output linearly to input with CIE1931 profile.
|
||||
void set_luminance_correct(bool on);
|
||||
bool luminance_correct() const;
|
||||
|
||||
void SetBrightness(uint8_t brightness);
|
||||
uint8_t brightness();
|
||||
|
||||
//-- Serialize()/Deserialize() are fast ways to store and re-create a canvas.
|
||||
|
||||
// Provides a pointer to a buffer of the internal representation to
|
||||
// be copied out for later Deserialize().
|
||||
//
|
||||
// Returns a "data" pointer and the data "len" in the given out-paramters;
|
||||
// the content can be copied from there by the caller.
|
||||
//
|
||||
// Note, the content is not simply RGB, it is the opaque and platform
|
||||
// specific representation which allows to make deserialization very fast.
|
||||
// It is also bigger than just RGB; if you want to store it somewhere,
|
||||
// using compression is a good idea.
|
||||
void Serialize(const char **data, size_t *len) const;
|
||||
|
||||
// Load data previously stored with Serialize(). Needs to be restored into
|
||||
// a FrameCanvas with exactly the same settings (rows, chain, transformer,...)
|
||||
// as serialized.
|
||||
// Returns 'false' if size is unexpected.
|
||||
// This method should only be called if FrameCanvas is off-screen.
|
||||
bool Deserialize(const char *data, size_t len);
|
||||
|
||||
// Copy content from other FrameCanvas owned by the same RGBMatrix.
|
||||
void CopyFrom(const FrameCanvas &other);
|
||||
|
||||
// -- Canvas interface.
|
||||
virtual int width() const;
|
||||
virtual int height() const;
|
||||
virtual void SetPixel(int x, int y,
|
||||
uint8_t red, uint8_t green, uint8_t blue);
|
||||
virtual void SetPixels(int x, int y, int width, int height,
|
||||
Color *colors);
|
||||
virtual void Clear();
|
||||
virtual void Fill(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
private:
|
||||
friend class RGBMatrix;
|
||||
|
||||
FrameCanvas(internal::Framebuffer *frame) : frame_(frame){}
|
||||
virtual ~FrameCanvas(); // Any FrameCanvas is owned by RGBMatrix.
|
||||
internal::Framebuffer *framebuffer() { return frame_; }
|
||||
|
||||
internal::Framebuffer *const frame_;
|
||||
};
|
||||
|
||||
// Runtime options to simplify doing common things for many programs such as
|
||||
// dropping privileges and becoming a daemon.
|
||||
struct RuntimeOptions {
|
||||
RuntimeOptions();
|
||||
|
||||
int gpio_slowdown; // 0 = no slowdown. Flag: --led-slowdown-gpio
|
||||
|
||||
// ----------
|
||||
// If the following options are set to disabled with -1, they are not
|
||||
// even offered via the command line flags.
|
||||
// ----------
|
||||
|
||||
// Thre are three possible values here
|
||||
// -1 : don't leave choise of becoming daemon to the command line
|
||||
// parsing. If set to -1, the --led-daemon option is not offered.
|
||||
// 0 : do not becoma a daemon, run in forgreound (default value)
|
||||
// 1 : become a daemon, run in background.
|
||||
//
|
||||
// If daemon is disabled (= -1), the user has to call
|
||||
// RGBMatrix::StartRefresh() manually once the matrix is created, to leave
|
||||
// the decision to become a daemon
|
||||
// after the call (which requires that no threads have been started yet).
|
||||
// In the other cases (off or on), the choice is already made, so the
|
||||
// thread is conveniently already started for you.
|
||||
int daemon; // -1 disabled. 0=off, 1=on. Flag: --led-daemon
|
||||
|
||||
// Drop privileges from 'root' to drop_priv_user/group once the hardware is
|
||||
// initialized.
|
||||
// This is usually a good idea unless you need to stay on elevated privs.
|
||||
// -1, 0, 1 similar meaning to 'daemon' above.
|
||||
int drop_privileges; // -1 disabled. 0=off, 1=on. flag: --led-drop-privs
|
||||
|
||||
// By default, the gpio is initialized for you, but if you run on a platform
|
||||
// not the Raspberry Pi, this will fail. If you don't need to access GPIO
|
||||
// e.g. you want to just create a stream output (see content-streamer.h),
|
||||
// set this to false.
|
||||
bool do_gpio_init;
|
||||
|
||||
// If drop privileges is enabled, this is the user/group we drop privileges
|
||||
// to. Unless chosen otherwise, the default is "daemon" for user and group.
|
||||
const char *drop_priv_user;
|
||||
const char *drop_priv_group;
|
||||
};
|
||||
|
||||
// Convenience utility functions to read standard rgb-matrix flags and create
|
||||
// a RGBMatrix. Commandline flags are something like --led-rows, --led-chain,
|
||||
// --led-parallel. See output of PrintMatrixFlags() for all available options
|
||||
// and detailed description in
|
||||
// https://github.com/hzeller/rpi-rgb-led-matrix#changing-parameters-via-command-line-flags
|
||||
//
|
||||
// Example use:
|
||||
/*
|
||||
using rgb_matrix::RGBMatrix;
|
||||
int main(int argc, char **argv) {
|
||||
RGBMatrix::Options led_options;
|
||||
rgb_matrix::RuntimeOptions runtime;
|
||||
|
||||
// Set defaults
|
||||
led_options.chain_length = 3;
|
||||
led_options.show_refresh_rate = true;
|
||||
runtime.drop_privileges = 1;
|
||||
if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv, &led_options, &runtime)) {
|
||||
rgb_matrix::PrintMatrixFlags(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Do your own command line handling with the remaining flags.
|
||||
while (getopt()) {...}
|
||||
|
||||
// Looks like we're ready to start
|
||||
RGBMatrix *matrix = RGBMatrix::CreateFromOptions(led_options, runtime);
|
||||
if (matrix == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// .. now use matrix
|
||||
|
||||
delete matrix; // Make sure to delete it in the end to switch off LEDs.
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
// This parses the flags from argv and updates the structs with the parsed-out
|
||||
// values. Structs can be NULL if you are not interested in it.
|
||||
//
|
||||
// The recongized flags are removed from argv if "remove_consumed_flags" is
|
||||
// true; this simplifies your command line processing for the remaining options.
|
||||
//
|
||||
// Returns 'true' on success, 'false' if there was flag parsing problem.
|
||||
bool ParseOptionsFromFlags(int *argc, char ***argv,
|
||||
RGBMatrix::Options *default_options,
|
||||
RuntimeOptions *rt_options,
|
||||
bool remove_consumed_flags = true);
|
||||
|
||||
// Show all the available options in a style that can be used in a --help
|
||||
// output on the command line.
|
||||
void PrintMatrixFlags(FILE *out,
|
||||
const RGBMatrix::Options &defaults = RGBMatrix::Options(),
|
||||
const RuntimeOptions &rt_opt = RuntimeOptions());
|
||||
|
||||
// Legacy version of RGBMatrix::CreateFromOptions()
|
||||
inline RGBMatrix *CreateMatrixFromOptions(
|
||||
const RGBMatrix::Options &options,
|
||||
const RuntimeOptions &runtime_options) {
|
||||
return RGBMatrix::CreateFromOptions(options, runtime_options);
|
||||
}
|
||||
|
||||
// Legacy version of RGBMatrix::CreateFromFlags()
|
||||
inline RGBMatrix *CreateMatrixFromFlags(
|
||||
int *argc, char ***argv,
|
||||
RGBMatrix::Options *default_options = NULL,
|
||||
RuntimeOptions *default_runtime_opts = NULL,
|
||||
bool remove_consumed_flags = true) {
|
||||
return RGBMatrix::CreateFromFlags(argc, argv,
|
||||
default_options, default_runtime_opts,
|
||||
remove_consumed_flags);
|
||||
}
|
||||
|
||||
} // end namespace rgb_matrix
|
||||
#endif // RPI_RGBMATRIX_H
|
||||
110
depends/rpi-rgb-led-matrix/include/pixel-mapper.h
Normal file
110
depends/rpi-rgb-led-matrix/include/pixel-mapper.h
Normal file
@@ -0,0 +1,110 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Copyright (C) 2018 Henner Zeller <h.zeller@acm.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
|
||||
#ifndef RGBMATRIX_PIXEL_MAPPER
|
||||
#define RGBMATRIX_PIXEL_MAPPER
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace rgb_matrix {
|
||||
|
||||
// A pixel mapper is a way for you to map pixels of LED matrixes to a different
|
||||
// layout. If you have an implementation of a PixelMapper, you can give it
|
||||
// to the RGBMatrix::ApplyPixelMapper(), which then presents you a canvas
|
||||
// that has the new "visible_width", "visible_height".
|
||||
class PixelMapper {
|
||||
public:
|
||||
virtual ~PixelMapper() {}
|
||||
|
||||
// Get the name of this PixelMapper. Each PixelMapper needs to have a name
|
||||
// so that it can be referred to with command line flags.
|
||||
virtual const char *GetName() const = 0;
|
||||
|
||||
// Pixel mappers receive the chain and parallel information and
|
||||
// might receive optional user-parameters, e.g. from command line flags.
|
||||
//
|
||||
// This is a single string containing the parameters.
|
||||
// You can be used from simple scalar parameters, such as the angle for
|
||||
// the rotate transformer, or more complex parameters that describe a mapping
|
||||
// of panels for instance.
|
||||
// Keep it concise (as people will give parameters on the command line) and
|
||||
// don't use semicolons in your string (as they are
|
||||
// used to separate pixel mappers on the command line).
|
||||
//
|
||||
// For instance, the rotate transformer is invoked like this
|
||||
// --led-pixel-mapper=rotate:90
|
||||
// And the parameter that is passed to SetParameter() is "90".
|
||||
//
|
||||
// Returns 'true' if parameter was parsed successfully.
|
||||
virtual bool SetParameters(int chain, int parallel,
|
||||
const char *parameter_string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Given a underlying matrix (width, height), returns the
|
||||
// visible (width, height) after the mapping.
|
||||
// E.g. a 90 degree rotation might map matrix=(64, 32) -> visible=(32, 64)
|
||||
// Some multiplexing matrices will double the height and half the width.
|
||||
//
|
||||
// While not technically necessary, one would expect that the number of
|
||||
// pixels stay the same, so
|
||||
// matrix_width * matrix_height == (*visible_width) * (*visible_height);
|
||||
//
|
||||
// Returns boolean "true" if the mapping can be successfully done with this
|
||||
// mapper.
|
||||
virtual bool GetSizeMapping(int matrix_width, int matrix_height,
|
||||
int *visible_width, int *visible_height)
|
||||
const = 0;
|
||||
|
||||
// Map where a visible pixel (x,y) is mapped to the underlying matrix (x,y).
|
||||
//
|
||||
// To be convienently stateless, the first parameters are the full
|
||||
// matrix width and height.
|
||||
//
|
||||
// So for many multiplexing methods this means to map a panel to a double
|
||||
// length and half height panel (32x16 -> 64x8).
|
||||
// The logic_x, logic_y are output parameters and guaranteed not to be
|
||||
// nullptr.
|
||||
virtual void MapVisibleToMatrix(int matrix_width, int matrix_height,
|
||||
int visible_x, int visible_y,
|
||||
int *matrix_x, int *matrix_y) const = 0;
|
||||
};
|
||||
|
||||
// This is a place to register PixelMappers globally. If you register your
|
||||
// PixelMapper before calling RGBMatrix::CreateFromFlags(), the named
|
||||
// PixelMapper is available in the --led-pixel-mapper options.
|
||||
//
|
||||
// Note, you don't _have_ to register your mapper, you can always call
|
||||
// RGBMatrix::ApplyPixelMapper() directly. Registering is for convenience and
|
||||
// commandline-flag support.
|
||||
//
|
||||
// There are a few standard mappers registered by default.
|
||||
void RegisterPixelMapper(PixelMapper *mapper);
|
||||
|
||||
// Get a list of the names of available pixel mappers.
|
||||
std::vector<std::string> GetAvailablePixelMappers();
|
||||
|
||||
// Given a name (e.g. "rotate") and a parameter (e.g. "90"), return the
|
||||
// parametrized PixelMapper with that name. Returns NULL if mapper
|
||||
// can not be found or parameter is invalid.
|
||||
// Ownership of the returned object is _NOT_ transferred to the caller.
|
||||
// Current available mappers are "U-mapper" and "Rotate". The "Rotate"
|
||||
// gets a parameter denoting the angle.
|
||||
const PixelMapper *FindPixelMapper(const char *name,
|
||||
int chain, int parallel,
|
||||
const char *parameter = NULL);
|
||||
} // namespace rgb_matrix
|
||||
|
||||
#endif // RGBMATRIX_PIXEL_MAPPER
|
||||
86
depends/rpi-rgb-led-matrix/include/thread.h
Normal file
86
depends/rpi-rgb-led-matrix/include/thread.h
Normal file
@@ -0,0 +1,86 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Copyright (C) 2013 Henner Zeller <h.zeller@acm.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
|
||||
|
||||
#ifndef RPI_THREAD_H
|
||||
#define RPI_THREAD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace rgb_matrix {
|
||||
// Simple thread abstraction.
|
||||
class Thread {
|
||||
public:
|
||||
Thread();
|
||||
|
||||
// The destructor waits for Run() to return so make sure it does.
|
||||
virtual ~Thread();
|
||||
|
||||
// Wait for the Run() method to return.
|
||||
void WaitStopped();
|
||||
|
||||
// Start thread. If realtime_priority is > 0, then this will be a
|
||||
// thread with SCHED_FIFO and the given priority.
|
||||
// If cpu_affinity is set !=, chooses the given bitmask of CPUs
|
||||
// this thread should have an affinity to.
|
||||
// On a Raspberry Pi 1, this doesn't matter, as there is only one core,
|
||||
// Raspberry Pi 2 can has 4 cores, so any combination of (1<<0) .. (1<<3) is
|
||||
// valid.
|
||||
virtual void Start(int realtime_priority = 0, uint32_t cpu_affinity_mask = 0);
|
||||
|
||||
// Override this to do the work.
|
||||
//
|
||||
// This will be called in a thread once Start() has been called. You typically
|
||||
// will have an endless loop doing stuff.
|
||||
//
|
||||
// It is a good idea to provide a way to communicate to the thread that
|
||||
// it should stop (see ThreadedCanvasManipulator for an example)
|
||||
virtual void Run() = 0;
|
||||
|
||||
private:
|
||||
static void *PthreadCallRun(void *tobject);
|
||||
bool started_;
|
||||
pthread_t thread_;
|
||||
};
|
||||
|
||||
// Non-recursive Mutex.
|
||||
class Mutex {
|
||||
public:
|
||||
Mutex() { pthread_mutex_init(&mutex_, NULL); }
|
||||
~Mutex() { pthread_mutex_destroy(&mutex_); }
|
||||
void Lock() { pthread_mutex_lock(&mutex_); }
|
||||
void Unlock() { pthread_mutex_unlock(&mutex_); }
|
||||
|
||||
// Wait on condition. If "timeout_ms" is < 0, it waits forever, otherwise
|
||||
// until timeout is reached.
|
||||
// Returns 'true' if condition is met, 'false', if wait timed out.
|
||||
bool WaitOn(pthread_cond_t *cond, long timeout_ms = -1);
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex_;
|
||||
};
|
||||
|
||||
// Useful RAII wrapper around mutex.
|
||||
class MutexLock {
|
||||
public:
|
||||
MutexLock(Mutex *m) : mutex_(m) { mutex_->Lock(); }
|
||||
~MutexLock() { mutex_->Unlock(); }
|
||||
private:
|
||||
Mutex *const mutex_;
|
||||
};
|
||||
|
||||
} // end namespace rgb_matrix
|
||||
|
||||
#endif // RPI_THREAD_H
|
||||
103
depends/rpi-rgb-led-matrix/include/threaded-canvas-manipulator.h
Normal file
103
depends/rpi-rgb-led-matrix/include/threaded-canvas-manipulator.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation version 2.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
|
||||
|
||||
// Utility base class for continuously updating the canvas.
|
||||
|
||||
// Note: considering removing this, as real applications likely have something
|
||||
// similar, but this might not be quite usable.
|
||||
// Since it is just a few lines of code, it is probably better
|
||||
// implemented in the application for readability.
|
||||
//
|
||||
// So for simplicity of the API, consider ThreadedCanvasManipulator deprecated.
|
||||
|
||||
#ifndef RPI_THREADED_CANVAS_MANIPULATOR_H
|
||||
#define RPI_THREADED_CANVAS_MANIPULATOR_H
|
||||
|
||||
#include "thread.h"
|
||||
#include "canvas.h"
|
||||
|
||||
namespace rgb_matrix {
|
||||
//
|
||||
// Typically, your programs will crate a canvas and then updating the image
|
||||
// in a loop. If you want to do stuff in parallel, then this utility class
|
||||
// helps you doing that. Also a demo for how to use the Thread class.
|
||||
//
|
||||
// Extend it, then just implement Run(). Example:
|
||||
/*
|
||||
class MyCrazyDemo : public ThreadedCanvasManipulator {
|
||||
public:
|
||||
MyCrazyDemo(Canvas *canvas) : ThreadedCanvasManipulator(canvas) {}
|
||||
virtual void Run() {
|
||||
unsigned char c;
|
||||
while (running()) {
|
||||
// Calculate the next frame.
|
||||
c++;
|
||||
for (int x = 0; x < canvas()->width(); ++x) {
|
||||
for (int y = 0; y < canvas()->height(); ++y) {
|
||||
canvas()->SetPixel(x, y, c, c, c);
|
||||
}
|
||||
}
|
||||
usleep(15 * 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Later, in your main method.
|
||||
RGBMatrix *matrix = RGBMatrix::CreateFromOptions(...);
|
||||
MyCrazyDemo *demo = new MyCrazyDemo(matrix);
|
||||
demo->Start(); // Start doing things.
|
||||
// This now runs in the background, you can do other things here,
|
||||
// e.g. aquiring new data or simply wait. But for waiting, you wouldn't
|
||||
// need a thread in the first place.
|
||||
demo->Stop();
|
||||
delete demo;
|
||||
*/
|
||||
class ThreadedCanvasManipulator : public Thread {
|
||||
public:
|
||||
ThreadedCanvasManipulator(Canvas *m) : running_(false), canvas_(m) {}
|
||||
virtual ~ThreadedCanvasManipulator() { Stop(); }
|
||||
|
||||
virtual void Start(int realtime_priority=0, uint32_t affinity_mask=0) {
|
||||
{
|
||||
MutexLock l(&mutex_);
|
||||
running_ = true;
|
||||
}
|
||||
Thread::Start(realtime_priority, affinity_mask);
|
||||
}
|
||||
|
||||
// Stop the thread at the next possible time Run() checks the running_ flag.
|
||||
void Stop() {
|
||||
MutexLock l(&mutex_);
|
||||
running_ = false;
|
||||
}
|
||||
|
||||
// Implement this and run while running() returns true.
|
||||
virtual void Run() = 0;
|
||||
|
||||
protected:
|
||||
inline Canvas *canvas() { return canvas_; }
|
||||
inline bool running() {
|
||||
MutexLock l(&mutex_);
|
||||
return running_;
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex mutex_;
|
||||
bool running_;
|
||||
Canvas *const canvas_;
|
||||
};
|
||||
} // namespace rgb_matrix
|
||||
|
||||
#endif // RPI_THREADED_CANVAS_MANIPULATOR_H
|
||||
Reference in New Issue
Block a user