Skip to content

Commit

Permalink
Carry over a few insights from comparing to original waveform (phase-…
Browse files Browse the repository at this point in the history
…sync) branch.
  • Loading branch information
dok-net committed Dec 10, 2022
1 parent 3edc7a9 commit aeb30f8
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 25 deletions.
6 changes: 3 additions & 3 deletions cores/esp8266/core_esp8266_waveform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@

#include "core_esp8266_waveform.h"
#include <Arduino.h>
#include "debug.h"
#include "ets_sys.h"
#include <atomic>

Expand Down Expand Up @@ -150,7 +149,7 @@ static void initTimer() {
timer1_write(IRQLATENCYCCYS); // Cause an interrupt post-haste
}

static void IRAM_ATTR deinitIdleTimer() {
static IRAM_ATTR void deinitIdleTimer() {
if (!waveform.timer1Running || waveform.enabled || waveform.timer1CB || pwmState.cnt) {
return;
}
Expand All @@ -174,8 +173,9 @@ extern "C" {
// Wait for mailbox to be emptied (either busy or delay() as needed)
static IRAM_ATTR void _notifyPWM(PWMState *p, bool idle) {
p->pwmUpdate = nullptr;
pwmState.pwmUpdate = p;
std::atomic_thread_fence(std::memory_order_release);
pwmState.pwmUpdate = p;
std::atomic_thread_fence(std::memory_order_acq_rel);
if (idle) {
forceTimerTrigger();
}
Expand Down
10 changes: 4 additions & 6 deletions cores/esp8266/core_esp8266_waveform.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ extern "C" {
// Setting autoPwm to true allows the wave generator to maintain PWM duty to idle cycle ratio
// under load, for applications where frequency or duty cycle must not change, leave false.
// Returns true or false on success or failure.
int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t runTimeUS = 0,
// Following parameters are ignored unless in PhaseLocked mode
int8_t alignPhase = -1, uint32_t phaseOffsetUS = 0, bool autoPwm = false);
int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS,
uint32_t runTimeUS = 0, int8_t alignPhase = -1, uint32_t phaseOffsetUS = 0, bool autoPwm = false);

// Start or change a waveform of the specified high and low CPU clock cycles on specific pin.
// If runtimeCycles > 0 then automatically stop it after that many CPU clock cycles, relative to the next
Expand All @@ -68,9 +67,8 @@ int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t
// Setting autoPwm to true allows the wave generator to maintain PWM duty to idle cycle ratio
// under load, for applications where frequency or duty cycle must not change, leave false.
// Returns true or false on success or failure.
int startWaveformClockCycles(uint8_t pin, uint32_t timeHighCcys, uint32_t timeLowCcys, uint32_t runTimeCcys = 0,
// Following parameters are ignored unless in PhaseLocked mode
int8_t alignPhase = -1, uint32_t phaseOffsetCcys = 0, bool autoPwm = false);
int startWaveformClockCycles(uint8_t pin, uint32_t timeHighCcys, uint32_t timeLowCcys,
uint32_t runTimeCcys = 0, int8_t alignPhase = -1, uint32_t phaseOffsetCcys = 0, bool autoPwm = false);

// Stop a waveform, if any, on the specified pin.
// Returns true or false on success or failure.
Expand Down
17 changes: 1 addition & 16 deletions cores/esp8266/core_esp8266_wiring_pwm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ extern void __analogWriteMode(uint8_t pin, int val, bool openDrain) {
if (pin > 16) {
return;
}
uint32_t analogPeriod = microsecondsToClockCycles(1000000UL) / analogFreq;
if (val < 0) {
val = 0;
} else if (val > analogScale) {
Expand All @@ -75,28 +74,14 @@ extern void __analogWriteMode(uint8_t pin, int val, bool openDrain) {
else {
pinMode(pin, openDrain ? OUTPUT_OPEN_DRAIN : OUTPUT);
}
uint32_t high = (analogPeriod * val) / analogScale;
uint32_t low = analogPeriod - high;
// 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)
int phaseReference = __builtin_ffs(analogMap) - 1;

// Per the Arduino docs at https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/
// val: the duty cycle: between 0 (always off) and 255 (always on).
// So if val = 0 we have digitalWrite(LOW), if we have val==range we have digitalWrite(HIGH)
if (_setPWM(pin, val, analogScale)) {
if (val > 0 && val < analogScale) {
analogMap |= (1 << pin);
}
} else {
const bool detach = (val == 0 || val == analogScale);
// To go steady LOW or HIGH, let the waveform run into next duty cycle, if any. Then stop.
if (startWaveformClockCycles(pin, high, low, static_cast<uint32_t>(detach), phaseReference, 0, true)) {
if (detach) {
delay((1000 + analogFreq) / analogFreq);
stopWaveform(pin);
} else {
analogMap |= (1 << pin);
}
}
}
}

Expand Down

0 comments on commit aeb30f8

Please sign in to comment.