From 55964e843c014b61fbbca1fa9f91aae0fadee665 Mon Sep 17 00:00:00 2001 From: Daniel Garcia Date: Thu, 15 Aug 2019 00:34:46 -0700 Subject: Preliminary work for ATmega4809 - needs work on the asm side to support clockless chips, also needs work to have hardware SPI available --- examples/Pintest/Pintest.ino | 6 +- led_sysdefs.h | 8 ++- platforms.h | 5 +- platforms/avr/clockless_trinket.h | 2 +- platforms/avrmega/fastled_avrmega.h | 13 ++++ platforms/avrmega/fastpin_avrmega.h | 123 ++++++++++++++++++++++++++++++++ platforms/avrmega/led_sysdefs_avrmega.h | 67 +++++++++++++++++ 7 files changed, 216 insertions(+), 8 deletions(-) create mode 100644 platforms/avrmega/fastled_avrmega.h create mode 100644 platforms/avrmega/fastpin_avrmega.h create mode 100644 platforms/avrmega/led_sysdefs_avrmega.h diff --git a/examples/Pintest/Pintest.ino b/examples/Pintest/Pintest.ino index a8141520..2189d0aa 100644 --- a/examples/Pintest/Pintest.ino +++ b/examples/Pintest/Pintest.ino @@ -146,14 +146,14 @@ template void PrintPins() { const char *pinport = GetPinPort((void*)systemThinksPortIs); if (pinport) { - Serial.print("__FL_DEFPIN("); Serial.print(PIN); + Serial.print("_FL_DEFPIN("); Serial.print(PIN); Serial.print(","); Serial.print(maskBit); Serial.print(","); Serial.print(pinport); Serial.print("); "); pcount++; if(pcount == 4) { pcount = 0; Serial.println(""); } } else { - // Serial.print("Not found for pin "); Serial.println(PIN); + Serial.print("Not found for pin "); Serial.println(PIN); } } @@ -178,7 +178,7 @@ template<> void PrintPins<0>() { int counter = 0; void setup() { delay(5000); - Serial.begin(38400); + Serial.begin(115200); Serial.println("resetting!"); } diff --git a/led_sysdefs.h b/led_sysdefs.h index 27da24a0..80dbcd97 100644 --- a/led_sysdefs.h +++ b/led_sysdefs.h @@ -32,9 +32,13 @@ #include "platforms/esp/8266/led_sysdefs_esp8266.h" #elif defined(ESP32) #include "platforms/esp/32/led_sysdefs_esp32.h" -#else -// AVR platforms +#elif defined(ARDUINO_ARCH_AVR) #include "platforms/avr/led_sysdefs_avr.h" +#elif defined(ARDUINO_ARCH_MEGAAVR) +#include "platforms/avrmega/led_sysdefs_avrmega.h" +#else +#error No platform definitions found, stoping compilation. +#include #endif #ifndef FASTLED_NAMESPACE_BEGIN diff --git a/platforms.h b/platforms.h index f66599fd..b9653b7d 100644 --- a/platforms.h +++ b/platforms.h @@ -34,9 +34,10 @@ #include "platforms/esp/8266/fastled_esp8266.h" #elif defined(ESP32) #include "platforms/esp/32/fastled_esp32.h" -#else -// AVR platforms +#elif defined(ARDUINO_ARCH_AVR) #include "platforms/avr/fastled_avr.h" +#elif defined(ARDUINO_ARCH_MEGAAVR) +#include "platforms/avrmega/fastled_avrmega.h" #endif #endif diff --git a/platforms/avr/clockless_trinket.h b/platforms/avr/clockless_trinket.h index 69f33d6a..3c1c2146 100644 --- a/platforms/avr/clockless_trinket.h +++ b/platforms/avr/clockless_trinket.h @@ -7,7 +7,7 @@ FASTLED_NAMESPACE_BEGIN -#if defined(FASTLED_AVR) +#if defined(FASTLED_AVR) || defined(FASTLED_AVRMEGA) // Scaling macro choice #ifndef TRINKET_SCALE diff --git a/platforms/avrmega/fastled_avrmega.h b/platforms/avrmega/fastled_avrmega.h new file mode 100644 index 00000000..3d4dcafb --- /dev/null +++ b/platforms/avrmega/fastled_avrmega.h @@ -0,0 +1,13 @@ +#ifndef __INC_FASTLED_AVRMEGA_H +#define __INC_FASTLED_AVRMEGA_H + +#include "fastpin_avrmega.h" +// #include "fastspi_avrmega.h" +// #include "../avr/clockless_trinket.h" + +// Default to using PROGMEM +#ifndef FASTLED_USE_PROGMEM +#define FASTLED_USE_PROGMEM 1 +#endif + +#endif diff --git a/platforms/avrmega/fastpin_avrmega.h b/platforms/avrmega/fastpin_avrmega.h new file mode 100644 index 00000000..b781ca79 --- /dev/null +++ b/platforms/avrmega/fastpin_avrmega.h @@ -0,0 +1,123 @@ +#ifndef __INC_FASTPIN_AVRMEGA_H +#define __INC_FASTPIN_AVRMEGA_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 + +// THe AVRmega doesn't have the low memory fast GPIO access that the avr does +#define AVR_PIN_CYCLES(_PIN) (2) + +/// Class definition for a Pin where we know the port registers at compile time for said pin. This allows us to make +/// a lot of optimizations, as the inlined hi/lo methods will devolve to a single io register write/bitset. +template class _AVRMEGAPIN { +public: + typedef volatile uint8_t * port_ptr_t; + typedef uint8_t port_t; + + inline static void setOutput() { pinMode(PIN, OUTPUT); } + inline static void setInput() { pinMode(PIN, INPUT); } + + inline static void hi() __attribute__ ((always_inline)) { _PORT::r().OUTSET = _MASK; } + inline static void lo() __attribute__ ((always_inline)) { _PORT::r().OUTCLR = _MASK; } + inline static void set(register uint8_t val) __attribute__ ((always_inline)) { _PORT::r().OUT = val; } + + inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); } + + inline static void toggle() __attribute__ ((always_inline)) { _PORT::r().OUTTGL = _MASK; } + + inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); } + inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { lo(); } + inline static void fastset(register port_ptr_t port, register uint8_t val) __attribute__ ((always_inline)) { set(val); } + + inline static port_t hival() __attribute__ ((always_inline)) { return _PORT::r().OUT | _MASK; } + inline static port_t loval() __attribute__ ((always_inline)) { return _PORT::r().OUT & ~_MASK; } + inline static port_ptr_t port() __attribute__ ((always_inline)) { return &_PORT::r().OUT; } + inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; } +}; + + + +/// AVR definitions for pins. Getting around the fact that I can't pass GPIO register addresses in as template arguments by instead creating +/// a custom type for each GPIO register with a single, static, aggressively inlined function that returns that specific GPIO register. A similar +/// trick is used a bit further below for the ARM GPIO registers (of which there are far more than on AVR!) +typedef volatile uint8_t & reg8_t; +#define _R(T) struct __gen_struct_ ## T +#define _RD8(T) struct __gen_struct_ ## T { static inline volatile PORT_t & r() { return T; }}; +#define _FL_IO(L,C) _RD8(PORT ## L); template<> struct __FL_PORT_INFO { static bool hasPort() { return 1; } \ + static const char *portName() { return #L; } \ + typedef _R(PORT ## L) __t_baseType; \ + static const void *portAddr() { return (void*)&(__t_baseType::r().OUT); } }; +#define _FL_DEFPIN(_PIN, BIT, L) template<> class FastPin<_PIN> : public _AVRMEGAPIN<_PIN, 1< {}; + +// Pre-do all the port definitions +#ifdef PORTA + _FL_IO(A,0) +#endif +#ifdef PORTB + _FL_IO(B,1) +#endif +#ifdef PORTC + _FL_IO(C,2) +#endif +#ifdef PORTD + _FL_IO(D,3) +#endif +#ifdef PORTE + _FL_IO(E,4) +#endif +#ifdef PORTF + _FL_IO(F,5) +#endif +#ifdef PORTG + _FL_IO(G,6) +#endif +#ifdef PORTH + _FL_IO(H,7) +#endif +#ifdef PORTI + _FL_IO(I,8) +#endif +#ifdef PORTJ + _FL_IO(J,9) +#endif +#ifdef PORTK + _FL_IO(K,10) +#endif +#ifdef PORTL + _FL_IO(L,11) +#endif +#ifdef PORTM + _FL_IO(M,12) +#endif +#ifdef PORTN + _FL_IO(N,13) +#endif + +#if defined(ARDUINO_AVR_NANO_EVERY) +_FL_DEFPIN(0,5,C); _FL_DEFPIN(1,4,C); _FL_DEFPIN(2,0,A); _FL_DEFPIN(3,5,F); +_FL_DEFPIN(4,6,C); _FL_DEFPIN(5,2,B); _FL_DEFPIN(6,4,F); _FL_DEFPIN(7,1,A); +_FL_DEFPIN(8,3,E); _FL_DEFPIN(9,0,B); _FL_DEFPIN(10,1,B); _FL_DEFPIN(11,0,E); +_FL_DEFPIN(12,1,E); _FL_DEFPIN(13,2,E); _FL_DEFPIN(14,3,D); _FL_DEFPIN(15,2,D); +_FL_DEFPIN(16,1,D); _FL_DEFPIN(17,0,D); _FL_DEFPIN(18,2,F); _FL_DEFPIN(19,3,F); +_FL_DEFPIN(20,4,D); _FL_DEFPIN(21,5,D); _FL_DEFPIN(22,2,A); + +#define HAS_HARDWARE_PIN_SUPPORT 1 +#define MAX_PIN 22 + +// no hardware SPI yet + +#else +#pragma warning No pin definitions found. Try running examples/Pintest/Pintest.ino to get definitions from your AVRMEGA device +#endif + +#endif // FASTLED_FORCE_SOFTWARE_PINS + +FASTLED_NAMESPACE_END + +#endif // __INC_FASTPIN_AVR_H diff --git a/platforms/avrmega/led_sysdefs_avrmega.h b/platforms/avrmega/led_sysdefs_avrmega.h new file mode 100644 index 00000000..86b3c034 --- /dev/null +++ b/platforms/avrmega/led_sysdefs_avrmega.h @@ -0,0 +1,67 @@ +#ifndef __INC_LED_SYSDEFS_AVR_H +#define __INC_LED_SYSDEFS_AVR_H + +#define FASTLED_AVRMEGA + +#ifndef INTERRUPT_THRESHOLD +#define INTERRUPT_THRESHOLD 2 +#endif + +#define FASTLED_SPI_BYTE_ONLY + +#include +#include // for cli/se definitions + +// Define the register types +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) */ + + +// Default to disallowing interrupts (may want to gate this on teensy2 vs. other arm platforms, since the +// teensy2 has a good, fast millis interrupt implementation) +#ifndef FASTLED_ALLOW_INTERRUPTS +#define FASTLED_ALLOW_INTERRUPTS 0 +#endif + +#if FASTLED_ALLOW_INTERRUPTS == 1 +#define FASTLED_ACCURATE_CLOCK +#endif + + +// Default to using PROGMEM here +#ifndef FASTLED_USE_PROGMEM +#define FASTLED_USE_PROGMEM 1 +#endif + +#if defined(ARDUINO_AVR_DIGISPARK) || defined(ARDUINO_AVR_DIGISPARKPRO) +#ifndef NO_CORRECTION +#define NO_CORRECTION 1 +#endif +#endif + +extern "C" { +# if defined(CORE_TEENSY) || defined(TEENSYDUINO) +extern volatile unsigned long timer0_millis_count; +# define MS_COUNTER timer0_millis_count +# elif defined(ATTINY_CORE) +extern volatile unsigned long millis_timer_millis; +# define MS_COUNTER millis_timer_millis +# else +extern volatile unsigned long timer0_millis; +# define MS_COUNTER timer0_millis +# endif +}; + +// special defs for the tiny environments +#if defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtinyX41__) || defined(__AVR_ATtiny841__) || defined(__AVR_ATtiny441__) +#define LIB8_ATTINY 1 +#define FASTLED_NEEDS_YIELD +#endif + +#if defined(ARDUINO) && (ARDUINO > 150) && !defined(IS_BEAN) && !defined (ARDUINO_AVR_DIGISPARK) && !defined (LIB8_TINY) && !defined (ARDUINO_AVR_LARDU_328E) +// don't need YIELD defined by the library +#else +#define FASTLED_NEEDS_YIELD +extern "C" void yield(); +#endif +#endif -- cgit v1.2.3