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
// SPDX-License-Identifier: AGPL-3.0-only
use cratePacket;
/// Stable, lossy error enum for the transport-agnostic [`Transceiver`] trait.
///
/// The driver's parametric [`crate::Error`] preserves the underlying SPI /
/// GPIO error types, which is useful for users that hold a concrete
/// `Rfm69<...>` but does not survive a `dyn` boundary or a generic that
/// abstracts over the backing radio. `TrxError` collapses those variants
/// into a fixed vocabulary for use across the `Transceiver` boundary.
///
/// **The lossy shape is deliberate** (the alternative was to make
/// `TrxError` parametric over the SPI / RESET / DIO0 error types). Reasons:
///
/// - Mirrors the `embassy-net::Stack` pattern — high-level Stack APIs
/// should not leak the underlying driver's error types across the
/// abstraction they were created to draw.
/// - Keeps `Stack<'a>`, `Runner<'a, TRX>`, and the channel slot type
/// free of an extra error-type generic, so user code threading `Stack`
/// around stays terse.
/// - Future multi-radio backends get to share one stable error
/// vocabulary; user code keeps working when swapping backings.
/// - Debuggability is preserved by the [`Runner`](crate::Runner) logging
/// the underlying error chain via the internal `error!` macro before
/// handing the collapsed `TrxError` to the user.
///
/// Power users who want the full parametric error chain can call the
/// inherent `Rfm69::send` / `Rfm69::recv` directly, which still return
/// `Error<SPI, RESET, DIO0>` — the lossy collapse only happens at the
/// `Transceiver` boundary.
// `async fn in trait` deliberately leaves the Send-bound on the returned
// futures unspecified. embassy on the targets this crate supports is
// single-executor, so Send isn't needed; if a future user runs across
// executor threads they can desugar a wrapper trait that adds the bound.