1
+ // coding: utf-8
2
+ /*
3
+ * Copyright (c) 2023, Rasmus Kleist Hørlyck Sørensen
4
+ *
5
+ * This file is part of the modm project.
6
+ *
7
+ * This Source Code Form is subject to the terms of the Mozilla Public
8
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
9
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
+ */
11
+ // ----------------------------------------------------------------------------
12
+
13
+ #include < atomic>
14
+
15
+ #include < modm/board.hpp>
16
+ #include < modm/debug/logger/logger.hpp>
17
+ #include < modm/driver/radio/sx128x.hpp>
18
+ #include < modm/platform.hpp>
19
+ #include < modm/processing.hpp>
20
+
21
+ using Sck = GpioA5;
22
+ using Miso = GpioA6;
23
+ using Mosi = GpioA7;
24
+ using SpiMaster = modm::platform::SpiMaster1;
25
+
26
+ namespace
27
+ {
28
+
29
+ namespace rx
30
+ {
31
+ std::atomic_bool dio1 = false ;
32
+ std::atomic_bool dio2 = false ;
33
+ std::atomic_bool dio3 = false ;
34
+ }
35
+
36
+ namespace tx
37
+ {
38
+ std::atomic_bool dio1 = false ;
39
+ std::atomic_bool dio2 = false ;
40
+ std::atomic_bool dio3 = false ;
41
+ }
42
+
43
+ static constexpr modm::sx128x::LoRa::ModulationParams modulationParams = {
44
+ spreadingFactor : modm::sx128x::LoRa::ModulationParams::SpreadingFactor::Sf9,
45
+ bandwidth : modm::sx128x::LoRa::ModulationParams::Bandwidth::Bw400,
46
+ codingRate : modm::sx128x::LoRa::ModulationParams::CodingRate::Cr_Li_4_7
47
+ };
48
+
49
+ static constexpr modm::sx128x::LoRa::PacketParams packetParams = {
50
+ preambleLength : 12 ,
51
+ headerType : modm::sx128x::LoRa::PacketParams::HeaderType::Explicit,
52
+ payloadLength : 4 ,
53
+ crc : modm::sx128x::LoRa::PacketParams::Crc::Enable,
54
+ invertIq : modm::sx128x::LoRa::PacketParams::InvertIq::Standard
55
+ };
56
+
57
+ }
58
+
59
+ class RxThread : public modm ::sx128x, public modm::pt::Protothread
60
+ {
61
+ using Reset = GpioB3;
62
+ using Busy = GpioB4;
63
+ using Dio1 = GpioB5;
64
+ using Dio2 = GpioB6;
65
+ using Dio3 = GpioB7;
66
+
67
+ using Nss = GpioD2;
68
+ using Transport = modm::Sx128xTransportSpi<SpiMaster, Nss>;
69
+
70
+ public:
71
+ RxThread () {}
72
+
73
+ inline bool
74
+ run ()
75
+ {
76
+ PT_BEGIN ();
77
+
78
+ Nss::setOutput (modm::Gpio::High);
79
+ Reset::setOutput (modm::Gpio::Low);
80
+ Busy::setInput (modm::platform::Gpio::InputType::PullDown);
81
+
82
+ Dio1::setInput (modm::platform::Gpio::InputType::PullDown);
83
+ Exti::connect<Dio1>(Exti::Trigger::RisingEdge, [](uint8_t ) { rx::dio1 = true ; });
84
+
85
+ Dio2::setInput (modm::platform::Gpio::InputType::PullDown);
86
+ Exti::connect<Dio2>(Exti::Trigger::RisingEdge, [](uint8_t ) { rx::dio2 = true ; });
87
+
88
+ Dio3::setInput (modm::platform::Gpio::InputType::PullDown);
89
+ Exti::connect<Dio3>(Exti::Trigger::RisingEdge, [](uint8_t ) { rx::dio3 = true ; });
90
+
91
+ PT_CALL (radio.reset ());
92
+ PT_CALL (radio.setStandby ());
93
+
94
+ // Initialize the sx128x
95
+ PT_CALL (radio.setPacketType (PacketType::LoRa));
96
+ PT_CALL (radio.setRfFrequency (2457_MHz / radio.frequencyLsb ));
97
+ PT_CALL (radio.setRegulatorMode (RegulatorMode::Ldo));
98
+ PT_CALL (radio.setBufferBaseAddress (0 , 0 ));
99
+ PT_CALL (radio.setModulationParams (modulationParams));
100
+ PT_CALL (radio.writeRegister (Register::SfAdditionalConfiguration, 0x32 ));
101
+ PT_CALL (radio.writeRegister (Register::FrequencyErrorCorrection, 0x01 ));
102
+ PT_CALL (radio.setPacketParams (packetParams));
103
+ PT_CALL (radio.setDioIrqParams (Irq::RxDone | Irq::RxTxTimeout, Irq::RxDone, Irq::RxTxTimeout));
104
+ PT_CALL (radio.setRx (sx128x::PeriodBase::ms1, 1000 ));
105
+
106
+ MODM_LOG_DEBUG << " Sx128x initialization complete!" << modm::endl;
107
+
108
+ while (true )
109
+ {
110
+ if (rx::dio1.exchange (false ))
111
+ {
112
+ PT_CALL (radio.getIrqStatus (&irqStatus));
113
+ if (irqStatus.any (Irq::RxDone))
114
+ {
115
+ PT_CALL (radio.clearIrqStatus (Irq::RxDone | Irq::RxTxTimeout));
116
+ PT_CALL (radio.setRx (sx128x::PeriodBase::ms1, 1000 ));
117
+
118
+ PT_CALL (radio.getRxBufferStatus (&rxBufferStatus));
119
+ PT_CALL (radio.getPacketStatus (&packetStatus));
120
+ PT_CALL (radio.readBuffer (rxBufferStatus.rxStartBufferPointer , std::span{buffer, rxBufferStatus.rxPayloadLength }));
121
+
122
+ // / TODO: read frequency error indicator (FEI) from register 0x0954 (MSB) 0x0955, 0x0956 (LSB).
123
+
124
+ MODM_LOG_DEBUG << " Received Message" << modm::endl;
125
+ MODM_LOG_DEBUG << " Counter: " << reinterpret_cast <uint32_t *>(buffer)[0 ] << modm::endl;
126
+ MODM_LOG_DEBUG << modm::endl;
127
+ }
128
+ }
129
+
130
+ if (rx::dio2.exchange (false ))
131
+ {
132
+ PT_CALL (radio.getIrqStatus (&irqStatus));
133
+ if (irqStatus.any (Irq::RxTxTimeout))
134
+ {
135
+ // RxTxTimeout Interrupt recieved!
136
+ // Clear irq and set to rx again.
137
+ PT_CALL (radio.clearIrqStatus (Irq::RxTxTimeout));
138
+ PT_CALL (radio.setRx (sx128x::PeriodBase::ms1, 1000 ));
139
+ MODM_LOG_DEBUG << " RxTxTimeout Interrupt!" << modm::endl;
140
+ }
141
+ }
142
+ PT_YIELD ();
143
+ }
144
+ PT_END ();
145
+ }
146
+
147
+ private:
148
+ Irq_t irqStatus;
149
+ PacketStatus packetStatus;
150
+ RxBufferStatus rxBufferStatus;
151
+
152
+ modm::Sx128x< Transport, Reset, Busy > radio;
153
+
154
+ private:
155
+
156
+ static constexpr uint8_t bufferSize = 124 ;
157
+ uint8_t buffer[bufferSize];
158
+ } rxThread;
159
+
160
+ class TxThread : public modm ::sx128x, public modm::pt::Protothread
161
+ {
162
+ using Reset = modm::platform::GpioC2;
163
+ using Busy = modm::platform::GpioC3;
164
+ using Dio1 = modm::platform::GpioA0;
165
+ using Dio2 = modm::platform::GpioA1;
166
+ using Dio3 = modm::platform::GpioA2;
167
+
168
+ using Nss = modm::platform::GpioC1;
169
+ using Transport = modm::Sx128xTransportSpi<SpiMaster, Nss>;
170
+
171
+ public:
172
+ TxThread () : timer(std::chrono::milliseconds(500 )) {}
173
+
174
+ inline bool
175
+ run ()
176
+ {
177
+ PT_BEGIN ();
178
+
179
+ Nss::setOutput (modm::Gpio::High);
180
+ Reset::setOutput (modm::Gpio::Low);
181
+ Busy::setInput (modm::platform::Gpio::InputType::PullDown);
182
+
183
+ Dio1::setInput (modm::platform::Gpio::InputType::PullDown);
184
+ Exti::connect<Dio1>(Exti::Trigger::RisingEdge, [](uint8_t ) { tx::dio1 = true ; });
185
+
186
+ Dio2::setInput (modm::platform::Gpio::InputType::PullDown);
187
+ Exti::connect<Dio2>(Exti::Trigger::RisingEdge, [](uint8_t ) { tx::dio2 = true ; });
188
+
189
+ Dio3::setInput (modm::platform::Gpio::InputType::PullDown);
190
+ Exti::connect<Dio3>(Exti::Trigger::RisingEdge, [](uint8_t ) { tx::dio3 = true ; });
191
+
192
+
193
+ PT_CALL (radio.reset ());
194
+ PT_CALL (radio.setStandby ());
195
+
196
+ // Initialize the sx128x
197
+ PT_CALL (radio.setPacketType (PacketType::LoRa));
198
+ PT_CALL (radio.setRfFrequency (2457_MHz / radio.frequencyLsb ));
199
+ PT_CALL (radio.setRegulatorMode (RegulatorMode::Ldo));
200
+ PT_CALL (radio.setBufferBaseAddress (0 , 0 ));
201
+ PT_CALL (radio.setModulationParams (modulationParams));
202
+ PT_CALL (radio.writeRegister (Register::SfAdditionalConfiguration, 0x32 ));
203
+ PT_CALL (radio.writeRegister (Register::FrequencyErrorCorrection, 0x01 ));
204
+ PT_CALL (radio.setPacketParams (packetParams));
205
+ PT_CALL (radio.setDioIrqParams (Irq::TxDone | Irq::RxTxTimeout, Irq::TxDone, Irq::RxTxTimeout));
206
+
207
+ MODM_LOG_DEBUG << " Sx128x initialization complete!" << modm::endl;
208
+
209
+ while (true )
210
+ {
211
+ if (tx::dio1.exchange (false ))
212
+ {
213
+ PT_CALL (radio.getIrqStatus (&irqStatus));
214
+ if (irqStatus.any (Irq::TxDone))
215
+ {
216
+ PT_CALL (radio.clearIrqStatus (Irq::TxDone));
217
+ irqStatus.reset (Irq::TxDone);
218
+
219
+ MODM_LOG_DEBUG << " Message sent" << modm::endl;
220
+ MODM_LOG_DEBUG << " Counter: " << counter << modm::endl;
221
+ counter++;
222
+ }
223
+ }
224
+
225
+ if (tx::dio2.exchange (false ))
226
+ {
227
+ PT_CALL (radio.getIrqStatus (&irqStatus));
228
+ if (irqStatus.any (Irq::RxTxTimeout))
229
+ {
230
+ PT_CALL (radio.clearIrqStatus (Irq::RxTxTimeout));
231
+ irqStatus.reset (Irq::RxTxTimeout);
232
+
233
+ MODM_LOG_DEBUG << " Received a timeout" << modm::endl;
234
+ }
235
+ }
236
+
237
+ if (timer.execute ())
238
+ {
239
+ PT_CALL (radio.writeBuffer (0 , std::span<const uint8_t >{(uint8_t *) &counter, sizeof (counter)}));
240
+ PT_CALL (radio.setTx (PeriodBase::ms1, 100 ));
241
+ }
242
+ PT_YIELD ();
243
+ }
244
+
245
+ PT_END ();
246
+ }
247
+
248
+ private:
249
+ Irq_t irqStatus;
250
+ modm::Sx128x< Transport, Reset, Busy > radio;
251
+
252
+ uint32_t counter = 0 ;
253
+ modm::PeriodicTimer timer;
254
+ };
255
+
256
+ int
257
+ main ()
258
+ {
259
+ Board::initialize ();
260
+
261
+ SpiMaster::connect<Mosi::Mosi, Mosi::Mosi, Sck::Sck>();
262
+ SpiMaster::initialize<Board::SystemClock, 21 .5_MHz>();
263
+
264
+ MODM_LOG_INFO << " ==========SX128x Test==========" << modm::endl;
265
+ MODM_LOG_DEBUG << " Debug logging here" << modm::endl;
266
+ MODM_LOG_INFO << " Info logging here" << modm::endl;
267
+ MODM_LOG_WARNING << " Warning logging here" << modm::endl;
268
+ MODM_LOG_ERROR << " Error logging here" << modm::endl;
269
+ MODM_LOG_INFO << " ===============================" << modm::endl;
270
+
271
+ while (true )
272
+ {
273
+ rxThread.run ();
274
+ }
275
+
276
+ return 0 ;
277
+ }
0 commit comments