src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
1 / 1
100.0%
Branches:
-
-%
Functions:
1 / 1
100.0%

RadioScheduler.h
Line Branch Exec Source
1 #ifndef RADIO_SCHEDULER_H
2 #define RADIO_SCHEDULER_H
3 #include <stdint.h>
4 #include "TxBuffer.h"
5
6 // Reasons the radio must not transmit. TX resumes once every reason is cleared.
7 #define TX_SUSPEND_SCAN 0x01
8 #define TX_SUSPEND_OTA 0x02
9 // No job is waiting so the radio task sleeps until it is woken.
10 #define RADIO_WAIT_FOREVER 0xFFFFFFFFu
11
12 // The radio jobs waiting for, or on, the air (see GLOSSARY.md). It decides
13 // their order, when a delayed job is due, what a flush or suspend drops, and
14 // reports the outcome of every job. Kept free of FreeRTOS and the radio so it
15 // can be unit tested on the PC (pio test -e native).
16 //
17 // Not thread safe. The caller serializes every call and passes the time in.
18 class RadioScheduler {
19 public:
20 // Queues a job. Its ticket comes back and is also set in job.ticket, 0 when
21 // the queue is full or suspended, or when outcomes aren't collected with
22 // popEvent() fast enough to leave room for its own. A priority job (a stop) may use the
23 // reserved slots and goes ahead of every job queued at the back, unless a
24 // job of its remote is already waiting: overtaking that would put the
25 // rolling codes out of order. A delayed job doesn't go on air until
26 // delayMs after it was queued and after the job ahead of it ended, and holds
27 // up the jobs queued behind it.
28 uint32_t submit(somfy_tx_job_t &job, bool priority, uint16_t delayMs, uint32_t now);
29 // Whether a normal (not priority) job would be taken right now.
30 bool hasRoom() const;
31 // For the radio task: takes the job to send next. False when there is
32 // none due, waitMs then says how long until there is (RADIO_WAIT_FOREVER
33 // when nothing waits). A job taken goes on air through start() and
34 // ended().
35 bool next(uint32_t now, somfy_tx_job_t &job, uint32_t &waitMs);
36 // The job taken is about to go on air. False when it was flushed since,
37 // it is then dropped and must not be sent.
38 bool start(uint32_t ticket, uint32_t now);
39 // Whether the job on air should send its next frame. A flush cuts it
40 // short.
41 bool keepSending(uint32_t ticket) const;
42 // The job on air stopped, after every frame when complete.
43 void ended(uint32_t ticket, bool complete, uint32_t now);
44 // Drops every waiting job and cuts short the one on air.
45 void flush(uint32_t now);
46 // Refuses new jobs until every reason (TX_SUSPEND_*) is resumed. Flushes.
47 void suspend(uint8_t reason, uint32_t now);
48 void resume(uint8_t reason);
49 3 bool suspended() const { return this->suspendMask != 0; }
50 // Takes the oldest job outcome not yet handed out. Every job submitted
51 // that isn't a repeater frame is started and then finished or aborted, or
52 // dropped.
53 bool popEvent(somfy_tx_event_t &evt);
54 private:
55 somfy_tx_job_t jobs[TX_JOB_QUEUE_SIZE];
56 uint8_t count = 0;
57 uint32_t lastTicket = 0;
58 uint8_t suspendMask = 0;
59 // The job taken by next() and not yet ended (0 for none), kept for its
60 // events.
61 uint32_t taken = 0;
62 somfy_tx_job_t takenJob;
63 bool takenFlushed = false;
64 // When a job last went off air, for the delay of the job after it.
65 uint32_t lastEnded = 0;
66 bool endedOnce = false;
67 somfy_tx_event_t events[TX_JOB_QUEUE_SIZE * 3];
68 uint8_t eventHead = 0;
69 uint8_t eventCount = 0;
70 // Whether the outcomes of every job not yet ended, and of one more, still
71 // fit in events. A job is refused otherwise so no outcome is ever lost.
72 bool outcomesFit() const;
73 // Whether a job of the remote is still waiting.
74 bool waitingFor(uint32_t remoteAddress) const;
75 void remove(uint8_t i);
76 void post(tx_event_t type, const somfy_tx_job_t &job, uint32_t at);
77 };
78 #endif
79