clang-format the lot
This commit is contained in:
parent
40cb6a9cac
commit
a51676db5e
5 changed files with 1564 additions and 1515 deletions
|
|
@ -64,23 +64,23 @@ extern Protomatter_core *_PM_protoPtr; ///< In core.c (via arch.h)
|
||||||
// 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 ///< Delay time between row address line changes (ms)
|
||||||
|
|
||||||
|
Adafruit_Protomatter::Adafruit_Protomatter(uint16_t bitWidth, uint8_t bitDepth,
|
||||||
Adafruit_Protomatter::Adafruit_Protomatter(
|
|
||||||
uint16_t bitWidth, uint8_t bitDepth,
|
|
||||||
uint8_t rgbCount, uint8_t *rgbList,
|
uint8_t rgbCount, uint8_t *rgbList,
|
||||||
uint8_t addrCount, uint8_t *addrList,
|
uint8_t addrCount, uint8_t *addrList,
|
||||||
uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
|
uint8_t clockPin, uint8_t latchPin,
|
||||||
bool doubleBuffer, void *timer) :
|
uint8_t oePin, bool doubleBuffer,
|
||||||
GFXcanvas16(bitWidth, (2 << min(addrCount, 5)) * min(rgbCount, 5)) {
|
void *timer)
|
||||||
if(bitDepth > 6) bitDepth = 6; // GFXcanvas16 color limit (565)
|
: 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
|
// Arguments are passed through to the C _PM_init() function which does
|
||||||
// some input validation and minor allocation. Return value is ignored
|
// some input validation and minor allocation. Return value is ignored
|
||||||
// because we can't really do anything about it in a C++ constructor.
|
// because we can't really do anything about it in a C++ constructor.
|
||||||
// The class begin() function checks rgbPins for NULL to determine
|
// The class begin() function checks rgbPins for NULL to determine
|
||||||
// whether to proceed or indicate an error.
|
// whether to proceed or indicate an error.
|
||||||
(void)_PM_init(&core, bitWidth, bitDepth, rgbCount, rgbList,
|
(void)_PM_init(&core, bitWidth, bitDepth, rgbCount, rgbList, addrCount,
|
||||||
addrCount, addrList, clockPin, latchPin, oePin, doubleBuffer, timer);
|
addrList, clockPin, latchPin, oePin, doubleBuffer, timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Adafruit_Protomatter::~Adafruit_Protomatter(void) {
|
Adafruit_Protomatter::~Adafruit_Protomatter(void) {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
the drawing operations.
|
the drawing operations.
|
||||||
*/
|
*/
|
||||||
class Adafruit_Protomatter : public GFXcanvas16 {
|
class Adafruit_Protomatter : public GFXcanvas16 {
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
@brief Adafruit_Protomatter constructor.
|
@brief Adafruit_Protomatter constructor.
|
||||||
@param bitWidth Total width of RGB matrix chain, in pixels.
|
@param bitWidth Total width of RGB matrix chain, in pixels.
|
||||||
|
|
@ -59,11 +59,10 @@ class Adafruit_Protomatter : public GFXcanvas16 {
|
||||||
struct (architecture-dependent), or NULL to
|
struct (architecture-dependent), or NULL to
|
||||||
use a default timer ID (also arch-dependent).
|
use a default timer ID (also arch-dependent).
|
||||||
*/
|
*/
|
||||||
Adafruit_Protomatter(uint16_t bitWidth, uint8_t bitDepth,
|
Adafruit_Protomatter(uint16_t bitWidth, uint8_t bitDepth, uint8_t rgbCount,
|
||||||
uint8_t rgbCount, uint8_t *rgbList,
|
uint8_t *rgbList, uint8_t addrCount, uint8_t *addrList,
|
||||||
uint8_t addrCount, uint8_t *addrList,
|
|
||||||
uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
|
uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
|
||||||
bool doubleBuffer, void *timer=NULL);
|
bool doubleBuffer, void *timer = NULL);
|
||||||
~Adafruit_Protomatter(void);
|
~Adafruit_Protomatter(void);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -95,7 +94,8 @@ class Adafruit_Protomatter : public GFXcanvas16 {
|
||||||
@return Frame count since previous call to function, as a uint32_t.
|
@return Frame count since previous call to function, as a uint32_t.
|
||||||
*/
|
*/
|
||||||
uint32_t getFrameCount(void);
|
uint32_t getFrameCount(void);
|
||||||
private:
|
|
||||||
|
private:
|
||||||
Protomatter_core core; // Underlying C struct
|
Protomatter_core core; // Underlying C struct
|
||||||
void convert_byte(uint8_t *dest); // GFXcanvas16-to-matrix
|
void convert_byte(uint8_t *dest); // GFXcanvas16-to-matrix
|
||||||
void convert_word(uint16_t *dest); // conversion functions
|
void convert_word(uint16_t *dest); // conversion functions
|
||||||
|
|
|
||||||
236
core.c
236
core.c
|
|
@ -29,10 +29,10 @@
|
||||||
// things hopefully makes function and variable name collisions much less
|
// things hopefully makes function and variable name collisions much less
|
||||||
// likely with one's own code.
|
// likely with one's own code.
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "core.h" // enums and structs
|
#include "core.h" // enums and structs
|
||||||
#include "arch.h" // Do NOT include this in any other source files
|
#include "arch.h" // Do NOT include this in any other source files
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.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
|
||||||
|
|
@ -72,22 +72,28 @@ static void blast_byte(Protomatter_core *core, uint8_t *data);
|
||||||
static void blast_word(Protomatter_core *core, uint16_t *data);
|
static void blast_word(Protomatter_core *core, uint16_t *data);
|
||||||
static void blast_long(Protomatter_core *core, uint32_t *data);
|
static void blast_long(Protomatter_core *core, uint32_t *data);
|
||||||
|
|
||||||
#define _PM_clearReg(x) (*(volatile _PM_PORT_TYPE*)((x).clearReg) = ((x).bit)) ///< Clear non-RGB-data-or-clock control line (_PM_pin type)
|
#define _PM_clearReg(x) \
|
||||||
#define _PM_setReg(x) (*(volatile _PM_PORT_TYPE*)((x).setReg) = ((x).bit)) ///< Set non-RGB-data-or-clock control line (_PM_pin type)
|
(*(volatile _PM_PORT_TYPE *)((x).clearReg) = \
|
||||||
|
((x).bit)) ///< Clear non-RGB-data-or-clock control line (_PM_pin type)
|
||||||
|
#define _PM_setReg(x) \
|
||||||
|
(*(volatile _PM_PORT_TYPE *)((x).setReg) = \
|
||||||
|
((x).bit)) ///< Set non-RGB-data-or-clock control line (_PM_pin type)
|
||||||
|
|
||||||
// Validate and populate vital elements of core structure.
|
// Validate and populate vital elements of core structure.
|
||||||
// Does NOT allocate core struct -- calling function must provide that.
|
// Does NOT allocate core struct -- calling function must provide that.
|
||||||
// (In the Arduino C++ library, it’s part of the Protomatter class.)
|
// (In the Arduino C++ library, it’s part of the Protomatter class.)
|
||||||
ProtomatterStatus _PM_init(Protomatter_core *core,
|
ProtomatterStatus _PM_init(Protomatter_core *core, uint16_t bitWidth,
|
||||||
uint16_t bitWidth, uint8_t bitDepth,
|
uint8_t bitDepth, uint8_t rgbCount, uint8_t *rgbList,
|
||||||
uint8_t rgbCount, uint8_t *rgbList,
|
|
||||||
uint8_t addrCount, uint8_t *addrList,
|
uint8_t addrCount, uint8_t *addrList,
|
||||||
uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
|
uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
|
||||||
bool doubleBuffer, void *timer) {
|
bool doubleBuffer, void *timer) {
|
||||||
if(!core) return PROTOMATTER_ERR_ARG;
|
if (!core)
|
||||||
|
return PROTOMATTER_ERR_ARG;
|
||||||
|
|
||||||
if(rgbCount > 5) rgbCount = 5; // Max 5 in parallel (32-bit PORT)
|
if (rgbCount > 5)
|
||||||
if(addrCount > 5) addrCount = 5; // Max 5 address lines (A-E)
|
rgbCount = 5; // Max 5 in parallel (32-bit PORT)
|
||||||
|
if (addrCount > 5)
|
||||||
|
addrCount = 5; // Max 5 address lines (A-E)
|
||||||
// bitDepth is NOT constrained here, handle in calling function
|
// bitDepth is NOT constrained here, handle in calling function
|
||||||
// (varies with implementation, e.g. GFX lib is max 6 bitplanes,
|
// (varies with implementation, e.g. GFX lib is max 6 bitplanes,
|
||||||
// but might be more or less elsewhere)
|
// but might be more or less elsewhere)
|
||||||
|
|
@ -96,9 +102,11 @@ ProtomatterStatus _PM_init(Protomatter_core *core,
|
||||||
// If NULL timer was passed in (the default case for the constructor),
|
// If NULL timer was passed in (the default case for the constructor),
|
||||||
// use default value from arch.h. For example, in the Arduino case it's
|
// use default value from arch.h. For example, in the Arduino case it's
|
||||||
// tied to TC4 specifically.
|
// tied to TC4 specifically.
|
||||||
if(timer == NULL) timer = _PM_TIMER_DEFAULT;
|
if (timer == NULL)
|
||||||
|
timer = _PM_TIMER_DEFAULT;
|
||||||
#else
|
#else
|
||||||
if(timer == NULL) return PROTOMATTER_ERR_ARG;
|
if (timer == NULL)
|
||||||
|
return PROTOMATTER_ERR_ARG;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
core->timer = timer;
|
core->timer = timer;
|
||||||
|
|
@ -120,10 +128,10 @@ ProtomatterStatus _PM_init(Protomatter_core *core,
|
||||||
// the pin bitmasks.
|
// the pin bitmasks.
|
||||||
|
|
||||||
rgbCount *= 6; // Convert parallel count to pin count
|
rgbCount *= 6; // Convert parallel count to pin count
|
||||||
if((core->rgbPins = (uint8_t *)_PM_ALLOCATOR(rgbCount * sizeof(uint8_t)))) {
|
if ((core->rgbPins = (uint8_t *)_PM_ALLOCATOR(rgbCount * sizeof(uint8_t)))) {
|
||||||
if((core->addr = (_PM_pin *)_PM_ALLOCATOR(addrCount * sizeof(_PM_pin)))) {
|
if ((core->addr = (_PM_pin *)_PM_ALLOCATOR(addrCount * sizeof(_PM_pin)))) {
|
||||||
memcpy(core->rgbPins, rgbList, rgbCount * sizeof(uint8_t));
|
memcpy(core->rgbPins, rgbList, rgbCount * sizeof(uint8_t));
|
||||||
for(uint8_t i=0; i<addrCount; i++) {
|
for (uint8_t i = 0; i < addrCount; i++) {
|
||||||
core->addr[i].pin = addrList[i];
|
core->addr[i].pin = addrList[i];
|
||||||
}
|
}
|
||||||
return PROTOMATTER_OK;
|
return PROTOMATTER_OK;
|
||||||
|
|
@ -136,9 +144,10 @@ ProtomatterStatus _PM_init(Protomatter_core *core,
|
||||||
|
|
||||||
// Allocate display buffers and populate additional elements.
|
// Allocate display buffers and populate additional elements.
|
||||||
ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
if(!core) return PROTOMATTER_ERR_ARG;
|
if (!core)
|
||||||
|
return PROTOMATTER_ERR_ARG;
|
||||||
|
|
||||||
if(!core->rgbPins) { // NULL if copy failed to allocate
|
if (!core->rgbPins) { // NULL if copy failed to allocate
|
||||||
return PROTOMATTER_ERR_MALLOC;
|
return PROTOMATTER_ERR_MALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,9 +167,9 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
uint32_t bitMask = 0;
|
uint32_t bitMask = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(uint8_t i=0; i<core->parallel * 6; i++) {
|
for (uint8_t i = 0; i < core->parallel * 6; i++) {
|
||||||
uint8_t *p2 = (uint8_t *)_PM_portOutRegister(core->rgbPins[i]);
|
uint8_t *p2 = (uint8_t *)_PM_portOutRegister(core->rgbPins[i]);
|
||||||
if(p2 != port) {
|
if (p2 != port) {
|
||||||
return PROTOMATTER_ERR_PINS;
|
return PROTOMATTER_ERR_PINS;
|
||||||
}
|
}
|
||||||
bitMask |= _PM_portBitMask(core->rgbPins[i]);
|
bitMask |= _PM_portBitMask(core->rgbPins[i]);
|
||||||
|
|
@ -173,11 +182,15 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
// register is present) are in the same byte, this can be stored more
|
// register is present) are in the same byte, this can be stored more
|
||||||
// compact than if they're spread across a word or long.
|
// compact than if they're spread across a word or long.
|
||||||
uint8_t byteMask = 0;
|
uint8_t byteMask = 0;
|
||||||
if(bitMask & 0xFF000000) byteMask |= 0b1000;
|
if (bitMask & 0xFF000000)
|
||||||
if(bitMask & 0x00FF0000) byteMask |= 0b0100;
|
byteMask |= 0b1000;
|
||||||
if(bitMask & 0x0000FF00) byteMask |= 0b0010;
|
if (bitMask & 0x00FF0000)
|
||||||
if(bitMask & 0x000000FF) byteMask |= 0b0001;
|
byteMask |= 0b0100;
|
||||||
switch(byteMask) {
|
if (bitMask & 0x0000FF00)
|
||||||
|
byteMask |= 0b0010;
|
||||||
|
if (bitMask & 0x000000FF)
|
||||||
|
byteMask |= 0b0001;
|
||||||
|
switch (byteMask) {
|
||||||
case 0b0001: // If all PORT bits are in the same byte...
|
case 0b0001: // If all PORT bits are in the same byte...
|
||||||
case 0b0010:
|
case 0b0010:
|
||||||
case 0b0100:
|
case 0b0100:
|
||||||
|
|
@ -200,17 +213,19 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
core->numRowPairs = 1 << core->numAddressLines;
|
core->numRowPairs = 1 << core->numAddressLines;
|
||||||
uint8_t chunks = (core->width + (_PM_chunkSize - 1)) / _PM_chunkSize;
|
uint8_t chunks = (core->width + (_PM_chunkSize - 1)) / _PM_chunkSize;
|
||||||
uint16_t columns = chunks * _PM_chunkSize; // Padded matrix width
|
uint16_t columns = chunks * _PM_chunkSize; // Padded matrix width
|
||||||
uint32_t screenBytes = columns * core->numRowPairs * core->numPlanes *
|
uint32_t screenBytes =
|
||||||
core->bytesPerElement;
|
columns * core->numRowPairs * core->numPlanes * core->bytesPerElement;
|
||||||
|
|
||||||
core->bufferSize = screenBytes; // Bytes per matrix buffer (1 or 2)
|
core->bufferSize = screenBytes; // Bytes per matrix buffer (1 or 2)
|
||||||
if(core->doubleBuffer) screenBytes *= 2; // Total for matrix buffer(s)
|
if (core->doubleBuffer)
|
||||||
|
screenBytes *= 2; // Total for matrix buffer(s)
|
||||||
uint32_t rgbMaskBytes = core->parallel * 6 * core->bytesPerElement;
|
uint32_t rgbMaskBytes = core->parallel * 6 * core->bytesPerElement;
|
||||||
|
|
||||||
// Allocate matrix buffer(s). Don't worry about the return type...
|
// Allocate matrix buffer(s). Don't worry about the return type...
|
||||||
// though we might be using words or longs for certain pin configs,
|
// though we might be using words or longs for certain pin configs,
|
||||||
// _PM_ALLOCATOR() by definition always aligns to the longest type.
|
// _PM_ALLOCATOR() by definition always aligns to the longest type.
|
||||||
if(!(core->screenData = (uint8_t *)_PM_ALLOCATOR(screenBytes + rgbMaskBytes))) {
|
if (!(core->screenData =
|
||||||
|
(uint8_t *)_PM_ALLOCATOR(screenBytes + rgbMaskBytes))) {
|
||||||
return PROTOMATTER_ERR_MALLOC;
|
return PROTOMATTER_ERR_MALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,34 +239,33 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Figure out clockMask and rgbAndClockMask, clear matrix buffers
|
// Figure out clockMask and rgbAndClockMask, clear matrix buffers
|
||||||
if(core->bytesPerElement == 1) {
|
if (core->bytesPerElement == 1) {
|
||||||
core->portOffset = _PM_byteOffset(core->rgbPins[0]);
|
core->portOffset = _PM_byteOffset(core->rgbPins[0]);
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
// Clock and rgbAndClockMask are 8-bit values
|
// Clock and rgbAndClockMask are 8-bit values
|
||||||
core->clockMask = _PM_portBitMask(core->clockPin) >>
|
core->clockMask = _PM_portBitMask(core->clockPin) >> (core->portOffset * 8);
|
||||||
(core->portOffset * 8);
|
core->rgbAndClockMask =
|
||||||
core->rgbAndClockMask = (bitMask >> (core->portOffset * 8)) |
|
(bitMask >> (core->portOffset * 8)) | core->clockMask;
|
||||||
core->clockMask;
|
|
||||||
memset(core->screenData, core->clockMask, screenBytes);
|
memset(core->screenData, core->clockMask, screenBytes);
|
||||||
#else
|
#else
|
||||||
// Clock and rgbAndClockMask are 32-bit values
|
// Clock and rgbAndClockMask are 32-bit values
|
||||||
core->clockMask = _PM_portBitMask(core->clockPin);
|
core->clockMask = _PM_portBitMask(core->clockPin);
|
||||||
core->rgbAndClockMask = bitMask | core->clockMask;
|
core->rgbAndClockMask = bitMask | core->clockMask;
|
||||||
#endif
|
#endif
|
||||||
for(uint8_t i=0; i<core->parallel * 6; i++) {
|
for (uint8_t i = 0; i < core->parallel * 6; i++) {
|
||||||
((uint8_t *)core->rgbMask)[i] = // Pin bitmasks are 8-bit
|
((uint8_t *)core->rgbMask)[i] = // Pin bitmasks are 8-bit
|
||||||
_PM_portBitMask(core->rgbPins[i]) >> (core->portOffset * 8);
|
_PM_portBitMask(core->rgbPins[i]) >> (core->portOffset * 8);
|
||||||
}
|
}
|
||||||
} else if(core->bytesPerElement == 2) {
|
} else if (core->bytesPerElement == 2) {
|
||||||
core->portOffset = _PM_wordOffset(core->rgbPins[0]);
|
core->portOffset = _PM_wordOffset(core->rgbPins[0]);
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
// Clock and rgbAndClockMask are 16-bit values
|
// Clock and rgbAndClockMask are 16-bit values
|
||||||
core->clockMask = _PM_portBitMask(core->clockPin) >>
|
core->clockMask =
|
||||||
(core->portOffset * 16);
|
_PM_portBitMask(core->clockPin) >> (core->portOffset * 16);
|
||||||
core->rgbAndClockMask = (bitMask >> (core->portOffset * 16)) |
|
core->rgbAndClockMask =
|
||||||
core->clockMask;
|
(bitMask >> (core->portOffset * 16)) | core->clockMask;
|
||||||
uint32_t elements = screenBytes / 2;
|
uint32_t elements = screenBytes / 2;
|
||||||
for(uint32_t i=0; i<elements; i++) {
|
for (uint32_t i = 0; i < elements; i++) {
|
||||||
((uint16_t *)core->screenData)[i] = core->clockMask;
|
((uint16_t *)core->screenData)[i] = core->clockMask;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
@ -259,7 +273,7 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
core->clockMask = _PM_portBitMask(core->clockPin);
|
core->clockMask = _PM_portBitMask(core->clockPin);
|
||||||
core->rgbAndClockMask = bitMask | core->clockMask;
|
core->rgbAndClockMask = bitMask | core->clockMask;
|
||||||
#endif
|
#endif
|
||||||
for(uint8_t i=0; i<core->parallel * 6; i++) {
|
for (uint8_t i = 0; i < core->parallel * 6; i++) {
|
||||||
((uint16_t *)core->rgbMask)[i] = // Pin bitmasks are 16-bit
|
((uint16_t *)core->rgbMask)[i] = // Pin bitmasks are 16-bit
|
||||||
_PM_portBitMask(core->rgbPins[i]) >> (core->portOffset * 16);
|
_PM_portBitMask(core->rgbPins[i]) >> (core->portOffset * 16);
|
||||||
}
|
}
|
||||||
|
|
@ -269,11 +283,11 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
core->rgbAndClockMask = bitMask | core->clockMask;
|
core->rgbAndClockMask = bitMask | core->clockMask;
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
uint32_t elements = screenBytes / 4;
|
uint32_t elements = screenBytes / 4;
|
||||||
for(uint32_t i=0; i<elements; i++) {
|
for (uint32_t i = 0; i < elements; i++) {
|
||||||
((uint32_t *)core->screenData)[i] = core->clockMask;
|
((uint32_t *)core->screenData)[i] = core->clockMask;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for(uint8_t i=0; i<core->parallel * 6; i++) {
|
for (uint8_t i = 0; i < core->parallel * 6; i++) {
|
||||||
((uint32_t *)core->rgbMask)[i] = // Pin bitmasks are 32-bit
|
((uint32_t *)core->rgbMask)[i] = // Pin bitmasks are 32-bit
|
||||||
_PM_portBitMask(core->rgbPins[i]);
|
_PM_portBitMask(core->rgbPins[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -283,7 +297,7 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
uint32_t minPeriodPerFrame = _PM_timerFreq / _PM_MAX_REFRESH_HZ;
|
uint32_t minPeriodPerFrame = _PM_timerFreq / _PM_MAX_REFRESH_HZ;
|
||||||
uint32_t minPeriodPerLine = minPeriodPerFrame / core->numRowPairs;
|
uint32_t minPeriodPerLine = minPeriodPerFrame / core->numRowPairs;
|
||||||
core->minPeriod = minPeriodPerLine / ((1 << core->numPlanes) - 1);
|
core->minPeriod = minPeriodPerLine / ((1 << core->numPlanes) - 1);
|
||||||
if(core->minPeriod < _PM_minMinPeriod) {
|
if (core->minPeriod < _PM_minMinPeriod) {
|
||||||
core->minPeriod = _PM_minMinPeriod;
|
core->minPeriod = _PM_minMinPeriod;
|
||||||
}
|
}
|
||||||
// Actual frame rate may be lower than this...it's only an estimate
|
// Actual frame rate may be lower than this...it's only an estimate
|
||||||
|
|
@ -313,7 +327,7 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
_PM_pinOutput(core->oe.pin);
|
_PM_pinOutput(core->oe.pin);
|
||||||
_PM_pinHigh(core->oe.pin); // Init OE HIGH (disable output)
|
_PM_pinHigh(core->oe.pin); // Init OE HIGH (disable output)
|
||||||
|
|
||||||
for(uint8_t i=0; i<core->parallel * 6; i++) {
|
for (uint8_t i = 0; i < core->parallel * 6; i++) {
|
||||||
_PM_pinOutput(core->rgbPins[i]);
|
_PM_pinOutput(core->rgbPins[i]);
|
||||||
_PM_pinLow(core->rgbPins[i]);
|
_PM_pinLow(core->rgbPins[i]);
|
||||||
}
|
}
|
||||||
|
|
@ -321,23 +335,20 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
core->addrPortToggle = _PM_portToggleRegister(core->addr[0].pin);
|
core->addrPortToggle = _PM_portToggleRegister(core->addr[0].pin);
|
||||||
core->singleAddrPort = 1;
|
core->singleAddrPort = 1;
|
||||||
#endif
|
#endif
|
||||||
for(uint8_t line=0,bit=1; line<core->numAddressLines; line++, bit<<=1) {
|
for (uint8_t line = 0, bit = 1; line < core->numAddressLines;
|
||||||
core->addr[line].setReg =
|
line++, bit <<= 1) {
|
||||||
_PM_portSetRegister(core->addr[line].pin);
|
core->addr[line].setReg = _PM_portSetRegister(core->addr[line].pin);
|
||||||
core->addr[line].clearReg =
|
core->addr[line].clearReg = _PM_portClearRegister(core->addr[line].pin);
|
||||||
_PM_portClearRegister(core->addr[line].pin);
|
core->addr[line].bit = _PM_portBitMask(core->addr[line].pin);
|
||||||
core->addr[line].bit =
|
|
||||||
_PM_portBitMask(core->addr[line].pin);
|
|
||||||
_PM_pinOutput(core->addr[line].pin);
|
_PM_pinOutput(core->addr[line].pin);
|
||||||
if(core->prevRow & bit) {
|
if (core->prevRow & bit) {
|
||||||
_PM_pinHigh(core->addr[line].pin);
|
_PM_pinHigh(core->addr[line].pin);
|
||||||
} else {
|
} else {
|
||||||
_PM_pinLow(core->addr[line].pin);
|
_PM_pinLow(core->addr[line].pin);
|
||||||
}
|
}
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
// If address pin on different port than addr 0, no singleAddrPort.
|
// If address pin on different port than addr 0, no singleAddrPort.
|
||||||
if(_PM_portToggleRegister(core->addr[line].pin) !=
|
if (_PM_portToggleRegister(core->addr[line].pin) != core->addrPortToggle) {
|
||||||
core->addrPortToggle) {
|
|
||||||
core->singleAddrPort = 0;
|
core->singleAddrPort = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -360,8 +371,9 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
||||||
// setting OE pin HIGH and writing all-zero data to matrix shift registers,
|
// setting OE pin HIGH and writing all-zero data to matrix shift registers,
|
||||||
// so it won't halt with lit LEDs.
|
// so it won't halt with lit LEDs.
|
||||||
void _PM_stop(Protomatter_core *core) {
|
void _PM_stop(Protomatter_core *core) {
|
||||||
if((core)) {
|
if ((core)) {
|
||||||
while(core->swapBuffers); // Wait for any pending buffer swap
|
while (core->swapBuffers)
|
||||||
|
; // Wait for any pending buffer swap
|
||||||
_PM_timerStop(core->timer); // Halt timer
|
_PM_timerStop(core->timer); // Halt timer
|
||||||
_PM_setReg(core->oe); // Set OE HIGH (disable output)
|
_PM_setReg(core->oe); // Set OE HIGH (disable output)
|
||||||
// So, in PRINCIPLE, setting OE high would be sufficient...
|
// So, in PRINCIPLE, setting OE high would be sufficient...
|
||||||
|
|
@ -369,11 +381,11 @@ void _PM_stop(Protomatter_core *core) {
|
||||||
// as the onloard LED (which pulses during bootloading) let's
|
// as the onloard LED (which pulses during bootloading) let's
|
||||||
// also clear out the matrix shift registers for good measure.
|
// also clear out the matrix shift registers for good measure.
|
||||||
// Set all RGB pins LOW...
|
// Set all RGB pins LOW...
|
||||||
for(uint8_t i=0; i<core->parallel * 6; i++) {
|
for (uint8_t i = 0; i < core->parallel * 6; i++) {
|
||||||
_PM_pinLow(core->rgbPins[i]);
|
_PM_pinLow(core->rgbPins[i]);
|
||||||
}
|
}
|
||||||
// Clock out bits (just need to toggle clock with RGBs held low)
|
// Clock out bits (just need to toggle clock with RGBs held low)
|
||||||
for(uint32_t i=0; i<core->width; i++) {
|
for (uint32_t i = 0; i < core->width; i++) {
|
||||||
_PM_pinHigh(core->clockPin);
|
_PM_pinHigh(core->clockPin);
|
||||||
_PM_clockHoldHigh;
|
_PM_clockHoldHigh;
|
||||||
_PM_pinLow(core->clockPin);
|
_PM_pinLow(core->clockPin);
|
||||||
|
|
@ -386,7 +398,7 @@ void _PM_stop(Protomatter_core *core) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _PM_resume(Protomatter_core *core) {
|
void _PM_resume(Protomatter_core *core) {
|
||||||
if((core)) {
|
if ((core)) {
|
||||||
// Init plane & row to max values so they roll over on 1st interrupt
|
// Init plane & row to max values so they roll over on 1st interrupt
|
||||||
core->plane = core->numPlanes - 1;
|
core->plane = core->numPlanes - 1;
|
||||||
core->row = core->numRowPairs - 1;
|
core->row = core->numRowPairs - 1;
|
||||||
|
|
@ -401,19 +413,20 @@ void _PM_resume(Protomatter_core *core) {
|
||||||
|
|
||||||
// Free memory associated with core structure. Does NOT dealloc struct.
|
// Free memory associated with core structure. Does NOT dealloc struct.
|
||||||
void _PM_free(Protomatter_core *core) {
|
void _PM_free(Protomatter_core *core) {
|
||||||
if((core)) {
|
if ((core)) {
|
||||||
_PM_stop(core);
|
_PM_stop(core);
|
||||||
// TO DO: Set all pins back to inputs here?
|
// TO DO: Set all pins back to inputs here?
|
||||||
if(core->screenData) _PM_FREE(core->screenData);
|
if (core->screenData)
|
||||||
if(core->addr) _PM_FREE(core->addr);
|
_PM_FREE(core->screenData);
|
||||||
if(core->rgbPins) {
|
if (core->addr)
|
||||||
|
_PM_FREE(core->addr);
|
||||||
|
if (core->rgbPins) {
|
||||||
_PM_FREE(core->rgbPins);
|
_PM_FREE(core->rgbPins);
|
||||||
core->rgbPins = NULL;
|
core->rgbPins = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ISR function (in arch.h) calls this function which it extern'd.
|
// ISR function (in arch.h) calls this function which it extern'd.
|
||||||
void _PM_row_handler(Protomatter_core *core) {
|
void _PM_row_handler(Protomatter_core *core) {
|
||||||
|
|
||||||
|
|
@ -430,41 +443,41 @@ void _PM_row_handler(Protomatter_core *core) {
|
||||||
// of the elapsed timer value, for subsequent bitplane timing (each
|
// of the elapsed timer value, for subsequent bitplane timing (each
|
||||||
// plane period is double the previous). Value is filtered slightly to
|
// plane period is double the previous). Value is filtered slightly to
|
||||||
// avoid jitter.
|
// avoid jitter.
|
||||||
if((prevPlane == 1) || (core->numPlanes == 1)) {
|
if ((prevPlane == 1) || (core->numPlanes == 1)) {
|
||||||
core->bitZeroPeriod = ((core->bitZeroPeriod * 7) + elapsed) / 8;
|
core->bitZeroPeriod = ((core->bitZeroPeriod * 7) + elapsed) / 8;
|
||||||
if(core->bitZeroPeriod < core->minPeriod) {
|
if (core->bitZeroPeriod < core->minPeriod) {
|
||||||
core->bitZeroPeriod = core->minPeriod;
|
core->bitZeroPeriod = core->minPeriod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(prevPlane == 0) { // Plane 0 just finished loading
|
if (prevPlane == 0) { // Plane 0 just finished loading
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
// If all address lines are on a single PORT (and bit toggle is
|
// If all address lines are on a single PORT (and bit toggle is
|
||||||
// available), do address line change all at once. Even doing all
|
// available), do address line change all at once. Even doing all
|
||||||
// this math takes MUCH less time than the delays required when
|
// this math takes MUCH less time than the delays required when
|
||||||
// doing line-by-line changes.
|
// doing line-by-line changes.
|
||||||
if(core->singleAddrPort) {
|
if (core->singleAddrPort) {
|
||||||
// Make bitmasks of prior and new row bits
|
// Make bitmasks of prior and new row bits
|
||||||
uint32_t priorBits = 0, newBits = 0;
|
uint32_t priorBits = 0, newBits = 0;
|
||||||
for(uint8_t line=0,bit=1; line<core->numAddressLines;
|
for (uint8_t line = 0, bit = 1; line < core->numAddressLines;
|
||||||
line++, bit<<=1) {
|
line++, bit <<= 1) {
|
||||||
if(core->row & bit) {
|
if (core->row & bit) {
|
||||||
newBits |= core->addr[line].bit;
|
newBits |= core->addr[line].bit;
|
||||||
}
|
}
|
||||||
if(core->prevRow & bit) {
|
if (core->prevRow & bit) {
|
||||||
priorBits |= core->addr[line].bit;
|
priorBits |= core->addr[line].bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(volatile _PM_PORT_TYPE*)core->addrPortToggle = newBits ^ priorBits;
|
*(volatile _PM_PORT_TYPE *)core->addrPortToggle = newBits ^ priorBits;
|
||||||
_PM_delayMicroseconds(_PM_ROW_DELAY);
|
_PM_delayMicroseconds(_PM_ROW_DELAY);
|
||||||
} else {
|
} else {
|
||||||
#endif
|
#endif
|
||||||
// Configure row address lines individually, making changes
|
// Configure row address lines individually, making changes
|
||||||
// (with delays) only where necessary.
|
// (with delays) only where necessary.
|
||||||
for(uint8_t line=0,bit=1; line<core->numAddressLines;
|
for (uint8_t line = 0, bit = 1; line < core->numAddressLines;
|
||||||
line++, bit<<=1) {
|
line++, bit <<= 1) {
|
||||||
if((core->row & bit) != (core->prevRow & bit)) {
|
if ((core->row & bit) != (core->prevRow & bit)) {
|
||||||
if(core->row & bit) { // Set addr line high
|
if (core->row & bit) { // Set addr line high
|
||||||
_PM_setReg(core->addr[line]);
|
_PM_setReg(core->addr[line]);
|
||||||
} else { // Set addr line low
|
} else { // Set addr line low
|
||||||
_PM_clearReg(core->addr[line]);
|
_PM_clearReg(core->addr[line]);
|
||||||
|
|
@ -479,12 +492,12 @@ void _PM_row_handler(Protomatter_core *core) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance bitplane index and/or row as necessary
|
// Advance bitplane index and/or row as necessary
|
||||||
if(++core->plane >= core->numPlanes) { // Next data bitplane, or
|
if (++core->plane >= core->numPlanes) { // Next data bitplane, or
|
||||||
core->plane = 0; // roll over bitplane to start
|
core->plane = 0; // roll over bitplane to start
|
||||||
if(++core->row >= core->numRowPairs) { // Next row, or
|
if (++core->row >= core->numRowPairs) { // Next row, or
|
||||||
core->row = 0; // roll over row to start
|
core->row = 0; // roll over row to start
|
||||||
// Switch matrix buffers if due (only if double-buffered)
|
// Switch matrix buffers if due (only if double-buffered)
|
||||||
if(core->swapBuffers) {
|
if (core->swapBuffers) {
|
||||||
core->activeBuffer = 1 - core->activeBuffer;
|
core->activeBuffer = 1 - core->activeBuffer;
|
||||||
core->swapBuffers = 0; // Swapped!
|
core->swapBuffers = 0; // Swapped!
|
||||||
}
|
}
|
||||||
|
|
@ -500,17 +513,18 @@ void _PM_row_handler(Protomatter_core *core) {
|
||||||
_PM_timerStart(core->timer, core->bitZeroPeriod << prevPlane);
|
_PM_timerStart(core->timer, core->bitZeroPeriod << prevPlane);
|
||||||
_PM_clearReg(core->oe); // Enable LED output
|
_PM_clearReg(core->oe); // Enable LED output
|
||||||
|
|
||||||
uint32_t elementsPerLine = _PM_chunkSize *
|
uint32_t elementsPerLine =
|
||||||
((core->width + (_PM_chunkSize - 1)) / _PM_chunkSize);
|
_PM_chunkSize * ((core->width + (_PM_chunkSize - 1)) / _PM_chunkSize);
|
||||||
uint32_t srcOffset = elementsPerLine *
|
uint32_t srcOffset = elementsPerLine *
|
||||||
(core->numPlanes * core->row + core->plane) * core->bytesPerElement;
|
(core->numPlanes * core->row + core->plane) *
|
||||||
if(core->doubleBuffer) {
|
core->bytesPerElement;
|
||||||
|
if (core->doubleBuffer) {
|
||||||
srcOffset += core->bufferSize * core->activeBuffer;
|
srcOffset += core->bufferSize * core->activeBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(core->bytesPerElement == 1) {
|
if (core->bytesPerElement == 1) {
|
||||||
blast_byte(core, (uint8_t *)(core->screenData + srcOffset));
|
blast_byte(core, (uint8_t *)(core->screenData + srcOffset));
|
||||||
} else if(core->bytesPerElement == 2) {
|
} else if (core->bytesPerElement == 2) {
|
||||||
blast_word(core, (uint16_t *)(core->screenData + srcOffset));
|
blast_word(core, (uint16_t *)(core->screenData + srcOffset));
|
||||||
} else {
|
} else {
|
||||||
blast_long(core, (uint32_t *)(core->screenData + srcOffset));
|
blast_long(core, (uint32_t *)(core->screenData + srcOffset));
|
||||||
|
|
@ -530,39 +544,41 @@ void _PM_row_handler(Protomatter_core *core) {
|
||||||
// before setting the clock back low. If undefined, nothing goes there.
|
// before setting the clock back low. If undefined, nothing goes there.
|
||||||
|
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
#define PEW \
|
#define PEW \
|
||||||
*toggle = *data++; /* Toggle in new data + toggle clock low */ \
|
*toggle = *data++; /* Toggle in new data + toggle clock low */ \
|
||||||
_PM_clockHoldLow; \
|
_PM_clockHoldLow; \
|
||||||
*toggle = clock; /* Toggle clock high */ \
|
*toggle = clock; /* Toggle clock high */ \
|
||||||
_PM_clockHoldHigh;
|
_PM_clockHoldHigh;
|
||||||
#else
|
#else
|
||||||
#define PEW \
|
#define PEW \
|
||||||
*set = *data++; /* Set RGB data high */ \
|
*set = *data++; /* Set RGB data high */ \
|
||||||
_PM_clockHoldLow; \
|
_PM_clockHoldLow; \
|
||||||
*set_full = clock; /* Set clock high */ \
|
*set_full = clock; /* Set clock high */ \
|
||||||
_PM_clockHoldHigh; \
|
_PM_clockHoldHigh; \
|
||||||
*clear_full = rgbclock; /* Clear RGB data + clock */ ///< Bitbang one set of RGB data bits to matrix
|
*clear_full = rgbclock; \
|
||||||
|
/* Clear RGB data + clock */ ///< Bitbang one set of RGB data bits to
|
||||||
|
///< matrix
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _PM_chunkSize == 1
|
#if _PM_chunkSize == 1
|
||||||
#define PEW_UNROLL PEW
|
#define PEW_UNROLL PEW
|
||||||
#elif _PM_chunkSize == 8
|
#elif _PM_chunkSize == 8
|
||||||
#define PEW_UNROLL PEW PEW PEW PEW PEW PEW PEW PEW ///< 8-way PEW unroll
|
#define PEW_UNROLL PEW PEW PEW PEW PEW PEW PEW PEW ///< 8-way PEW unroll
|
||||||
#elif _PM_chunkSize == 16
|
#elif _PM_chunkSize == 16
|
||||||
#define PEW_UNROLL \
|
#define PEW_UNROLL \
|
||||||
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW
|
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW
|
||||||
#elif _PM_chunkSize == 32
|
#elif _PM_chunkSize == 32
|
||||||
#define PEW_UNROLL \
|
#define PEW_UNROLL \
|
||||||
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW \
|
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW \
|
||||||
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW
|
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW
|
||||||
#elif _PM_chunkSize == 64
|
#elif _PM_chunkSize == 64
|
||||||
#define PEW_UNROLL \
|
#define PEW_UNROLL \
|
||||||
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW \
|
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW \
|
||||||
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW \
|
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW \
|
||||||
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW \
|
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW \
|
||||||
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW
|
PEW PEW PEW PEW PEW PEW PEW PEW PEW PEW
|
||||||
#else
|
#else
|
||||||
#error "Unimplemented _PM_chunkSize value"
|
#error "Unimplemented _PM_chunkSize value"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// There are THREE COPIES of the following function -- one each for byte,
|
// There are THREE COPIES of the following function -- one each for byte,
|
||||||
|
|
@ -577,8 +593,8 @@ static void blast_byte(Protomatter_core *core, uint8_t *data) {
|
||||||
// clock are all within the same byte of a PORT register, else we'd be
|
// clock are all within the same byte of a PORT register, else we'd be
|
||||||
// in the word- or long-blasting functions now. So we just need an
|
// in the word- or long-blasting functions now. So we just need an
|
||||||
// 8-bit pointer to the PORT.
|
// 8-bit pointer to the PORT.
|
||||||
volatile uint8_t *toggle = (volatile uint8_t *)core->toggleReg +
|
volatile uint8_t *toggle =
|
||||||
core->portOffset;
|
(volatile uint8_t *)core->toggleReg + core->portOffset;
|
||||||
#else
|
#else
|
||||||
// No-toggle version is a little different. If here, RGB data is all
|
// No-toggle version is a little different. If here, RGB data is all
|
||||||
// in one byte of PORT register, clock can be any bit in 32-bit PORT.
|
// in one byte of PORT register, clock can be any bit in 32-bit PORT.
|
||||||
|
|
@ -596,7 +612,7 @@ static void blast_byte(Protomatter_core *core, uint8_t *data) {
|
||||||
// PORT has already been initialized with RGB data + clock bits
|
// PORT has already been initialized with RGB data + clock bits
|
||||||
// all LOW, so we don't need to initialize that state here.
|
// all LOW, so we don't need to initialize that state here.
|
||||||
|
|
||||||
while(chunks--) {
|
while (chunks--) {
|
||||||
PEW_UNROLL // _PM_chunkSize RGB+clock writes
|
PEW_UNROLL // _PM_chunkSize RGB+clock writes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,8 +630,8 @@ static void blast_byte(Protomatter_core *core, uint8_t *data) {
|
||||||
static void blast_word(Protomatter_core *core, uint16_t *data) {
|
static void blast_word(Protomatter_core *core, uint16_t *data) {
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
// See notes above -- except now 16-bit word in PORT.
|
// See notes above -- except now 16-bit word in PORT.
|
||||||
volatile uint16_t *toggle = (volatile uint16_t *)core->toggleReg +
|
volatile uint16_t *toggle =
|
||||||
core->portOffset;
|
(volatile uint16_t *)core->toggleReg + core->portOffset;
|
||||||
#else
|
#else
|
||||||
volatile uint16_t *set; // For RGB data set
|
volatile uint16_t *set; // For RGB data set
|
||||||
volatile _PM_PORT_TYPE *set_full; // For clock set
|
volatile _PM_PORT_TYPE *set_full; // For clock set
|
||||||
|
|
@ -627,7 +643,7 @@ static void blast_word(Protomatter_core *core, uint16_t *data) {
|
||||||
#endif
|
#endif
|
||||||
_PM_PORT_TYPE clock = core->clockMask; // Clock bit
|
_PM_PORT_TYPE clock = core->clockMask; // Clock bit
|
||||||
uint8_t chunks = (core->width + (_PM_chunkSize - 1)) / _PM_chunkSize;
|
uint8_t chunks = (core->width + (_PM_chunkSize - 1)) / _PM_chunkSize;
|
||||||
while(chunks--) {
|
while (chunks--) {
|
||||||
PEW_UNROLL // _PM_chunkSize RGB+clock writes
|
PEW_UNROLL // _PM_chunkSize RGB+clock writes
|
||||||
}
|
}
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
|
|
@ -655,7 +671,7 @@ static void blast_long(Protomatter_core *core, uint32_t *data) {
|
||||||
#endif
|
#endif
|
||||||
_PM_PORT_TYPE clock = core->clockMask; // Clock bit
|
_PM_PORT_TYPE clock = core->clockMask; // Clock bit
|
||||||
uint8_t chunks = (core->width + (_PM_chunkSize - 1)) / _PM_chunkSize;
|
uint8_t chunks = (core->width + (_PM_chunkSize - 1)) / _PM_chunkSize;
|
||||||
while(chunks--) {
|
while (chunks--) {
|
||||||
PEW_UNROLL // _PM_chunkSize RGB+clock writes
|
PEW_UNROLL // _PM_chunkSize RGB+clock writes
|
||||||
}
|
}
|
||||||
#if defined(_PM_portToggleRegister)
|
#if defined(_PM_portToggleRegister)
|
||||||
|
|
@ -669,7 +685,7 @@ static void blast_long(Protomatter_core *core, uint32_t *data) {
|
||||||
// the matrix (since this is difficult to estimate beforehand).
|
// the matrix (since this is difficult to estimate beforehand).
|
||||||
uint32_t _PM_getFrameCount(Protomatter_core *core) {
|
uint32_t _PM_getFrameCount(Protomatter_core *core) {
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
if((core)) {
|
if ((core)) {
|
||||||
count = core->frameCount;
|
count = core->frameCount;
|
||||||
core->frameCount = 0;
|
core->frameCount = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
core.h
16
core.h
|
|
@ -21,8 +21,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/** Status type returned by some functions. */
|
/** Status type returned by some functions. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -148,11 +148,11 @@ typedef struct {
|
||||||
PROTOMATTER_ERR_ARG if a bad value (core or timer pointer) was
|
PROTOMATTER_ERR_ARG if a bad value (core or timer pointer) was
|
||||||
passed in.
|
passed in.
|
||||||
*/
|
*/
|
||||||
extern ProtomatterStatus _PM_init(Protomatter_core *core,
|
extern ProtomatterStatus _PM_init(Protomatter_core *core, uint16_t bitWidth,
|
||||||
uint16_t bitWidth, uint8_t bitDepth,
|
uint8_t bitDepth, uint8_t rgbCount,
|
||||||
uint8_t rgbCount, uint8_t *rgbList,
|
uint8_t *rgbList, uint8_t addrCount,
|
||||||
uint8_t addrCount, uint8_t *addrList,
|
uint8_t *addrList, uint8_t clockPin,
|
||||||
uint8_t clockPin, uint8_t latchPin, uint8_t oePin,
|
uint8_t latchPin, uint8_t oePin,
|
||||||
bool doubleBuffer, void *timer);
|
bool doubleBuffer, void *timer);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -246,8 +246,8 @@ extern uint32_t _PM_timerGetCount(void *tptr);
|
||||||
@param width Width of canvas in pixels, as this may be different than
|
@param width Width of canvas in pixels, as this may be different than
|
||||||
the matrix pixel width due to row padding.
|
the matrix pixel width due to row padding.
|
||||||
*/
|
*/
|
||||||
extern void _PM_convert_565(Protomatter_core *core,
|
extern void _PM_convert_565(Protomatter_core *core, uint16_t *source,
|
||||||
uint16_t *source, uint16_t width);
|
uint16_t width);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Pauses until the next vertical blank to avoid 'tearing' animation
|
@brief Pauses until the next vertical blank to avoid 'tearing' animation
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue