aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/lib/protomatter/src/core.h
diff options
context:
space:
mode:
Diffstat (limited to 'circuitpython/lib/protomatter/src/core.h')
-rw-r--r--circuitpython/lib/protomatter/src/core.h274
1 files changed, 274 insertions, 0 deletions
diff --git a/circuitpython/lib/protomatter/src/core.h b/circuitpython/lib/protomatter/src/core.h
new file mode 100644
index 0000000..ef8e316
--- /dev/null
+++ b/circuitpython/lib/protomatter/src/core.h
@@ -0,0 +1,274 @@
+/*!
+ * @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.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/** Status type returned by some functions. */
+typedef enum {
+ PROTOMATTER_OK, // Everything is hunky-dory!
+ PROTOMATTER_ERR_PINS, // Clock and/or data pins on different PORTs
+ PROTOMATTER_ERR_MALLOC, // Couldn't allocate memory for display
+ PROTOMATTER_ERR_ARG, // Bad input to function
+} ProtomatterStatus;
+
+/** 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
+ differently as they have specific requirements (and might use a toggle
+ 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
+ also declared as separate things in the core structure that follows. */
+typedef struct {
+ volatile void *setReg; ///< GPIO bit set register
+ volatile void *clearReg; ///< GPIO bit clear register
+ uint32_t bit; ///< GPIO bitmask
+ uint8_t pin; ///< Some unique ID, e.g. Arduino pin #
+} _PM_pin;
+
+/** 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
+ 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
+ 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
+ them would result in differing representations of this structure which
+ 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
+ check, but that's just dirty pool and asking for trouble.) */
+typedef struct {
+ void *timer; ///< Arch-specific timer/counter info
+ void *setReg; ///< RGBC bit set register (cast to use)
+ void *clearReg; ///< RGBC bit clear register "
+ void *toggleReg; ///< RGBC bit toggle register "
+ uint8_t *rgbPins; ///< Array of RGB data pins (mult of 6)
+ void *rgbMask; ///< PORT bit mask for each RGB pin
+ uint32_t clockMask; ///< PORT bit mask for RGB clock
+ uint32_t rgbAndClockMask; ///< PORT bit mask for RGB data + clock
+ volatile void *addrPortToggle; ///< See singleAddrPort below
+ void *screenData; ///< Per-bitplane RGB data for matrix
+ _PM_pin latch; ///< RGB data latch
+ _PM_pin oe; ///< !OE (LOW out enable)
+ _PM_pin *addr; ///< Array of address pins
+ uint32_t bufferSize; ///< Bytes per matrix buffer
+ uint32_t bitZeroPeriod; ///< Bitplane 0 timer period
+ uint32_t minPeriod; ///< Plane 0 timer period for ~250Hz
+ volatile uint32_t frameCount; ///< For estimating refresh rate
+ uint16_t width; ///< Matrix chain width only in bits
+ uint16_t chainBits; ///< Matrix chain width*tiling in bits
+ uint8_t bytesPerElement; ///< Using 8, 16 or 32 bits of PORT?
+ uint8_t clockPin; ///< RGB clock pin identifier
+ uint8_t parallel; ///< Number of concurrent matrix outs
+ uint8_t numAddressLines; ///< Number of address line pins
+ uint8_t portOffset; ///< Active 8- or 16-bit pos. in PORT
+ uint8_t numPlanes; ///< Display bitplanes (1 to 6)
+ uint8_t numRowPairs; ///< Addressable row pairs
+ int8_t tile; ///< Vertical tiling repetitions
+ bool doubleBuffer; ///< 2X buffers for clean switchover
+ bool singleAddrPort; ///< If 1, all addr lines on same PORT
+ volatile uint8_t activeBuffer; ///< Index of currently-displayed buf
+ volatile uint8_t plane; ///< Current bitplane (changes in ISR)
+ volatile uint8_t row; ///< Current scanline (changes in ISR)
+ volatile uint8_t prevRow; ///< Scanline from prior ISR
+ volatile bool swapBuffers; ///< If 1, awaiting double-buf switch
+} Protomatter_core;
+
+// Protomatter core function prototypes. Environment-specific code (like the
+// Adafruit_Protomatter class for Arduino) calls on these underlying things,
+// 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.
+
+/*!
+ @brief Initialize values in Protomatter_core structure.
+ @param core Pointer to Protomatter_core structure.
+ @param bitWidth Total width of RGB matrix chain, in pixels.
+ Usu. some multiple of 32, but maybe exceptions.
+ @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 tile If multiple matrices are chained and stacked
+ vertically (rather than or in addition to
+ horizontally), the number of vertical tiles is
+ specified here. Positive values indicate a
+ "progressive" arrangement (always left-to-right),
+ negative for a "serpentine" arrangement (alternating
+ 180 degree orientation). Horizontal tiles are implied
+ in the 'bitWidth' argument.
+ @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, int8_t tile, 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);
+
+/*!
+ @brief Disable (but do not deallocate) a Protomatter matrix. Disables
+ matrix by setting OE pin HIGH and writing all-zero data to
+ matrix shift registers, so it won't halt with lit LEDs.
+ @param core Pointer to Protomatter_core structure.
+*/
+extern void _PM_stop(Protomatter_core *core);
+
+/*!
+ @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_deallocate(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 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);
+
+#if defined(ARDUINO) || defined(CIRCUITPY)
+
+/*!
+ @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);
+
+#endif // END ARDUINO || CIRCUITPY
+
+#ifdef __cplusplus
+} // extern "C"
+#endif