Skyward boardcore
Loading...
Searching...
No Matches
SX1278Common.cpp
Go to the documentation of this file.
1/* Copyright (c) 2022 Skyward Experimental Rocketry
2 * Author: Davide Mor
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "SX1278Common.h"
24
25#include <kernel/scheduler/scheduler.h>
26#include <utils/KernelTime.h>
27
28namespace Boardcore
29{
30
31namespace SX1278
32{
33
35{
36 if (state.irq_wait_thread)
37 {
38 state.irq_wait_thread->IRQwakeup();
39 if (state.irq_wait_thread->IRQgetPriority() >
40 miosix::Thread::IRQgetCurrentThread()->IRQgetPriority())
41 {
42 miosix::Scheduler::IRQfindNextThread();
43 }
44
45 state.irq_wait_thread = nullptr;
46 }
47}
48
49void SX1278Common::enableIrqs()
50{
54}
55
56void SX1278Common::disableIrqs()
57{
61}
62
64 InterruptTrigger dio1_trigger,
65 bool tx_frontend, bool rx_frontend)
66{
67 miosix::Lock<miosix::FastMutex> lock(mutex);
68 enterMode(mode, mapping, dio1_trigger, tx_frontend, rx_frontend);
69}
70
72 IrqFlags reset_irq, bool unlock)
73{
74 IrqFlags ret_irq = 0;
75
76 do
77 {
78 // An interrupt could occur and read from this variables
79 {
80 miosix::FastInterruptDisableLock lock;
81 state.irq_wait_thread = miosix::Thread::IRQgetCurrentThread();
82 }
83
84 // Check that this hasn't already happened
86 break;
87
88 if (!waitForIrqInner(guard, unlock))
89 {
90 // TODO: Something bad happened, do something!
91 }
92
93 // TODO: Check state of the device, and reset if needed!
94
95 // Protect against sporadic IRQs
96 } while ((ret_irq = checkForIrqAndReset(set_irq, reset_irq)) == 0);
97
98 return ret_irq;
99}
100
104{
105 // Take a reference to a _guard to MAKE SURE that the mutex is locked, but
106 // otherwise don't do anything with it
107 (void)_guard;
108
109 long long start = Kernel::getOldTick();
110 IrqFlags ret_irq = 0;
111
112 while ((Kernel::getOldTick() - start) < timeout)
113 {
114 // Delay between polls
115 const unsigned int DELAY = 100;
116
117 // Tight loop on IRQ register
118 for (unsigned int i = 0; i < 1000 / DELAY; i++)
119 {
120 // Check if some of the interrupts triggered
122 return ret_irq;
123
124 miosix::delayUs(DELAY);
125 }
126 }
127
128 return 0;
129}
130
131bool SX1278Common::waitForIrqInner(LockMode& _guard, bool unlock)
132{
133 // Take a reference to a _guard to MAKE SURE that the mutex is locked, but
134 // otherwise don't do anything with it
135 (void)_guard;
136
137 // Release the lock for others to take
138 if (unlock)
139 mutex.unlock();
140
141 int start = Kernel::getOldTick();
142 miosix::TimedWaitResult result = miosix::TimedWaitResult::NoTimeout;
143
144 {
145 miosix::FastInterruptDisableLock lock;
146 while (state.irq_wait_thread &&
147 result == miosix::TimedWaitResult::NoTimeout)
148 {
150 lock, start + IRQ_TIMEOUT);
151 }
152 }
153
154 // Regain ownership of the lock
155 if (unlock)
156 mutex.lock();
157
158 // Check that we didn't have a timeout
159 return result == miosix::TimedWaitResult::NoTimeout;
160}
161
164{
166 if (cur_irq & set_irq)
167 {
168 // Reset all of the interrupts we have detected
170 }
171
172 return (cur_irq & set_irq) | (~cur_irq & reset_irq);
173}
174
176
178
179SX1278Common::DeviceState SX1278Common::lockMode(Mode mode, DioMapping mapping,
180 InterruptTrigger dio1_trigger,
181 bool tx_frontend,
182 bool rx_frontend)
183{
184 // Store previous state
185 DeviceState old_state = state;
186
187 enterMode(mode, mapping, dio1_trigger, tx_frontend, rx_frontend);
188 state.irq_wait_thread = nullptr;
189
190 return old_state;
191}
192
193void SX1278Common::unlockMode(DeviceState old_state)
194{
195 // Do this copy manually, we want stuff to be copied in a specific order
196 state.irq_wait_thread = old_state.irq_wait_thread;
197 enterMode(old_state.mode, old_state.mapping, old_state.dio1_trigger,
198 old_state.is_tx_frontend_on, old_state.is_rx_frontend_on);
199}
200
201void SX1278Common::lock() { mutex.lock(); }
202
203void SX1278Common::unlock() { mutex.unlock(); }
204
205void SX1278Common::enterMode(Mode mode, DioMapping mapping,
206 InterruptTrigger dio1_trigger,
207 bool set_tx_frontend_on, bool set_rx_frontend_on)
208{
209 // disable - enable in order to avoid having both RX/TX frontends active at
210 // the same time
211
212 // First disable all of the frontend if necessary
213 if (set_tx_frontend_on != state.is_tx_frontend_on && !set_tx_frontend_on)
215
216 if (set_rx_frontend_on != state.is_rx_frontend_on && !set_rx_frontend_on)
218
219 // Then enable the newly requested ones
220 if (set_tx_frontend_on != state.is_tx_frontend_on && set_tx_frontend_on)
222
223 if (set_rx_frontend_on != state.is_rx_frontend_on && set_rx_frontend_on)
225
226 state.is_tx_frontend_on = set_tx_frontend_on;
227 state.is_rx_frontend_on = set_rx_frontend_on;
228
229 if (mode != state.mode)
230 {
231 setMode(mode);
232 state.mode = mode;
233 }
234
235 // Change DIO1 interrupt kind
236 if (dio1_trigger != state.dio1_trigger)
237 {
238 changeInterruptTrigger(dio1, dio1_trigger);
239 state.dio1_trigger = dio1_trigger;
240 }
241
242 // Finally setup DIO mapping
243 if (mapping != state.mapping)
244 {
245 setMapping(mapping);
246 state.mapping = mapping;
247 }
248}
249
250} // namespace SX1278
251
252} // namespace Boardcore
Shared interface between all SX1278 frontends.
virtual IrqFlags getIrqFlags()=0
virtual void setMode(Mode mode)=0
virtual void setMapping(DioMapping mapping)=0
virtual void resetIrqFlags(IrqFlags flags)=0
RAII scoped bus lock guard.
RAII scoped mode lock, requires a previous lock.
void handleDioIRQ()
Handle generic DIO irq.
IrqFlags waitForIrqBusy(LockMode &guard, IrqFlags set_irq, IrqFlags reset_irq, int timeout)
Busy waits for an interrupt by polling the irq register.
void setDefaultMode(Mode mode, DioMapping mapping, InterruptTrigger dio1_trigger, bool set_tx_frontend_on, bool set_rx_frontend_on)
Set default device mode.
IrqFlags checkForIrqAndReset(IrqFlags set_irq, IrqFlags reset_irq)
Returns a mask containing triggered interrupts.
IrqFlags waitForIrq(LockMode &guard, IrqFlags set_irq, IrqFlags reset_irq, bool unlock=false)
Wait for generic irq.
void changeInterruptTrigger(unsigned int gpioPort, unsigned int gpioNum, InterruptTrigger trigger)
Changes interrupt trigger on an enabled interrupt.
void disableExternalInterrupt(unsigned int gpioPort, unsigned int gpioNum)
Disables external interrupts on the provided pin.
void enableExternalInterrupt(unsigned int gpioPort, unsigned int gpioNum, InterruptTrigger trigger, unsigned int priority)
Enables external interrupts on the provided pin. Remember to set the GPIO to input mode!
InterruptTrigger
miosix::TimedWaitResult IRQenableIrqAndTimedWaitMs(miosix::FastInterruptDisableLock &dLock, long long absoluteTimeMs)
Stops the thread until wakeup() is called or the specified absolute time in milliseconds is reached.
Definition KernelTime.h:87
long long getOldTick()
Get the current time in milliseconds.
Definition KernelTime.h:43
RegDioMapping::Mapping DioMapping
This file includes all the types the logdecoder script will decode.
Contains information about a single SPI slave device.
Represents an actual Dio mapping..
Definition SX1278Defs.h:93