-
Notifications
You must be signed in to change notification settings - Fork 0
/
Commander.h
132 lines (111 loc) · 3.43 KB
/
Commander.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*TODO: сделать диспетчер задач, системный таймер и очередь в виде кольцевого буфера (продумать мьютексы)*/
/*TODO:если на проходе по списку вызывается функция у задачи, которая помещает задачу в конец списка с временем 0, то задача будет все время туда помещатся и не выходить из цикла,
нужно добавить флаг который бы показывал, что данная задача уже выполнялась в этом цикле update*/
#pragma once
#include <Arduino.h>
#include <stdint.h>
// #define avr
// #define esp
// период таймера для работы с частотой в 1кГц
// #define FREQ_TIMER 16000UL
struct Task{
Task(void(*f)()) : func(f) {}
void (*func)() = nullptr;
uint64_t timer = 0;
bool mutex = false;
Task *nextTask = nullptr;
bool fExecuted = false;
};
class Commander{
public:
Commander() = default;
~Commander() = default;
void begin();
void check(); /*проверяет очередь и убирает из нее задачи после их выполнения*/
bool moveToQueue(Task* task, uint64_t time);
void updateTimer();
private:
Task *head = nullptr;
};
/*
void Commander::begin()
{
cli();
TCCR1B = 0b001; //clock div1
TCNT1 = 0;
TCCR1A = 0;
OCR1A = FREQ_TIMER;
TIMSK1 |= (1 << OCIE1A);
SREG |= (1<<SREG_I);
sei();
}
*/
void Commander::check()
{
if(head == nullptr)
return; //пустой список
Task *prevTask = nullptr;
Task *curTask = head;
while(curTask != nullptr) {
//выполнение задачи по истечению таймера и если функция не заблокирована
Task *nextTask = curTask->nextTask;
if(!curTask->mutex && !curTask->fExecuted && curTask->timer <= millis()) {
if(prevTask == nullptr) {
head = curTask->nextTask;
}
else {
prevTask->nextTask = curTask->nextTask;
//curTask = prevTask;
}
curTask->func();
curTask->fExecuted = true;
}
else {
prevTask = curTask;
curTask->fExecuted = false;
}
curTask = nextTask;
}
}
/*
Move task to queue that will emit after time_ms
*/
bool Commander::moveToQueue(Task* task, uint64_t time_ms)
{
cli();
task->timer = millis() + time_ms;
task->nextTask = nullptr;
sei();
// Serial.println("Move task");
if(head == nullptr) {
head = task;
// Serial.println("Move to head");
return;
}
Task *curTask = head;
while (curTask->nextTask != nullptr)
{
curTask = curTask->nextTask;
}
curTask->nextTask = task;
// Serial.println("Move to end");
}
void Commander::updateTimer()
{
Task *curTask = head;
while(curTask != nullptr){
if(curTask->timer != 0) {
curTask->timer--;
}
curTask = curTask->nextTask;
}
}
Commander commander;
/*
ISR(TIMER1_COMPA_vect)
{
TCNT1 = 0;
sei();
commander.updateTimer();
}
*/