-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathQueueISR.ino
131 lines (101 loc) · 2.39 KB
/
QueueISR.ino
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
#include <frt.h>
namespace
{
// This is our queue holding at most five unsigned 16 bit integers
frt::Queue<uint16_t, 5> queue;
// This is the mutex to protect our output from getting mixed up
frt::Mutex serial_mutex;
// The print task
class PrintTask final :
public frt::Task<PrintTask>
{
public:
PrintTask() :
conversion_count(0)
{
}
bool run()
{
startConversion();
uint16_t adc_value;
// This task could be stopped, as we wait with timeout here
if (queue.pop(adc_value, 15)) {
// conversion_count is concurrently accessed
mutex.lock();
++conversion_count;
mutex.unlock();
// Serial needs to be locked against MonitoringTask
serial_mutex.lock();
Serial.println(adc_value);
serial_mutex.unlock();
// If you comment out the Serial.println() above
// you get way more conversions per second.
}
return true;
}
uint32_t getAndResetConversionCount()
{
// Called from MonitoringTask, thus the mutex
mutex.lock();
const uint32_t res = conversion_count;
conversion_count = 0;
mutex.unlock();
return res;
}
private:
void startConversion()
{
ADCSRA |= bit(ADSC) | bit(ADIE);
}
uint32_t conversion_count;
frt::Mutex mutex;
};
// Our PrintTask instance
PrintTask print_task;
// The monitoring task
class MonitoringTask final :
public frt::Task<MonitoringTask>
{
public:
bool run()
{
msleep(1000, remainder);
serial_mutex.lock();
Serial.print(F("Queue fill level: "));
Serial.println(queue.getFillLevel());
Serial.print(F("Print stack used: "));
Serial.println(print_task.getUsedStackSize());
Serial.print(F("Conversions per second: "));
Serial.println(print_task.getAndResetConversionCount());
serial_mutex.unlock();
return true;
}
private:
unsigned int remainder = 0;
};
// The MonitoringTask instance
MonitoringTask monitoring_task;
}
void setup()
{
Serial.begin(9600);
while (!Serial);
// This is ATMega328 specific
ADMUX = bit(REFS0); // AVcc as reference
// Start monitoring task with low priority
monitoring_task.start(1);
// Start print task with high priority
print_task.start(2);
}
void loop()
{
// Nothing to do here
}
// This ISR is called when the ADC is finished
ISR(ADC_vect)
{
queue.preparePushFromInterrupt();
const uint16_t adc_value = ADCL | ADCH << 8;
queue.pushFromInterrupt(adc_value);
queue.finalizePushFromInterrupt();
}