Skip to content

Commit

Permalink
允许在重复类任务结束后触发一个回调
Browse files Browse the repository at this point in the history
  • Loading branch information
Ebola-Chan-bot committed Jul 6, 2021
1 parent 37ee4c7 commit b114560
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 90 deletions.
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ void DoAfter(uint16_t AfterMilliseconds);
//Repetitively and infinitely call your function with a timer interrupt for each IntervalMilliseconds. The first interrupt happens after IntervalMilliseconds, too.
template <uint8_t TimerCode, uint16_t IntervalMilliseconds, void (*DoTask)()>
void RepeatAfter();
//仅重复有限次数
//Repeat for only RepeatTimes
template <uint8_t TimerCode, uint16_t IntervalMilliseconds, void (*DoTask)(), int32_t RepeatTimes>
//仅重复有限次数,重复全部结束后触发DoneCallback回调
//Repeat for only RepeatTimes. After all repeats done, DoneCallback is called.
template <uint8_t TimerCode, uint16_t IntervalMilliseconds, void (*DoTask)(), int32_t RepeatTimes, void (*DoneCallback)() = nullptr>
void RepeatAfter();
//允许运行时动态设置毫秒数。重复次数不指定的话则为无限重复。
//Specify milliseconds at runtime
template <uint8_t TimerCode, void (*DoTask)(), int32_t RepeatTimes>
//允许运行时动态设置毫秒数。重复次数不指定的话则为无限重复。重复全部结束后触发DoneCallback回调
//Specify milliseconds at runtime. After all repeats done, DoneCallback is called.
template <uint8_t TimerCode, void (*DoTask)(), int32_t RepeatTimes, void (*DoneCallback)() = nullptr>
void RepeatAfter(uint16_t IntervalMilliseconds);

//将当前时刻设为0,计量经过的毫秒数。读取MillisecondsElapsed变量来获得经过的毫秒数。
Expand All @@ -79,26 +79,26 @@ static volatile uint16_t MillisecondsElapsed;
//Play a tone of FrequencyHz on PinCode endlessly.
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz>
void PlayTone();
//只播放限定的毫秒数
//Play for only given Milliseconds
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz, uint16_t Milliseconds>
//只播放限定的毫秒数。播放结束后触发DoneCallback回调
//Play for only given Milliseconds. After the tone ended, DoneCallback is called.
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz, uint16_t Milliseconds, void (*DoneCallback)() = nullptr>
void PlayTone();
//允许运行时动态设置毫秒数。
//Specify milliseconds at runtime
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz>
//允许运行时动态设置毫秒数。播放结束后触发DoneCallback回调
//Specify milliseconds at runtime. After the tone ended, DoneCallback is called.
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz, void (*DoneCallback)() = nullptr>
void PlayTone(uint16_t Milliseconds);

//在引脚上生成无限循环的方波。不同于音调,这里可以指定高电平和低电平的不同时长
//Generate an infinite sequence of square wave. The high level and low level can have different time length.
template <uint8_t TimerCode, uint8_t PinCode, uint16_t HighMilliseconds, uint16_t LowMilliseconds>
void SquareWave()
//仅生成有限个周期数的方波
//Generate the square wave for only RepeatTimes cycles.
template <uint8_t TimerCode, uint8_t PinCode, uint16_t HighMilliseconds, uint16_t LowMilliseconds, int16_t RepeatTimes>
//仅生成有限个周期数的方波。周期全部结束后触发DoneCallback回调
//Generate the square wave for only RepeatTimes cycles. After all cycles done, DoneCallback is called.
template <uint8_t TimerCode, uint8_t PinCode, uint16_t HighMilliseconds, uint16_t LowMilliseconds, int16_t RepeatTimes, void (*DoneCallback)() = nullptr>
void SquareWave()
//允许运行时动态设置毫秒数。重复次数不指定的话则为无限重复。
//Specify milliseconds at runtime
template <uint8_t TimerCode, uint8_t PinCode, int16_t RepeatTimes>
//允许运行时动态设置毫秒数。重复次数不指定的话则为无限重复。周期全部结束后触发DoneCallback回调
//Specify milliseconds at runtime. After all cycles done, DoneCallback is called.
template <uint8_t TimerCode, uint8_t PinCode, int16_t RepeatTimes, void (*DoneCallback)() = nullptr>
void SquareWave(uint16_t HighMilliseconds, uint16_t LowMilliseconds)

//阻塞当前代码执行指定毫秒数
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=TimersOneForAll
version=1.1.1
version=1.2.0
author=EbolaChan <[email protected]>
maintainer=EbolaChan <[email protected]>
sentence=Make full use of all your hardware timers on your Arduino board. 充分利用你开发板上所有的硬件计时器
Expand Down
4 changes: 2 additions & 2 deletions src/Internal/DoAfter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ namespace TimersOneForAll
void DoAfter()
{
constexpr Internal::TimerSetting TS = Internal::GetTimerSetting(TimerCode, AfterMilliseconds);
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, DoTask, 1>();
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, DoTask, 1, nullptr>();
}
//在指定毫秒数后执行任务
template <uint8_t TimerCode, void (*DoTask)()>
void DoAfter(uint16_t AfterMilliseconds)
{
Internal::TimerSetting TS = Internal::GetTimerSetting<TimerCode>(AfterMilliseconds);
Internal::SLRepeaterSet<TimerCode, DoTask, 1>(TS.TCNT, TS.PrescalerBits);
Internal::SLRepeaterSet<TimerCode, DoTask, 1, nullptr>(TS.TCNT, TS.PrescalerBits);
}
}
62 changes: 39 additions & 23 deletions src/Internal/Kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace TimersOneForAll
{
//礼品API:虽然跟本库主题不合,但本库实际上用到了,并且觉得你可能也会感兴趣
namespace Gifts
{
{
//快速翻转引脚电平,比digitalWrite性能更高
template <uint8_t PinCode>
void EfficientDigitalToggle()
Expand Down Expand Up @@ -209,38 +209,42 @@ namespace TimersOneForAll
#pragma endregion
#pragma region 全模板实现
//Compa0表示自我重复,不切换
template <uint8_t TimerCode, void (*DoTask)(), uint16_t SmallRepeats, bool InfiniteLr>
template <uint8_t TimerCode, void (*DoTask)(), uint16_t SmallRepeats, bool InfiniteLr, void (*DoneCallback)()>
void Compa0()
{
if (!--SR<TimerCode>)
{
if (InfiniteLr || --LR<TimerCode>)
SR<TimerCode> = SmallRepeats;
else
{
TIMSK<TimerCode> = 0;
if (DoneCallback)
DoneCallback();
}
DoTask();
}
}
template <uint8_t TimerCode, void (*DoTask)(), uint16_t Tcnt1, uint16_t Tcnt2, uint16_t SR1, uint16_t SR2, bool InfiniteLr>
template <uint8_t TimerCode, void (*DoTask)(), uint16_t Tcnt1, uint16_t Tcnt2, uint16_t SR1, uint16_t SR2, bool InfiniteLr, void (*DoneCallback)()>
void Compa2();
//Compa1是小重复,结束后要切换到大重复,但是大重复有可能是COMPA也可能是OVF
template <uint8_t TimerCode, void (*DoTask)(), uint16_t Tcnt1, uint16_t Tcnt2, uint16_t SR1, uint16_t SR2, bool InfiniteLr>
template <uint8_t TimerCode, void (*DoTask)(), uint16_t Tcnt1, uint16_t Tcnt2, uint16_t SR1, uint16_t SR2, bool InfiniteLr, void (*DoneCallback)()>
void Compa1()
{
if (!--SR<TimerCode>)
{
if (Tcnt2 < TimerMax[TimerCode])
{
SetOCRA<TimerCode>(Tcnt2);
COMPA<TimerCode> = Compa2<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, InfiniteLr>;
COMPA<TimerCode> = Compa2<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, InfiniteLr, DoneCallback>;
}
else
TIMSK<TimerCode> = 1;
SR<TimerCode> = SR2;
}
}
//Compa2是大重复,结束后要执行动作,如果有重复次数还要切换到小重复
template <uint8_t TimerCode, void (*DoTask)(), uint16_t Tcnt1, uint16_t Tcnt2, uint16_t SR1, uint16_t SR2, bool InfiniteLr>
template <uint8_t TimerCode, void (*DoTask)(), uint16_t Tcnt1, uint16_t Tcnt2, uint16_t SR1, uint16_t SR2, bool InfiniteLr, void (*DoneCallback)()>
void Compa2()
{
if (!--SR<TimerCode>)
Expand All @@ -250,18 +254,22 @@ namespace TimersOneForAll
if (Tcnt2 < TimerMax[TimerCode])
{
SetOCRA<TimerCode>(Tcnt1);
COMPA<TimerCode> = Compa1<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, InfiniteLr>;
COMPA<TimerCode> = Compa1<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, InfiniteLr, DoneCallback>;
}
else
TIMSK<TimerCode> = 2;
SR<TimerCode> = SR1;
}
else
{
TIMSK<TimerCode> = 0;
if (DoneCallback)
DoneCallback();
}
DoTask();
}
}
template <uint8_t TimerCode, uint32_t TCNT, uint8_t PrescalerBits, void (*DoTask)(), int32_t RepeatTimes = -1>
template <uint8_t TimerCode, uint32_t TCNT, uint8_t PrescalerBits, void (*DoTask)(), int32_t RepeatTimes, void (*DoneCallback)()>
void SLRepeaterSet()
{
TIMSK<TimerCode> = 0;
Expand Down Expand Up @@ -291,20 +299,20 @@ namespace TimersOneForAll
SR<TimerCode> = SR1;
if (SR2)
{
COMPA<TimerCode> = Compa1<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, (RepeatTimes < 0)>;
COMPA<TimerCode> = Compa1<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, (RepeatTimes < 0), DoneCallback>;
if (Tcnt2 == TM)
OVF<TimerCode> = Compa2<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, (RepeatTimes < 0)>;
OVF<TimerCode> = Compa2<TimerCode, DoTask, Tcnt1, Tcnt2, SR1, SR2, (RepeatTimes < 0), DoneCallback>;
}
else
COMPA<TimerCode> = Compa0<TimerCode, DoTask, SR1, (RepeatTimes < 0)>;
COMPA<TimerCode> = Compa0<TimerCode, DoTask, SR1, (RepeatTimes < 0), DoneCallback>;
SetTCNT<TimerCode>(0);
TIFR<TimerCode> = 255;
TIMSK<TimerCode> = 2;
}
else
{
SR<TimerCode> = IdealRepeats;
OVF<TimerCode> = Compa0<TimerCode, DoTask, IdealRepeats, (RepeatTimes < 0)>;
OVF<TimerCode> = Compa0<TimerCode, DoTask, IdealRepeats, (RepeatTimes < 0), DoneCallback>;
if (Timer02)
TCCRA<TimerCode> = 0;
else
Expand All @@ -326,22 +334,26 @@ namespace TimersOneForAll
template <uint8_t TimerCode>
static volatile uint16_t SR2;
//Compa0表示自我重复,不切换
template <uint8_t TimerCode, void (*DoTask)(), bool InfiniteLr>
template <uint8_t TimerCode, void (*DoTask)(), bool InfiniteLr, void (*DoneCallback)()>
void Compa0()
{
if (!--SR<TimerCode>)
{
if (InfiniteLr || --LR<TimerCode>)
SR<TimerCode> = SR1<TimerCode>;
else
{
TIMSK<TimerCode> = 0;
if (DoneCallback)
DoneCallback();
}
DoTask();
}
}
template <uint8_t TimerCode, void (*DoTask)(), bool InfiniteLr, bool UseOvf>
template <uint8_t TimerCode, void (*DoTask)(), bool InfiniteLr, bool UseOvf, void (*DoneCallback)()>
void Compa2();
//Compa1是小重复,结束后要切换到大重复,但是大重复有可能是COMPA也可能是OVF
template <uint8_t TimerCode, void (*DoTask)(), bool InfiniteLr, bool UseOvf>
template <uint8_t TimerCode, void (*DoTask)(), bool InfiniteLr, bool UseOvf, void (*DoneCallback)()>
void Compa1()
{
if (!--SR<TimerCode>)
Expand All @@ -351,13 +363,13 @@ namespace TimersOneForAll
else
{
SetOCRA<TimerCode>(Tcnt2<TimerCode>);
COMPA<TimerCode> = Compa2<TimerCode, DoTask, InfiniteLr, UseOvf>;
COMPA<TimerCode> = Compa2<TimerCode, DoTask, InfiniteLr, UseOvf, DoneCallback>;
}
SR<TimerCode> = SR2<TimerCode>;
}
}
//Compa2是大重复,结束后要执行动作,如果有重复次数还要切换到小重复
template <uint8_t TimerCode, void (*DoTask)(), bool InfiniteLr, bool UseOvf>
template <uint8_t TimerCode, void (*DoTask)(), bool InfiniteLr, bool UseOvf, void (*DoneCallback)()>
void Compa2()
{
if (!--SR<TimerCode>)
Expand All @@ -369,16 +381,20 @@ namespace TimersOneForAll
else
{
SetOCRA<TimerCode>(Tcnt1<TimerCode>);
COMPA<TimerCode> = Compa1<TimerCode, DoTask, InfiniteLr, UseOvf>;
COMPA<TimerCode> = Compa1<TimerCode, DoTask, InfiniteLr, UseOvf, DoneCallback>;
}
SR<TimerCode> = SR1<TimerCode>;
}
else
{
TIMSK<TimerCode> = 0;
if (DoneCallback)
DoneCallback();
}
DoTask();
}
}
template <uint8_t TimerCode, void (*DoTask)(), int32_t RepeatTimes = -1>
template <uint8_t TimerCode, void (*DoTask)(), int32_t RepeatTimes, void (*DoneCallback)()>
void SLRepeaterSet(uint32_t TCNT, uint8_t PrescalerBits)
{
TIMSK<TimerCode> = 0;
Expand Down Expand Up @@ -410,20 +426,20 @@ namespace TimersOneForAll
bool UseOvf = Tcnt2<TimerCode> == TM;
if (SR2<TimerCode>)
{
COMPA<TimerCode> = UseOvf ? Compa1<TimerCode, DoTask, InfiniteRepeat, true> : Compa1<TimerCode, DoTask, InfiniteRepeat, false>;
COMPA<TimerCode> = UseOvf ? Compa1<TimerCode, DoTask, InfiniteRepeat, true, DoneCallback> : Compa1<TimerCode, DoTask, InfiniteRepeat, false, DoneCallback>;
if (Tcnt2<TimerCode> == TM)
OVF<TimerCode> = UseOvf ? Compa2<TimerCode, DoTask, InfiniteRepeat, true> : Compa2<TimerCode, DoTask, InfiniteRepeat, false>;
OVF<TimerCode> = UseOvf ? Compa2<TimerCode, DoTask, InfiniteRepeat, true, DoneCallback> : Compa2<TimerCode, DoTask, InfiniteRepeat, false, DoneCallback>;
}
else
COMPA<TimerCode> = Compa0<TimerCode, DoTask, InfiniteRepeat>;
COMPA<TimerCode> = Compa0<TimerCode, DoTask, InfiniteRepeat, DoneCallback>;
SetTCNT<TimerCode>(0);
TIFR<TimerCode> = 255;
TIMSK<TimerCode> = 2;
}
else
{
SR<TimerCode> = SR1<TimerCode>;
OVF<TimerCode> = Compa0<TimerCode, DoTask, InfiniteRepeat>;
OVF<TimerCode> = Compa0<TimerCode, DoTask, InfiniteRepeat, DoneCallback>;
if (Timer02)
TCCRA<TimerCode> = 0;
else
Expand Down
10 changes: 5 additions & 5 deletions src/Internal/PlayTone.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ namespace TimersOneForAll
{
constexpr Internal::TimerSetting TS = Internal::GetTimerSetting(TimerCode, 500.f / FrequencyHz);
Gifts::EfficientDigitalToggle<PinCode>();
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, Gifts::EfficientDigitalToggle<PinCode>>();
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, Gifts::EfficientDigitalToggle<PinCode>, -1, nullptr>();
}
//播放有限的毫秒数
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz, uint16_t Milliseconds>
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz, uint16_t Milliseconds, void (*DoneCallback)() = nullptr>
void PlayTone()
{
constexpr Internal::TimerSetting TS = Internal::GetTimerSetting(TimerCode, 500.f / FrequencyHz);
Gifts::EfficientDigitalToggle<PinCode>();
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, Gifts::EfficientDigitalToggle<PinCode>, uint32_t(FrequencyHz) * Milliseconds / 500>();
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, Gifts::EfficientDigitalToggle<PinCode>, uint32_t(FrequencyHz) * Milliseconds / 500, DoneCallback>();
}
//播放有限的毫秒数
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz>
template <uint8_t TimerCode, uint8_t PinCode, uint16_t FrequencyHz, void (*DoneCallback)() = nullptr>
void PlayTone(uint16_t Milliseconds)
{
constexpr Internal::TimerSetting TS = Internal::GetTimerSetting(TimerCode, 500.f / FrequencyHz);
Gifts::EfficientDigitalToggle<PinCode>();
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, Gifts::EfficientDigitalToggle<PinCode>>(uint32_t(FrequencyHz) * Milliseconds / 500);
Internal::SLRepeaterSet<TimerCode, Gifts::EfficientDigitalToggle<PinCode>, uint32_t(FrequencyHz) * Milliseconds / 500, DoneCallback>(TS.TCNT, TS.PrescalerBits);
}
}
8 changes: 4 additions & 4 deletions src/Internal/RepeatAfter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
namespace TimersOneForAll
{
//每隔指定毫秒数重复执行任务。重复次数若为负数,或不指定重复次数,则默认无限重复
template <uint8_t TimerCode, uint16_t IntervalMilliseconds, void (*DoTask)(), int32_t RepeatTimes = -1>
template <uint8_t TimerCode, uint16_t IntervalMilliseconds, void (*DoTask)(), int32_t RepeatTimes = -1, void (*DoneCallback)() = nullptr>
void RepeatAfter()
{
constexpr Internal::TimerSetting TS = Internal::GetTimerSetting(TimerCode, IntervalMilliseconds);
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, DoTask, RepeatTimes>();
Internal::SLRepeaterSet<TimerCode, TS.TCNT, TS.PrescalerBits, DoTask, RepeatTimes, DoneCallback>();
}
//每隔指定毫秒数重复执行任务。重复次数若为负数,或不指定重复次数,则默认无限重复
template <uint8_t TimerCode, void (*DoTask)(), int32_t RepeatTimes = -1>
template <uint8_t TimerCode, void (*DoTask)(), int32_t RepeatTimes = -1, void (*DoneCallback)() = nullptr>
void RepeatAfter(uint16_t IntervalMilliseconds)
{
Internal::TimerSetting TS = Internal::GetTimerSetting<TimerCode>(IntervalMilliseconds);
Internal::SLRepeaterSet<TimerCode, DoTask, RepeatTimes>(TS.TCNT, TS.PrescalerBits);
Internal::SLRepeaterSet<TimerCode, DoTask, RepeatTimes, DoneCallback>(TS.TCNT, TS.PrescalerBits);
}
}
Loading

0 comments on commit b114560

Please sign in to comment.