Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2907b65133 |
3 changed files with 42 additions and 7 deletions
|
|
@ -20,6 +20,8 @@
|
|||
#if defined(ESP32) || \
|
||||
defined(ESP_PLATFORM) // *All* ESP32 variants (OG, S2, S3, etc.)
|
||||
|
||||
extern volatile uint8_t bitz;
|
||||
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
// NOTE: there is some intentional repetition in the macros and functions
|
||||
|
|
@ -58,6 +60,7 @@ static hw_timer_t *_PM_esp32timer = NULL;
|
|||
#define _PM_TIMER_DEFAULT &_PM_esp32timer
|
||||
|
||||
extern IRAM_ATTR void _PM_row_handler(Protomatter_core *core); // In core.c
|
||||
extern IRAM_ATTR void _PM_OE_off(Protomatter_core *core);
|
||||
|
||||
// Timer interrupt handler. This, _PM_row_handler() and any functions
|
||||
// called by _PM_row_handler() should all have the IRAM_ATTR attribute
|
||||
|
|
@ -65,7 +68,13 @@ extern IRAM_ATTR void _PM_row_handler(Protomatter_core *core); // In core.c
|
|||
// callback invoked by the real ISR (in arduino-esp32's esp32-hal-timer.c)
|
||||
// which takes care of interrupt status bits & such.
|
||||
IRAM_ATTR static void _PM_esp32timerCallback(void) {
|
||||
_PM_row_handler(_PM_protoPtr); // In core.c
|
||||
bitz |= 2;
|
||||
if (bitz == 3) {
|
||||
_PM_row_handler(_PM_protoPtr); // In core.c
|
||||
} else {
|
||||
_PM_OE_off(_PM_protoPtr);
|
||||
_PM_timerStop(_PM_protoPtr);
|
||||
}
|
||||
}
|
||||
|
||||
// Set timer period, initialize count value to zero, enable timer.
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ IRAM_ATTR inline uint32_t _PM_timerGetCount(Protomatter_core *core) {
|
|||
// slightly different length of time, but duty cycle scales with this so it's
|
||||
// perceptually consistent; don't see bright or dark rows.
|
||||
|
||||
#define _PM_minMinPeriod (200 + (uint32_t)core->chainBits * 2)
|
||||
//#define _PM_minMinPeriod (200 + (uint32_t)core->chainBits * 2)
|
||||
#define _PM_minMinPeriod 40
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR == 5)
|
||||
#include <esp_private/periph_ctrl.h>
|
||||
|
|
@ -129,6 +130,7 @@ static void pinmux(int8_t pin, uint8_t signal) {
|
|||
}
|
||||
|
||||
#if defined(ARDUINO) // COMPILING FOR ARDUINO ------------------------------
|
||||
|
||||
// LCD_CAM requires a complete replacement of the "blast" functions in order
|
||||
// to use the DMA-based peripheral.
|
||||
#define _PM_CUSTOM_BLAST // Disable blast_*() functions in core.c
|
||||
|
|
@ -160,6 +162,19 @@ IRAM_ATTR static void blast_byte(Protomatter_core *core, uint8_t *data) {
|
|||
// See notes near top of this file for what's done with this info.
|
||||
}
|
||||
|
||||
volatile uint32_t bloop = 0;
|
||||
extern volatile uint8_t bitz;
|
||||
extern IRAM_ATTR void _PM_OE_off(Protomatter_core *core);
|
||||
|
||||
IRAM_ATTR static bool dma_callback(gdma_channel_handle_t dma_chan,
|
||||
gdma_event_data_t *event_data, void *user_data) {
|
||||
bitz |= 1; // DMA xfer has finished
|
||||
if (bitz == 3)
|
||||
_PM_row_handler(_PM_protoPtr); // In core.c
|
||||
bloop++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _PM_timerInit(Protomatter_core *core) {
|
||||
// On S3, initialize the LCD_CAM peripheral and DMA.
|
||||
|
||||
|
|
@ -247,9 +262,11 @@ void _PM_timerInit(Protomatter_core *core) {
|
|||
gdma_set_transfer_ability(dma_chan, &ability);
|
||||
gdma_start(dma_chan, (intptr_t)&desc);
|
||||
|
||||
// Enable TRANS_DONE interrupt. Note that we do NOT require nor install
|
||||
// an interrupt service routine, but DO need to enable the TRANS_DONE
|
||||
// flag to make the LCD DMA transfer work.
|
||||
// Enable DMA transfer callback
|
||||
gdma_tx_event_callbacks_t tx_cbs = {
|
||||
.on_trans_eof = dma_callback
|
||||
};
|
||||
gdma_register_tx_event_callbacks(dma_chan, &tx_cbs, NULL);
|
||||
LCD_CAM.lc_dma_int_ena.val |= LCD_LL_EVENT_TRANS_DONE & 0x03;
|
||||
|
||||
_PM_esp32commonTimerInit(core); // In esp32-common.h
|
||||
|
|
|
|||
13
src/core.c
13
src/core.c
|
|
@ -341,6 +341,7 @@ ProtomatterStatus _PM_begin(Protomatter_core *core) {
|
|||
uint32_t minPeriodPerFrame = _PM_timerFreq / _PM_MAX_REFRESH_HZ;
|
||||
uint32_t minPeriodPerLine = minPeriodPerFrame / core->numRowPairs;
|
||||
core->minPeriod = minPeriodPerLine / ((1 << core->numPlanes) - 1);
|
||||
core->minPeriod = _PM_minMinPeriod;
|
||||
if (core->minPeriod < _PM_minMinPeriod) {
|
||||
core->minPeriod = _PM_minMinPeriod;
|
||||
}
|
||||
|
|
@ -487,6 +488,13 @@ void _PM_deallocate(Protomatter_core *core) {
|
|||
}
|
||||
}
|
||||
|
||||
volatile uint8_t bitz = 3;
|
||||
|
||||
IRAM_ATTR void _PM_OE_off(Protomatter_core *core) {
|
||||
_PM_clearReg(core->oe);
|
||||
_PM_setReg(core->oe); // Disable LED output
|
||||
}
|
||||
|
||||
// ISR function (in arch.h) calls this function which it extern'd.
|
||||
// Profuse apologies for the ESP32-specific IRAM_ATTR here -- the goal was
|
||||
// for all architecture-specific detauls to be in arch.h -- but the need
|
||||
|
|
@ -497,6 +505,7 @@ void _PM_deallocate(Protomatter_core *core) {
|
|||
// specific section of arch.h. Sorry. :/
|
||||
// Any functions called by this function should also be IRAM_ATTR'd.
|
||||
IRAM_ATTR void _PM_row_handler(Protomatter_core *core) {
|
||||
bitz = 0;
|
||||
|
||||
_PM_setReg(core->oe); // Disable LED output
|
||||
|
||||
|
|
@ -577,7 +586,7 @@ IRAM_ATTR void _PM_row_handler(Protomatter_core *core) {
|
|||
|
||||
// Set timer and enable LED output for data loaded on PRIOR pass:
|
||||
_PM_timerStart(core, core->bitZeroPeriod << prevPlane);
|
||||
_PM_delayMicroseconds(1); // Appease Teensy4
|
||||
// _PM_delayMicroseconds(1); // Appease Teensy4
|
||||
_PM_clearReg(core->oe); // Enable LED output
|
||||
|
||||
uint32_t elementsPerLine =
|
||||
|
|
@ -610,7 +619,7 @@ IRAM_ATTR void _PM_row_handler(Protomatter_core *core) {
|
|||
// Timer is still running and counting up at this point.
|
||||
uint32_t elapsed = _PM_timerGetCount(core);
|
||||
// Nudge the plane-zero time up or down (filtering to avoid jitter)
|
||||
core->bitZeroPeriod = ((core->bitZeroPeriod * 7) + elapsed + 4) / 8;
|
||||
// core->bitZeroPeriod = ((core->bitZeroPeriod * 7) + elapsed + 4) / 8;
|
||||
// But don't allow it to drop below the minimum period calculated during
|
||||
// begin(), that's a hard limit and would just waste cycles.
|
||||
if (core->bitZeroPeriod < core->minPeriod) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue