Compare commits

..

No commits in common. "circuitpython-build-fix" and "master" have entirely different histories.

11 changed files with 1146 additions and 1987 deletions

4
.gitignore vendored
View file

@ -1,4 +0,0 @@
# Our handy .gitignore for automation ease
Doxyfile*
doxygen_sqlite3.db
html

View file

@ -1,41 +0,0 @@
language: c
sudo: false
cache:
directories:
- ~/arduino_ide
- ~/.arduino15/packages/
git:
depth: false
quiet: true
addons:
apt:
sources:
- llvm-toolchain-trusty-5.0
- key_url: 'http://apt.llvm.org/llvm-snapshot.gpg.key'
packages:
- python3-pip
- python3-wheel
- clang-format-5.0
env:
global:
# - ARDUINO_IDE_VERSION="1.8.10"
- PRETTYNAME="Adafruit Protomatter"
# Optional, will default to "$TRAVIS_BUILD_DIR/Doxyfile"
# - DOXYFILE: $TRAVIS_BUILD_DIR/Doxyfile
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
- curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/run-clang-format.py > run-clang-format.py
install:
- arduino --install-library "Adafruit GFX Library"
script:
- python run-clang-format.py -r .
- build_m4_platforms
- build_nrf5x_platforms
# Generate and deploy documentation
after_success:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)

View file

@ -1,38 +1,3 @@
/*!
* @file Adafruit_Protomatter.cpp
*
* @mainpage Adafruit Protomatter RGB LED matrix library.
*
* @section intro_sec Introduction
*
* This is documentation for Adafruit's protomatter library for HUB75-style
* RGB LED matrices. It is designed to work with various matrices sold by
* Adafruit ("HUB75" is a vague term and other similar matrices are not
* guaranteed to work). This file is the Arduino-specific calls; the
* underlying C code is more platform-neutral.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing products
* from Adafruit!
*
* @section dependencies Dependencies
*
* This library depends on
* <a href="https://github.com/adafruit/Adafruit-GFX-Library">Adafruit_GFX</a>
* being present on your system. Please make sure you have installed the
* latest version before using this library.
*
* @section author Author
*
* Written by Phil "Paint Your Dragon" Burgess and Jeff Epler for
* Adafruit Industries, with contributions from the open source community.
*
* @section license License
*
* BSD license, all text here must be included in any redistribution.
*
*/
// Arduino-specific wrapper for the Protomatter C library (provides // Arduino-specific wrapper for the Protomatter C library (provides
// constructor and so forth, builds on Adafruit_GFX). There should // constructor and so forth, builds on Adafruit_GFX). There should
// not be any device-specific #ifdefs here. See notes in core.c and // not be any device-specific #ifdefs here. See notes in core.c and
@ -40,7 +5,7 @@
#include "Adafruit_Protomatter.h" // Also includes core.h & Adafruit_GFX.h #include "Adafruit_Protomatter.h" // Also includes core.h & Adafruit_GFX.h
extern Protomatter_core *_PM_protoPtr; ///< In core.c (via arch.h) extern Protomatter_core *_PM_protoPtr; // In core.c (via arch.h)
// Overall matrix refresh rate (frames/second) is a function of matrix width // Overall matrix refresh rate (frames/second) is a function of matrix width
// and chain length, number of address lines, number of bit planes, CPU speed // and chain length, number of address lines, number of bit planes, CPU speed
@ -56,49 +21,67 @@ extern Protomatter_core *_PM_protoPtr; ///< In core.c (via arch.h)
// refresh slower than this, and in many cases will...just need to set an // refresh slower than this, and in many cases will...just need to set an
// upper limit to avoid excessive CPU load). An incredibly long comment block // upper limit to avoid excessive CPU load). An incredibly long comment block
// for a single constant, thank you for coming to my TED talk! // for a single constant, thank you for coming to my TED talk!
#define _PM_MAX_REFRESH_HZ 250 ///< Upper limit (ish) to matrix refresh rate #define _PM_MAX_REFRESH_HZ 250
// Time (in milliseconds) to pause following any change in address lines // Time (in milliseconds) to pause following any change in address lines
// (individually or collectively). Some matrices respond slowly there... // (individually or collectively). Some matrices respond slowly there...
// must pause on change for matrix to catch up. Defined here (rather than // must pause on change for matrix to catch up. Defined here (rather than
// arch.h) because it's not architecture-specific. // arch.h) because it's not architecture-specific.
#define _PM_ROW_DELAY 8 ///< Delay time between row address line changes (ms) #define _PM_ROW_DELAY 8
Adafruit_Protomatter::Adafruit_Protomatter(uint16_t bitWidth, uint8_t bitDepth,
uint8_t rgbCount, uint8_t *rgbList,
uint8_t addrCount, uint8_t *addrList,
uint8_t clockPin, uint8_t latchPin,
uint8_t oePin, bool doubleBuffer,
void *timer)
: GFXcanvas16(bitWidth, (2 << min(addrCount, 5)) * min(rgbCount, 5)) {
if (bitDepth > 6)
bitDepth = 6; // GFXcanvas16 color limit (565)
// Arguments are passed through to the C _PM_init() function which does Adafruit_Protomatter::Adafruit_Protomatter(
// some input validation and minor allocation. Return value is ignored uint16_t bitWidth, uint8_t bitDepth,
// because we can't really do anything about it in a C++ constructor. uint8_t rgbCount, uint8_t *rgbList,
// The class begin() function checks rgbPins for NULL to determine uint8_t addrCount, uint8_t *addrList,
// whether to proceed or indicate an error. uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
(void)_PM_init(&core, bitWidth, bitDepth, rgbCount, rgbList, addrCount, bool doubleBuffer, void *timer) :
addrList, clockPin, latchPin, oePin, doubleBuffer, timer); GFXcanvas16(bitWidth, (2 << min(addrCount, 5)) * min(rgbCount, 5)) {
if(bitDepth > 6) bitDepth = 6; // GFXcanvas16 color limit (565)
// Arguments are passed through to the C _PM_init() function which does
// some input validation and minor allocation. Return value is ignored
// because we can't really do anything about it in a C++ constructor.
// The class begin() function checks rgbPins for NULL to determine
// whether to proceed or indicate an error.
(void)_PM_init(&core, bitWidth, bitDepth, rgbCount, rgbList,
addrCount, addrList, clockPin, latchPin, oePin, doubleBuffer, timer);
} }
Adafruit_Protomatter::~Adafruit_Protomatter(void) { Adafruit_Protomatter::~Adafruit_Protomatter(void) {
_PM_free(&core); _PM_free(&core);
_PM_protoPtr = NULL; _PM_protoPtr = NULL;
} }
ProtomatterStatus Adafruit_Protomatter::begin(void) { ProtomatterStatus Adafruit_Protomatter::begin(void) {
_PM_protoPtr = &core; _PM_protoPtr = &core;
return _PM_begin(&core); _PM_begin(&core);
return PROTOMATTER_OK;
} }
// Transfer data from GFXcanvas16 to the matrix framebuffer's weird // Transfer data from GFXcanvas16 to the matrix framebuffer's weird
// internal format. The actual conversion functions referenced below // internal format. The actual conversion functions referenced below
// are in core.c, reasoning is explained there. // are in core.c, reasoning is explained there.
void Adafruit_Protomatter::show(void) { void Adafruit_Protomatter::show(void) {
_PM_convert_565(&core, getBuffer(), WIDTH);
_PM_swapbuffer_maybe(&core); // Destination address is computed in convert function
// (based on active buffer value, if double-buffering),
// just need to pass in the canvas buffer address and
// width in pixels.
if(core.bytesPerElement == 1) {
_PM_convert_565_byte(&core, getBuffer(), WIDTH);
} else if(core.bytesPerElement == 2) {
_PM_convert_565_word(&core, getBuffer(), WIDTH);
} else {
_PM_convert_565_long(&core, getBuffer(), WIDTH);
}
if(core.doubleBuffer) {
core.swapBuffers = 1;
// To avoid overwriting data on the matrix, don't return
// until the timer ISR has performed the swap at the right time.
while(core.swapBuffers);
}
} }
// Returns current value of frame counter and resets its value to zero. // Returns current value of frame counter and resets its value to zero.
@ -106,5 +89,5 @@ void Adafruit_Protomatter::show(void) {
// intervals), can be used to get a rough frames-per-second value for // intervals), can be used to get a rough frames-per-second value for
// the matrix (since this is difficult to estimate beforehand). // the matrix (since this is difficult to estimate beforehand).
uint32_t Adafruit_Protomatter::getFrameCount(void) { uint32_t Adafruit_Protomatter::getFrameCount(void) {
return _PM_getFrameCount(_PM_protoPtr); return _PM_getFrameCount(_PM_protoPtr);
} }

View file

@ -7,99 +7,22 @@
#include "core.h" #include "core.h"
#include <Adafruit_GFX.h> #include <Adafruit_GFX.h>
/*!
@brief Class representing the Arduino-facing side of the Protomatter
library. Subclass of Adafruit_GFX's GFXcanvas16 to allow all
the drawing operations.
*/
class Adafruit_Protomatter : public GFXcanvas16 { class Adafruit_Protomatter : public GFXcanvas16 {
public: public:
/*! Adafruit_Protomatter(uint16_t bitWidth, uint8_t bitDepth,
@brief Adafruit_Protomatter constructor. uint8_t rgbCount, uint8_t *rgbList,
@param bitWidth Total width of RGB matrix chain, in pixels. uint8_t addrCount, uint8_t *addrList,
Usu. some multiple of 32, but maybe exceptions. uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
@param bitDepth Color "depth" in bitplanes, determines range of bool doubleBuffer, void *timer=NULL);
shades of red, green and blue. e.g. passing 4 ~Adafruit_Protomatter(void);
bits = 16 shades ea. R,G,B = 16x16x16 = 4096 ProtomatterStatus begin(void);
colors. Max is 6, since the GFX library works void show(void);
with "565" RGB colors (6 bits green, 5 red/blue). uint32_t getFrameCount(void);
@param rgbCount Number of "sets" of RGB data pins, each set private:
containing 6 pins (2 ea. R,G,B). Typically 1, Protomatter_core core; // Underlying C struct
indicating a single matrix (or matrix chain). void convert_byte(uint8_t *dest); // GFXcanvas16-to-matrix
In theory (but not yet extensively tested), void convert_word(uint16_t *dest); // conversion functions
multiple sets of pins can be driven in parallel, void convert_long(uint32_t *dest); // for 8/16/32 bit bufs
up to 5 on some devices (if the hardware design
provides all those bits on one PORT).
@param rgbList A uint8_t array of pins (Arduino pin numbering),
6X the prior rgbCount value, corresponding to
the 6 output color bits for a matrix (or chain).
Order is upper-half red, green, blue, lower-half
red, green blue (repeat for each add'l chain).
All the RGB pins (plus the clock pin below on
some architectures) MUST be on the same PORT
register. It's recommended (but not required)
that all RGB pins (and clock depending on arch)
be within the same byte of a PORT (but do not
need to be sequential or contiguous within that
byte) for more efficient RAM utilization. For
two concurrent chains, same principle but 16-bit
word instead of byte.
@param addrCount Number of row address lines required of matrix.
Total pixel height is then 2 x 2^addrCount, e.g.
32-pixel-tall matrices have 4 row address lines.
@param addrList A uint8_t array of pins (Arduino pin numbering),
one per row address line.
@param clockPin RGB clock pin (Arduino pin #).
@param latchPin RGB data latch pin (Arduino pin #).
@param oePin Output enable pin (Arduino pin #), active low.
@param doubleBuffer If true, two matrix buffers are allocated,
so changing display contents doesn't introduce
artifacts mid-conversion. Requires ~2X RAM.
@param timer Pointer to timer peripheral or timer-related
struct (architecture-dependent), or NULL to
use a default timer ID (also arch-dependent).
*/
Adafruit_Protomatter(uint16_t bitWidth, uint8_t bitDepth, uint8_t rgbCount,
uint8_t *rgbList, uint8_t addrCount, uint8_t *addrList,
uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
bool doubleBuffer, void *timer = NULL);
~Adafruit_Protomatter(void);
/*!
@brief Start a Protomatter matrix display running -- initialize
pins, timer and interrupt into existence.
@return A ProtomatterStatus status, one of:
PROTOMATTER_OK if everything is good.
PROTOMATTER_ERR_PINS if data and/or clock pins are split
across different PORTs.
PROTOMATTER_ERR_MALLOC if insufficient RAM to allocate
display memory.
PROTOMATTER_ERR_ARG if a bad value was passed to the
constructor.
*/
ProtomatterStatus begin(void);
/*!
@brief Process data from GFXcanvas16 to the matrix framebuffer's
internal format for display.
*/
void show(void);
/*!
@brief Returns current value of frame counter and resets its value
to zero. Two calls to this, timed one second apart (or use
math with other intervals), can be used to get a rough
frames-per-second value for the matrix (since this is
difficult to estimate beforehand).
@return Frame count since previous call to function, as a uint32_t.
*/
uint32_t getFrameCount(void);
private:
Protomatter_core core; // Underlying C struct
void convert_byte(uint8_t *dest); // GFXcanvas16-to-matrix
void convert_word(uint16_t *dest); // conversion functions
void convert_long(uint32_t *dest); // for 8/16/32 bit bufs
}; };
#endif // _ADAFRUIT_PROTOMATTER_H_ #endif // _ADAFRUIT_PROTOMATTER_H_

View file

@ -1,4 +1,4 @@
# Adafruit_Protomatter [![Build Status](https://travis-ci.com/adafruit/Adafruit_Protomatter.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_Protomatter) # Adafruit_Protomatter
"I used protomatter in the Genesis matrix." - David Marcus, Star Trek III "I used protomatter in the Genesis matrix." - David Marcus, Star Trek III
@ -6,6 +6,8 @@ Code for driving HUB75-style RGB LED matrices, targeted at 32-bit MCUs
using brute-force GPIO (that is, not relying on DMA or other specialized using brute-force GPIO (that is, not relying on DMA or other specialized
peripherals beyond a timer interrupt, goal being portability). peripherals beyond a timer interrupt, goal being portability).
Name might change as it's nondescriptive and tedious to type in code.
# Matrix Concepts and Jargon # Matrix Concepts and Jargon
HUB75 RGB LED matrices are basically a set of six concurrent shift register HUB75 RGB LED matrices are basically a set of six concurrent shift register

1565
arch.h

File diff suppressed because it is too large Load diff

952
core.c

File diff suppressed because it is too large Load diff

313
core.h
View file

@ -1,19 +1,3 @@
/*!
* @file core.h
*
* Part of Adafruit's Protomatter library for HUB75-style RGB LED matrices.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Phil "Paint Your Dragon" Burgess and Jeff Epler for
* Adafruit Industries, with contributions from the open source community.
*
* BSD license, all text here must be included in any redistribution.
*
*/
#ifndef _PROTOMATTER_CORE_H_ #ifndef _PROTOMATTER_CORE_H_
#define _PROTOMATTER_CORE_H_ #define _PROTOMATTER_CORE_H_
@ -21,240 +5,103 @@
extern "C" { extern "C" {
#endif #endif
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
/** Status type returned by some functions. */ // Status type returned by some functions.
typedef enum { typedef enum {
PROTOMATTER_OK, // Everything is hunky-dory! PROTOMATTER_OK, // Everything is hunky-dory!
PROTOMATTER_ERR_PINS, // Clock and/or data pins on different PORTs PROTOMATTER_ERR_PINS, // Clock and/or data pins on different PORTs
PROTOMATTER_ERR_MALLOC, // Couldn't allocate memory for display PROTOMATTER_ERR_MALLOC, // Couldn't allocate memory for display
PROTOMATTER_ERR_ARG, // Bad input to function PROTOMATTER_ERR_ARG, // Bad input to function
} ProtomatterStatus; } ProtomatterStatus;
/** Struct for matrix control lines NOT related to RGB data or clock, i.e. // Struct for matrix control lines NOT related to RGB data or clock, i.e.
latch, OE and address lines. RGB data and clock ("RGBC") are handled // latch, OE and address lines. RGB data and clock ("RGBC") are handled
differently as they have specific requirements (and might use a toggle // differently as they have specific requirements (and might use a toggle
register if present). The data conversion functions need bitmasks for // register if present). The data conversion functions need bitmasks for
RGB data but do NOT need the set or clear registers, so those items are // RGB data but do NOT need the set or clear registers, so those items
also declared as separate things in the core structure that follows. */ // are also declared as separate things in the core structure that follows.
typedef struct { typedef struct {
volatile void *setReg; ///< GPIO bit set register volatile uint32_t *setReg; // GPIO bit set register
volatile void *clearReg; ///< GPIO bit clear register volatile uint32_t *clearReg; // GPIO bit clear register
uint32_t bit; ///< GPIO bitmask uint32_t bit; // GPIO bitmask
uint8_t pin; ///< Some unique ID, e.g. Arduino pin # uint8_t pin; // Some identifier, e.g. Arduino pin #
} _PM_pin; } _PM_pin;
/** Struct with info about an RGB matrix chain and lots of state and buffer // Struct with info about an RGB matrix chain and lots of state and buffer
details for the library. Toggle-related items in this structure MUST be // details for the library. Toggle-related items in this structure MUST be
declared even if the device lacks GPIO bit-toggle registers (i.e. don't // declared even if the device lacks GPIO bit-toggle registers (i.e. don't
do an ifdef check around these). All hardware-specific details (including // do an ifdef check around these). All hardware-specific details (including
the presence or lack of toggle registers) are isolated to a single // the presence or lack of toggle registers) are isolated to a single
file -- arch.h -- which should ONLY be included by core.c, and ifdef'ing // file -- arch.h -- which should ONLY be included by core.c, and ifdef'ing
them would result in differing representations of this structure which // them would result in differing representations of this structure which
must be shared between the library and calling code. (An alternative is // must be shared between the library and calling code. (An alternative is
to put any toggle-specific stuff at the end of the struct with an ifdef // to put any toggle-specific stuff at the end of the struct with an ifdef
check, but that's just dirty pool and asking for trouble.) */ // check, but that's just dirty pool and asking for trouble.)
typedef struct { typedef struct {
void *timer; ///< Arch-specific timer/counter info void *timer; // Arch-specific timer/counter info
void *setReg; ///< RGBC bit set register (cast to use) void *setReg; // RGBC bit set register (cast to use)
void *clearReg; ///< RGBC bit clear register " void *clearReg; // RGBC bit clear register "
void *toggleReg; ///< RGBC bit toggle register " void *toggleReg; // RGBC bit toggle register "
uint8_t *rgbPins; ///< Array of RGB data pins (mult of 6) uint8_t *rgbPins; // Array of RGB data pins (mult of 6)
void *rgbMask; ///< PORT bit mask for each RGB pin void *rgbMask; // PORT bit mask for each RGB pin
uint32_t clockMask; ///< PORT bit mask for RGB clock uint32_t clockMask; // PORT bit mask for RGB clock
uint32_t rgbAndClockMask; ///< PORT bit mask for RGB data + clock uint32_t rgbAndClockMask; // PORT bit mask for RGB data + clock
volatile void *addrPortToggle; ///< See singleAddrPort below volatile uint32_t *addrPortToggle; // See singleAddrPort below
void *screenData; ///< Per-bitplane RGB data for matrix void *screenData; // Per-bitplane RGB data for matrix
_PM_pin latch; ///< RGB data latch _PM_pin latch; // RGB data latch
_PM_pin oe; ///< !OE (LOW out enable) _PM_pin oe; // !OE (LOW out enable)
_PM_pin *addr; ///< Array of address pins _PM_pin *addr; // Array of address pins
uint32_t bufferSize; ///< Bytes per matrix buffer uint32_t bufferSize; // Bytes per matrix buffer
uint32_t bitZeroPeriod; ///< Bitplane 0 timer period uint32_t bitZeroPeriod; // Bitplane 0 timer period
uint32_t minPeriod; ///< Plane 0 timer period for ~250Hz uint32_t minPeriod; // Plane 0 timer period for ~250Hz
volatile uint32_t frameCount; ///< For estimating refresh rate volatile uint32_t frameCount; // For estimating refresh rate
uint16_t width; ///< Matrix chain width in bits uint16_t width; // Matrix chain width in bits
uint8_t bytesPerElement; ///< Using 8, 16 or 32 bits of PORT? uint8_t bytesPerElement; // Using 8, 16 or 32 bits of PORT?
uint8_t clockPin; ///< RGB clock pin identifier uint8_t clockPin; // RGB clock pin identifier
uint8_t parallel; ///< Number of concurrent matrix outs uint8_t parallel; // Number of concurrent matrix outs
uint8_t numAddressLines; ///< Number of address line pins uint8_t numAddressLines; // Number of address line pins
uint8_t portOffset; ///< Active 8- or 16-bit pos. in PORT uint8_t portOffset; // Active 8- or 16-bit pos. in PORT
uint8_t numPlanes; ///< Display bitplanes (1 to 6) uint8_t numPlanes; // Display bitplanes (1 to 6)
uint8_t numRowPairs; ///< Addressable row pairs uint8_t numRowPairs; // Addressable row pairs
bool doubleBuffer; ///< 2X buffers for clean switchover bool doubleBuffer; // 2X buffers for clean switchover
bool singleAddrPort; ///< If 1, all addr lines on same PORT bool singleAddrPort; // If 1, all addr lines on same PORT
volatile uint8_t activeBuffer; ///< Index of currently-displayed buf volatile uint8_t activeBuffer; // Index of currently-displayed buf
volatile uint8_t plane; ///< Current bitplane (changes in ISR) volatile uint8_t plane; // Current bitplane (changes in ISR)
volatile uint8_t row; ///< Current scanline (changes in ISR) volatile uint8_t row; // Current scanline (changes in ISR)
volatile uint8_t prevRow; ///< Scanline from prior ISR volatile uint8_t prevRow; // Scanline from prior ISR
volatile bool swapBuffers; ///< If 1, awaiting double-buf switch volatile bool swapBuffers; // If 1, awaiting double-buf switch
} Protomatter_core; } Protomatter_core;
// Protomatter core function prototypes. Environment-specific code (like the // Protomatter core function prototypes. Environment-specific code (like the
// Adafruit_Protomatter class for Arduino) calls on these underlying things, // Adafruit_Protomatter class for Arduino) calls on these underlying things,
// and has to provide a few extras of its own (interrupt handlers and such). // and has to provide a few extras of its own (interrupt handlers and such).
// User code shouldn't need to invoke any of them directly. // User code shouldn't need to invoke any of them directly.
extern ProtomatterStatus _PM_init(Protomatter_core *core,
/*! uint16_t bitWidth, uint8_t bitDepth,
@brief Initialize values in Protomatter_core structure. uint8_t rgbCount, uint8_t *rgbList,
@param core Pointer to Protomatter_core structure. uint8_t addrCount, uint8_t *addrList,
@param bitWidth Total width of RGB matrix chain, in pixels. uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
Usu. some multiple of 32, but maybe exceptions. bool doubleBuffer, void *timer);
@param bitDepth Color "depth" in bitplanes, determines range of
shades of red, green and blue. e.g. passing 4
bits = 16 shades ea. R,G,B = 16x16x16 = 4096
colors.
@param rgbCount Number of "sets" of RGB data pins, each set
containing 6 pins (2 ea. R,G,B). Typically 1,
indicating a single matrix (or matrix chain).
In theory (but not yet extensively tested),
multiple sets of pins can be driven in parallel,
up to 5 on some devices (if the hardware design
provides all those bits on one PORT).
@param rgbList A uint8_t array of pins (values are platform-
dependent), 6X the prior rgbCount value,
corresponding to the 6 output color bits for a
matrix (or chain). Order is upper-half red, green,
blue, lower-half red, green blue (repeat for each
add'l chain). All the RGB pins (plus the clock pin
below on some architectures) MUST be on the same
PORT register. It's recommended (but not required)
that all RGB pins (and clock depending on arch) be
within the same byte of a PORT (but do not need to
be sequential or contiguous within that byte) for
more efficient RAM utilization. For two concurrent
chains, same principle but 16-bit word.
@param addrCount Number of row address lines required of matrix.
Total pixel height is then 2 x 2^addrCount, e.g.
32-pixel-tall matrices have 4 row address lines.
@param addrList A uint8_t array of pins (platform-dependent pin
numbering), one per row address line.
@param clockPin RGB clock pin (platform-dependent pin #).
@param latchPin RGB data latch pin (platform-dependent pin #).
@param oePin Output enable pin (platform-dependent pin #),
active low.
@param doubleBuffer If true, two matrix buffers are allocated,
so changing display contents doesn't introduce
artifacts mid-conversion. Requires ~2X RAM.
@param timer Pointer to timer peripheral or timer-related
struct (architecture-dependent), or NULL to
use a default timer ID (also arch-dependent).
@return A ProtomatterStatus status, one of:
PROTOMATTER_OK if everything is good.
PROTOMATTER_ERR_PINS if data and/or clock pins are split across
different PORTs.
PROTOMATTER_ERR_MALLOC if insufficient RAM to allocate display
memory.
PROTOMATTER_ERR_ARG if a bad value (core or timer pointer) was
passed in.
*/
extern ProtomatterStatus _PM_init(Protomatter_core *core, uint16_t bitWidth,
uint8_t bitDepth, uint8_t rgbCount,
uint8_t *rgbList, uint8_t addrCount,
uint8_t *addrList, uint8_t clockPin,
uint8_t latchPin, uint8_t oePin,
bool doubleBuffer, void *timer);
/*!
@brief Allocate display buffers and populate additional elements of a
Protomatter matrix.
@param core Pointer to Protomatter_core structure.
@return A ProtomatterStatus status, one of:
PROTOMATTER_OK if everything is good.
PROTOMATTER_ERR_PINS if data and/or clock pins are split across
different PORTs.
PROTOMATTER_ERR_MALLOC if insufficient RAM to allocate display
memory.
PROTOMATTER_ERR_ARG if a bad value.
*/
extern ProtomatterStatus _PM_begin(Protomatter_core *core); extern ProtomatterStatus _PM_begin(Protomatter_core *core);
extern void _PM_stop(Protomatter_core *core);
extern void _PM_resume(Protomatter_core *core);
extern void _PM_free(Protomatter_core *core);
extern void _PM_row_handler(Protomatter_core *core);
extern uint32_t _PM_getFrameCount(Protomatter_core *core);
extern void _PM_timerStart(void *tptr, uint32_t period);
extern uint32_t _PM_timerStop(void *tptr);
extern uint32_t _PM_timerGetCount(void *tptr);
/*! #if defined(ARDUINO)
@brief Disable (but do not deallocate) a Protomatter matrix. Disables extern void _PM_convert_565_byte(Protomatter_core *core,
matrix by setting OE pin HIGH and writing all-zero data to uint16_t *source, uint16_t width);
matrix shift registers, so it won't halt with lit LEDs. extern void _PM_convert_565_word(Protomatter_core *core,
@param core Pointer to Protomatter_core structure. uint16_t *source, uint16_t width);
*/ extern void _PM_convert_565_long(Protomatter_core *core,
extern void _PM_stop(Protomatter_core *core); uint16_t *source, uint16_t width);
#endif // ARDUINO
/*!
@brief Start or restart a matrix. Initialize counters, configure and
start timer.
@param core Pointer to Protomatter_core structure.
*/
extern void _PM_resume(Protomatter_core *core);
/*!
@brief Deallocate memory associated with Protomatter_core structure
(e.g. screen data, pin lists for data and rows). Does not
deallocate the structure itself.
@param core Pointer to Protomatter_core structure.
*/
extern void _PM_free(Protomatter_core *core);
/*!
@brief Matrix "row handler" that's called by the timer interrupt.
Handles row address lines and issuing data to matrix.
@param core Pointer to Protomatter_core structure.
*/
extern void _PM_row_handler(Protomatter_core *core);
/*!
@brief Returns current value of frame counter and resets its value to
zero. Two calls to this, timed one second apart (or use math with
other intervals), can be used to get a rough frames-per-second
value for the matrix (since this is difficult to estimate
beforehand).
@param core Pointer to Protomatter_core structure.
@return Frame count since previous call to function, as a uint32_t.
*/
extern uint32_t _PM_getFrameCount(Protomatter_core *core);
/*!
@brief Start (or restart) a timer/counter peripheral.
@param tptr Pointer to timer/counter peripheral OR a struct
encapsulating information about a timer/counter
periph (architecture-dependent).
@param period Timer 'top' / rollover value.
*/
extern void _PM_timerStart(void *tptr, uint32_t period);
/*!
@brief Stop timer/counter peripheral.
@param tptr Pointer to timer/counter peripheral OR a struct
encapsulating information about a timer/counter
periph (architecture-dependent).
@return Counter value when timer was stopped.
*/
extern uint32_t _PM_timerStop(void *tptr);
/*!
@brief Query a timer/counter peripheral's current count.
@param tptr Pointer to timer/counter peripheral OR a struct
encapsulating information about a timer/counter
periph (architecture-dependent).
@return Counter value.
*/
extern uint32_t _PM_timerGetCount(void *tptr);
/*!
@brief Converts image data from GFX16 canvas to the matrices weird
internal format.
@param core Pointer to Protomatter_core structure.
@param source Pointer to source image data (see Adafruit_GFX 16-bit
canvas type for format).
@param width Width of canvas in pixels, as this may be different than
the matrix pixel width due to row padding.
*/
extern void _PM_convert_565(Protomatter_core *core, uint16_t *source,
uint16_t width);
/*!
@brief Pauses until the next vertical blank to avoid 'tearing' animation
(if display is double-buffered). If single-buffered, has no effect.
@param core Pointer to Protomatter_core structure.
*/
extern void _PM_swapbuffer_maybe(Protomatter_core *core);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View file

@ -41,16 +41,6 @@ PA05 A4 PA13 PA21 D7 PB05 PB13
PA06 PA14 PA22 SDA PB06 PB14 PA06 PA14 PA22 SDA PB06 PB14
PA07 D9 PA15 D5 PA23 SCL PB07 PB15 PA07 D9 PA15 D5 PA23 SCL PB07 PB15
FEATHER nRF52840:
P0.00 P0.08 D12 P0.24 RXD P1.08 D5
P0.01 P0.09 P0.25 TXD P1.09 D13
P0.02 A4 P0.10 D2 (NFC) P0.26 D9 P1.10
P0.03 A5 P0.11 SCL P0.27 D10 P1.11
P0.04 A0 P0.12 SDA P0.28 A3 P1.12
P0.05 A1 P0.13 MOSI P0.29 P1.13
P0.06 D11 P0.14 SCK P0.30 A2 P1.14
P0.07 D6 P0.15 MISO P0.31 P1.15
RGB Matrix FeatherWing: RGB Matrix FeatherWing:
R1 D6 A A5 R1 D6 A A5
G1 D5 B A4 G1 D5 B A4
@ -65,7 +55,6 @@ the code could run there (with some work to be done in the convert_*
functions), but would be super RAM-inefficient. Should be fine on other functions), but would be super RAM-inefficient. Should be fine on other
M0 devices like a Metro, if wiring manually so one can pick a contiguous M0 devices like a Metro, if wiring manually so one can pick a contiguous
byte of PORT bits. byte of PORT bits.
RGB+clock are on different PORTs on nRF52840.
*/ */
#if defined(__SAMD51__) #if defined(__SAMD51__)
@ -75,18 +64,12 @@ RGB+clock are on different PORTs on nRF52840.
uint8_t clockPin = 13; uint8_t clockPin = 13;
uint8_t latchPin = 0; uint8_t latchPin = 0;
uint8_t oePin = 1; uint8_t oePin = 1;
#elif defined(_SAMD21_) #else // SAMD21
uint8_t rgbPins[] = {6, 7, 10, 11, 12, 13}; uint8_t rgbPins[] = {6, 7, 10, 11, 12, 13};
uint8_t addrPins[] = {0, 1, 2, 3}; uint8_t addrPins[] = {0, 1, 2, 3};
uint8_t clockPin = SDA; uint8_t clockPin = SDA;
uint8_t latchPin = 4; uint8_t latchPin = 4;
uint8_t oePin = 5; uint8_t oePin = 5;
#elif defined(NRF52_SERIES)
uint8_t rgbPins[] = {6, 11, A0, A1, A4, A5};
uint8_t addrPins[] = {5, 9, 10, 13};
uint8_t clockPin = 12;
uint8_t latchPin = A2;
uint8_t oePin = A3;
#endif #endif
// Last arg here enables double-buffering // Last arg here enables double-buffering

View file

@ -41,16 +41,6 @@ PA05 A4 PA13 PA21 D7 PB05 PB13
PA06 PA14 PA22 SDA PB06 PB14 PA06 PA14 PA22 SDA PB06 PB14
PA07 D9 PA15 D5 PA23 SCL PB07 PB15 PA07 D9 PA15 D5 PA23 SCL PB07 PB15
FEATHER nRF52840:
P0.00 P0.08 D12 P0.24 RXD P1.08 D5
P0.01 P0.09 P0.25 TXD P1.09 D13
P0.02 A4 P0.10 D2 (NFC) P0.26 D9 P1.10
P0.03 A5 P0.11 SCL P0.27 D10 P1.11
P0.04 A0 P0.12 SDA P0.28 A3 P1.12
P0.05 A1 P0.13 MOSI P0.29 P1.13
P0.06 D11 P0.14 SCK P0.30 A2 P1.14
P0.07 D6 P0.15 MISO P0.31 P1.15
RGB Matrix FeatherWing: RGB Matrix FeatherWing:
R1 D6 A A5 R1 D6 A A5
G1 D5 B A4 G1 D5 B A4
@ -65,7 +55,6 @@ the code could run there (with some work to be done in the convert_*
functions), but would be super RAM-inefficient. Should be fine on other functions), but would be super RAM-inefficient. Should be fine on other
M0 devices like a Metro, if wiring manually so one can pick a contiguous M0 devices like a Metro, if wiring manually so one can pick a contiguous
byte of PORT bits. byte of PORT bits.
RGB+clock are on different PORTs on nRF52840.
*/ */
#if defined(__SAMD51__) #if defined(__SAMD51__)
@ -75,18 +64,12 @@ RGB+clock are on different PORTs on nRF52840.
uint8_t clockPin = 13; uint8_t clockPin = 13;
uint8_t latchPin = 0; uint8_t latchPin = 0;
uint8_t oePin = 1; uint8_t oePin = 1;
#elif defined(_SAMD21_) #else // SAMD21
uint8_t rgbPins[] = {6, 7, 10, 11, 12, 13}; uint8_t rgbPins[] = {6, 7, 10, 11, 12, 13};
uint8_t addrPins[] = {0, 1, 2, 3}; uint8_t addrPins[] = {0, 1, 2, 3};
uint8_t clockPin = SDA; uint8_t clockPin = SDA;
uint8_t latchPin = 4; uint8_t latchPin = 4;
uint8_t oePin = 5; uint8_t oePin = 5;
#elif defined(NRF52_SERIES)
uint8_t rgbPins[] = {6, 11, A0, A1, A4, A5};
uint8_t addrPins[] = {5, 9, 10, 13};
uint8_t clockPin = 12;
uint8_t latchPin = A2;
uint8_t oePin = A3;
#endif #endif
Adafruit_Protomatter matrix( Adafruit_Protomatter matrix(

View file

@ -1,10 +1,10 @@
name=Adafruit Protomatter name=Adafruit Protomatter
version=1.0.0 version=0.0.0
author=Adafruit author=Adafruit
maintainer=Adafruit <info@adafruit.com> maintainer=Adafruit <info@adafruit.com>
sentence=This is a library for the Adafruit RGB LED matrix. sentence=This is a library for the Adafruit RGB LED matrix.
paragraph=RGB LED matrix. paragraph=RGB LED matrix.
category=Display category=Display
url=https://github.com/adafruit/Adafruit_protomatter url=https://github.com/adafruit/Adafruit_protomatter
architectures=samd,nrf52,stm32 architectures=*
depends=Adafruit GFX Library depends=Adafruit GFX Library