aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/lib/protomatter/src/arch/samd-common.h
diff options
context:
space:
mode:
Diffstat (limited to 'circuitpython/lib/protomatter/src/arch/samd-common.h')
-rw-r--r--circuitpython/lib/protomatter/src/arch/samd-common.h98
1 files changed, 98 insertions, 0 deletions
diff --git a/circuitpython/lib/protomatter/src/arch/samd-common.h b/circuitpython/lib/protomatter/src/arch/samd-common.h
new file mode 100644
index 0000000..d2e039d
--- /dev/null
+++ b/circuitpython/lib/protomatter/src/arch/samd-common.h
@@ -0,0 +1,98 @@
+/*!
+ * @file samd-common.h
+ *
+ * Part of Adafruit's Protomatter library for HUB75-style RGB LED matrices.
+ * This file contains SAMD-SPECIFIC CODE (SAMD51 & SAMD21).
+ *
+ * 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
+
+#if defined(__SAMD51__) || defined(SAM_D5X_E5X) || defined(_SAMD21_) || \
+ defined(SAMD21)
+
+#if defined(ARDUINO) // COMPILING FOR ARDUINO ------------------------------
+
+// g_APinDescription[] table and pin indices are Arduino specific:
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define _PM_byteOffset(pin) (g_APinDescription[pin].ulPin / 8)
+#define _PM_wordOffset(pin) (g_APinDescription[pin].ulPin / 16)
+#else
+#define _PM_byteOffset(pin) (3 - (g_APinDescription[pin].ulPin / 8))
+#define _PM_wordOffset(pin) (1 - (g_APinDescription[pin].ulPin / 16))
+#endif
+
+// Arduino implementation is tied to a specific timer/counter & freq:
+#if defined(TC4)
+#define _PM_TIMER_DEFAULT TC4
+#define _PM_IRQ_HANDLER TC4_Handler
+#else // No TC4 on some M4's
+#define _PM_TIMER_DEFAULT TC3
+#define _PM_IRQ_HANDLER TC3_Handler
+#endif
+#define _PM_timerFreq 48000000
+// Partly because IRQs must be declared at compile-time, and partly
+// because we know Arduino's already set up one of the GCLK sources
+// for 48 MHz.
+
+// Because it's tied to a specific timer right now, there can be only
+// one instance of the Protomatter_core struct. The Arduino library
+// sets up this pointer when calling begin().
+void *_PM_protoPtr = NULL;
+
+// Timer interrupt service routine
+void _PM_IRQ_HANDLER(void) {
+ // Clear overflow flag:
+ _PM_TIMER_DEFAULT->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF;
+ _PM_row_handler(_PM_protoPtr); // In core.c
+}
+
+#elif defined(CIRCUITPY) // COMPILING FOR CIRCUITPYTHON --------------------
+
+#include "hal_gpio.h"
+
+#define _PM_pinOutput(pin) gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT)
+#define _PM_pinInput(pin) gpio_set_pin_direction(pin, GPIO_DIRECTION_IN)
+#define _PM_pinHigh(pin) gpio_set_pin_level(pin, 1)
+#define _PM_pinLow(pin) gpio_set_pin_level(pin, 0)
+#define _PM_portBitMask(pin) (1u << ((pin)&31))
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define _PM_byteOffset(pin) ((pin & 31) / 8)
+#define _PM_wordOffset(pin) ((pin & 31) / 16)
+#else
+#define _PM_byteOffset(pin) (3 - ((pin & 31) / 8))
+#define _PM_wordOffset(pin) (1 - ((pin & 31) / 16))
+#endif
+
+// CircuitPython implementation is tied to a specific freq (but the counter
+// is dynamically allocated):
+#define _PM_timerFreq 48000000
+
+// As currently implemented, there can be only one instance of the
+// Protomatter_core struct. This pointer is set up when starting the matrix.
+void *_PM_protoPtr = NULL;
+
+// Timer interrupt service routine
+void _PM_IRQ_HANDLER(void) {
+ ((Tc *)(((Protomatter_core *)_PM_protoPtr)->timer))->COUNT16.INTFLAG.reg =
+ TC_INTFLAG_OVF;
+ _PM_row_handler(_PM_protoPtr); // In core.c
+}
+
+#else // END CIRCUITPYTHON -------------------------------------------------
+
+// Byte offset macros, timer and ISR work for other environments go here.
+
+#endif
+
+#endif // END SAMD5x/SAME5x/SAMD21