mirror of
https://github.com/bbulkow/FastLED-idf.git
synced 2025-07-30 18:58:07 +02:00
Make the 4-wire LEDs compile.
Had to pull in far more of the Arduino HAL.
This commit is contained in:
88
README.md
88
README.md
@ -34,7 +34,7 @@ changing the duty cycle and brightness, it doesn't control color-controlled LEDs
|
|||||||
|
|
||||||
Thus, we need FastLED.
|
Thus, we need FastLED.
|
||||||
|
|
||||||
# Use of ESP32 hardware
|
# Use of ESP32 hardware for 3 wire LEDs
|
||||||
|
|
||||||
The ESP32 has an interesting module, called RMT. It's a module that's
|
The ESP32 has an interesting module, called RMT. It's a module that's
|
||||||
meant to make arbitrary waveforms on pins, without having to bang each pin at
|
meant to make arbitrary waveforms on pins, without having to bang each pin at
|
||||||
@ -60,6 +60,25 @@ I have not yet validated if this library correctly uses RMT.
|
|||||||
|
|
||||||
No extra commands in `menuconfig` seem necessary.
|
No extra commands in `menuconfig` seem necessary.
|
||||||
|
|
||||||
|
# Four wire LEDs ( APA102 and similar )
|
||||||
|
|
||||||
|
Interestingly, four wire LEDs can't use the RMT interface, because
|
||||||
|
the clock and data lines have to be controled together ( duh ),
|
||||||
|
and the RMT interface doesn't do that. What does do that is the SPI
|
||||||
|
interface, and I don't think I've wired that up.
|
||||||
|
|
||||||
|
There are two hardware SPI ports in the system, so that should be
|
||||||
|
able to be enabled. I haven't tried that.
|
||||||
|
|
||||||
|
Since hardware banging is used ( that's the big ugly warning ),
|
||||||
|
these LEDs are very likely far slower, and probably do not respond to parallelism
|
||||||
|
the same way.
|
||||||
|
|
||||||
|
I have pulled in enough of the HAL for the APA102 code to compile,
|
||||||
|
but I don't know if it works, since I don't have any four-wire LEDs
|
||||||
|
around. Since it's very much a different code path, I'm not going to make
|
||||||
|
promises until someone tries it.
|
||||||
|
|
||||||
# async mode
|
# async mode
|
||||||
|
|
||||||
The right way to use a system like this is with some form of async mode, where the CPU
|
The right way to use a system like this is with some form of async mode, where the CPU
|
||||||
@ -68,27 +87,15 @@ happening. This would allow much better multi-channel work, because the CPU coul
|
|||||||
one channel, then go off and fill the next channel, etc. For that, you'd have to use
|
one channel, then go off and fill the next channel, etc. For that, you'd have to use
|
||||||
the LastLED async interfaces.
|
the LastLED async interfaces.
|
||||||
|
|
||||||
Why do you want to use multiple channels? Apply the FadeCandy algos. The reason the fadecandy
|
It turns out this all works just peachy, it's just that the FastLED interface is a little
|
||||||
is teh awesome is it applies "temporal anti-aliasing", which is to say, it always drives the
|
peculiar. If you see the THREADING document in this directory, you'll
|
||||||
LEDs at full speed, and when it's trying to display a certain color, it actually displays a blend
|
see that this port is enabling multi-channel mode when using 3-wire LEDs,
|
||||||
of other colors. This allows far more resolution than the underlying LED hardware might be
|
which means you change all the pixels, and when you call FastLED.show(), they'll
|
||||||
capable of.
|
all bang on the RMT hardware, and use very little main CPU.
|
||||||
|
|
||||||
However, it means you need to drive lots of bytes all the time. The fadecandy appears to drive
|
It would be nicer if FastLED had some sort of Async mode, but that's not
|
||||||
400Khz across its 64-led maximum strings _all the time_. If we did that with this system, one core
|
really the Arduino way, and this code is meant for arduino. Arduino doesn't
|
||||||
would drive one string. Sure, we've got two cores, but that's not very fun.
|
have threads of control or message queues or anything like that.
|
||||||
|
|
||||||
With an async system, you can drive as many strings as you want in parallel, and let RMT loose.
|
|
||||||
There are only 8 RMT channels, so you can at least get up to the capacity of a single FadeCandy.
|
|
||||||
|
|
||||||
Still - imagine the possibilities. If you're not applying temporal dithering, you can at least have
|
|
||||||
a ton more parallel strings. Instead of being limited to about 1k LEDs saturating an entire core
|
|
||||||
at 30fps with no "temporal dithering", you might be able to get upward of 4k or 8k ( to be measured ).
|
|
||||||
|
|
||||||
In order to do this in the happiest way, you'd like to use FastLED's coordination systems. You'd
|
|
||||||
like an async call to complete using a C feature, to take mutexes because it might be interrupting
|
|
||||||
with the scheduler, or to put a message on one of the message queues for service. Doing all
|
|
||||||
that would be a major expansion of the FastLED interface and would diverge from the "published spec".
|
|
||||||
|
|
||||||
# A bit about esp-idf
|
# A bit about esp-idf
|
||||||
|
|
||||||
@ -131,6 +138,10 @@ simply changes the duty cycle on a pin using the RMT interface.
|
|||||||
It doesn't do pixel color control. It can be an example of using
|
It doesn't do pixel color control. It can be an example of using
|
||||||
the RMT system, that's it.
|
the RMT system, that's it.
|
||||||
|
|
||||||
|
There is an example of LED control, using the RMT interface directly.
|
||||||
|
If you just want to it like that, without all the cool stuff in FastLED,
|
||||||
|
be everyone's guest!
|
||||||
|
|
||||||
I did reach out to Espressif. I think they should include or have a FastLED port.
|
I did reach out to Espressif. I think they should include or have a FastLED port.
|
||||||
In their forums, they said they don't intend to do anything like that.
|
In their forums, they said they don't intend to do anything like that.
|
||||||
|
|
||||||
@ -342,6 +353,8 @@ Note: what's up with registering the driver? I should, right? Make sure that's d
|
|||||||
menuconfig? Doen't seem to be. There are no settings anywhere in the menuconfig regarding
|
menuconfig? Doen't seem to be. There are no settings anywhere in the menuconfig regarding
|
||||||
gpio. Should probably look at the examples to see if I have to enable the ISR or something.
|
gpio. Should probably look at the examples to see if I have to enable the ISR or something.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## using RMT vs I2S
|
## using RMT vs I2S
|
||||||
|
|
||||||
Note to self: There is a define in the platforms area that lets a person choose.
|
Note to self: There is a define in the platforms area that lets a person choose.
|
||||||
@ -389,10 +402,9 @@ After looking a bit, it doesn't seem unreasonable to remove all the memmoves and
|
|||||||
loops. It's been done in other places of the code. Otherwise, one could say "IF GCC8" or something
|
loops. It's been done in other places of the code. Otherwise, one could say "IF GCC8" or something
|
||||||
similar, because I bet it really does matter on smaller systems. Maybe even on this one.
|
similar, because I bet it really does matter on smaller systems. Maybe even on this one.
|
||||||
|
|
||||||
There is a menuconfig to turn off new warnings introduced from GCC6 to GCC8.
|
In the upstream code of FastLED, there is an introduction of a void * cast in these two places.
|
||||||
|
That's the other way of doing it, and the code does "promise" that the classes in question
|
||||||
The other thing is to cast these to void, but ewww. Anyone who uses C++ on an embedded system
|
can be memcpy'd. If someone re-ports the code, they could fix this.
|
||||||
should go whole hog.
|
|
||||||
|
|
||||||
## Don't use C
|
## Don't use C
|
||||||
|
|
||||||
@ -400,8 +412,28 @@ Had a main.c , and FastLED.h includes nothing but C++. Therefore, all the source
|
|||||||
that include FastLED have to be using the C++ compiler, and ESP-IDF has the standard rules
|
that include FastLED have to be using the C++ compiler, and ESP-IDF has the standard rules
|
||||||
for using C for C and CPP for CPP because it's not like they are subsets or something.
|
for using C for C and CPP for CPP because it's not like they are subsets or something.
|
||||||
|
|
||||||
|
## CXX_STUFF
|
||||||
|
|
||||||
|
There is some really scary code about guards. It is defined if ESP32,
|
||||||
|
and seems to override the way the compiler executes a certain kind of guard.
|
||||||
|
I've turned that off, because I think we should probably trust esp-idf to do the
|
||||||
|
right and best thing for that
|
||||||
|
|
||||||
|
## pulled in too much of the hal
|
||||||
|
|
||||||
|
In order to get 4-wire LEDs compiling, it's necessary to pull in the HAL gpio.c .
|
||||||
|
Just to get one lousy function - pinMode. I probably should
|
||||||
|
have simply had the function call gpio_set_direction(), which is the esp_idf
|
||||||
|
function, directly. If you have a 4-wire system, I left a breadcrumb in the
|
||||||
|
fastpin_esp32 directory. If the alternate code works, then you can take the
|
||||||
|
gpio.c out of the hal compile.
|
||||||
|
|
||||||
## message about no hardware SPI pins defined
|
## message about no hardware SPI pins defined
|
||||||
|
|
||||||
This appears widely known to be a warning on ESP32 to go look and see if the RMT system
|
It's true! There are no hardware SPI pins defined. SPI is used for 4-wire LEDs, where
|
||||||
is getting included. Do need to put in some printfs to see if RMT is enabled,
|
you have to synchronize the clock and data.
|
||||||
and see if the async system works, which would be the cool part of RMT.
|
|
||||||
|
If you have 3-wire LEDs, you'll be using the RMT system, which is super fast anyway.
|
||||||
|
|
||||||
|
The upstream code doesn't seem to use SPI on ESP32 either, so that's just a big hairy
|
||||||
|
todo, and don't worry overmuch.
|
@ -12,6 +12,7 @@ set(srcs
|
|||||||
"power_mgt.cpp"
|
"power_mgt.cpp"
|
||||||
"wiring.cpp"
|
"wiring.cpp"
|
||||||
"hal/esp32-hal-misc.c"
|
"hal/esp32-hal-misc.c"
|
||||||
|
"hal/esp32-hal-gpio.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
# everything needs the ESP32 flag, not sure why this won't work
|
# everything needs the ESP32 flag, not sure why this won't work
|
||||||
|
307
components/FastLED-idf/hal/esp32-hal-gpio.c
Normal file
307
components/FastLED-idf/hal/esp32-hal-gpio.c
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "esp32-hal-gpio.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "esp32/rom/ets_sys.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "esp32/rom/gpio.h"
|
||||||
|
#include "soc/gpio_reg.h"
|
||||||
|
#include "soc/io_mux_reg.h"
|
||||||
|
#include "soc/gpio_struct.h"
|
||||||
|
#include "soc/rtc_io_reg.h"
|
||||||
|
|
||||||
|
const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26};
|
||||||
|
|
||||||
|
// BB
|
||||||
|
#define GPIO_PIN_COUNT 40
|
||||||
|
|
||||||
|
const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[GPIO_PIN_COUNT]={
|
||||||
|
{0x44, 11, 11, 1},
|
||||||
|
{0x88, -1, -1, -1},
|
||||||
|
{0x40, 12, 12, 2},
|
||||||
|
{0x84, -1, -1, -1},
|
||||||
|
{0x48, 10, 10, 0},
|
||||||
|
{0x6c, -1, -1, -1},
|
||||||
|
{0x60, -1, -1, -1},
|
||||||
|
{0x64, -1, -1, -1},
|
||||||
|
{0x68, -1, -1, -1},
|
||||||
|
{0x54, -1, -1, -1},
|
||||||
|
{0x58, -1, -1, -1},
|
||||||
|
{0x5c, -1, -1, -1},
|
||||||
|
{0x34, 15, 15, 5},
|
||||||
|
{0x38, 14, 14, 4},
|
||||||
|
{0x30, 16, 16, 6},
|
||||||
|
{0x3c, 13, 13, 3},
|
||||||
|
{0x4c, -1, -1, -1},
|
||||||
|
{0x50, -1, -1, -1},
|
||||||
|
{0x70, -1, -1, -1},
|
||||||
|
{0x74, -1, -1, -1},
|
||||||
|
{0x78, -1, -1, -1},
|
||||||
|
{0x7c, -1, -1, -1},
|
||||||
|
{0x80, -1, -1, -1},
|
||||||
|
{0x8c, -1, -1, -1},
|
||||||
|
{0, -1, -1, -1},
|
||||||
|
{0x24, 6, 18, -1}, //DAC1
|
||||||
|
{0x28, 7, 19, -1}, //DAC2
|
||||||
|
{0x2c, 17, 17, 7},
|
||||||
|
{0, -1, -1, -1},
|
||||||
|
{0, -1, -1, -1},
|
||||||
|
{0, -1, -1, -1},
|
||||||
|
{0, -1, -1, -1},
|
||||||
|
{0x1c, 9, 4, 8},
|
||||||
|
{0x20, 8, 5, 9},
|
||||||
|
{0x14, 4, 6, -1},
|
||||||
|
{0x18, 5, 7, -1},
|
||||||
|
{0x04, 0, 0, -1},
|
||||||
|
{0x08, 1, 1, -1},
|
||||||
|
{0x0c, 2, 2, -1},
|
||||||
|
{0x10, 3, 3, -1}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*voidFuncPtr)(void);
|
||||||
|
typedef void (*voidFuncPtrArg)(void*);
|
||||||
|
typedef struct {
|
||||||
|
voidFuncPtr fn;
|
||||||
|
void* arg;
|
||||||
|
bool functional;
|
||||||
|
} InterruptHandle_t;
|
||||||
|
static InterruptHandle_t __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,};
|
||||||
|
|
||||||
|
#include "driver/rtc_io.h"
|
||||||
|
|
||||||
|
extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!digitalPinIsValid(pin)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rtc_reg = rtc_gpio_desc[pin].reg;
|
||||||
|
if(mode == ANALOG) {
|
||||||
|
if(!rtc_reg) {
|
||||||
|
return;//not rtc pin
|
||||||
|
}
|
||||||
|
//lock rtc
|
||||||
|
uint32_t reg_val = ESP_REG(rtc_reg);
|
||||||
|
if(reg_val & rtc_gpio_desc[pin].mux){
|
||||||
|
return;//already in adc mode
|
||||||
|
}
|
||||||
|
reg_val &= ~(
|
||||||
|
(RTC_IO_TOUCH_PAD1_FUN_SEL_V << rtc_gpio_desc[pin].func)
|
||||||
|
|rtc_gpio_desc[pin].ie
|
||||||
|
|rtc_gpio_desc[pin].pullup
|
||||||
|
|rtc_gpio_desc[pin].pulldown);
|
||||||
|
ESP_REG(RTC_GPIO_ENABLE_W1TC_REG) = (1 << (rtc_gpio_desc[pin].rtc_num + RTC_GPIO_ENABLE_W1TC_S));
|
||||||
|
ESP_REG(rtc_reg) = reg_val | rtc_gpio_desc[pin].mux;
|
||||||
|
//unlock rtc
|
||||||
|
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)2 << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//RTC pins PULL settings
|
||||||
|
if(rtc_reg) {
|
||||||
|
//lock rtc
|
||||||
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
||||||
|
if(mode & PULLUP) {
|
||||||
|
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pullup) & ~(rtc_gpio_desc[pin].pulldown);
|
||||||
|
} else if(mode & PULLDOWN) {
|
||||||
|
ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pulldown) & ~(rtc_gpio_desc[pin].pullup);
|
||||||
|
} else {
|
||||||
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
||||||
|
}
|
||||||
|
//unlock rtc
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pinFunction = 0, pinControl = 0;
|
||||||
|
|
||||||
|
//lock gpio
|
||||||
|
if(mode & INPUT) {
|
||||||
|
if(pin < 32) {
|
||||||
|
GPIO.enable_w1tc = ((uint32_t)1 << pin);
|
||||||
|
} else {
|
||||||
|
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
}
|
||||||
|
} else if(mode & OUTPUT) {
|
||||||
|
if(pin > 33){
|
||||||
|
//unlock gpio
|
||||||
|
return;//pins above 33 can be only inputs
|
||||||
|
} else if(pin < 32) {
|
||||||
|
GPIO.enable_w1ts = ((uint32_t)1 << pin);
|
||||||
|
} else {
|
||||||
|
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode & PULLUP) {
|
||||||
|
pinFunction |= FUN_PU;
|
||||||
|
} else if(mode & PULLDOWN) {
|
||||||
|
pinFunction |= FUN_PD;
|
||||||
|
}
|
||||||
|
|
||||||
|
pinFunction |= ((uint32_t)2 << FUN_DRV_S);//what are the drivers?
|
||||||
|
pinFunction |= FUN_IE;//input enable but required for output as well?
|
||||||
|
|
||||||
|
if(mode & (INPUT | OUTPUT)) {
|
||||||
|
pinFunction |= ((uint32_t)2 << MCU_SEL_S);
|
||||||
|
} else if(mode == SPECIAL) {
|
||||||
|
pinFunction |= ((uint32_t)(((pin)==1||(pin)==3)?0:1) << MCU_SEL_S);
|
||||||
|
} else {
|
||||||
|
pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
|
||||||
|
|
||||||
|
if(mode & OPEN_DRAIN) {
|
||||||
|
pinControl = (1 << GPIO_PIN0_PAD_DRIVER_S);
|
||||||
|
}
|
||||||
|
|
||||||
|
GPIO.pin[pin].val = pinControl;
|
||||||
|
//unlock gpio
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void IRAM_ATTR __digitalWrite(uint8_t pin, uint8_t val)
|
||||||
|
{
|
||||||
|
if(val) {
|
||||||
|
if(pin < 32) {
|
||||||
|
GPIO.out_w1ts = ((uint32_t)1 << pin);
|
||||||
|
} else if(pin < 34) {
|
||||||
|
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(pin < 32) {
|
||||||
|
GPIO.out_w1tc = ((uint32_t)1 << pin);
|
||||||
|
} else if(pin < 34) {
|
||||||
|
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int IRAM_ATTR __digitalRead(uint8_t pin)
|
||||||
|
{
|
||||||
|
if(pin < 32) {
|
||||||
|
return (GPIO.in >> pin) & 0x1;
|
||||||
|
} else if(pin < 40) {
|
||||||
|
return (GPIO.in1.val >> (pin - 32)) & 0x1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static intr_handle_t gpio_intr_handle = NULL;
|
||||||
|
|
||||||
|
static void IRAM_ATTR __onPinInterrupt()
|
||||||
|
{
|
||||||
|
uint32_t gpio_intr_status_l=0;
|
||||||
|
uint32_t gpio_intr_status_h=0;
|
||||||
|
|
||||||
|
gpio_intr_status_l = GPIO.status;
|
||||||
|
gpio_intr_status_h = GPIO.status1.val;
|
||||||
|
GPIO.status_w1tc = gpio_intr_status_l;//Clear intr for gpio0-gpio31
|
||||||
|
GPIO.status1_w1tc.val = gpio_intr_status_h;//Clear intr for gpio32-39
|
||||||
|
|
||||||
|
uint8_t pin=0;
|
||||||
|
if(gpio_intr_status_l) {
|
||||||
|
do {
|
||||||
|
if(gpio_intr_status_l & ((uint32_t)1 << pin)) {
|
||||||
|
if(__pinInterruptHandlers[pin].fn) {
|
||||||
|
if(__pinInterruptHandlers[pin].arg){
|
||||||
|
((voidFuncPtrArg)__pinInterruptHandlers[pin].fn)(__pinInterruptHandlers[pin].arg);
|
||||||
|
} else {
|
||||||
|
__pinInterruptHandlers[pin].fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(++pin<32);
|
||||||
|
}
|
||||||
|
if(gpio_intr_status_h) {
|
||||||
|
pin=32;
|
||||||
|
do {
|
||||||
|
if(gpio_intr_status_h & ((uint32_t)1 << (pin - 32))) {
|
||||||
|
if(__pinInterruptHandlers[pin].fn) {
|
||||||
|
if(__pinInterruptHandlers[pin].arg){
|
||||||
|
((voidFuncPtrArg)__pinInterruptHandlers[pin].fn)(__pinInterruptHandlers[pin].arg);
|
||||||
|
} else {
|
||||||
|
__pinInterruptHandlers[pin].fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(++pin<GPIO_PIN_COUNT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void cleanupFunctional(void* arg);
|
||||||
|
|
||||||
|
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type, bool functional)
|
||||||
|
{
|
||||||
|
static bool interrupt_initialized = false;
|
||||||
|
|
||||||
|
if(!interrupt_initialized) {
|
||||||
|
interrupt_initialized = true;
|
||||||
|
esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __onPinInterrupt, NULL, &gpio_intr_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if new attach without detach remove old info
|
||||||
|
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
|
||||||
|
{
|
||||||
|
cleanupFunctional(__pinInterruptHandlers[pin].arg);
|
||||||
|
}
|
||||||
|
__pinInterruptHandlers[pin].fn = (voidFuncPtr)userFunc;
|
||||||
|
__pinInterruptHandlers[pin].arg = arg;
|
||||||
|
__pinInterruptHandlers[pin].functional = functional;
|
||||||
|
|
||||||
|
esp_intr_disable(gpio_intr_handle);
|
||||||
|
if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
|
||||||
|
GPIO.pin[pin].int_ena = 1;
|
||||||
|
} else { //PRO_CPU
|
||||||
|
GPIO.pin[pin].int_ena = 4;
|
||||||
|
}
|
||||||
|
GPIO.pin[pin].int_type = intr_type;
|
||||||
|
esp_intr_enable(gpio_intr_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void * arg, int intr_type)
|
||||||
|
{
|
||||||
|
__attachInterruptFunctionalArg(pin, userFunc, arg, intr_type, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type) {
|
||||||
|
__attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, NULL, intr_type, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void __detachInterrupt(uint8_t pin)
|
||||||
|
{
|
||||||
|
esp_intr_disable(gpio_intr_handle);
|
||||||
|
if (__pinInterruptHandlers[pin].functional && __pinInterruptHandlers[pin].arg)
|
||||||
|
{
|
||||||
|
cleanupFunctional(__pinInterruptHandlers[pin].arg);
|
||||||
|
}
|
||||||
|
__pinInterruptHandlers[pin].fn = NULL;
|
||||||
|
__pinInterruptHandlers[pin].arg = NULL;
|
||||||
|
__pinInterruptHandlers[pin].functional = false;
|
||||||
|
|
||||||
|
GPIO.pin[pin].int_ena = 0;
|
||||||
|
GPIO.pin[pin].int_type = 0;
|
||||||
|
esp_intr_enable(gpio_intr_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pinMode")));
|
||||||
|
extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite")));
|
||||||
|
extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead")));
|
||||||
|
extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt")));
|
||||||
|
extern void attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void * arg, int mode) __attribute__ ((weak, alias("__attachInterruptArg")));
|
||||||
|
extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt")));
|
||||||
|
|
@ -34,7 +34,7 @@
|
|||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/apb_ctrl_reg.h"
|
#include "soc/apb_ctrl_reg.h"
|
||||||
#include "rom/rtc.h"
|
#include "esp32/rom/rtc.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
#include "esp32-hal.h"
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
@ -248,4 +248,4 @@ const char * IRAM_ATTR pathToFileName(const char * path)
|
|||||||
return path+pos;
|
return path+pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/semphr.h"
|
||||||
#include "rom/ets_sys.h"
|
#include "esp32/rom/ets_sys.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_intr.h"
|
#include "esp_intr.h"
|
||||||
#include "rom/gpio.h"
|
#include "esp32/rom/gpio.h"
|
||||||
#include "soc/spi_reg.h"
|
#include "soc/spi_reg.h"
|
||||||
#include "soc/spi_struct.h"
|
#include "soc/spi_struct.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
|
@ -17,6 +17,13 @@ public:
|
|||||||
typedef volatile uint32_t * port_ptr_t;
|
typedef volatile uint32_t * port_ptr_t;
|
||||||
typedef uint32_t port_t;
|
typedef uint32_t port_t;
|
||||||
|
|
||||||
|
// BB
|
||||||
|
// It could be better to to the following, then not have to pull in as
|
||||||
|
// much of the hal:
|
||||||
|
// inline static void setOutput() { gpio_set_direction(PIN, GPIO_MODE_OUTPUT); }
|
||||||
|
// inline static void setInput() { gpio_set_direction(PIN, GPIO_MODE_INPUT); }
|
||||||
|
|
||||||
|
|
||||||
inline static void setOutput() { pinMode(PIN, OUTPUT); }
|
inline static void setOutput() { pinMode(PIN, OUTPUT); }
|
||||||
inline static void setInput() { pinMode(PIN, INPUT); }
|
inline static void setInput() { pinMode(PIN, INPUT); }
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ typedef unsigned long prog_uint32_t;
|
|||||||
# define INTERRUPT_THRESHOLD 0
|
# define INTERRUPT_THRESHOLD 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NEED_CXX_BITS
|
// BB - I think I'm compiling in CXX in this project
|
||||||
|
// #define NEED_CXX_BITS
|
||||||
|
|
||||||
// These can be overridden
|
// These can be overridden
|
||||||
# define FASTLED_ESP32_RAW_PIN_ORDER
|
# define FASTLED_ESP32_RAW_PIN_ORDER
|
||||||
|
@ -23,8 +23,8 @@ extern const TProgmemPalette16 IRAM_ATTR myRedWhiteBluePalette_p;
|
|||||||
#include "palettes.h"
|
#include "palettes.h"
|
||||||
|
|
||||||
#define NUM_LEDS 40
|
#define NUM_LEDS 40
|
||||||
#define DATA_PIN 18
|
#define DATA_PIN 13
|
||||||
#define BRIGHTNESS 64
|
#define BRIGHTNESS 80
|
||||||
#define LED_TYPE WS2811
|
#define LED_TYPE WS2811
|
||||||
#define COLOR_ORDER RGB
|
#define COLOR_ORDER RGB
|
||||||
CRGB leds[NUM_LEDS];
|
CRGB leds[NUM_LEDS];
|
||||||
@ -99,17 +99,18 @@ CRGB colors[N_COLORS] = {
|
|||||||
|
|
||||||
void blinkLeds_simple(void *pvParameters){
|
void blinkLeds_simple(void *pvParameters){
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
printf("blink leds\n");
|
|
||||||
|
|
||||||
for (int j=0;j<N_COLORS;j++) {
|
for (int j=0;j<N_COLORS;j++) {
|
||||||
for (int i=0;i<NUM_LEDS;i++) {
|
printf("blink leds\n");
|
||||||
leds[i] = colors[j];
|
|
||||||
}
|
for (int i=0;i<NUM_LEDS;i++) {
|
||||||
FastLED.show();
|
leds[i] = colors[j];
|
||||||
delay(1000);
|
}
|
||||||
};
|
FastLED.show();
|
||||||
}
|
delay(1000);
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define N_COLORS_CHASE 7
|
#define N_COLORS_CHASE 7
|
||||||
@ -154,9 +155,13 @@ void blinkLeds_chase(void *pvParameters) {
|
|||||||
|
|
||||||
void app_main() {
|
void app_main() {
|
||||||
printf(" entering app main, call add leds\n");
|
printf(" entering app main, call add leds\n");
|
||||||
|
// the WS2811 family uses the RMT driver
|
||||||
FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, NUM_LEDS);
|
FastLED.addLeds<LED_TYPE, DATA_PIN>(leds, NUM_LEDS);
|
||||||
|
// this is a good test because it uses the GPIO ports
|
||||||
|
//FastLED.addLeds<APA102, 13, 15>(leds, NUM_LEDS);
|
||||||
|
|
||||||
printf(" set max power\n");
|
printf(" set max power\n");
|
||||||
FastLED.setMaxPowerInVoltsAndMilliamps(5,1000);
|
FastLED.setMaxPowerInVoltsAndMilliamps(5,2000);
|
||||||
printf("create task for led blinking\n");
|
printf("create task for led blinking\n");
|
||||||
xTaskCreatePinnedToCore(&blinkLeds_simple, "blinkLeds", 4000, NULL, 5, NULL, 0);
|
xTaskCreatePinnedToCore(&blinkLeds_simple, "blinkLeds", 4000, NULL, 5, NULL, 0);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user