src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
12 / 12
100.0%
Branches:
2 / 2
100.0%
Functions:
3 / 3
100.0%

TxBuffer.h
Line Branch Exec Source
1 #ifndef TX_BUFFER_H
2 #define TX_BUFFER_H
3 #include <Arduino.h>
4 #include "SomfyFrame.h"
5
6 // Repeater frames waiting to be handed to the radio task, and the jobs and
7 // events passed to and from it. Kept free of the radio and timers so it can be
8 // unit tested on the PC (pio test -e native).
9
10 #define MAX_TX_BUFFER 5
11 #define TX_JOB_QUEUE_SIZE 32
12 // Slots only priority jobs (stops) may use so a stop always fits in the queue.
13 #define TX_RESERVED_SLOTS 4
14 // The radio task bit-bangs a whole job on loop()'s core at a higher priority
15 // so loop() only runs between jobs. A frame takes about 140ms so this keeps a
16 // job around 7s, well inside the 15s task watchdog loop() is subscribed to.
17 #define TX_MAX_REPEATS 50
18
19 struct somfy_tx_t {
20 72 void clear() {
21 72 this->hwsync = 0;
22 72 this->bit_length = 0;
23 72 memset(this->payload, 0x00, sizeof(this->payload));
24 72 }
25 uint8_t hwsync = 0;
26 uint8_t bit_length = 0;
27 uint8_t payload[10] = {};
28 };
29 struct somfy_tx_queue_t {
30 7 somfy_tx_queue_t() { this->clear(); }
31 8 void clear() {
32
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 8 times.
48 for (uint8_t i = 0; i < MAX_TX_BUFFER; i++) {
33 40 this->index[i] = 255;
34 40 this->items[i].clear();
35 }
36 8 this->length = 0;
37 8 }
38 unsigned long delay_time = 0; // Set by the caller, not before this millis().
39 uint8_t length = 0;
40 uint8_t index[MAX_TX_BUFFER] = {255};
41 somfy_tx_t items[MAX_TX_BUFFER];
42 // The oldest frame without removing it, so it can stay queued until the radio
43 // takes it.
44 bool peek(somfy_tx_t *tx) const;
45 bool pop(somfy_tx_t *tx);
46 // When full the oldest frame is thrown away.
47 void push(uint8_t hwsync, byte *payload, uint8_t bit_length);
48 private:
49 // Position in index of the oldest frame, -1 when empty.
50 int8_t oldest() const;
51 };
52 // A transmission handed off to the radio task. The first frame is encoded by
53 // the producer into tx. The frame is a copy so the radio task never touches the
54 // remote's lastFrame and is only used to re-encode 80-bit repeat frames.
55 struct somfy_tx_job_t {
56 somfy_tx_t tx; // Encoded first frame with its hw sync count and bit length.
57 somfy_frame_t frame;
58 uint8_t repeats = 0; // Number of repeat frames after the first frame.
59 uint8_t firstRepeat = 1; // 80-bit repeat counter used for the first repeat frame.
60 bool repeater = false; // Repeater frame. Waits for the receiver to be idle.
61 // Set by RadioScheduler::submit().
62 bool priority = false; // May use the reserved slots.
63 bool front = false; // Queued ahead of the back. Only for priority jobs.
64 uint32_t ticket = 0; // Matches the job's events up with it.
65 uint32_t queuedAt = 0; // millis() when it was submitted.
66 uint16_t delayMs = 0; // How long it waits after it was queued and after the job ahead of it ended.
67 };
68 enum class tx_event_t : uint8_t {
69 started, // The job is going on air.
70 finished, // Every frame of the job went on air.
71 aborted, // The job was cut short by a flush or a radio reconfiguration.
72 dropped // The job was flushed and will never go on air.
73 };
74 // Reported by the radio task for every queued non-repeater job.
75 struct somfy_tx_event_t {
76 tx_event_t type = tx_event_t::started;
77 somfy_commands cmd = somfy_commands::My;
78 uint32_t remoteAddress = 0;
79 uint32_t ticket = 0;
80 uint32_t at = 0; // millis() when the job started or was dropped.
81 };
82 // Encodes the first frame of a transmission into the job. Encoding here keeps
83 // its side effects on the frame (valid flag, default step size) visible to the
84 // caller and the radio task only re-encodes the 80-bit repeat frames. More
85 // than TX_MAX_REPEATS repeats are cut down to it.
86 void encodeTxJob(somfy_tx_job_t &job, somfy_frame_t &frame, uint8_t repeat);
87 // Encodes a repeat of the frame last sent. The first frame carries the
88 // frame's current repeat counter and the radio task counts up from there.
89 void encodeRepeatJob(somfy_tx_job_t &job, somfy_frame_t &frame, uint8_t repeat);
90 // Advances the frame's repeat counter past a repeat job the radio took.
91 void noteRepeatQueued(somfy_frame_t &frame, const somfy_tx_job_t &job);
92 #endif
93