Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit adac2c1

Browse filesBrowse files
committed
Move wave initialization and modification outside the inner loop.
1 parent 0b707cd commit adac2c1
Copy full SHA for adac2c1

File tree

Expand file treeCollapse file tree

1 file changed

+40
-40
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+40
-40
lines changed

‎cores/esp8266/core_esp8266_waveform.cpp

Copy file name to clipboardExpand all lines: cores/esp8266/core_esp8266_waveform.cpp
+40-40Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ namespace {
9090
volatile uint32_t enabled = 0; // Is it actively running, updated in NMI so no access outside the NMI code
9191

9292
// Enable lock-free by only allowing updates to waveform.states and waveform.enabled from IRQ service routine
93-
volatile uint32_t toEnable = 0; // Message to the NMI handler to start exactly one waveform on a inactive pin
94-
volatile uint32_t toDisable = 0; // Message to the NMI handler to disable exactly one pin from waveform generation
93+
volatile int32_t toSet = -1; // Message to the NMI handler to start/modify exactly one waveform
94+
volatile int32_t toDisable = -1; // Message to the NMI handler to disable exactly one pin from waveform generation
9595

9696
uint32_t(*timer1CB)() = nullptr;
9797

@@ -180,7 +180,7 @@ int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
180180
}
181181
}
182182
std::atomic_thread_fence(std::memory_order_release);
183-
waveform.toEnable = 1UL << pin;
183+
waveform.toSet = pin;
184184
if (!waveform.timer1Running) {
185185
initTimer();
186186
timer1_write(microsecondsToClockCycles(1));
@@ -189,20 +189,20 @@ int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
189189
// Must not interfere if Timer is due shortly, cluster phases to reduce interrupt load
190190
timer1_write(microsecondsToClockCycles(1));
191191
}
192-
while (waveform.toEnable) {
193-
delay(0); // Wait for waveform to update
194-
}
195192
}
196193
else {
197194
wave.mode = WaveformMode::INFINITE; // turn off possible expiry to make update atomic from NMI
198195
std::atomic_thread_fence(std::memory_order_release);
199196
wave.expiryCcy = runTimeCcys; // in WaveformMode::UPDATEEXPIRY, temporarily hold relative cycle count
200-
std::atomic_thread_fence(std::memory_order_release);
201197
if (runTimeCcys) {
202198
wave.mode = WaveformMode::UPDATEEXPIRY;
203199
std::atomic_thread_fence(std::memory_order_release);
200+
waveform.toSet = pin;
204201
}
205202
}
203+
while (waveform.toSet >= 0) {
204+
delay(0); // Wait for waveform to update
205+
}
206206
return true;
207207
}
208208

@@ -215,12 +215,12 @@ int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) {
215215
// If user sends in a pin >16 but <32, this will always point to a 0 bit
216216
// If they send >=32, then the shift will result in 0 and it will also return false
217217
if (waveform.enabled & (1UL << pin)) {
218-
waveform.toDisable = 1UL << pin;
218+
waveform.toDisable = pin;
219219
// Must not interfere if Timer is due shortly
220220
if (T1L > IRQLATENCY + DELTAIRQ) {
221221
timer1_write(microsecondsToClockCycles(1));
222222
}
223-
while (waveform.toDisable) {
223+
while (waveform.toDisable >= 0) {
224224
/* no-op */ // Can't delay() since stopWaveform may be called from an IRQ
225225
}
226226
}
@@ -242,21 +242,45 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
242242
static int nextPin = 0;
243243

244244
const uint32_t isrStartCcy = ESP.getCycleCount();
245-
246-
if (waveform.toEnable || waveform.toDisable) {
245+
const uint32_t toSetMask = waveform.toSet >= 0 ? 1UL << waveform.toSet : 0;
246+
const uint32_t toDisableMask = waveform.toDisable >= 0 ? 1UL << waveform.toDisable : 0;
247+
if ((toSetMask && !(waveform.enabled & toSetMask)) || toDisableMask) {
247248
// Handle enable/disable requests from main app.
248-
waveform.enabled = (waveform.enabled & ~waveform.toDisable) | waveform.toEnable; // Set the requested waveforms on/off
249-
waveform.toEnable = 0;
250-
waveform.toDisable = 0;
249+
waveform.enabled = (waveform.enabled & ~toDisableMask) | toSetMask; // Set the requested waveforms on/off
251250
// Find the first GPIO being generated by checking GCC's find-first-set (returns 1 + the bit of the first 1 in an int32_t)
252251
startPin = __builtin_ffs(waveform.enabled) - 1;
253252
// Find the last bit by subtracting off GCC's count-leading-zeros (no offset in this one)
254253
endPin = 32 - __builtin_clz(waveform.enabled);
254+
waveform.toDisable = -1;
255+
}
256+
257+
uint32_t now = ESP.getCycleCount();
258+
259+
if (toSetMask) {
260+
Waveform& wave = waveform.pins[waveform.toSet];
261+
switch (wave.mode) {
262+
case WaveformMode::INIT:
263+
waveform.states &= ~toSetMask; // Clear the state of any just started
264+
wave.nextPeriodCcy = (wave.alignPhase >= 0 && waveform.enabled & (1UL << wave.alignPhase)) ?
265+
waveform.pins[wave.alignPhase].nextPeriodCcy + wave.nextPeriodCcy : now;
266+
wave.nextEventCcy = wave.nextPeriodCcy;
267+
if (!wave.expiryCcy) {
268+
wave.mode = WaveformMode::INFINITE;
269+
break;
270+
}
271+
// fall through
272+
case WaveformMode::UPDATEEXPIRY:
273+
wave.expiryCcy += wave.nextPeriodCcy; // in WaveformMode::UPDATEEXPIRY, expiryCcy temporarily holds relative CPU cycle count
274+
wave.mode = WaveformMode::EXPIRES;
275+
break;
276+
default:
277+
break;
278+
}
279+
waveform.toSet = -1;
255280
}
256281

257282
// Exit the loop if the next event, if any, is sufficiently distant.
258283
const uint32_t isrTimeoutCcy = isrStartCcy + ISRTIMEOUTCCYS;
259-
uint32_t now = ESP.getCycleCount();
260284
uint32_t nextTimerCcy;
261285
bool busy = waveform.enabled;
262286
if (!busy) {
@@ -265,7 +289,6 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
265289
else if (!(waveform.enabled & (1UL << nextPin))) {
266290
nextPin = startPin;
267291
}
268-
bool initPins = true;
269292
while (busy) {
270293
nextTimerCcy = now + MAXIRQCCYS;
271294
int stopPin = nextPin;
@@ -277,28 +300,6 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
277300

278301
Waveform& wave = waveform.pins[pin];
279302

280-
if (initPins) {
281-
switch (wave.mode) {
282-
case WaveformMode::INIT:
283-
waveform.states &= ~(1UL << pin); // Clear the state of any just started
284-
wave.nextPeriodCcy = (waveform.enabled & (1UL << wave.alignPhase)) ?
285-
waveform.pins[wave.alignPhase].nextPeriodCcy + wave.nextPeriodCcy : now;
286-
wave.nextEventCcy = wave.nextPeriodCcy;
287-
if (!wave.expiryCcy) {
288-
wave.mode = WaveformMode::INFINITE;
289-
break;
290-
}
291-
// fall through
292-
case WaveformMode::UPDATEEXPIRY:
293-
wave.expiryCcy += wave.nextPeriodCcy; // in WaveformMode::UPDATEEXPIRY, expiryCcy temporarily holds relative CPU cycle count
294-
wave.mode = WaveformMode::EXPIRES;
295-
initPins = false; // only one pin per IRQ
296-
break;
297-
default:
298-
break;
299-
}
300-
}
301-
302303
int32_t overshootCcys = now - wave.nextEventCcy;
303304
if (overshootCcys >= 0) {
304305
if (WaveformMode::EXPIRES == wave.mode && wave.nextEventCcy == wave.expiryCcy) {
@@ -328,7 +329,7 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
328329
// preceeding period had zero idle cycle, continue direct into new duty cycle
329330
if (fwdPeriods) {
330331
wave.nextPeriodCcy += fwdPeriods * wave.periodCcys;
331-
// adapt expiry such that it occurs during intended cycle
332+
// adapt expiry such that it occurs during intended cycle
332333
if (WaveformMode::EXPIRES == wave.mode)
333334
wave.expiryCcy += fwdPeriods * wave.periodCcys;
334335
}
@@ -391,7 +392,6 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
391392

392393
} while ((pin = (pin < endPin) ? pin + 1 : startPin, pin != stopPin));
393394

394-
initPins = false;
395395
now = ESP.getCycleCount();
396396
const int32_t timerMarginCcys = isrTimeoutCcy - nextTimerCcy;
397397
busy = timerMarginCcys > 0;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.