Minor changes in example .ino files
Real-Time Event Frameworks based on active objects & state machines
Brought to you by:
quantum-leaps
Suggestion-1 For newbies like me, we can get all tick rates called ISR(TIMER2_COMPA_vect), not just 0. It wasn't obvious to me and took a while to realize. It can come commented out, but at least one can see what to do and uncomment them easily.
ISR(TIMER2_COMPA_vect) {
// process time events
QF_tickXISR(0); // tick rate 0
QF_tickXISR(1); // tick rate 1
QF_tickXISR(2); // tick rate 2
QF_tickXISR(3); // tick rate 3
}
Suggestion-2 Some helpful macros:
#define SELF ((QActive*)me)
#define SEND_EVT_TO(_SM_, _EVT_, _PAR_) QACTIVE_POST(&_SM_, _EVT_##_SIG, _PAR_)
#define SEND_EVT_TO_SELF(_EVT_, _PAR_) QACTIVE_POST(SELF, _EVT_##_SIG, _PAR_)
#define START_PERIODIC_TIMER(_EVT_, _PER_) QActive_armX((QActive *)me, (_EVT_##_SIG - Q_TIMEOUT_SIG), _PER_, _PER_)
#define START_ONE_SHOT_TIMER(_EVT_, _TIMEOUT_) QActive_armX((QActive *)me, (_EVT_##_SIG - Q_TIMEOUT_SIG), _TIMEOUT_, 0)
#define STOP_TIMER(_EVT_) QActive_disarmX((QActive*)me, (_EVT_##_SIG - Q_TIMEOUT_SIG))
Suggestion-3 We can get a better accuracy with the smallest prescaler, espacially when we are more interested in micro/milliseconds periods (or kHz tick rates), rather than ticks.
void QF_onStartup(void) {
/*
CS22 CS21 CS20 Description
---- ---- ---- -----------
0 0 0 No clock source (Timer/Counter stopped)
0 0 1 1(No prescaling)
0 1 0 1/8
0 1 1 1/32
1 0 0 1/64
1 0 1 1/128
1 1 0 1/256
1 1 1 1/1024
Since Timer2 has an 8-bit counter:
(F_CPU / PRESCALER) * (1 / BPS_TICS_PER_SEC) <= 256
For the most accurate timing, we will need the smallest prescaler
(so that each increment in TCNT2 is a smaller step)
such that the following expression is true
PRESCALER >= F_CPU / (256 * BPS_TICS_PER_SEC)
Example
For 1000 ticks per sec, we use 1/64 as prescaler
When F_CPU is 16.000000 MHz, F_CPU/64 = 250 kHz.
In 1 ms, there are 250000 * 0.001 = 250 cycles
Hence, OCR2A is 250-1 = 249 (counter cycles through 0-249)
*/
enum {
PRESCL_CFG_1 = (1),
PRESCL_CFG_8 = (2),
PRESCL_CFG_32 = (3),
PRESCL_CFG_64 = (4),
PRESCL_CFG_128 = (5),
PRESCL_CFG_256 = (6),
PRESCL_CFG_1024 = (7)
};
uint8_t cs22_21_20 = 0;
uint8_t prescaler = 1024;
float ratio = F_CPU / (256.0f * BSP_TICKS_PER_SEC);
if (1 > ratio) {
cs22_21_20 = PRESCL_CFG_1;
prescaler = 1;
}else if (8 > ratio) {
cs22_21_20 = PRESCL_CFG_8;
prescaler = 8;
}else if (32 > ratio) {
cs22_21_20 = PRESCL_CFG_32;
prescaler = 32;
}else if (64 > ratio) {
cs22_21_20 = PRESCL_CFG_64;
prescaler = 64;
}else if (128 > ratio) {
cs22_21_20 = PRESCL_CFG_128;
prescaler = 128;
}else if (256 > ratio) {
cs22_21_20 = PRESCL_CFG_256;
prescaler = 256;
}else if (1024 > ratio) {
cs22_21_20 = PRESCL_CFG_1024;
prescaler = 1024;
}
// set Timer2 in CTC mode, with calculated prescaler, and start the timer ticking...
TCCR2A = (1U << WGM21) | (0U << WGM20); // Set CTC mode for Timer2 (Clear Timer on Compare Match (CTC) Mode)
TCCR2B = cs22_21_20; // Set the prescaler
ASSR &= ~(1U << AS2); // Enable async. mode (async: use F_CPU * prescale)
TIMSK2 = (1U << OCIE2A); // enable TIMER2 compare Interrupt
TCNT2 = 0U; // initialize TIMER2 counter to 0
// set the output-compare register based on the desired tick frequency
OCR2A = ((F_CPU / prescaler) / BSP_TICKS_PER_SEC) - 1U; // Set compare-matched value
}
Anonymous
Regarding the proposed changes in the handler
ISR(TIMER2_COMPA_vect), it seems to be a misunderstanding of what the different clock ticks are for.So, the different clock tick rates are intended for different frequency (rate) of ticking. For example rate-0 might be for fast-speed ticking (say, 100Hz), while rate-1 for slow ticking (say, 1Hz).
For this reason, it really doesn't make sense to call the handles for the various tick rates at the same tick rate. Perhaps you could use a software pre-scaler, like in the following pseudo-code:
Regarding the suggested new macros (
SELF,SEND_EVT_TO, etc.), its good that you notice the repeating patterns. But at this point it's not clear that they would simplify coding enough to justify adding another layer of indirection to the QP-nano API. I mean, such things only bloat the API, increase amount of documentation, etc.--MMS