1use esp_sync::NonReentrantMutex;
2
3use super::hal::{
4 set_cca_mode,
5 set_cca_threshold,
6 set_coordinator,
7 set_freq,
8 set_multipan_enable_mask,
9 set_multipan_ext_addr,
10 set_multipan_panid,
11 set_multipan_short_addr,
12 set_pending_mode,
13 set_power,
14 set_promiscuous,
15 set_rx_auto_ack,
16 set_tx_auto_ack,
17 set_tx_enhance_ack,
18};
19
20pub(crate) const CONFIG_IEEE802154_CCA_THRESHOLD: i8 = -60;
21pub(crate) const IEEE802154_FRAME_EXT_ADDR_SIZE: usize = 8;
22
23const IEEE802154_MULTIPAN_0: u8 = 0;
24const IEEE802154_MULTIPAN_MAX: usize = 4;
25
26#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
28pub enum PendingMode {
29 #[default]
31 Disable = 0,
32 Enable = 1,
35 Enhanced = 2,
37 Zigbee = 3,
40}
41
42#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
44pub enum CcaMode {
45 #[default]
47 Carrier = 0x00,
48 Ed = 0x01,
50 CarrierOrEd = 0x02,
52 CarrierAndEd = 0x03,
54}
55
56#[derive(Debug, Default, Clone, Copy)]
57struct Pib {
58 auto_ack_tx: bool,
59 auto_ack_rx: bool,
60 enhance_ack_tx: bool,
61 promiscuous: bool,
62 coordinator: bool,
63 rx_when_idle: bool,
64 txpower: i8,
65 channel: u8,
66 pending_mode: PendingMode,
67 multipan_mask: u8,
68 panid: [u16; IEEE802154_MULTIPAN_MAX],
69 short_addr: [u16; IEEE802154_MULTIPAN_MAX],
70 ext_addr: [[u8; IEEE802154_FRAME_EXT_ADDR_SIZE]; IEEE802154_MULTIPAN_MAX],
71 cca_threshold: i8,
72 cca_mode: CcaMode,
73}
74
75static PIB: NonReentrantMutex<Pib> = NonReentrantMutex::new(Pib {
76 auto_ack_tx: false,
77 auto_ack_rx: false,
78 enhance_ack_tx: false,
79 coordinator: false,
80 promiscuous: false,
81 rx_when_idle: false,
82 txpower: 0,
83 channel: 0,
84 pending_mode: PendingMode::Disable,
85 multipan_mask: 0,
86 panid: [0u16; 4],
87 short_addr: [0u16; IEEE802154_MULTIPAN_MAX],
88 ext_addr: [[0; IEEE802154_FRAME_EXT_ADDR_SIZE]; IEEE802154_MULTIPAN_MAX],
89 cca_threshold: 0,
90 cca_mode: CcaMode::Carrier,
91});
92
93pub(crate) fn ieee802154_pib_init() {
94 PIB.with(|pib| {
95 *pib = Pib {
96 auto_ack_tx: true,
97 auto_ack_rx: true,
98 enhance_ack_tx: true,
99 coordinator: false,
100 promiscuous: true,
101 rx_when_idle: false,
102 txpower: 10,
103 channel: 11,
104 pending_mode: PendingMode::Disable,
105 multipan_mask: 1 << IEEE802154_MULTIPAN_0,
106 panid: [0u16; 4],
107 short_addr: [0u16; IEEE802154_MULTIPAN_MAX],
108 ext_addr: [[0xffu8; IEEE802154_FRAME_EXT_ADDR_SIZE]; IEEE802154_MULTIPAN_MAX],
109 cca_threshold: CONFIG_IEEE802154_CCA_THRESHOLD,
110 cca_mode: CcaMode::Ed,
111 }
112 });
113}
114
115pub(crate) fn ieee802154_pib_set_panid(index: u8, panid: u16) {
116 PIB.with(|pib| pib.panid[index as usize] = panid)
117}
118
119pub(crate) fn ieee802154_pib_set_promiscuous(enable: bool) {
120 PIB.with(|pib| pib.promiscuous = enable)
121}
122
123pub(crate) fn ieee802154_pib_set_auto_ack_tx(enable: bool) {
124 PIB.with(|pib| pib.auto_ack_tx = enable)
125}
126
127pub(crate) fn ieee802154_pib_set_auto_ack_rx(enable: bool) {
128 PIB.with(|pib| pib.auto_ack_rx = enable)
129}
130
131pub(crate) fn ieee802154_pib_set_enhance_ack_tx(enable: bool) {
132 PIB.with(|pib| pib.enhance_ack_tx = enable)
133}
134
135pub(crate) fn ieee802154_pib_set_coordinator(enable: bool) {
136 PIB.with(|pib| pib.coordinator = enable)
137}
138
139pub(crate) fn ieee802154_pib_set_rx_when_idle(enable: bool) {
140 PIB.with(|pib| pib.rx_when_idle = enable)
141}
142
143pub(crate) fn ieee802154_pib_get_rx_when_idle() -> bool {
144 PIB.with(|pib| pib.rx_when_idle)
145}
146
147pub(crate) fn ieee802154_pib_set_tx_power(power: i8) {
148 PIB.with(|pib| pib.txpower = power)
149}
150
151pub(crate) fn ieee802154_pib_set_channel(channel: u8) {
152 PIB.with(|pib| pib.channel = channel)
153}
154
155pub(crate) fn ieee802154_pib_set_pending_mode(mode: PendingMode) {
156 PIB.with(|pib| pib.pending_mode = mode)
157}
158
159pub(crate) fn ieee802154_pib_set_short_address(index: u8, address: u16) {
160 PIB.with(|pib| pib.short_addr[index as usize] = address)
161}
162
163pub(crate) fn ieee802154_pib_set_extended_address(
164 index: u8,
165 address: [u8; IEEE802154_FRAME_EXT_ADDR_SIZE],
166) {
167 PIB.with(|pib| pib.ext_addr[index as usize] = address)
168}
169
170pub(crate) fn ieee802154_pib_set_cca_theshold(cca_threshold: i8) {
171 PIB.with(|pib| pib.cca_threshold = cca_threshold)
172}
173
174pub(crate) fn ieee802154_pib_set_cca_mode(mode: CcaMode) {
175 PIB.with(|pib| pib.cca_mode = mode)
176}
177
178pub(crate) fn ieee802154_pib_update() {
179 PIB.with(|pib| {
180 set_freq(channel_to_freq(pib.channel));
181 set_power(ieee802154_txpower_convert(pib.txpower));
182
183 set_multipan_enable_mask(pib.multipan_mask);
184 ieee802154_set_multipan_hal(pib);
185
186 set_cca_mode(pib.cca_mode);
187 set_cca_threshold(pib.cca_threshold);
188
189 set_tx_auto_ack(pib.auto_ack_tx);
190 set_rx_auto_ack(pib.auto_ack_rx);
191 set_tx_enhance_ack(pib.enhance_ack_tx);
192
193 set_coordinator(pib.coordinator);
194 set_promiscuous(pib.promiscuous);
195 set_pending_mode(pib.pending_mode == PendingMode::Enhanced);
196 })
197}
198
199fn channel_to_freq(channel: u8) -> u8 {
200 (channel - 11) * 5 + 3
201}
202
203fn ieee802154_set_multipan_hal(pib: &Pib) {
204 for index in 0..IEEE802154_MULTIPAN_MAX {
205 if (pib.multipan_mask & (1 << index)) != 0 {
206 set_multipan_panid(index.into(), pib.panid[index]);
207 set_multipan_short_addr(index.into(), pib.short_addr[index]);
208 set_multipan_ext_addr(index.into(), pib.ext_addr[index]);
209 }
210 }
211}
212
213fn ieee802154_txpower_convert(txpower: i8) -> u8 {
215 cfg_if::cfg_if! {
216 if #[cfg(feature="esp32h2")] {
217 const IEEE802154_TXPOWER_VALUE_MAX: i8 = 20;
219 const IEEE802154_TXPOWER_VALUE_MIN: i8 = -24;
220 const IEEE802154_TXPOWER_INDEX_MIN: i8 = 0;
221 } else if #[cfg(feature="esp32c6")]{
222 const IEEE802154_TXPOWER_VALUE_MAX: i8 = 20;
224 const IEEE802154_TXPOWER_VALUE_MIN: i8 = -15;
225 const IEEE802154_TXPOWER_INDEX_MIN: i8 = 3;
226 }
227 }
228 if txpower > IEEE802154_TXPOWER_VALUE_MAX {
229 15
230 } else if txpower <= IEEE802154_TXPOWER_VALUE_MIN {
231 IEEE802154_TXPOWER_INDEX_MIN as u8
232 } else {
233 (((txpower - IEEE802154_TXPOWER_VALUE_MIN) / 3) + IEEE802154_TXPOWER_INDEX_MIN) as u8
234 }
235}