initial commit
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
# FastLED Platform: apollo3
|
||||
|
||||
Ambiq Apollo3 platform support.
|
||||
|
||||
## Files (quick pass)
|
||||
- `fastled_apollo3.h`: Aggregator; includes `fastpin_apollo3.h`, `fastspi_apollo3.h`, `clockless_apollo3.h`.
|
||||
- `fastpin_apollo3.h`: Pin helpers using Ambiq fastgpio; board‑specific `(pin,pad)` mappings (e.g., SFE Edge/Thing Plus/ATP, Artemis Nano, LoRa Thing Plus expLoRaBLE). Defines `HAS_HARDWARE_PIN_SUPPORT` when applicable.
|
||||
- `fastspi_apollo3.h`: Bit‑banged SPI via fastgpio (all pins usable). Provides `APOLLO3HardwareSPIOutput` with `writeBytes`, `writePixels`, and bit‑level toggling.
|
||||
- `clockless_apollo3.h`: Clockless WS281x controller using SysTick for timing on Apollo3 Blue; sets `FASTLED_HAS_CLOCKLESS`.
|
||||
|
||||
## Supported boards and toolchains
|
||||
|
||||
Known‑good Arduino cores/boards:
|
||||
|
||||
- SparkFun Apollo3 (Artemis) core and boards: Edge, Thing Plus, ATP, Artemis Nano, LoRa Thing Plus (expLoRaBLE)
|
||||
- Ambiq SDK‑based environments via the SparkFun core
|
||||
|
||||
Toolchain notes:
|
||||
|
||||
- Uses Ambiq's fastgpio for high‑rate toggling where available; otherwise falls back to standard GPIO which is significantly slower.
|
||||
- Ensure your core exposes `am_hal_gpio_*` APIs used by `fastpin_apollo3.h`. When missing, hardware pin specialization will be disabled.
|
||||
|
||||
Timing caveats:
|
||||
|
||||
- `clockless_apollo3.h` relies on SysTick for delay loops; large interrupt windows can corrupt WS281x signaling. Prefer short ISRs during frame output.
|
||||
- For best stability, keep Wi‑Fi/BLE stacks idle during `show()` and avoid heavy serial printing.
|
||||
@@ -0,0 +1,184 @@
|
||||
#ifndef __INC_CLOCKLESS_APOLLO3_H
|
||||
#define __INC_CLOCKLESS_APOLLO3_H
|
||||
|
||||
FASTLED_NAMESPACE_BEGIN
|
||||
|
||||
#if defined(FASTLED_APOLLO3)
|
||||
|
||||
// Clockless support for the SparkFun Artemis / Ambiq Micro Apollo3 Blue
|
||||
// Uses SysTick to govern the pulse timing
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Code taken from Ambiq Micro's am_hal_systick.c
|
||||
// and converted to inline static for speed
|
||||
//
|
||||
//! @brief Get the current count value in the SYSTICK.
|
||||
//!
|
||||
//! This function gets the current count value in the systick timer.
|
||||
//!
|
||||
//! @return Current count value.
|
||||
//
|
||||
//*****************************************************************************
|
||||
__attribute__ ((always_inline)) inline static uint32_t __am_hal_systick_count() {
|
||||
return SysTick->VAL;
|
||||
}
|
||||
|
||||
#define FASTLED_HAS_CLOCKLESS 1
|
||||
|
||||
template <uint8_t DATA_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 280>
|
||||
class ClocklessController : public CPixelLEDController<RGB_ORDER> {
|
||||
typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t;
|
||||
typedef typename FastPin<DATA_PIN>::port_t data_t;
|
||||
|
||||
CMinWait<WAIT_TIME> mWait;
|
||||
|
||||
public:
|
||||
virtual void init() {
|
||||
// Initialize everything
|
||||
|
||||
// Configure DATA_PIN for FastGPIO (settings are in fastpin_apollo3.h)
|
||||
FastPin<DATA_PIN>::setOutput();
|
||||
FastPin<DATA_PIN>::lo();
|
||||
|
||||
// Make sure the system clock is running at the full 48MHz
|
||||
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
|
||||
|
||||
// Make sure interrupts are enabled
|
||||
//am_hal_interrupt_master_enable();
|
||||
|
||||
// Enable SysTick Interrupts in the NVIC
|
||||
//NVIC_EnableIRQ(SysTick_IRQn);
|
||||
|
||||
// SysTick is 24-bit and counts down (not up)
|
||||
|
||||
// Stop the SysTick (just in case it is already running).
|
||||
// This clears the ENABLE bit in the SysTick Control and Status Register (SYST_CSR).
|
||||
// In Ambiq naming convention, the control register is SysTick->CTRL
|
||||
am_hal_systick_stop();
|
||||
|
||||
// Call SysTick_Config
|
||||
// This is defined in core_cm4.h
|
||||
// It loads the specified LOAD value into the SysTick Reload Value Register (SYST_RVR)
|
||||
// In Ambiq naming convention, the reload register is SysTick->LOAD
|
||||
// It sets the SysTick interrupt priority
|
||||
// It clears the SysTick Current Value Register (SYST_CVR)
|
||||
// In Ambiq naming convention, the current value register is SysTick->VAL
|
||||
// Finally it sets these bits in the SysTick Control and Status Register (SYST_CSR):
|
||||
// CLKSOURCE: SysTick uses the processor clock
|
||||
// TICKINT: When the count reaches zero, the SysTick exception (interrupt) is changed to pending
|
||||
// ENABLE: Enables the counter
|
||||
// SysTick_Config returns 0 if successful. 1 indicates a failure (the LOAD value was invalid).
|
||||
SysTick_Config(0xFFFFFFUL); // The LOAD value needs to be 24-bit
|
||||
}
|
||||
|
||||
virtual uint16_t getMaxRefreshRate() const { return 400; }
|
||||
|
||||
protected:
|
||||
virtual void showPixels(PixelController<RGB_ORDER> & pixels) {
|
||||
mWait.wait();
|
||||
if(!showRGBInternal(pixels)) {
|
||||
sei(); delayMicroseconds(WAIT_TIME); cli();
|
||||
showRGBInternal(pixels);
|
||||
}
|
||||
mWait.mark();
|
||||
}
|
||||
|
||||
template<int BITS> __attribute__ ((always_inline)) inline static void writeBits(FASTLED_REGISTER uint32_t & next_mark, FASTLED_REGISTER uint8_t & b) {
|
||||
// SysTick counts down (not up) and is 24-bit
|
||||
for(FASTLED_REGISTER uint32_t i = BITS-1; i > 0; i--) { // We could speed this up by using Bit Banding
|
||||
while(__am_hal_systick_count() > next_mark) { ; } // Wait for the remainder of this cycle to complete
|
||||
// Calculate next_mark (the time of the next DATA_PIN transition) by subtracting T1+T2+T3
|
||||
// SysTick counts down (not up) and is 24-bit
|
||||
next_mark = (__am_hal_systick_count() - (T1+T2+T3)) & 0xFFFFFFUL;
|
||||
FastPin<DATA_PIN>::hi();
|
||||
if(b&0x80) {
|
||||
// "1 code" = longer pulse width
|
||||
while((__am_hal_systick_count() - next_mark) > (T3+(3*(F_CPU/24000000)))) { ; }
|
||||
FastPin<DATA_PIN>::lo();
|
||||
} else {
|
||||
// "0 code" = shorter pulse width
|
||||
while((__am_hal_systick_count() - next_mark) > (T2+T3+(4*(F_CPU/24000000)))) { ; }
|
||||
FastPin<DATA_PIN>::lo();
|
||||
}
|
||||
b <<= 1;
|
||||
}
|
||||
|
||||
while(__am_hal_systick_count() > next_mark) { ; }// Wait for the remainder of this cycle to complete
|
||||
// Calculate next_mark (the time of the next DATA_PIN transition) by subtracting T1+T2+T3
|
||||
// SysTick counts down (not up) and is 24-bit
|
||||
next_mark = (__am_hal_systick_count() - (T1+T2+T3)) & 0xFFFFFFUL;
|
||||
FastPin<DATA_PIN>::hi();
|
||||
if(b&0x80) {
|
||||
// "1 code" = longer pulse width
|
||||
while((__am_hal_systick_count() - next_mark) > (T3+(2*(F_CPU/24000000)))) { ; }
|
||||
FastPin<DATA_PIN>::lo();
|
||||
} else {
|
||||
// "0 code" = shorter pulse width
|
||||
while((__am_hal_systick_count() - next_mark) > (T2+T3+(4*(F_CPU/24000000)))) { ; }
|
||||
FastPin<DATA_PIN>::lo();
|
||||
}
|
||||
}
|
||||
|
||||
// This method is made static to force making register Y available to use for data on AVR - if the method is non-static, then
|
||||
// gcc will use register Y for the this pointer.
|
||||
static uint32_t showRGBInternal(PixelController<RGB_ORDER> pixels) {
|
||||
|
||||
// Setup the pixel controller and load/scale the first byte
|
||||
pixels.preStepFirstByteDithering();
|
||||
FASTLED_REGISTER uint8_t b = pixels.loadAndScale0();
|
||||
|
||||
cli();
|
||||
|
||||
// Calculate next_mark (the time of the next DATA_PIN transition) by subtracting T1+T2+T3
|
||||
// SysTick counts down (not up) and is 24-bit
|
||||
// The subtraction could underflow (wrap round) so let's mask the result to 24 bits
|
||||
FASTLED_REGISTER uint32_t next_mark = (__am_hal_systick_count() - (T1+T2+T3)) & 0xFFFFFFUL;
|
||||
|
||||
while(pixels.has(1)) { // Keep going for as long as we have pixels
|
||||
pixels.stepDithering();
|
||||
|
||||
#if (FASTLED_ALLOW_INTERRUPTS == 1)
|
||||
cli();
|
||||
|
||||
// Have we already missed the next_mark?
|
||||
if(__am_hal_systick_count() < next_mark) {
|
||||
// If we have exceeded next_mark by an excessive amount, then bail (return 0)
|
||||
if((next_mark - __am_hal_systick_count()) > ((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US)) { sei(); return 0; }
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write first byte, read next byte
|
||||
writeBits<8+XTRA0>(next_mark, b);
|
||||
b = pixels.loadAndScale1();
|
||||
|
||||
// Write second byte, read 3rd byte
|
||||
writeBits<8+XTRA0>(next_mark, b);
|
||||
b = pixels.loadAndScale2();
|
||||
|
||||
// Write third byte, read 1st byte of next pixel
|
||||
writeBits<8+XTRA0>(next_mark, b);
|
||||
b = pixels.advanceAndLoadAndScale0();
|
||||
|
||||
#if (FASTLED_ALLOW_INTERRUPTS == 1)
|
||||
sei();
|
||||
#endif
|
||||
}; // end of while(pixels.has(1))
|
||||
|
||||
// Unfortunately SysTick relies on an interrupt to reload it once it reaches zero
|
||||
// and having interrupts disabled for most of the above means the interrupt doesn't get serviced.
|
||||
// So we had better reload it here instead...
|
||||
am_hal_systick_load(0xFFFFFFUL);
|
||||
|
||||
sei();
|
||||
return (1);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
FASTLED_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#define FASTLED_INTERNAL
|
||||
#include "FastLED.h"
|
||||
|
||||
namespace fl {
|
||||
|
||||
void apollo3_compile_tests() {
|
||||
#if FASTLED_USE_PROGMEM != 0
|
||||
#error "FASTLED_USE_PROGMEM should be 0 for Apollo3"
|
||||
#endif
|
||||
|
||||
#if SKETCH_HAS_LOTS_OF_MEMORY != 1
|
||||
#error "SKETCH_HAS_LOTS_OF_MEMORY should be 1 for Apollo3"
|
||||
#endif
|
||||
|
||||
#if FASTLED_ALLOW_INTERRUPTS != 1
|
||||
#error "FASTLED_ALLOW_INTERRUPTS should be 1 for Apollo3"
|
||||
#endif
|
||||
|
||||
#ifndef F_CPU
|
||||
#error "F_CPU should be defined for Apollo3"
|
||||
#endif
|
||||
|
||||
// Check that Apollo3-specific features are available
|
||||
#ifndef APOLLO3
|
||||
#warning "APOLLO3 macro not defined - this may indicate platform detection issues"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef __INC_FASTLED_APOLLO3_H
|
||||
#define __INC_FASTLED_APOLLO3_H
|
||||
|
||||
#include "fastpin_apollo3.h"
|
||||
#include "fastspi_apollo3.h"
|
||||
#include "clockless_apollo3.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
#ifndef __INC_FASTPIN_APOLLO3_H
|
||||
#define __INC_FASTPIN_APOLLO3_H
|
||||
|
||||
#include "fl/stdint.h"
|
||||
#include "fl/namespace.h"
|
||||
|
||||
FASTLED_NAMESPACE_BEGIN
|
||||
|
||||
#if defined(FASTLED_FORCE_SOFTWARE_PINS)
|
||||
#warning "Software pin support forced, pin access will be slightly slower."
|
||||
#define NO_HARDWARE_PIN_SUPPORT
|
||||
#undef HAS_HARDWARE_PIN_SUPPORT
|
||||
|
||||
#else
|
||||
|
||||
template<uint8_t PIN, uint8_t PAD> class _APOLLO3PIN {
|
||||
public:
|
||||
typedef volatile uint32_t * port_ptr_t;
|
||||
typedef uint32_t port_t;
|
||||
|
||||
inline static void setOutput() { pinMode(PIN, OUTPUT); am_hal_gpio_fastgpio_enable(PAD); }
|
||||
inline static void setInput() { am_hal_gpio_fastgpio_disable(PAD); pinMode(PIN, INPUT); }
|
||||
|
||||
inline static void hi() __attribute__ ((always_inline)) { am_hal_gpio_fastgpio_set(PAD); }
|
||||
inline static void lo() __attribute__ ((always_inline)) { am_hal_gpio_fastgpio_clr(PAD); }
|
||||
inline static void set(FASTLED_REGISTER port_t val) __attribute__ ((always_inline)) { if(val) { am_hal_gpio_fastgpio_set(PAD); } else { am_hal_gpio_fastgpio_clr(PAD); } }
|
||||
|
||||
inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); }
|
||||
|
||||
inline static void toggle() __attribute__ ((always_inline)) { if( am_hal_gpio_fastgpio_read(PAD)) { lo(); } else { hi(); } }
|
||||
|
||||
inline static void hi(FASTLED_REGISTER port_ptr_t port) __attribute__ ((always_inline)) { hi(); }
|
||||
inline static void lo(FASTLED_REGISTER port_ptr_t port) __attribute__ ((always_inline)) { lo(); }
|
||||
inline static void fastset(FASTLED_REGISTER port_ptr_t port, FASTLED_REGISTER port_t val) __attribute__ ((always_inline)) { set(val); }
|
||||
|
||||
inline static port_t hival() __attribute__ ((always_inline)) { return 0; }
|
||||
inline static port_t loval() __attribute__ ((always_inline)) { return 0; }
|
||||
inline static port_ptr_t port() __attribute__ ((always_inline)) { return NULL; }
|
||||
inline static port_t mask() __attribute__ ((always_inline)) { return 0; }
|
||||
};
|
||||
|
||||
// For the Apollo3 we need to define both the pin number and the associated pad
|
||||
// to avoid having to use ap3_gpio_pin2pad for fastgpio (which would slow things down)
|
||||
#define _FL_DEFPIN(PIN, PAD) template<> class FastPin<PIN> : public _APOLLO3PIN<PIN, PAD> {};
|
||||
|
||||
// Actual (pin, pad) definitions
|
||||
#if defined(ARDUINO_SFE_EDGE)
|
||||
|
||||
#define MAX_PIN 49
|
||||
_FL_DEFPIN(0, 0); _FL_DEFPIN(1, 1); _FL_DEFPIN(3, 3); _FL_DEFPIN(4, 4);
|
||||
_FL_DEFPIN(5, 5); _FL_DEFPIN(6, 6); _FL_DEFPIN(7, 7); _FL_DEFPIN(8, 8); _FL_DEFPIN(9, 9);
|
||||
_FL_DEFPIN(10, 10); _FL_DEFPIN(11, 11); _FL_DEFPIN(12, 12); _FL_DEFPIN(13, 13); _FL_DEFPIN(14, 14);
|
||||
_FL_DEFPIN(15, 15); _FL_DEFPIN(17, 17);
|
||||
_FL_DEFPIN(20, 20); _FL_DEFPIN(21, 21); _FL_DEFPIN(22, 22); _FL_DEFPIN(23, 23); _FL_DEFPIN(24, 24);
|
||||
_FL_DEFPIN(25, 25); _FL_DEFPIN(26, 26); _FL_DEFPIN(27, 27); _FL_DEFPIN(28, 28); _FL_DEFPIN(29, 29);
|
||||
_FL_DEFPIN(33, 33);
|
||||
_FL_DEFPIN(36, 36); _FL_DEFPIN(37, 37); _FL_DEFPIN(38, 38); _FL_DEFPIN(39, 39);
|
||||
_FL_DEFPIN(40, 40); _FL_DEFPIN(42, 42); _FL_DEFPIN(43, 43); _FL_DEFPIN(44, 44);
|
||||
_FL_DEFPIN(46, 46); _FL_DEFPIN(47, 47); _FL_DEFPIN(48, 48); _FL_DEFPIN(49, 49);
|
||||
|
||||
#define HAS_HARDWARE_PIN_SUPPORT 1
|
||||
|
||||
#elif defined(ARDUINO_SFE_EDGE2)
|
||||
|
||||
#define MAX_PIN 49
|
||||
_FL_DEFPIN(0, 0);
|
||||
_FL_DEFPIN(5, 5); _FL_DEFPIN(6, 6); _FL_DEFPIN(7, 7); _FL_DEFPIN(8, 8); _FL_DEFPIN(9, 9);
|
||||
_FL_DEFPIN(11, 11); _FL_DEFPIN(12, 12); _FL_DEFPIN(13, 13); _FL_DEFPIN(14, 14);
|
||||
_FL_DEFPIN(15, 15); _FL_DEFPIN(16, 16); _FL_DEFPIN(17, 17); _FL_DEFPIN(18, 18); _FL_DEFPIN(19, 19);
|
||||
_FL_DEFPIN(20, 20); _FL_DEFPIN(21, 21); _FL_DEFPIN(23, 23);
|
||||
_FL_DEFPIN(25, 25); _FL_DEFPIN(26, 26); _FL_DEFPIN(27, 27); _FL_DEFPIN(28, 28); _FL_DEFPIN(29, 29);
|
||||
_FL_DEFPIN(31, 31); _FL_DEFPIN(32, 32); _FL_DEFPIN(33, 33); _FL_DEFPIN(34, 34);
|
||||
_FL_DEFPIN(35, 35); _FL_DEFPIN(37, 37); _FL_DEFPIN(39, 39);
|
||||
_FL_DEFPIN(40, 40); _FL_DEFPIN(41, 41); _FL_DEFPIN(42, 42); _FL_DEFPIN(43, 43); _FL_DEFPIN(44, 44);
|
||||
_FL_DEFPIN(45, 45); _FL_DEFPIN(48, 48); _FL_DEFPIN(49, 49);
|
||||
|
||||
#define HAS_HARDWARE_PIN_SUPPORT 1
|
||||
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_BB_ARTEMIS)
|
||||
|
||||
#define MAX_PIN 31
|
||||
_FL_DEFPIN(0, 25); _FL_DEFPIN(1, 24); _FL_DEFPIN(2, 35); _FL_DEFPIN(3, 4); _FL_DEFPIN(4, 22);
|
||||
_FL_DEFPIN(5, 23); _FL_DEFPIN(6, 27); _FL_DEFPIN(7, 28); _FL_DEFPIN(8, 32); _FL_DEFPIN(9, 12);
|
||||
_FL_DEFPIN(10, 13); _FL_DEFPIN(11, 7); _FL_DEFPIN(12, 6); _FL_DEFPIN(13, 5); _FL_DEFPIN(14, 40);
|
||||
_FL_DEFPIN(15, 39); _FL_DEFPIN(16, 29); _FL_DEFPIN(17, 11); _FL_DEFPIN(18, 34); _FL_DEFPIN(19, 33);
|
||||
_FL_DEFPIN(20, 16); _FL_DEFPIN(21, 31); _FL_DEFPIN(22, 48); _FL_DEFPIN(23, 49); _FL_DEFPIN(24, 8);
|
||||
_FL_DEFPIN(25, 9); _FL_DEFPIN(26, 10); _FL_DEFPIN(27, 38); _FL_DEFPIN(28, 42); _FL_DEFPIN(29, 43);
|
||||
_FL_DEFPIN(30, 36); _FL_DEFPIN(31, 37);
|
||||
|
||||
#define HAS_HARDWARE_PIN_SUPPORT 1
|
||||
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_BB_ARTEMIS_NANO) || defined(ARDUINO_APOLLO3_SFE_ARTEMIS_NANO)
|
||||
|
||||
|
||||
#define MAX_PIN 23
|
||||
_FL_DEFPIN(0, 13); _FL_DEFPIN(1, 33); _FL_DEFPIN(2, 11); _FL_DEFPIN(3, 29); _FL_DEFPIN(4, 18);
|
||||
_FL_DEFPIN(5, 31); _FL_DEFPIN(6, 43); _FL_DEFPIN(7, 42); _FL_DEFPIN(8, 38); _FL_DEFPIN(9, 39);
|
||||
_FL_DEFPIN(10, 40); _FL_DEFPIN(11, 5); _FL_DEFPIN(12, 7); _FL_DEFPIN(13, 6); _FL_DEFPIN(14, 35);
|
||||
_FL_DEFPIN(15, 32); _FL_DEFPIN(16, 12); _FL_DEFPIN(17, 32); _FL_DEFPIN(18, 12); _FL_DEFPIN(19, 19);
|
||||
_FL_DEFPIN(20, 48); _FL_DEFPIN(21, 49); _FL_DEFPIN(22, 36); _FL_DEFPIN(23, 37);
|
||||
|
||||
#define HAS_HARDWARE_PIN_SUPPORT 1
|
||||
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_THING_PLUS)
|
||||
|
||||
#define MAX_PIN 28
|
||||
_FL_DEFPIN(0, 25); _FL_DEFPIN(1, 24); _FL_DEFPIN(2, 44); _FL_DEFPIN(3, 35); _FL_DEFPIN(4, 4);
|
||||
_FL_DEFPIN(5, 22); _FL_DEFPIN(6, 23); _FL_DEFPIN(7, 27); _FL_DEFPIN(8, 28); _FL_DEFPIN(9, 32);
|
||||
_FL_DEFPIN(10, 14); _FL_DEFPIN(11, 7); _FL_DEFPIN(12, 6); _FL_DEFPIN(13, 5); _FL_DEFPIN(14, 40);
|
||||
_FL_DEFPIN(15, 39); _FL_DEFPIN(16, 43); _FL_DEFPIN(17, 42); _FL_DEFPIN(18, 26); _FL_DEFPIN(19, 33);
|
||||
_FL_DEFPIN(20, 13); _FL_DEFPIN(21, 11); _FL_DEFPIN(22, 29); _FL_DEFPIN(23, 12); _FL_DEFPIN(24, 31);
|
||||
_FL_DEFPIN(25, 48); _FL_DEFPIN(26, 49); _FL_DEFPIN(27, 36); _FL_DEFPIN(28, 37);
|
||||
|
||||
#define HAS_HARDWARE_PIN_SUPPORT 1
|
||||
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_BB_ARTEMIS_ATP) || defined(ARDUINO_SFE_ARTEMIS) || defined(ARDUINO_APOLLO3_SFE_ARTEMIS_ATP)
|
||||
|
||||
#define MAX_PIN 49
|
||||
_FL_DEFPIN(0, 0); _FL_DEFPIN(1, 1); _FL_DEFPIN(2, 2); _FL_DEFPIN(3, 3); _FL_DEFPIN(4, 4);
|
||||
_FL_DEFPIN(5, 5); _FL_DEFPIN(6, 6); _FL_DEFPIN(7, 7); _FL_DEFPIN(8, 8); _FL_DEFPIN(9, 9);
|
||||
_FL_DEFPIN(10, 10); _FL_DEFPIN(11, 11); _FL_DEFPIN(12, 12); _FL_DEFPIN(13, 13); _FL_DEFPIN(14, 14);
|
||||
_FL_DEFPIN(15, 15); _FL_DEFPIN(16, 16); _FL_DEFPIN(17, 17); _FL_DEFPIN(18, 18); _FL_DEFPIN(19, 19);
|
||||
_FL_DEFPIN(20, 20); _FL_DEFPIN(21, 21); _FL_DEFPIN(22, 22); _FL_DEFPIN(23, 23); _FL_DEFPIN(24, 24);
|
||||
_FL_DEFPIN(25, 25); _FL_DEFPIN(26, 26); _FL_DEFPIN(27, 27); _FL_DEFPIN(28, 28); _FL_DEFPIN(29, 29);
|
||||
_FL_DEFPIN(31, 31); _FL_DEFPIN(32, 32); _FL_DEFPIN(33, 33); _FL_DEFPIN(34, 34);
|
||||
_FL_DEFPIN(35, 35); _FL_DEFPIN(36, 36); _FL_DEFPIN(37, 37); _FL_DEFPIN(38, 38); _FL_DEFPIN(39, 39);
|
||||
_FL_DEFPIN(40, 40); _FL_DEFPIN(41, 41); _FL_DEFPIN(42, 42); _FL_DEFPIN(43, 43); _FL_DEFPIN(44, 44);
|
||||
_FL_DEFPIN(45, 45); _FL_DEFPIN(47, 47); _FL_DEFPIN(48, 48); _FL_DEFPIN(49, 49);
|
||||
|
||||
#define HAS_HARDWARE_PIN_SUPPORT 1
|
||||
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_ARTEMIS_DK)
|
||||
|
||||
#define MAX_PIN 49
|
||||
_FL_DEFPIN(0, 0); _FL_DEFPIN(1, 1); _FL_DEFPIN(2, 2); _FL_DEFPIN(3, 3); _FL_DEFPIN(4, 4);
|
||||
_FL_DEFPIN(5, 5); _FL_DEFPIN(6, 6); _FL_DEFPIN(7, 7); _FL_DEFPIN(8, 8); _FL_DEFPIN(9, 9);
|
||||
_FL_DEFPIN(10, 10); _FL_DEFPIN(11, 11); _FL_DEFPIN(12, 12); _FL_DEFPIN(13, 13); _FL_DEFPIN(14, 14);
|
||||
_FL_DEFPIN(15, 15); _FL_DEFPIN(16, 16); _FL_DEFPIN(17, 17); _FL_DEFPIN(18, 18); _FL_DEFPIN(19, 19);
|
||||
_FL_DEFPIN(20, 20); _FL_DEFPIN(21, 21); _FL_DEFPIN(22, 22); _FL_DEFPIN(23, 23); _FL_DEFPIN(24, 24);
|
||||
_FL_DEFPIN(25, 25); _FL_DEFPIN(26, 26); _FL_DEFPIN(27, 27); _FL_DEFPIN(28, 28); _FL_DEFPIN(29, 29);
|
||||
_FL_DEFPIN(31, 31); _FL_DEFPIN(32, 32); _FL_DEFPIN(33, 33); _FL_DEFPIN(34, 34);
|
||||
_FL_DEFPIN(35, 35); _FL_DEFPIN(36, 36); _FL_DEFPIN(37, 37); _FL_DEFPIN(38, 38); _FL_DEFPIN(39, 39);
|
||||
_FL_DEFPIN(40, 40); _FL_DEFPIN(41, 41); _FL_DEFPIN(42, 42); _FL_DEFPIN(43, 43); _FL_DEFPIN(44, 44);
|
||||
_FL_DEFPIN(45, 45); _FL_DEFPIN(47, 47); _FL_DEFPIN(48, 48); _FL_DEFPIN(49, 49);
|
||||
#define HAS_HARDWARE_PIN_SUPPORT 1
|
||||
|
||||
#elif defined(ARDUINO_LoRa_THING_PLUS_expLoRaBLE) || defined(ARDUINO_AM_AP3_THING_PLUS_expLoRaBLE)
|
||||
|
||||
#define MAX_PIN 47
|
||||
|
||||
// Provided by the community:
|
||||
// https://www.reddit.com/r/FastLED/comments/1i30ycy/ambiq_apollo3_commit_specifically_the_spe_lora/
|
||||
// Special Thanks to reddit.com/u/Aromatic-Effort-9414 for providing these pin definitions
|
||||
_FL_DEFPIN(0, 19); _FL_DEFPIN(1, 18); _FL_DEFPIN(2, 41); _FL_DEFPIN(3, 31); _FL_DEFPIN(4, 10);
|
||||
_FL_DEFPIN(5, 30); _FL_DEFPIN(6, 37); _FL_DEFPIN(7, 24); _FL_DEFPIN(8, 46); _FL_DEFPIN(9, 33);
|
||||
_FL_DEFPIN(10, 4); _FL_DEFPIN(11, 28); _FL_DEFPIN(12, 25); _FL_DEFPIN(13, 27); _FL_DEFPIN(14, 6);
|
||||
_FL_DEFPIN(15, 5); _FL_DEFPIN(16, 9); _FL_DEFPIN(17, 8); _FL_DEFPIN(18, 26); _FL_DEFPIN(19, 13);
|
||||
_FL_DEFPIN(20, 12); _FL_DEFPIN(21, 32); _FL_DEFPIN(22, 35); _FL_DEFPIN(23, 34); _FL_DEFPIN(24, 11);
|
||||
_FL_DEFPIN(25, 36); _FL_DEFPIN(26, 38); _FL_DEFPIN(27, 39); _FL_DEFPIN(28, 40); _FL_DEFPIN(29, 42);
|
||||
_FL_DEFPIN(30, 43); _FL_DEFPIN(31, 44); _FL_DEFPIN(32, 47);
|
||||
|
||||
#define HAS_HARDWARE_PIN_SUPPORT 1
|
||||
#else
|
||||
|
||||
#error "Unrecognised APOLLO3 board!"
|
||||
|
||||
#endif
|
||||
|
||||
#endif // FASTLED_FORCE_SOFTWARE_PINS
|
||||
|
||||
FASTLED_NAMESPACE_END
|
||||
|
||||
#endif // __INC_FASTPIN_AVR_H
|
||||
@@ -0,0 +1,134 @@
|
||||
#ifndef __INC_FASTSPI_APOLLO3_H
|
||||
#define __INC_FASTSPI_APOLLO3_H
|
||||
|
||||
// This is the implementation of fastspi for the Apollo3.
|
||||
// It uses fastgpio instead of actual SPI, which means you can use it on all pins.
|
||||
// It can run slightly faster than the default fastpin (bit banging).
|
||||
|
||||
#include "FastLED.h"
|
||||
|
||||
FASTLED_NAMESPACE_BEGIN
|
||||
|
||||
#if defined(FASTLED_APOLLO3)
|
||||
|
||||
#define FASTLED_ALL_PINS_HARDWARE_SPI
|
||||
|
||||
template <uint8_t _DATA_PIN, uint8_t _CLOCK_PIN, uint32_t _SPI_CLOCK_DIVIDER>
|
||||
class APOLLO3HardwareSPIOutput {
|
||||
Selectable *m_pSelect;
|
||||
|
||||
public:
|
||||
APOLLO3HardwareSPIOutput() { m_pSelect = NULL; }
|
||||
APOLLO3HardwareSPIOutput(Selectable *pSelect) { m_pSelect = pSelect; }
|
||||
|
||||
// set the object representing the selectable
|
||||
void setSelect(Selectable *pSelect) { m_pSelect = pSelect; }
|
||||
|
||||
// initialize the pins for fastgpio
|
||||
void init() {
|
||||
FastPin<_CLOCK_PIN>::setOutput();
|
||||
FastPin<_CLOCK_PIN>::lo();
|
||||
FastPin<_DATA_PIN>::setOutput();
|
||||
FastPin<_DATA_PIN>::lo();
|
||||
}
|
||||
|
||||
// latch the CS select
|
||||
void inline select() { /* TODO */ }
|
||||
|
||||
// release the CS select
|
||||
void inline release() { /* TODO */ }
|
||||
|
||||
// wait until all queued up data has been written
|
||||
static void waitFully() { /* TODO */ }
|
||||
|
||||
// write a byte as bits
|
||||
static void writeByte(uint8_t b) {
|
||||
writeBit<7>(b);
|
||||
writeBit<6>(b);
|
||||
writeBit<5>(b);
|
||||
writeBit<4>(b);
|
||||
writeBit<3>(b);
|
||||
writeBit<2>(b);
|
||||
writeBit<1>(b);
|
||||
writeBit<0>(b);
|
||||
}
|
||||
|
||||
// write a word out via SPI (returns immediately on writing register)
|
||||
static void writeWord(uint16_t w) {
|
||||
writeByte((uint8_t)((w >> 8) & 0xff));
|
||||
writeByte((uint8_t)(w & 0xff));
|
||||
}
|
||||
|
||||
// A raw set of writing byte values, assumes setup/init/waiting done elsewhere
|
||||
static void writeBytesValueRaw(uint8_t value, int len) {
|
||||
while(len--) { writeByte(value); }
|
||||
}
|
||||
|
||||
// A full cycle of writing a value for len bytes, including select, release, and waiting
|
||||
void writeBytesValue(uint8_t value, int len) {
|
||||
select();
|
||||
writeBytesValueRaw(value, len);
|
||||
release();
|
||||
}
|
||||
|
||||
// A full cycle of writing a value for len bytes, including select, release, and waiting
|
||||
template <class D> void writeBytes(FASTLED_REGISTER uint8_t *data, int len) {
|
||||
uint8_t *end = data + len;
|
||||
select();
|
||||
// could be optimized to write 16bit words out instead of 8bit bytes
|
||||
while(data != end) {
|
||||
writeByte(D::adjust(*data++));
|
||||
}
|
||||
D::postBlock(len);
|
||||
waitFully();
|
||||
release();
|
||||
}
|
||||
|
||||
// A full cycle of writing a value for len bytes, including select, release, and waiting
|
||||
void writeBytes(FASTLED_REGISTER uint8_t *data, int len) { writeBytes<DATA_NOP>(data, len); }
|
||||
|
||||
// write a single bit out, which bit from the passed in byte is determined by template parameter
|
||||
template <uint8_t BIT> inline static void writeBit(uint8_t b) {
|
||||
//waitFully();
|
||||
if(b & (1 << BIT)) {
|
||||
FastPin<_DATA_PIN>::hi();
|
||||
} else {
|
||||
FastPin<_DATA_PIN>::lo();
|
||||
}
|
||||
|
||||
FastPin<_CLOCK_PIN>::hi();
|
||||
for (uint32_t d = (_SPI_CLOCK_DIVIDER >> 1); d > 0; d--) { __NOP(); }
|
||||
FastPin<_CLOCK_PIN>::lo();
|
||||
for (uint32_t d = (_SPI_CLOCK_DIVIDER >> 1); d > 0; d--) { __NOP(); }
|
||||
}
|
||||
|
||||
// write a block of uint8_ts out in groups of three. len is the total number of uint8_ts to write out. The template
|
||||
// parameters indicate how many uint8_ts to skip at the beginning and/or end of each grouping
|
||||
template <uint8_t FLAGS, class D, EOrder RGB_ORDER> void writePixels(PixelController<RGB_ORDER> pixels, void* context = NULL) {
|
||||
select();
|
||||
|
||||
int len = pixels.mLen;
|
||||
|
||||
while(pixels.has(1)) {
|
||||
if(FLAGS & FLAG_START_BIT) {
|
||||
writeBit<0>(1);
|
||||
}
|
||||
writeByte(D::adjust(pixels.loadAndScale0()));
|
||||
writeByte(D::adjust(pixels.loadAndScale1()));
|
||||
writeByte(D::adjust(pixels.loadAndScale2()));
|
||||
|
||||
pixels.advanceData();
|
||||
pixels.stepDithering();
|
||||
}
|
||||
D::postBlock(len);
|
||||
//waitFully();
|
||||
release();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
FASTLED_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef __INC_LED_SYSDEFS_APOLLO3_H
|
||||
#define __INC_LED_SYSDEFS_APOLLO3_H
|
||||
|
||||
#define FASTLED_APOLLO3
|
||||
|
||||
#ifndef INTERRUPT_THRESHOLD
|
||||
#define INTERRUPT_THRESHOLD 1
|
||||
#endif
|
||||
|
||||
// Default to allowing interrupts
|
||||
#ifndef FASTLED_ALLOW_INTERRUPTS
|
||||
#define FASTLED_ALLOW_INTERRUPTS 1
|
||||
#endif
|
||||
|
||||
#if FASTLED_ALLOW_INTERRUPTS == 1
|
||||
#define FASTLED_ACCURATE_CLOCK
|
||||
#endif
|
||||
|
||||
#ifndef F_CPU
|
||||
#define F_CPU 48000000
|
||||
#endif
|
||||
|
||||
// Default to NOT using PROGMEM
|
||||
#ifndef FASTLED_USE_PROGMEM
|
||||
#define FASTLED_USE_PROGMEM 0
|
||||
#endif
|
||||
|
||||
// data type defs
|
||||
typedef volatile uint8_t RoReg; /**< Read only 8-bit register (volatile const unsigned int) */
|
||||
typedef volatile uint8_t RwReg; /**< Read-Write 8-bit register (volatile unsigned int) */
|
||||
|
||||
#define FASTLED_NO_PINMAP
|
||||
|
||||
// reusing/abusing cli/sei defs for due
|
||||
// These should be fine for the Apollo3. It has its own defines in cmsis_gcc.h
|
||||
#define cli() __disable_irq(); //__disable_fault_irq();
|
||||
#define sei() __enable_irq(); //__enable_fault_irq();
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user