From aeafa855397198b145b93f07a4e61aa15cc1b348 Mon Sep 17 00:00:00 2001 From: csonsino Date: Mon, 9 Sep 2019 10:28:29 -0600 Subject: [PATCH] Start adding support for Apollo3 devices Signed-off-by: Carey Sonsino --- Adafruit_NeoPixel.cpp | 17 +++++- Adafruit_NeoPixel.h | 6 ++ apollo3.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 apollo3.cpp diff --git a/Adafruit_NeoPixel.cpp b/Adafruit_NeoPixel.cpp index 97ff0cfc..c647beb8 100644 --- a/Adafruit_NeoPixel.cpp +++ b/Adafruit_NeoPixel.cpp @@ -1700,6 +1700,10 @@ void Adafruit_NeoPixel::show(void) { } #endif +#elif defined (AM_PART_APOLLO3) // Apollo3 + + apollo3Show(pin, pixels, numBytes, is800KHz); + #elif defined (__SAMD51__) // M4 uint8_t *ptr, *end, p, bitMask, portNum, bit; @@ -2210,7 +2214,18 @@ void Adafruit_NeoPixel::show(void) { @param p Arduino pin number (-1 = no pin). */ void Adafruit_NeoPixel::setPin(uint16_t p) { - if(begun && (pin >= 0)) pinMode(pin, INPUT); + if(begun && (pin >= 0)) { +#if defined(AM_PART_APOLLO3) + // The pin has already been mapped to the Apollo3 pad + apollo3UnsetPin(pin); +#endif + pinMode(pin, INPUT); + } +#if defined(AM_PART_APOLLO3) + // Map the specified pin to the Apollo3 pad + p = ap3_gpio_pin2pad(p); + apollo3SetPin(p); +#endif pin = p; if(begun) { pinMode(p, OUTPUT); diff --git a/Adafruit_NeoPixel.h b/Adafruit_NeoPixel.h index c09c99a5..62d549eb 100644 --- a/Adafruit_NeoPixel.h +++ b/Adafruit_NeoPixel.h @@ -334,6 +334,12 @@ class Adafruit_NeoPixel { protected: +#if defined (AM_PART_APOLLO3) + void apollo3UnsetPin(uint16_t pin); + void apollo3SetPin(uint16_t pin); + void apollo3Show(uint16_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz); +#endif // AM_PART_APOLLO3 + #ifdef NEO_KHZ400 // If 400 KHz NeoPixel support enabled... boolean is800KHz; ///< true if 800 KHz pixels #endif diff --git a/apollo3.cpp b/apollo3.cpp new file mode 100644 index 00000000..e2d5a911 --- /dev/null +++ b/apollo3.cpp @@ -0,0 +1,135 @@ +// This provides the functionality for Apollo3 devices. + +#if defined(AM_PART_APOLLO3) + +#include +#include + +#include "Adafruit_NeoPixel.h" + +// The timing method used to control the NeoPixels +// TODO: Implement something better (interrupts, DMA, etc) +#define PIN_METHOD_FAST_GPIO + +/*! + @brief Unset the NeoPixel output pin number. + @param p Arduino pin number (-1 = no pin). +*/ +void Adafruit_NeoPixel::apollo3UnsetPin(uint16_t pin) { +#if defined(PIN_METHOD_FAST_GPIO) + // Unconfigure the pin for Fast GPIO. + am_hal_gpio_fastgpio_disable(pin); +#endif +} + +/*! + @brief Set the NeoPixel output pin number. + @param p Arduino pin number (-1 = no pin). +*/ +void Adafruit_NeoPixel::apollo3SetPin(uint16_t pin) { +#if defined(PIN_METHOD_FAST_GPIO) + // Configure the pin to be used for Fast GPIO. + am_hal_gpio_fastgpio_disable(pin); + am_hal_gpio_fastgpio_clr(pin); + + am_hal_gpio_fast_pinconfig((uint64_t)0x1 << pin, + g_AM_HAL_GPIO_OUTPUT, 0); + // uint32_t ui32Ret = am_hal_gpio_fast_pinconfig((uint64_t)0x1 << pin, + // g_AM_HAL_GPIO_OUTPUT, 0); + // if (ui32Ret) { + // am_util_stdio_printf( + // "Error returned from am_hal_gpio_fast_pinconfig() = .\n", ui32Ret); + // } +#endif +} + +// Note - The timings used below are based on the Arduino Zero, +// Gemma/Trinket M0 code. + +/*! + @brief Transmit pixel data in RAM to NeoPixels. + @note The current design is a quick hack and should be replaced with + a more robust timing mechanism. +*/ +void Adafruit_NeoPixel::apollo3Show( + uint16_t pin, uint8_t *pixels, uint32_t numBytes, boolean is800KHz) { + + uint8_t *ptr, *end, p, bitMask; + ptr = pixels; + end = ptr + numBytes; + p = *ptr++; + bitMask = 0x80; + +#if defined(PIN_METHOD_FAST_GPIO) + + // disable interrupts + am_hal_interrupt_master_disable(); + +#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled + if(is800KHz) { +#endif + for(;;) { + am_hal_gpio_fastgpio_set(pin); + //asm("nop; nop; nop; nop; nop; nop; nop; nop;"); + asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); + if(p & bitMask) { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop;"); + am_hal_gpio_fastgpio_clr(pin); + } else { + am_hal_gpio_fastgpio_clr(pin); + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop;"); + } + if(bitMask >>= 1) { + asm("nop; nop; nop; nop; nop; nop; nop; nop; nop;"); + } else { + if(ptr >= end) break; + p = *ptr++; + bitMask = 0x80; + } + } +#ifdef NEO_KHZ400 + } else { // 400 KHz bitstream + // NOTE - These timings may need to be tweaked + for(;;) { + am_hal_gpio_fastgpio_set(pin); + //asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); + asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); + if(p & bitMask) { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop;"); + am_hal_gpio_fastgpio_clr(pin); + } else { + am_hal_gpio_fastgpio_clr(pin); + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop;"); + } + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;"); + if(bitMask >>= 1) { + asm("nop; nop; nop; nop; nop; nop; nop;"); + } else { + if(ptr >= end) break; + p = *ptr++; + bitMask = 0x80; + } + } + } + + // re-enable interrupts + am_hal_interrupt_master_enable(); + +#endif // NEO_KHZ400 +#endif // PIN_METHOD_FAST_GPIO +} + +#endif // AM_PART_APOLLO3