matrix implementation
parent
fd15458b4b
commit
58fa88515e
@ -1,112 +1,184 @@
|
||||
package main
|
||||
package rgbmatrix
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -std=c99 -Ivendor/rpi-rgb-led-matrix/include -DSHOW_REFRESH_RATE
|
||||
#cgo LDFLAGS: -lrgbmatrix -Lvendor/rpi-rgb-led-matrix/lib -lstdc++ -lm
|
||||
#cgo CFLAGS: -std=c99 -I${SRCDIR}/vendor/rpi-rgb-led-matrix/include -DSHOW_REFRESH_RATE
|
||||
#cgo LDFLAGS: -lrgbmatrix -L${SRCDIR}/vendor/rpi-rgb-led-matrix/lib -lstdc++ -lm
|
||||
#include <led-matrix-c.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct RGBLedMatrix *matrix;
|
||||
struct LedCanvas *offscreen_canvas;
|
||||
|
||||
void setCanvas(struct LedCanvas *offscreen_canvas, const uint32_t pixels[]) {
|
||||
void led_matrix_swap(struct LedCanvas *offscreen_canvas,
|
||||
int width, int height, const uint32_t pixels[]) {
|
||||
int i, x, y;
|
||||
uint32_t color;
|
||||
for (y = 0; y < 32; ++y) {
|
||||
for (x = 0; x < 64; ++x) {
|
||||
for (y = 0; y < height; ++y) {
|
||||
for (x = 0; x < width; ++x) {
|
||||
i = x + (y * 64);
|
||||
|
||||
color = pixels[i];
|
||||
|
||||
led_canvas_set_pixel(offscreen_canvas, x, y,
|
||||
(color >> 16) & 255, (color >> 8) & 255, color & 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int example(struct RGBLedMatrixOptions *options) {
|
||||
struct LedCanvas *offscreen_canvas;
|
||||
int width, height;
|
||||
int x, y, i;
|
||||
|
||||
matrix = led_matrix_create_from_options(options, NULL, NULL);
|
||||
if (matrix == NULL)
|
||||
return 1;
|
||||
|
||||
offscreen_canvas = led_matrix_create_offscreen_canvas(matrix);
|
||||
|
||||
led_canvas_get_size(offscreen_canvas, &width, &height);
|
||||
|
||||
fprintf(stderr, "Size: %dx%d. Hardware gpio mapping: %s\n",
|
||||
width, height, options->hardware_mapping);
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
for (y = 0; y < height; ++y) {
|
||||
for (x = 0; x < width; ++x) {
|
||||
led_canvas_set_pixel(offscreen_canvas, x, y, i & 0xff, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
offscreen_canvas = led_matrix_swap_on_vsync(matrix, offscreen_canvas);
|
||||
}
|
||||
|
||||
led_matrix_delete(matrix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
o := &C.struct_RGBLedMatrixOptions{}
|
||||
o.rows = 32
|
||||
o.chain_length = 2
|
||||
// DefaultConfig default WS281x configuration
|
||||
var DefaultConfig = HardwareConfig{
|
||||
Rows: 32,
|
||||
ChainLength: 1,
|
||||
Parallel: 1,
|
||||
PWMBits: 11,
|
||||
PWMLSBNanoseconds: 130,
|
||||
Brightness: 100,
|
||||
ScanMode: Progressive,
|
||||
}
|
||||
|
||||
s := time.Now()
|
||||
C.example(o)
|
||||
fmt.Println(time.Since(s))
|
||||
// HardwareConfig rgb-led-matrix configuration
|
||||
type HardwareConfig struct {
|
||||
// Rows the number of rows supported by the display, so 32 or 16.
|
||||
Rows int
|
||||
// ChainLengthis the number of displays daisy-chained together
|
||||
// (output of one connected to input of next).
|
||||
ChainLength int
|
||||
// Parallel is 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.
|
||||
Parallel int
|
||||
// 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.
|
||||
PWMBits int
|
||||
// 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.
|
||||
PWMLSBNanoseconds int // the DMA channel to use
|
||||
// Brightness is the initial brightness of the panel in percent. Valid range
|
||||
// is 1..100
|
||||
Brightness int
|
||||
// ScanMode progressive or interlaced
|
||||
ScanMode ScanMode // strip color layout
|
||||
// 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.
|
||||
DisableHardwarePulsing bool
|
||||
|
||||
ShowRefreshRate bool
|
||||
InverseColors bool
|
||||
}
|
||||
|
||||
s = time.Now()
|
||||
example(o)
|
||||
fmt.Println(time.Since(s))
|
||||
func (c *HardwareConfig) geometry() (width, height int) {
|
||||
return c.Rows * c.ChainLength, c.Rows
|
||||
}
|
||||
|
||||
func (c *HardwareConfig) toC() *C.struct_RGBLedMatrixOptions {
|
||||
o := &C.struct_RGBLedMatrixOptions{}
|
||||
o.rows = C.int(c.Rows)
|
||||
o.chain_length = C.int(c.ChainLength)
|
||||
o.parallel = C.int(c.Parallel)
|
||||
o.pwm_bits = C.int(c.PWMBits)
|
||||
o.pwm_lsb_nanoseconds = C.int(c.PWMLSBNanoseconds)
|
||||
o.brightness = C.int(c.Brightness)
|
||||
o.scan_mode = C.int(c.ScanMode)
|
||||
// o.disable_hardware_pulsing = c.DisableHardwarePulsing
|
||||
// o.show_refresh_rate = c.ShowRefreshRate
|
||||
// o.inverse_colors = c.InverseColors
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func example(o *C.struct_RGBLedMatrixOptions) {
|
||||
matrix := C.led_matrix_create_from_options(o, nil, nil)
|
||||
if matrix == nil {
|
||||
panic("jodido")
|
||||
}
|
||||
type ScanMode int8
|
||||
|
||||
const (
|
||||
Progressive ScanMode = 0
|
||||
Interlaced ScanMode = 1
|
||||
)
|
||||
|
||||
//offscreen := C.led_matrix_create_offscreen_canvas(matrix)
|
||||
for i := 1; i < 1000; i++ {
|
||||
p := make([]C.uint32_t, 2048)
|
||||
for y := 0; y < 32; y++ {
|
||||
for x := 0; x < 64; x++ {
|
||||
pos := x + (y * 64)
|
||||
// RGBLedMatrix matrix representation for ws281x
|
||||
type RGBLedMatrix struct {
|
||||
Config *HardwareConfig
|
||||
|
||||
c := color.RGBA{uint8(i & 0xff), uint8(x), uint8(y), 0}
|
||||
p[pos] = C.uint32_t(colorToUint32(c))
|
||||
}
|
||||
height int
|
||||
width int
|
||||
matrix *C.struct_RGBLedMatrix
|
||||
leds []C.uint32_t
|
||||
}
|
||||
|
||||
// NewRGBLedMatrix returns a new matrix using the given size and config
|
||||
func NewRGBLedMatrix(config *HardwareConfig) (Matrix, error) {
|
||||
w, h := config.geometry()
|
||||
|
||||
c := &RGBLedMatrix{
|
||||
Config: config,
|
||||
width: w, height: h,
|
||||
matrix: C.led_matrix_create_from_options(config.toC(), nil, nil),
|
||||
leds: make([]C.uint32_t, 2048),
|
||||
}
|
||||
|
||||
C.setCanvas(matrix, (*C.uint32_t)(unsafe.Pointer(&p[0])))
|
||||
//offscreen = C.led_matrix_swap_on_vsync(matrix, offscreen)
|
||||
if c.matrix == nil {
|
||||
return nil, fmt.Errorf("unable to allocate memory")
|
||||
}
|
||||
|
||||
C.led_matrix_delete(matrix)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Initialize initialize library, must be called once before other functions are
|
||||
// called.
|
||||
func (c *RGBLedMatrix) Initialize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Geometry returns the width and the height of the matrix
|
||||
func (c *RGBLedMatrix) Geometry() (width, height int) {
|
||||
return c.width, c.height
|
||||
}
|
||||
|
||||
// Render update the display with the data from the LED buffer
|
||||
func (c *RGBLedMatrix) Render() error {
|
||||
C.led_matrix_swap(
|
||||
c.matrix,
|
||||
C.int(64), C.int(32),
|
||||
(*C.uint32_t)(unsafe.Pointer(&c.leds[0])),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// At return an Color which allows access to the LED display data as
|
||||
// if it were a sequence of 24-bit RGB values.
|
||||
func (c *RGBLedMatrix) At(position int) color.Color {
|
||||
return uint32ToColor(c.leds[position])
|
||||
}
|
||||
|
||||
// Set set LED at position x,y to the provided 24-bit color value.
|
||||
func (c *RGBLedMatrix) Set(position int, color color.Color) {
|
||||
c.leds[position] = C.uint32_t(colorToUint32(color))
|
||||
}
|
||||
|
||||
// Close finalizes the ws281x interface
|
||||
func (c *RGBLedMatrix) Close() error {
|
||||
C.led_matrix_delete(c.matrix)
|
||||
return nil
|
||||
}
|
||||
|
||||
func colorToUint32(c color.Color) uint32 {
|
||||
// A color's RGBA method returns values in the range [0, 65535]
|
||||
red, green, blue, _ := c.RGBA()
|
||||
// r<<16 | g<<8 | b
|
||||
return (red>>8)<<16 | (green>>8)<<8 | blue>>8
|
||||
}
|
||||
|
||||
func uint32ToColor(u C.uint32_t) color.Color {
|
||||
return color.RGBA{
|
||||
uint8(u>>16) & 255,
|
||||
uint8(u>>8) & 255,
|
||||
uint8(u>>0) & 255,
|
||||
0,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue