-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow specifying waveform generator in source code (#7800)
* Allow specifying waveform generator in source code Allows code to explicitly specify which waveform generator it wants, without needing to use one of the 100 IDE menus or adding a `-D` compile-time define. Uses weakrefs to allow for apps to call `enablePhaseLockedWaveform();` within their `setup()` (or anywhere, really) and have the phase locked versions override the default waveform generators automatically. For example: ```` void setup() { // Uncomment following line to use phase-locked waveform generator // enablePhaseLockedWaveform(); Serial.begin(115200); pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output analogWriteRange(1000); } void loop() { analogWrite(LED_BUILTIN, 100); delay(1000); // Wait for a second analogWrite(LED_BUILTIN, 900); delay(2000); // Wait for two seconds (to demonstrate the active low LED) } ```` Also adds an example showing it's use. Address @dok-net's comments and also remove the _weak/_bound version of startWaveform() since it's invariant of the actual waveform generator.
- Loading branch information
1 parent
a4b6003
commit f5fd591
Showing
14 changed files
with
283 additions
and
413 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,128 @@ | ||
// Wrapper to include both versions of the waveform generator | ||
/* | ||
esp8266_waveform - General purpose waveform generation and control, | ||
supporting outputs on all pins in parallel. | ||
-- Default, PWM locked version -- | ||
Copyright (c) 2018 Earle F. Philhower, III. All rights reserved. | ||
The core idea is to have a programmable waveform generator with a unique | ||
high and low period (defined in microseconds or CPU clock cycles). TIMER1 is | ||
set to 1-shot mode and is always loaded with the time until the next edge | ||
of any live waveforms. | ||
Up to one waveform generator per pin supported. | ||
Each waveform generator is synchronized to the ESP clock cycle counter, not the | ||
timer. This allows for removing interrupt jitter and delay as the counter | ||
always increments once per 80MHz clock. Changes to a waveform are | ||
contiguous and only take effect on the next waveform transition, | ||
allowing for smooth transitions. | ||
This replaces older tone(), analogWrite(), and the Servo classes. | ||
Everywhere in the code where "cycles" is used, it means ESP.getCycleCount() | ||
clock cycle count, or an interval measured in CPU clock cycles, but not TIMER1 | ||
cycles (which may be 2 CPU clock cycles @ 160MHz). | ||
---------- | ||
-- Phase locked version -- | ||
Copyright (c) 2020 Dirk O. Kaar. | ||
The core idea is to have a programmable waveform generator with a unique | ||
high and low period (defined in microseconds or CPU clock cycles). TIMER1 is | ||
set to 1-shot mode and is always loaded with the time until the next edge | ||
of any live waveforms. | ||
Up to one waveform generator per pin supported. | ||
Each waveform generator is synchronized to the ESP clock cycle counter, not the | ||
timer. This allows for removing interrupt jitter and delay as the counter | ||
always increments once per 80MHz clock. Changes to a waveform are | ||
contiguous and only take effect on the next waveform transition, | ||
allowing for smooth transitions. | ||
This replaces older tone(), analogWrite(), and the Servo classes. | ||
Everywhere in the code where "ccy" or "ccys" is used, it means ESP.getCycleCount() | ||
clock cycle count, or an interval measured in CPU clock cycles, but not TIMER1 | ||
cycles (which may be 2 CPU clock cycles @ 160MHz). | ||
---------- | ||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
This library is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
|
||
#include <Arduino.h> | ||
|
||
#ifndef __ESP8266_WAVEFORM_H | ||
#define __ESP8266_WAVEFORM_H | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
// Call this function in your setup() to cause the phase locked version of the generator to | ||
// be linked in automatically. Otherwise, the default PWM locked version will be used. | ||
void enablePhaseLockedWaveform(void); | ||
|
||
|
||
// Start or change a waveform of the specified high and low times on specific pin. | ||
// If runtimeUS > 0 then automatically stop it after that many usecs, relative to the next | ||
// full period. | ||
// If waveform is not yet started on pin, and on pin == alignPhase a waveform is running, | ||
// the new waveform is started at phaseOffsetUS phase offset, in microseconds, to that. | ||
// 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); | ||
|
||
// 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 | ||
// full period. | ||
// If waveform is not yet started on pin, and on pin == alignPhase a waveform is running, | ||
// the new waveform is started at phaseOffsetCcys phase offset, in CPU clock cycles, to that. | ||
// 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); | ||
|
||
// Stop a waveform, if any, on the specified pin. | ||
// Returns true or false on success or failure. | ||
int stopWaveform(uint8_t pin); | ||
|
||
// Add a callback function to be called on *EVERY* timer1 trigger. The | ||
// callback must return the number of CPU clock cycles until the next desired call. | ||
// However, since it is called every timer1 interrupt, it may be called | ||
// again before this period. It should therefore use the ESP Cycle Counter | ||
// to determine whether or not to perform an operation. | ||
// Pass in NULL to disable the callback and, if no other waveforms being | ||
// generated, stop the timer as well. | ||
// Make sure the CB function has the ICACHE_RAM_ATTR decorator. | ||
void setTimer1Callback(uint32_t (*fn)()); | ||
|
||
|
||
// Internal-only calls, not for applications | ||
extern void _setPWMFreq(uint32_t freq); | ||
extern bool _stopPWM(uint8_t pin); | ||
extern bool _setPWM(int pin, uint32_t val, uint32_t range); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#ifdef WAVEFORM_LOCKED_PHASE | ||
#include "core_esp8266_waveform_phase.h" | ||
#else | ||
#include "core_esp8266_waveform_pwm.h" | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.