mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
polledTimeout: add option to use CPU count instead of millis() (#5870)
* polledTimeout: add option to use CPU count instead of millis() * use more "using" alias * more c++/clear code, using typename (thanks @devyte) * rename class name to include unit, introduce timeMax() and check it with assert() * remove useless defines * improve api readability, add micro-second unit * update example * mock: emulate getCycleCount, add/fix polledTimeout CI test * + nano-seconds, assert -> message, comments, host test * allow 0 for timeout (enables immediate timeout, fix division by 0) * typo, set member instead of local variable * unify error message * slight change on checkExpired() allows "never expired" also removed printed message, add YieldAndDelay, simplify calculations * remove traces of debug.h/cpp in this PR * include missing <limits> header * back to original expired test, introduce boolean _neverExpires, fix reset(), getTimeout() is invalid * fix expiredOneShot with _timeout==0 check * reenable getTimeout() * expose checkExpired with unit conversion * fix timing comments, move critical code to iram * add member ::neverExpires and use it where relevant * improve clarity * remove exposed checkExpired(), adapt LEAmDNS with equivalent * add API ::resetToNeverExpires(), use it in LEAmDNS * remove offending constness from ::flagged() LEAmDNS (due do API fix in PolledTimeout) * simplify "Fast" base classes * minor variable rename * Fix examples * compliance with good c++ manners * minor changes for consistency * add missing const * expired() and bool() moved to iram * constexpr compensation computing * add/update comments * move neverExpires and alwaysExpired
This commit is contained in:
parent
f0eb5509a0
commit
9a2ed274f3
@ -200,15 +200,20 @@ class EspClass {
|
|||||||
|
|
||||||
bool eraseConfig();
|
bool eraseConfig();
|
||||||
|
|
||||||
inline uint32_t getCycleCount();
|
#ifndef CORE_MOCK
|
||||||
|
inline
|
||||||
|
#endif
|
||||||
|
uint32_t getCycleCount();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef CORE_MOCK
|
||||||
uint32_t EspClass::getCycleCount()
|
uint32_t EspClass::getCycleCount()
|
||||||
{
|
{
|
||||||
uint32_t ccount;
|
uint32_t ccount;
|
||||||
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
__asm__ __volatile__("esync; rsr %0,ccount":"=a" (ccount));
|
||||||
return ccount;
|
return ccount;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern EspClass ESP;
|
extern EspClass ESP;
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ size_t HardwareSerial::readBytes(char* buffer, size_t size)
|
|||||||
|
|
||||||
while (got < size)
|
while (got < size)
|
||||||
{
|
{
|
||||||
esp8266::polledTimeout::oneShot timeOut(_timeout);
|
esp8266::polledTimeout::oneShotFastMs timeOut(_timeout);
|
||||||
size_t avail;
|
size_t avail;
|
||||||
while ((avail = available()) == 0 && !timeOut);
|
while ((avail = available()) == 0 && !timeOut);
|
||||||
if (avail == 0)
|
if (avail == 0)
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
namespace esp8266
|
namespace esp8266
|
||||||
@ -45,19 +47,112 @@ struct YieldOrSkip
|
|||||||
static void execute() {delay(0);}
|
static void execute() {delay(0);}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <unsigned long delayMs>
|
||||||
|
struct YieldAndDelayMs
|
||||||
|
{
|
||||||
|
static void execute() {delay(delayMs);}
|
||||||
|
};
|
||||||
|
|
||||||
} //YieldPolicy
|
} //YieldPolicy
|
||||||
|
|
||||||
|
namespace TimePolicy
|
||||||
|
{
|
||||||
|
|
||||||
template <bool PeriodicT, typename YieldPolicyT = YieldPolicy::DoNothing>
|
struct TimeSourceMillis
|
||||||
|
{
|
||||||
|
// time policy in milli-seconds based on millis()
|
||||||
|
|
||||||
|
using timeType = decltype(millis());
|
||||||
|
static timeType time() {return millis();}
|
||||||
|
static constexpr timeType ticksPerSecond = 1000;
|
||||||
|
static constexpr timeType ticksPerSecondMax = 1000;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimeSourceCycles
|
||||||
|
{
|
||||||
|
// time policy based on ESP.getCycleCount()
|
||||||
|
// this particular time measurement is intended to be called very often
|
||||||
|
// (every loop, every yield)
|
||||||
|
|
||||||
|
using timeType = decltype(ESP.getCycleCount());
|
||||||
|
static timeType time() {return ESP.getCycleCount();}
|
||||||
|
static constexpr timeType ticksPerSecond = F_CPU; // 80'000'000 or 160'000'000 Hz
|
||||||
|
static constexpr timeType ticksPerSecondMax = 160000000; // 160MHz
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TimeSourceType, unsigned long long second_th>
|
||||||
|
// "second_th" units of timeType for one second
|
||||||
|
struct TimeUnit
|
||||||
|
{
|
||||||
|
using timeType = typename TimeSourceType::timeType;
|
||||||
|
|
||||||
|
#if __GNUC__ < 5
|
||||||
|
// gcc-4.8 cannot compile the constexpr-only version of this function
|
||||||
|
// using #defines instead luckily works
|
||||||
|
static constexpr timeType computeRangeCompensation ()
|
||||||
|
{
|
||||||
|
#define number_of_secondTh_in_one_tick ((1.0 * second_th) / ticksPerSecond)
|
||||||
|
#define fractional (number_of_secondTh_in_one_tick - (long)number_of_secondTh_in_one_tick)
|
||||||
|
|
||||||
|
return ({
|
||||||
|
fractional == 0?
|
||||||
|
1: // no need for compensation
|
||||||
|
(number_of_secondTh_in_one_tick / fractional) + 0.5; // scalar multiplier allowing exact division
|
||||||
|
});
|
||||||
|
|
||||||
|
#undef number_of_secondTh_in_one_tick
|
||||||
|
#undef fractional
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static constexpr timeType computeRangeCompensation ()
|
||||||
|
{
|
||||||
|
return ({
|
||||||
|
constexpr double number_of_secondTh_in_one_tick = (1.0 * second_th) / ticksPerSecond;
|
||||||
|
constexpr double fractional = number_of_secondTh_in_one_tick - (long)number_of_secondTh_in_one_tick;
|
||||||
|
fractional == 0?
|
||||||
|
1: // no need for compensation
|
||||||
|
(number_of_secondTh_in_one_tick / fractional) + 0.5; // scalar multiplier allowing exact division
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static constexpr timeType ticksPerSecond = TimeSourceType::ticksPerSecond;
|
||||||
|
static constexpr timeType ticksPerSecondMax = TimeSourceType::ticksPerSecondMax;
|
||||||
|
static constexpr timeType rangeCompensate = computeRangeCompensation();
|
||||||
|
static constexpr timeType user2UnitMultiplierMax = (ticksPerSecondMax * rangeCompensate) / second_th;
|
||||||
|
static constexpr timeType user2UnitMultiplier = (ticksPerSecond * rangeCompensate) / second_th;
|
||||||
|
static constexpr timeType user2UnitDivider = rangeCompensate;
|
||||||
|
// std::numeric_limits<timeType>::max() is reserved
|
||||||
|
static constexpr timeType timeMax = (std::numeric_limits<timeType>::max() - 1) / user2UnitMultiplierMax;
|
||||||
|
|
||||||
|
static timeType toTimeTypeUnit (const timeType userUnit) {return (userUnit * user2UnitMultiplier) / user2UnitDivider;}
|
||||||
|
static timeType toUserUnit (const timeType internalUnit) {return (internalUnit * user2UnitDivider) / user2UnitMultiplier;}
|
||||||
|
static timeType time () {return TimeSourceType::time();}
|
||||||
|
};
|
||||||
|
|
||||||
|
using TimeMillis = TimeUnit< TimeSourceMillis, 1000 >;
|
||||||
|
using TimeFastMillis = TimeUnit< TimeSourceCycles, 1000 >;
|
||||||
|
using TimeFastMicros = TimeUnit< TimeSourceCycles, 1000000 >;
|
||||||
|
using TimeFastNanos = TimeUnit< TimeSourceCycles, 1000000000 >;
|
||||||
|
|
||||||
|
} //TimePolicy
|
||||||
|
|
||||||
|
template <bool PeriodicT, typename YieldPolicyT = YieldPolicy::DoNothing, typename TimePolicyT = TimePolicy::TimeMillis>
|
||||||
class timeoutTemplate
|
class timeoutTemplate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using timeType = decltype(millis());
|
using timeType = typename TimePolicyT::timeType;
|
||||||
|
|
||||||
timeoutTemplate(timeType timeout)
|
static constexpr timeType alwaysExpired = 0;
|
||||||
: _timeout(timeout), _start(millis())
|
static constexpr timeType neverExpires = std::numeric_limits<timeType>::max();
|
||||||
{}
|
static constexpr timeType rangeCompensate = TimePolicyT::rangeCompensate; //debug
|
||||||
|
|
||||||
|
timeoutTemplate(const timeType userTimeout)
|
||||||
|
{
|
||||||
|
reset(userTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
ICACHE_RAM_ATTR
|
||||||
bool expired()
|
bool expired()
|
||||||
{
|
{
|
||||||
YieldPolicyT::execute(); //in case of DoNothing: gets optimized away
|
YieldPolicyT::execute(); //in case of DoNothing: gets optimized away
|
||||||
@ -66,37 +161,69 @@ public:
|
|||||||
return expiredOneShot();
|
return expiredOneShot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ICACHE_RAM_ATTR
|
||||||
operator bool()
|
operator bool()
|
||||||
{
|
{
|
||||||
return expired();
|
return expired();
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(const timeType newTimeout)
|
bool canExpire () const
|
||||||
|
{
|
||||||
|
return !_neverExpires;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool canWait () const
|
||||||
|
{
|
||||||
|
return _timeout != alwaysExpired;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(const timeType newUserTimeout)
|
||||||
{
|
{
|
||||||
_timeout = newTimeout;
|
|
||||||
reset();
|
reset();
|
||||||
|
_timeout = TimePolicyT::toTimeTypeUnit(newUserTimeout);
|
||||||
|
_neverExpires = (newUserTimeout < 0) || (newUserTimeout > timeMax());
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
_start = millis();
|
_start = TimePolicyT::time();
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetToNeverExpires ()
|
||||||
|
{
|
||||||
|
_timeout = alwaysExpired + 1; // because canWait() has precedence
|
||||||
|
_neverExpires = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeType getTimeout() const
|
timeType getTimeout() const
|
||||||
{
|
{
|
||||||
return _timeout;
|
return TimePolicyT::toUserUnit(_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkExpired(const timeType t) const
|
static constexpr timeType timeMax()
|
||||||
{
|
{
|
||||||
return (t - _start) >= _timeout;
|
return TimePolicyT::timeMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ICACHE_RAM_ATTR
|
||||||
|
bool checkExpired(const timeType internalUnit) const
|
||||||
|
{
|
||||||
|
// canWait() is not checked here
|
||||||
|
// returns "can expire" and "time expired"
|
||||||
|
return (!_neverExpires) && ((internalUnit - _start) >= _timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
ICACHE_RAM_ATTR
|
||||||
bool expiredRetrigger()
|
bool expiredRetrigger()
|
||||||
{
|
{
|
||||||
timeType current = millis();
|
if (!canWait())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
timeType current = TimePolicyT::time();
|
||||||
if(checkExpired(current))
|
if(checkExpired(current))
|
||||||
{
|
{
|
||||||
unsigned long n = (current - _start) / _timeout; //how many _timeouts periods have elapsed, will usually be 1 (current - _start >= _timeout)
|
unsigned long n = (current - _start) / _timeout; //how many _timeouts periods have elapsed, will usually be 1 (current - _start >= _timeout)
|
||||||
@ -106,23 +233,50 @@ protected:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ICACHE_RAM_ATTR
|
||||||
bool expiredOneShot() const
|
bool expiredOneShot() const
|
||||||
{
|
{
|
||||||
return checkExpired(millis());
|
// returns "always expired" or "has expired"
|
||||||
|
return !canWait() || checkExpired(TimePolicyT::time());
|
||||||
}
|
}
|
||||||
|
|
||||||
timeType _timeout;
|
timeType _timeout;
|
||||||
timeType _start;
|
timeType _start;
|
||||||
|
bool _neverExpires;
|
||||||
};
|
};
|
||||||
|
|
||||||
using oneShot = polledTimeout::timeoutTemplate<false>;
|
// legacy type names, deprecated (unit is milliseconds)
|
||||||
using periodic = polledTimeout::timeoutTemplate<true>;
|
|
||||||
|
using oneShot = polledTimeout::timeoutTemplate<false> /*__attribute__((deprecated("use oneShotMs")))*/;
|
||||||
|
using periodic = polledTimeout::timeoutTemplate<true> /*__attribute__((deprecated("use periodicMs")))*/;
|
||||||
|
|
||||||
|
// standard versions (based on millis())
|
||||||
|
// timeMax() is 49.7 days ((2^32)-2 ms)
|
||||||
|
|
||||||
|
using oneShotMs = polledTimeout::timeoutTemplate<false>;
|
||||||
|
using periodicMs = polledTimeout::timeoutTemplate<true>;
|
||||||
|
|
||||||
|
// Time policy based on ESP.getCycleCount(), and intended to be called very often:
|
||||||
|
// "Fast" versions sacrifices time range for improved precision and reduced execution time (by 86%)
|
||||||
|
// (cpu cycles for ::expired(): 372 (millis()) vs 52 (ESP.getCycleCount()))
|
||||||
|
// timeMax() values:
|
||||||
|
// Ms: max is 26843 ms (26.8 s)
|
||||||
|
// Us: max is 26843545 us (26.8 s)
|
||||||
|
// Ns: max is 1073741823 ns ( 1.07 s)
|
||||||
|
// (time policy based on ESP.getCycleCount() is intended to be called very often)
|
||||||
|
|
||||||
|
using oneShotFastMs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
|
||||||
|
using periodicFastMs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMillis>;
|
||||||
|
using oneShotFastUs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastMicros>;
|
||||||
|
using periodicFastUs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastMicros>;
|
||||||
|
using oneShotFastNs = polledTimeout::timeoutTemplate<false, YieldPolicy::DoNothing, TimePolicy::TimeFastNanos>;
|
||||||
|
using periodicFastNs = polledTimeout::timeoutTemplate<true, YieldPolicy::DoNothing, TimePolicy::TimeFastNanos>;
|
||||||
|
|
||||||
} //polledTimeout
|
} //polledTimeout
|
||||||
|
|
||||||
|
|
||||||
/* A 1-shot timeout that auto-yields when in CONT can be built as follows:
|
/* A 1-shot timeout that auto-yields when in CONT can be built as follows:
|
||||||
* using oneShotYield = esp8266::polledTimeout::timeoutTemplate<false, esp8266::polledTimeout::YieldPolicy::YieldOrSkip>;
|
* using oneShotYieldMs = esp8266::polledTimeout::timeoutTemplate<false, esp8266::polledTimeout::YieldPolicy::YieldOrSkip>;
|
||||||
*
|
*
|
||||||
* Other policies can be implemented by the user, e.g.: simple yield that panics in SYS, and the polledTimeout types built as needed as shown above, without modifying this file.
|
* Other policies can be implemented by the user, e.g.: simple yield that panics in SYS, and the polledTimeout types built as needed as shown above, without modifying this file.
|
||||||
*/
|
*/
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
WiFiServer statusServer(TCP_PORT);
|
WiFiServer statusServer(TCP_PORT);
|
||||||
WiFiUDP udp;
|
WiFiUDP udp;
|
||||||
esp8266::polledTimeout::periodic statusPeriod(STATUSDELAY_MS);
|
esp8266::polledTimeout::periodicMs showStatusOnSerialNow(STATUSDELAY_MS);
|
||||||
|
|
||||||
void fqdn(Print& out, const String& fqdn) {
|
void fqdn(Print& out, const String& fqdn) {
|
||||||
out.print(F("resolving "));
|
out.print(F("resolving "));
|
||||||
@ -149,7 +149,7 @@ void setup() {
|
|||||||
Serial.print(F(" - UDP server on port "));
|
Serial.print(F(" - UDP server on port "));
|
||||||
Serial.println(UDP_PORT);
|
Serial.println(UDP_PORT);
|
||||||
|
|
||||||
statusPeriod.reset();
|
showStatusOnSerialNow.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long statusTimeMs = 0;
|
unsigned long statusTimeMs = 0;
|
||||||
@ -182,7 +182,7 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (statusPeriod) {
|
if (showStatusOnSerialNow) {
|
||||||
status(Serial);
|
status(Serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ void loop(void) {
|
|||||||
// Allow MDNS processing
|
// Allow MDNS processing
|
||||||
MDNS.update();
|
MDNS.update();
|
||||||
|
|
||||||
static esp8266::polledTimeout::periodic timeout(UPDATE_CYCLE);
|
static esp8266::polledTimeout::periodicMs timeout(UPDATE_CYCLE);
|
||||||
if (timeout.expired()) {
|
if (timeout.expired()) {
|
||||||
|
|
||||||
if (hMDNSService) {
|
if (hMDNSService) {
|
||||||
|
@ -907,7 +907,7 @@ protected:
|
|||||||
struct stcProbeInformation {
|
struct stcProbeInformation {
|
||||||
enuProbingStatus m_ProbingStatus;
|
enuProbingStatus m_ProbingStatus;
|
||||||
uint8_t m_u8SentCount; // Used for probes and announcements
|
uint8_t m_u8SentCount; // Used for probes and announcements
|
||||||
esp8266::polledTimeout::oneShot m_Timeout; // Used for probes and announcements
|
esp8266::polledTimeout::oneShotMs m_Timeout; // Used for probes and announcements
|
||||||
//clsMDNSTimeFlag m_TimeFlag; // Used for probes and announcements
|
//clsMDNSTimeFlag m_TimeFlag; // Used for probes and announcements
|
||||||
bool m_bConflict;
|
bool m_bConflict;
|
||||||
bool m_bTiebreakNeeded;
|
bool m_bTiebreakNeeded;
|
||||||
@ -975,13 +975,13 @@ protected:
|
|||||||
const timeoutLevel_t TIMEOUTLEVEL_FINAL = 100;
|
const timeoutLevel_t TIMEOUTLEVEL_FINAL = 100;
|
||||||
|
|
||||||
uint32_t m_u32TTL;
|
uint32_t m_u32TTL;
|
||||||
esp8266::polledTimeout::oneShot m_TTLTimeout;
|
esp8266::polledTimeout::oneShotMs m_TTLTimeout;
|
||||||
timeoutLevel_t m_timeoutLevel;
|
timeoutLevel_t m_timeoutLevel;
|
||||||
|
|
||||||
stcTTL(void);
|
stcTTL(void);
|
||||||
bool set(uint32_t p_u32TTL);
|
bool set(uint32_t p_u32TTL);
|
||||||
|
|
||||||
bool flagged(void) const;
|
bool flagged(void);
|
||||||
bool restart(void);
|
bool restart(void);
|
||||||
|
|
||||||
bool prepareDeletion(void);
|
bool prepareDeletion(void);
|
||||||
@ -1078,7 +1078,7 @@ protected:
|
|||||||
MDNSServiceQueryCallbackFunc m_fnCallback;
|
MDNSServiceQueryCallbackFunc m_fnCallback;
|
||||||
bool m_bLegacyQuery;
|
bool m_bLegacyQuery;
|
||||||
uint8_t m_u8SentCount;
|
uint8_t m_u8SentCount;
|
||||||
esp8266::polledTimeout::oneShot m_ResendTimeout;
|
esp8266::polledTimeout::oneShotMs m_ResendTimeout;
|
||||||
bool m_bAwaitingAnswers;
|
bool m_bAwaitingAnswers;
|
||||||
stcAnswer* m_pAnswers;
|
stcAnswer* m_pAnswers;
|
||||||
|
|
||||||
|
@ -1047,7 +1047,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
|||||||
m_HostProbeInformation.m_ProbingStatus = ProbingStatus_InProgress;
|
m_HostProbeInformation.m_ProbingStatus = ProbingStatus_InProgress;
|
||||||
}
|
}
|
||||||
else if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing AND
|
else if ((ProbingStatus_InProgress == m_HostProbeInformation.m_ProbingStatus) && // Probing AND
|
||||||
(m_HostProbeInformation.m_Timeout.checkExpired(millis()))) { // Time for next probe
|
(m_HostProbeInformation.m_Timeout.expired())) { // Time for next probe
|
||||||
|
|
||||||
if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8SentCount) { // Send next probe
|
if (MDNS_PROBE_COUNT > m_HostProbeInformation.m_u8SentCount) { // Send next probe
|
||||||
if ((bResult = _sendHostProbe())) {
|
if ((bResult = _sendHostProbe())) {
|
||||||
@ -1059,7 +1059,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
|||||||
else { // Probing finished
|
else { // Probing finished
|
||||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host probing.\n")););
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host probing.\n")););
|
||||||
m_HostProbeInformation.m_ProbingStatus = ProbingStatus_Done;
|
m_HostProbeInformation.m_ProbingStatus = ProbingStatus_Done;
|
||||||
m_HostProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
m_HostProbeInformation.m_Timeout.resetToNeverExpires();
|
||||||
if (m_HostProbeInformation.m_fnHostProbeResultCallback) {
|
if (m_HostProbeInformation.m_fnHostProbeResultCallback) {
|
||||||
m_HostProbeInformation.m_fnHostProbeResultCallback(m_pcHostname, true);
|
m_HostProbeInformation.m_fnHostProbeResultCallback(m_pcHostname, true);
|
||||||
}
|
}
|
||||||
@ -1071,7 +1071,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
|||||||
}
|
}
|
||||||
} // else: Probing already finished OR waiting for next time slot
|
} // else: Probing already finished OR waiting for next time slot
|
||||||
else if ((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) &&
|
else if ((ProbingStatus_Done == m_HostProbeInformation.m_ProbingStatus) &&
|
||||||
(m_HostProbeInformation.m_Timeout.checkExpired(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()))) {
|
(m_HostProbeInformation.m_Timeout.expired())) {
|
||||||
|
|
||||||
if ((bResult = _announce(true, false))) { // Don't announce services here
|
if ((bResult = _announce(true, false))) { // Don't announce services here
|
||||||
++m_HostProbeInformation.m_u8SentCount;
|
++m_HostProbeInformation.m_u8SentCount;
|
||||||
@ -1081,7 +1081,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
|||||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%lu).\n\n"), m_HostProbeInformation.m_u8SentCount););
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing host (%lu).\n\n"), m_HostProbeInformation.m_u8SentCount););
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_HostProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
m_HostProbeInformation.m_Timeout.resetToNeverExpires();
|
||||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host announcing.\n\n")););
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done host announcing.\n\n")););
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1096,7 +1096,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
|||||||
pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_InProgress;
|
pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_InProgress;
|
||||||
}
|
}
|
||||||
else if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND
|
else if ((ProbingStatus_InProgress == pService->m_ProbeInformation.m_ProbingStatus) && // Probing AND
|
||||||
(pService->m_ProbeInformation.m_Timeout.checkExpired(millis()))) { // Time for next probe
|
(pService->m_ProbeInformation.m_Timeout.expired())) { // Time for next probe
|
||||||
|
|
||||||
if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8SentCount) { // Send next probe
|
if (MDNS_PROBE_COUNT > pService->m_ProbeInformation.m_u8SentCount) { // Send next probe
|
||||||
if ((bResult = _sendServiceProbe(*pService))) {
|
if ((bResult = _sendServiceProbe(*pService))) {
|
||||||
@ -1108,7 +1108,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
|||||||
else { // Probing finished
|
else { // Probing finished
|
||||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service probing %s.%s.%s\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol););
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service probing %s.%s.%s\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol););
|
||||||
pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_Done;
|
pService->m_ProbeInformation.m_ProbingStatus = ProbingStatus_Done;
|
||||||
pService->m_ProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
pService->m_ProbeInformation.m_Timeout.resetToNeverExpires();
|
||||||
if (pService->m_ProbeInformation.m_fnServiceProbeResultCallback) {
|
if (pService->m_ProbeInformation.m_fnServiceProbeResultCallback) {
|
||||||
pService->m_ProbeInformation.m_fnServiceProbeResultCallback(pService->m_pcName, pService, true);
|
pService->m_ProbeInformation.m_fnServiceProbeResultCallback(pService->m_pcName, pService, true);
|
||||||
}
|
}
|
||||||
@ -1119,7 +1119,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
|||||||
}
|
}
|
||||||
} // else: Probing already finished OR waiting for next time slot
|
} // else: Probing already finished OR waiting for next time slot
|
||||||
else if ((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) &&
|
else if ((ProbingStatus_Done == pService->m_ProbeInformation.m_ProbingStatus) &&
|
||||||
(pService->m_ProbeInformation.m_Timeout.checkExpired(millis()))) {
|
(pService->m_ProbeInformation.m_Timeout.expired())) {
|
||||||
|
|
||||||
if ((bResult = _announceService(*pService))) { // Announce service
|
if ((bResult = _announceService(*pService))) { // Announce service
|
||||||
++pService->m_ProbeInformation.m_u8SentCount;
|
++pService->m_ProbeInformation.m_u8SentCount;
|
||||||
@ -1129,7 +1129,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
|
|||||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%lu)\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount););
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Announcing service %s.%s.%s (%lu)\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol, pService->m_ProbeInformation.m_u8SentCount););
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pService->m_ProbeInformation.m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
pService->m_ProbeInformation.m_Timeout.resetToNeverExpires();
|
||||||
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service announcing for %s.%s.%s\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol););
|
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Done service announcing for %s.%s.%s\n\n"), (pService->m_pcName ?: m_pcHostname), pService->m_pcService, pService->m_pcProtocol););
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1441,13 +1441,13 @@ bool MDNSResponder::_checkServiceQueryCache(void) {
|
|||||||
// Resend dynamic service queries, if not already done often enough
|
// Resend dynamic service queries, if not already done often enough
|
||||||
if ((!pServiceQuery->m_bLegacyQuery) &&
|
if ((!pServiceQuery->m_bLegacyQuery) &&
|
||||||
(MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) &&
|
(MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount) &&
|
||||||
(pServiceQuery->m_ResendTimeout.checkExpired(millis()))) {
|
(pServiceQuery->m_ResendTimeout.expired())) {
|
||||||
|
|
||||||
if ((bResult = _sendMDNSServiceQuery(*pServiceQuery))) {
|
if ((bResult = _sendMDNSServiceQuery(*pServiceQuery))) {
|
||||||
++pServiceQuery->m_u8SentCount;
|
++pServiceQuery->m_u8SentCount;
|
||||||
pServiceQuery->m_ResendTimeout.reset((MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount)
|
pServiceQuery->m_ResendTimeout.reset((MDNS_DYNAMIC_QUERY_RESEND_COUNT > pServiceQuery->m_u8SentCount)
|
||||||
? (MDNS_DYNAMIC_QUERY_RESEND_DELAY * (pServiceQuery->m_u8SentCount - 1))
|
? (MDNS_DYNAMIC_QUERY_RESEND_DELAY * (pServiceQuery->m_u8SentCount - 1))
|
||||||
: std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
: esp8266::polledTimeout::oneShotMs::neverExpires);
|
||||||
}
|
}
|
||||||
DEBUG_EX_INFO(
|
DEBUG_EX_INFO(
|
||||||
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: %s to resend service query!"), (bResult ? "Succeeded" : "FAILED"));
|
DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _checkServiceQueryCache: %s to resend service query!"), (bResult ? "Succeeded" : "FAILED"));
|
||||||
|
@ -1159,7 +1159,7 @@ bool MDNSResponder::stcMDNS_RRAnswerGeneric::clear(void) {
|
|||||||
MDNSResponder::stcProbeInformation::stcProbeInformation(void)
|
MDNSResponder::stcProbeInformation::stcProbeInformation(void)
|
||||||
: m_ProbingStatus(ProbingStatus_WaitingForData),
|
: m_ProbingStatus(ProbingStatus_WaitingForData),
|
||||||
m_u8SentCount(0),
|
m_u8SentCount(0),
|
||||||
m_Timeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()),
|
m_Timeout(esp8266::polledTimeout::oneShotMs::neverExpires),
|
||||||
m_bConflict(false),
|
m_bConflict(false),
|
||||||
m_bTiebreakNeeded(false),
|
m_bTiebreakNeeded(false),
|
||||||
m_fnHostProbeResultCallback(0),
|
m_fnHostProbeResultCallback(0),
|
||||||
@ -1173,7 +1173,7 @@ bool MDNSResponder::stcProbeInformation::clear(bool p_bClearUserdata /*= false*/
|
|||||||
|
|
||||||
m_ProbingStatus = ProbingStatus_WaitingForData;
|
m_ProbingStatus = ProbingStatus_WaitingForData;
|
||||||
m_u8SentCount = 0;
|
m_u8SentCount = 0;
|
||||||
m_Timeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
m_Timeout.resetToNeverExpires();
|
||||||
m_bConflict = false;
|
m_bConflict = false;
|
||||||
m_bTiebreakNeeded = false;
|
m_bTiebreakNeeded = false;
|
||||||
if (p_bClearUserdata) {
|
if (p_bClearUserdata) {
|
||||||
@ -1421,7 +1421,7 @@ bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::isOutdated(void) con
|
|||||||
*/
|
*/
|
||||||
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(void)
|
MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::stcTTL(void)
|
||||||
: m_u32TTL(0),
|
: m_u32TTL(0),
|
||||||
m_TTLTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()),
|
m_TTLTimeout(esp8266::polledTimeout::oneShotMs::neverExpires),
|
||||||
m_timeoutLevel(TIMEOUTLEVEL_UNSET) {
|
m_timeoutLevel(TIMEOUTLEVEL_UNSET) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1438,7 +1438,7 @@ bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TT
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_timeoutLevel = TIMEOUTLEVEL_UNSET; // undef
|
m_timeoutLevel = TIMEOUTLEVEL_UNSET; // undef
|
||||||
m_TTLTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
m_TTLTimeout.resetToNeverExpires();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1446,11 +1446,11 @@ bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::set(uint32_t p_u32TT
|
|||||||
/*
|
/*
|
||||||
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged
|
* MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged
|
||||||
*/
|
*/
|
||||||
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged(void) const {
|
bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::flagged(void) {
|
||||||
|
|
||||||
return ((m_u32TTL) &&
|
return ((m_u32TTL) &&
|
||||||
(TIMEOUTLEVEL_UNSET != m_timeoutLevel) &&
|
(TIMEOUTLEVEL_UNSET != m_timeoutLevel) &&
|
||||||
(m_TTLTimeout.checkExpired(millis())));
|
(m_TTLTimeout.expired()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1468,7 +1468,7 @@ bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::restart(void) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bResult = false;
|
bResult = false;
|
||||||
m_TTLTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
m_TTLTimeout.resetToNeverExpires();
|
||||||
m_timeoutLevel = TIMEOUTLEVEL_UNSET;
|
m_timeoutLevel = TIMEOUTLEVEL_UNSET;
|
||||||
}
|
}
|
||||||
return bResult;
|
return bResult;
|
||||||
@ -1498,7 +1498,7 @@ bool MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::finalTimeoutLevel(vo
|
|||||||
*/
|
*/
|
||||||
unsigned long MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout(void) const {
|
unsigned long MDNSResponder::stcMDNSServiceQuery::stcAnswer::stcTTL::timeout(void) const {
|
||||||
|
|
||||||
uint32_t u32Timeout = std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max();
|
uint32_t u32Timeout = esp8266::polledTimeout::oneShotMs::neverExpires;
|
||||||
|
|
||||||
if (TIMEOUTLEVEL_BASE == m_timeoutLevel) { // 80%
|
if (TIMEOUTLEVEL_BASE == m_timeoutLevel) { // 80%
|
||||||
u32Timeout = (m_u32TTL * 800); // to milliseconds
|
u32Timeout = (m_u32TTL * 800); // to milliseconds
|
||||||
@ -1922,7 +1922,7 @@ MDNSResponder::stcMDNSServiceQuery::stcMDNSServiceQuery(void)
|
|||||||
m_fnCallback(0),
|
m_fnCallback(0),
|
||||||
m_bLegacyQuery(false),
|
m_bLegacyQuery(false),
|
||||||
m_u8SentCount(0),
|
m_u8SentCount(0),
|
||||||
m_ResendTimeout(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max()),
|
m_ResendTimeout(esp8266::polledTimeout::oneShotMs::neverExpires),
|
||||||
m_bAwaitingAnswers(true),
|
m_bAwaitingAnswers(true),
|
||||||
m_pAnswers(0) {
|
m_pAnswers(0) {
|
||||||
|
|
||||||
@ -1945,7 +1945,7 @@ bool MDNSResponder::stcMDNSServiceQuery::clear(void) {
|
|||||||
m_fnCallback = 0;
|
m_fnCallback = 0;
|
||||||
m_bLegacyQuery = false;
|
m_bLegacyQuery = false;
|
||||||
m_u8SentCount = 0;
|
m_u8SentCount = 0;
|
||||||
m_ResendTimeout.reset(std::numeric_limits<esp8266::polledTimeout::oneShot::timeType>::max());
|
m_ResendTimeout.resetToNeverExpires();
|
||||||
m_bAwaitingAnswers = true;
|
m_bAwaitingAnswers = true;
|
||||||
while (m_pAnswers) {
|
while (m_pAnswers) {
|
||||||
stcAnswer* pNext = m_pAnswers->m_pNext;
|
stcAnswer* pNext = m_pAnswers->m_pNext;
|
||||||
|
@ -73,7 +73,7 @@ private:
|
|||||||
DEBUGV("SDFS: Clear FAT/DIR writeStart failed");
|
DEBUGV("SDFS: Clear FAT/DIR writeStart failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
esp8266::polledTimeout::periodic timeToYield(5); // Yield every 5ms of runtime
|
esp8266::polledTimeout::periodicFastMs timeToYield(5); // Yield every 5ms of runtime
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
if (timeToYield) {
|
if (timeToYield) {
|
||||||
delay(0); // WDT feed
|
delay(0); // WDT feed
|
||||||
|
@ -23,7 +23,7 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
using periodic = esp8266::polledTimeout::periodic;
|
using periodic = esp8266::polledTimeout::periodicMs;
|
||||||
static periodic nextPing(1000);
|
static periodic nextPing(1000);
|
||||||
|
|
||||||
if (nextPing) {
|
if (nextPing) {
|
||||||
|
@ -24,7 +24,7 @@ void setup() {
|
|||||||
byte x = 0;
|
byte x = 0;
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
using periodic = esp8266::polledTimeout::periodic;
|
using periodic = esp8266::polledTimeout::periodicMs;
|
||||||
static periodic nextPing(1000);
|
static periodic nextPing(1000);
|
||||||
|
|
||||||
if (nextPing) {
|
if (nextPing) {
|
||||||
|
@ -38,20 +38,34 @@ void ledToggle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp8266::polledTimeout::periodicFastUs halfPeriod(500000); //use fully qualified type and avoid importing all ::esp8266 namespace to the global namespace
|
||||||
esp8266::polledTimeout::periodic halfPeriod(500); //use fully qualified type and avoid importing all ::esp8266 namespace to the global namespace
|
|
||||||
|
|
||||||
// the setup function runs only once at start
|
// the setup function runs only once at start
|
||||||
void setup() {
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
Serial.printf("periodic/oneShotMs::timeMax() = %u ms\n", (uint32_t)esp8266::polledTimeout::periodicMs::timeMax());
|
||||||
|
Serial.printf("periodic/oneShotFastMs::timeMax() = %u ms\n", (uint32_t)esp8266::polledTimeout::periodicFastMs::timeMax());
|
||||||
|
Serial.printf("periodic/oneShotFastUs::timeMax() = %u us\n", (uint32_t)esp8266::polledTimeout::periodicFastUs::timeMax());
|
||||||
|
Serial.printf("periodic/oneShotFastNs::timeMax() = %u ns\n", (uint32_t)esp8266::polledTimeout::periodicFastNs::timeMax());
|
||||||
|
|
||||||
|
#if 0 // 1 for debugging polledTimeout
|
||||||
|
Serial.printf("periodic/oneShotMs::rangeCompensate = %u\n", (uint32_t)esp8266::polledTimeout::periodicMs::rangeCompensate);
|
||||||
|
Serial.printf("periodic/oneShotFastMs::rangeCompensate = %u\n", (uint32_t)esp8266::polledTimeout::periodicFastMs::rangeCompensate);
|
||||||
|
Serial.printf("periodic/oneShotFastUs::rangeCompensate = %u\n", (uint32_t)esp8266::polledTimeout::periodicFastUs::rangeCompensate);
|
||||||
|
Serial.printf("periodic/oneShotFastNs::rangeCompensate = %u\n", (uint32_t)esp8266::polledTimeout::periodicFastNs::rangeCompensate);
|
||||||
|
#endif
|
||||||
|
|
||||||
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
|
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
|
||||||
|
|
||||||
using esp8266::polledTimeout::oneShot; //import the type to the local namespace
|
using esp8266::polledTimeout::oneShotMs; //import the type to the local namespace
|
||||||
|
|
||||||
//STEP1; turn the led ON
|
//STEP1; turn the led ON
|
||||||
ledOn();
|
ledOn();
|
||||||
|
|
||||||
//STEP2: wait for ON timeout
|
//STEP2: wait for ON timeout
|
||||||
oneShot timeoutOn(2000);
|
oneShotMs timeoutOn(2000);
|
||||||
while (!timeoutOn) {
|
while (!timeoutOn) {
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
@ -60,7 +74,7 @@ void setup() {
|
|||||||
ledOff();
|
ledOff();
|
||||||
|
|
||||||
//STEP4: wait for OFF timeout to assure the led is kept off for this time before exiting setup
|
//STEP4: wait for OFF timeout to assure the led is kept off for this time before exiting setup
|
||||||
oneShot timeoutOff(2000);
|
oneShotMs timeoutOff(2000);
|
||||||
while (!timeoutOff) {
|
while (!timeoutOff) {
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include <Esp.h>
|
#include <Esp.h>
|
||||||
#include <eboot_command.h>
|
#include <eboot_command.h>
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
unsigned long long operator"" _kHz(unsigned long long x) {
|
unsigned long long operator"" _kHz(unsigned long long x) {
|
||||||
@ -215,3 +217,9 @@ void EspClass::resetFreeContStack()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t EspClass::getCycleCount()
|
||||||
|
{
|
||||||
|
timeval t;
|
||||||
|
gettimeofday(&t, NULL);
|
||||||
|
return (((uint64_t)t.tv_sec) * 1000000 + t.tv_usec) * (F_CPU / 1000000);
|
||||||
|
}
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
DEALINGS WITH THE SOFTWARE.
|
DEALINGS WITH THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define CORE_MOCK 1
|
||||||
|
|
||||||
// include host's STL before any other include file
|
// include host's STL before any other include file
|
||||||
// because core definition like max() is in the way
|
// because core definition like max() is in the way
|
||||||
|
|
||||||
@ -138,8 +140,6 @@ void mock_stop_spiffs ();
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
#define CORE_MOCK 1
|
|
||||||
|
|
||||||
#define ARDUINO 267
|
#define ARDUINO 267
|
||||||
#define ESP8266 1
|
#define ESP8266 1
|
||||||
#define A0 0
|
#define A0 0
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include "PolledTimeout.h"
|
#include "PolledTimeout.h"
|
||||||
|
|
||||||
|
#define mockverbose printf
|
||||||
|
#include "common/MockEsp.cpp" // getCycleCount
|
||||||
|
|
||||||
//This won't work for
|
//This won't work for
|
||||||
template<typename argT>
|
template<typename argT>
|
||||||
inline bool
|
inline bool
|
||||||
@ -10,15 +13,83 @@ fuzzycomp(argT a, argT b)
|
|||||||
return (std::max(a,b) - std::min(a,b) <= epsilon);
|
return (std::max(a,b) - std::min(a,b) <= epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("OneShot Timeout 500000000ns (0.5s)", "[polledTimeout]")
|
||||||
|
{
|
||||||
|
using esp8266::polledTimeout::oneShotFastNs;
|
||||||
|
using timeType = oneShotFastNs::timeType;
|
||||||
|
timeType before, after, delta;
|
||||||
|
|
||||||
|
Serial.println("OneShot Timeout 500000000ns (0.5s)");
|
||||||
|
|
||||||
|
oneShotFastNs timeout(500000000);
|
||||||
|
before = micros();
|
||||||
|
while(!timeout.expired())
|
||||||
|
yield();
|
||||||
|
after = micros();
|
||||||
|
|
||||||
|
delta = after - before;
|
||||||
|
Serial.printf("delta = %u\n", delta);
|
||||||
|
|
||||||
|
REQUIRE(fuzzycomp(delta/1000, (timeType)500));
|
||||||
|
|
||||||
|
|
||||||
|
Serial.print("reset\n");
|
||||||
|
|
||||||
|
timeout.reset();
|
||||||
|
before = micros();
|
||||||
|
while(!timeout)
|
||||||
|
yield();
|
||||||
|
after = micros();
|
||||||
|
|
||||||
|
delta = after - before;
|
||||||
|
Serial.printf("delta = %u\n", delta);
|
||||||
|
|
||||||
|
REQUIRE(fuzzycomp(delta/1000, (timeType)500));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("OneShot Timeout 3000000us", "[polledTimeout]")
|
||||||
|
{
|
||||||
|
using esp8266::polledTimeout::oneShotFastUs;
|
||||||
|
using timeType = oneShotFastUs::timeType;
|
||||||
|
timeType before, after, delta;
|
||||||
|
|
||||||
|
Serial.println("OneShot Timeout 3000000us");
|
||||||
|
|
||||||
|
oneShotFastUs timeout(3000000);
|
||||||
|
before = micros();
|
||||||
|
while(!timeout.expired())
|
||||||
|
yield();
|
||||||
|
after = micros();
|
||||||
|
|
||||||
|
delta = after - before;
|
||||||
|
Serial.printf("delta = %u\n", delta);
|
||||||
|
|
||||||
|
REQUIRE(fuzzycomp(delta/1000, (timeType)3000));
|
||||||
|
|
||||||
|
|
||||||
|
Serial.print("reset\n");
|
||||||
|
|
||||||
|
timeout.reset();
|
||||||
|
before = micros();
|
||||||
|
while(!timeout)
|
||||||
|
yield();
|
||||||
|
after = micros();
|
||||||
|
|
||||||
|
delta = after - before;
|
||||||
|
Serial.printf("delta = %u\n", delta);
|
||||||
|
|
||||||
|
REQUIRE(fuzzycomp(delta/1000, (timeType)3000));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("OneShot Timeout 3000ms", "[polledTimeout]")
|
TEST_CASE("OneShot Timeout 3000ms", "[polledTimeout]")
|
||||||
{
|
{
|
||||||
using esp8266::polledTimeout::oneShot;
|
using esp8266::polledTimeout::oneShotMs;
|
||||||
using timeType = oneShot::timeType;
|
using timeType = oneShotMs::timeType;
|
||||||
timeType before, after, delta;
|
timeType before, after, delta;
|
||||||
|
|
||||||
Serial.println("OneShot Timeout 3000ms");
|
Serial.println("OneShot Timeout 3000ms");
|
||||||
|
|
||||||
oneShot timeout(3000);
|
oneShotMs timeout(3000);
|
||||||
before = millis();
|
before = millis();
|
||||||
while(!timeout.expired())
|
while(!timeout.expired())
|
||||||
yield();
|
yield();
|
||||||
@ -46,13 +117,13 @@ TEST_CASE("OneShot Timeout 3000ms", "[polledTimeout]")
|
|||||||
|
|
||||||
TEST_CASE("OneShot Timeout 3000ms reset to 1000ms", "[polledTimeout]")
|
TEST_CASE("OneShot Timeout 3000ms reset to 1000ms", "[polledTimeout]")
|
||||||
{
|
{
|
||||||
using esp8266::polledTimeout::oneShot;
|
using esp8266::polledTimeout::oneShotMs;
|
||||||
using timeType = oneShot::timeType;
|
using timeType = oneShotMs::timeType;
|
||||||
timeType before, after, delta;
|
timeType before, after, delta;
|
||||||
|
|
||||||
Serial.println("OneShot Timeout 3000ms");
|
Serial.println("OneShot Timeout 3000ms");
|
||||||
|
|
||||||
oneShot timeout(3000);
|
oneShotMs timeout(3000);
|
||||||
before = millis();
|
before = millis();
|
||||||
while(!timeout.expired())
|
while(!timeout.expired())
|
||||||
yield();
|
yield();
|
||||||
@ -80,13 +151,13 @@ TEST_CASE("OneShot Timeout 3000ms reset to 1000ms", "[polledTimeout]")
|
|||||||
|
|
||||||
TEST_CASE("Periodic Timeout 1T 3000ms", "[polledTimeout]")
|
TEST_CASE("Periodic Timeout 1T 3000ms", "[polledTimeout]")
|
||||||
{
|
{
|
||||||
using esp8266::polledTimeout::periodic;
|
using esp8266::polledTimeout::periodicMs;
|
||||||
using timeType = periodic::timeType;
|
using timeType = periodicMs::timeType;
|
||||||
timeType before, after, delta;
|
timeType before, after, delta;
|
||||||
|
|
||||||
Serial.println("Periodic Timeout 1T 3000ms");
|
Serial.println("Periodic Timeout 1T 3000ms");
|
||||||
|
|
||||||
periodic timeout(3000);
|
periodicMs timeout(3000);
|
||||||
before = millis();
|
before = millis();
|
||||||
while(!timeout)
|
while(!timeout)
|
||||||
yield();
|
yield();
|
||||||
@ -112,15 +183,15 @@ TEST_CASE("Periodic Timeout 1T 3000ms", "[polledTimeout]")
|
|||||||
|
|
||||||
TEST_CASE("Periodic Timeout 10T 1000ms", "[polledTimeout]")
|
TEST_CASE("Periodic Timeout 10T 1000ms", "[polledTimeout]")
|
||||||
{
|
{
|
||||||
using esp8266::polledTimeout::periodic;
|
using esp8266::polledTimeout::periodicMs;
|
||||||
using timeType = periodic::timeType;
|
using timeType = periodicMs::timeType;
|
||||||
timeType before, after, delta;
|
timeType before, after, delta;
|
||||||
|
|
||||||
Serial.println("Periodic 10T Timeout 1000ms");
|
Serial.println("Periodic 10T Timeout 1000ms");
|
||||||
|
|
||||||
int counter = 10;
|
int counter = 10;
|
||||||
|
|
||||||
periodic timeout(1000);
|
periodicMs timeout(1000);
|
||||||
before = millis();
|
before = millis();
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
@ -142,14 +213,14 @@ TEST_CASE("Periodic Timeout 10T 1000ms", "[polledTimeout]")
|
|||||||
TEST_CASE("OneShot Timeout 3000ms reset to 1000ms custom yield", "[polledTimeout]")
|
TEST_CASE("OneShot Timeout 3000ms reset to 1000ms custom yield", "[polledTimeout]")
|
||||||
{
|
{
|
||||||
using YieldOrSkipPolicy = esp8266::polledTimeout::YieldPolicy::YieldOrSkip;
|
using YieldOrSkipPolicy = esp8266::polledTimeout::YieldPolicy::YieldOrSkip;
|
||||||
using oneShotYield = esp8266::polledTimeout::timeoutTemplate<false, YieldOrSkipPolicy>;
|
using oneShotMsYield = esp8266::polledTimeout::timeoutTemplate<false, YieldOrSkipPolicy>;
|
||||||
using timeType = oneShotYield::timeType;
|
using timeType = oneShotMsYield::timeType;
|
||||||
timeType before, after, delta;
|
timeType before, after, delta;
|
||||||
|
|
||||||
Serial.println("OneShot Timeout 3000ms");
|
Serial.println("OneShot Timeout 3000ms");
|
||||||
|
|
||||||
|
|
||||||
oneShotYield timeout(3000);
|
oneShotMsYield timeout(3000);
|
||||||
before = millis();
|
before = millis();
|
||||||
while(!timeout.expired());
|
while(!timeout.expired());
|
||||||
after = millis();
|
after = millis();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user