SatNOGS-COMMS  4.1.0
A COMMS subsystem for CubeSats
Loading...
Searching...
No Matches
bsp.hpp
Go to the documentation of this file.
1/*
2 * SatNOGS-COMMS MCU software
3 *
4 * Copyright (C) 2022-2024, Libre Space Foundation <http://libre.space>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * SPDX-License-Identifier: GNU General Public License v3.0 or later
20 */
21
22#pragma once
23
24#include <cstdint>
33#include <scoped_lock.hpp>
34#include <settings.hpp>
35#include <zephyr/device.h>
36#include <zephyr/drivers/adc.h>
37#include <zephyr/drivers/dac.h>
38#include <zephyr/drivers/gpio.h>
39#include <zephyr/drivers/hwinfo.h>
40#include <zephyr/drivers/i2c.h>
41#include <zephyr/drivers/sensor.h>
42#include <zephyr/drivers/spi.h>
43#include <zephyr/kernel.h>
44#include <zephyr/logging/log.h>
45#include <zephyr/sys/reboot.h>
46
47namespace satnogs::comms
48{
49
51{
52public:
53 watchdog_exception(string_type file_name, numeric_type line)
54 : exception(lib::exception::severity::CRITICAL, file_name, line,
55 error_msg{"Error in watchdog initialization", "errwdt", EWDT})
56 {
57 }
58};
59
61{
62public:
63 device_not_ready_exception(string_type file_name, numeric_type line)
64 : exception(lib::exception::severity::MAJOR, file_name, line,
65 error_msg{"Sensor: device not ready.", "devnotready",
67 {
68 }
69};
70
72{
73public:
74 device_not_configured_exception(string_type file_name, numeric_type line)
75 : exception(
76 lib::exception::severity::MAJOR, file_name, line,
77 error_msg{"Could not configure device", "devnotconf", EDEVNOTCONF})
78 {
79 }
80};
81
83{
84public:
85 v_bat_exception(string_type file_name, numeric_type line)
86 : exception(lib::exception::severity::MAJOR, file_name, line,
87 error_msg{"Sensor: device failed to read VBAT.", "vbaterror",
88 EVBAT})
89 {
90 }
91};
92
94{
95public:
96 sensor_bsp(const struct device *dev);
97
98 float
99 vbat();
100
101 float
102 vref();
103
104private:
105 const struct device *m_dev;
106};
108{
109public:
110 gpio_bsp(const struct gpio_dt_spec *io, bool output = true)
111 : gpio(), m_gpio(io)
112 {
113 if (output) {
114 gpio_pin_configure_dt(m_gpio, GPIO_OUTPUT_INACTIVE | m_gpio->dt_flags);
115 } else {
116 gpio_pin_configure_dt(m_gpio, GPIO_INPUT | m_gpio->dt_flags);
117 }
118 }
119
120 void
122 {
123 gpio_pin_toggle_dt(m_gpio);
124 }
125
126 bool
128 {
129 int ret = gpio_pin_get_dt(m_gpio);
130 return ret > 0;
131 }
132
133 bool
135 {
136 int ret = gpio_pin_get_raw(m_gpio->port, m_gpio->pin);
137 return ret > 0;
138 }
139
140 void
141 set(bool s)
142 {
143 gpio_pin_set_dt(m_gpio, s);
144 }
145
146 void
147 set_raw(bool s)
148 {
149 gpio_pin_set_raw(m_gpio->port, m_gpio->pin, s);
150 }
151
152 void
154 {
156 gpio_dt_flags_t mask = 0xFFFF;
157 mask ^= GPIO_OUTPUT_ACTIVE;
158 mask ^= GPIO_OUTPUT;
159 gpio_pin_configure_dt(m_gpio, GPIO_INPUT | (m_gpio->dt_flags & mask));
160 } else {
161 gpio_dt_flags_t mask = 0xFFFF;
162 mask ^= GPIO_INPUT;
163 gpio_pin_configure_dt(m_gpio, GPIO_OUTPUT | GPIO_OUTPUT_INACTIVE |
164 (m_gpio->dt_flags & mask));
165 }
166 }
167
168private:
169 const struct gpio_dt_spec *m_gpio;
170};
171
173{
174public:
175 spi_bsp_exception(string_type file_name, numeric_type line)
176 : exception(lib::exception::severity::MAJOR, file_name, line,
177 error_msg{"SPI error", "spierr", ESPI})
178 {
179 }
180};
181
182class spi_bsp : public lib::bsp::spi
183{
184public:
185 spi_bsp(const struct device *dev, const struct spi_config &spi_cfg);
186
187 void
188 read(uint8_t *rx, const uint8_t *tx, size_t tx_len, size_t rx_len) override;
189
190 void
191 write(const uint8_t *tx, size_t len) override;
192
193private:
194 const struct device *m_dev;
195 const struct spi_config m_spi_cfg;
196 struct k_mutex m_mtx;
197};
198
204{
205public:
206 spi_manual_cs_bsp(const struct device *dev, const struct spi_config &spi_cfg,
207 const struct gpio_dt_spec *cs)
208 : spi_bsp(dev, spi_cfg), m_cs(cs, true)
209 {
210 }
211
213 cs() override
214 {
215 return m_cs;
216 }
217
218private:
219 gpio_bsp m_cs;
220};
221
223{
224
225 void
226 delay_us(size_t us) override
227 {
228 k_usleep(us);
229 }
230
231 void
232 busy_wait_us(size_t us) override
233 {
234 k_busy_wait(us);
235 }
236
237 int64_t
238 time_ms() override
239 {
240 return k_uptime_get();
241 }
242};
243
245{
246public:
247 i2c_bsp_exception(string_type file_name, numeric_type line)
248 : exception(lib::exception::severity::MINOR, file_name, line,
249 error_msg{"i2c error", "i2cerr", EI2C})
250 {
251 }
252};
253
254class i2c_bsp : public lib::bsp::i2c
255{
256public:
257 i2c_bsp(const struct device *i2c_dev);
258
259 void
260 read(uint16_t addr, uint8_t *rx, size_t rxlen, const uint8_t *tx,
261 size_t txlen);
262
263 void
264 read(uint16_t addr, uint8_t start_addr, uint8_t *rx, size_t len);
265
266 void
267 write(uint16_t addr, const uint8_t *tx, size_t len);
268
269 void
270 write(uint16_t addr, uint8_t start_addr, const uint8_t *tx, size_t len);
271
272 const struct device *
273 dev();
274
275private:
276 const struct device *m_i2c;
277};
279{
280public:
281 adc_initialization_exception(string_type file_name, numeric_type line)
282 : exception(
283 lib::exception::severity::MAJOR, file_name, line,
284 error_msg{"Error in ADC initialization", "adcerror", EADCINIT})
285 {
286 }
287};
288
289class adc_bsp : public lib::bsp::adc
290{
291public:
292 adc_bsp(const struct adc_dt_spec &adc_channel);
293
294 void
295 start();
296
297 void
298 stop();
299
300 uint32_t
301 read();
302
303 float
304 voltage();
305
306private:
307 const struct adc_dt_spec &m_adc_channel;
308 uint16_t m_adc_sample;
309 struct adc_sequence m_sequence;
310};
311
312class dac_bsp : public lib::bsp::dac
313{
314public:
315 dac_bsp(const struct device *dac_dev, uint8_t channel, uint8_t resolution)
316 : dac(resolution, 3.3f), m_dac(dac_dev), m_channel(channel)
317 {
318 const struct dac_channel_cfg dac_ch_cfg = {
319 .channel_id = channel, .resolution = resolution, .buffered = true};
320 dac_channel_setup(m_dac, &dac_ch_cfg);
321 set_voltage(0.0f);
322 }
323
324 void
326 {
327 }
328 void
330 {
331 set_voltage(0.0f);
332 }
333
334protected:
335 void
336 write(uint32_t x)
337 {
338 dac_write_value(m_dac, m_channel, x);
339 }
340
341private:
342 const struct device *m_dac;
343 const uint8_t m_channel;
344};
345
346template <typename T, const size_t LEN>
347class msgq : public lib::bsp::msgq<T, LEN>
348{
349public:
350 msgq() : lib::bsp::msgq<T, LEN>()
351 {
352 k_msgq_init(&m_mq, m_buffer, sizeof(T), LEN);
353 }
354
355 size_t
357 {
358 return k_msgq_num_used_get(&m_mq);
359 }
360
361 uint32_t
363 {
364 return k_msgq_num_free_get(&m_mq);
365 }
366
367 int
368 put(const T &msg, size_t timeout_ms)
369 {
370 return k_msgq_put(&m_mq, &msg, K_MSEC(timeout_ms));
371 }
372
373 int
374 put_isr(const T &msg)
375 {
376 return k_msgq_put(&m_mq, &msg, K_NO_WAIT);
377 }
378
379 int
380 peek(T *msg)
381 {
382 return k_msgq_peek(&m_mq, msg);
383 }
384
385 void
387 {
388 return k_msgq_purge(&m_mq);
389 }
390
391 int
392 get(T *msg, size_t timeout_ms)
393 {
394 return k_msgq_get(&m_mq, msg, K_MSEC(timeout_ms));
395 }
396
397 int
398 get_isr(T *msg)
399 {
400 return k_msgq_get(&m_mq, msg, K_NO_WAIT);
401 }
402
403private:
404 struct k_msgq m_mq;
405 char __aligned(4) m_buffer[LEN * sizeof(T)];
406};
407
408} // namespace satnogs::comms
void stop()
Stops the ADC.
Definition bsp.cpp:189
uint32_t read()
Get the ADC value.
Definition bsp.cpp:194
float voltage()
Get the ADC voltage.
Definition bsp.cpp:201
void start()
Starts the ADC.
Definition bsp.cpp:184
adc_bsp(const struct adc_dt_spec &adc_channel)
Definition bsp.cpp:159
adc_initialization_exception(string_type file_name, numeric_type line)
Definition bsp.hpp:281
void start()
A virtual method to start the DAC.
Definition bsp.hpp:325
void write(uint32_t x)
Definition bsp.hpp:336
dac_bsp(const struct device *dac_dev, uint8_t channel, uint8_t resolution)
Definition bsp.hpp:315
void stop()
A virtual method to stop the DAC.
Definition bsp.hpp:329
device_not_configured_exception(string_type file_name, numeric_type line)
Definition bsp.hpp:74
device_not_ready_exception(string_type file_name, numeric_type line)
Definition bsp.hpp:63
void set_direction(lib::bsp::gpio::direction dir)
Set the direction of the GPIO.
Definition bsp.hpp:153
void toggle()
Toggles the GPIO pin if it is configured as output. Has no effect if it is conigured as input.
Definition bsp.hpp:121
void set(bool s)
Sets the logical output of the pin. For example, if the pin has been configured as active low,...
Definition bsp.hpp:141
gpio_bsp(const struct gpio_dt_spec *io, bool output=true)
Definition bsp.hpp:110
void set_raw(bool s)
Sets the physical output of the pin.
Definition bsp.hpp:147
bool get_raw()
Gets the physical level of the GPIO pin. For example, if the input level is 0V, this method will retu...
Definition bsp.hpp:134
bool get()
Gets the logical level of the GPIO pin. For example, if the pin has been configured as active low,...
Definition bsp.hpp:127
i2c_bsp_exception(string_type file_name, numeric_type line)
Definition bsp.hpp:247
const struct device * dev()
Get the I2C device.
Definition bsp.cpp:152
void read(uint16_t addr, uint8_t *rx, size_t rxlen, const uint8_t *tx, size_t txlen)
Performs an I2C read operation.
Definition bsp.cpp:80
void write(uint16_t addr, const uint8_t *tx, size_t len)
Performs an I2C write operation.
Definition bsp.cpp:127
i2c_bsp(const struct device *i2c_dev)
Definition bsp.cpp:77
ADC device abstraction.
Definition adc.hpp:39
Chrono device abstraction.
Definition chrono.hpp:41
virtual int64_t time_ms()=0
Retrieves the current time in milliseconds.
DAC device abstraction.
Definition dac.hpp:40
dac(uint16_t resolution, float vref)
Construct a new DAC object.
Definition dac.hpp:48
virtual void set_voltage(float volts)
Sets the output voltage of the DAC.
Definition dac.hpp:93
GPIO device abstraction.
Definition gpio.hpp:38
gpio(direction dir=direction::INPUT)
Construct a new GPIO object.
Definition gpio.hpp:52
@ INPUT
GPIO pin is configured as input.
Definition gpio.hpp:42
I2C device abstraction.
Definition i2c.hpp:40
Message queue device abstraction with custom maximum number of messages.
Definition msgq.hpp:152
Sensor device abstraction.
Definition sensor.hpp:41
SPI device abstraction.
Definition spi.hpp:41
A class representing error messages in the SatNOGS-COMMS system.
Definition exception.hpp:83
Exception base class.
Definition exception.hpp:63
severity
Severity levels of exceptions.
Definition exception.hpp:71
@ MINOR
Failure having minimal impact.
Definition exception.hpp:75
@ MAJOR
Failure causing minor mission degradation.
Definition exception.hpp:74
@ CRITICAL
Failure causing mission degradation or significant damage.
Definition exception.hpp:73
exception(severity sev, const char *file, int lineno, const error_msg &err_msg)
Constructor for the exception class.
int get(T *msg, size_t timeout_ms)
A virtual method that retrieves a message from the queue.
Definition bsp.hpp:392
size_t size()
A virtual method that returns the current number of messages in the queue.
Definition bsp.hpp:356
uint32_t free_space()
Definition bsp.hpp:362
int peek(T *msg)
A virtual method that peeks at the next message in the queue without removing it.
Definition bsp.hpp:380
int put_isr(const T &msg)
A virtual method that enqueues a message into the queue from an interrupt context.
Definition bsp.hpp:374
int get_isr(T *msg)
A virtual method that retrieves a message from the queue from an interrupt context.
Definition bsp.hpp:398
int put(const T &msg, size_t timeout_ms)
A virtual method that enqueues a message into the queue.
Definition bsp.hpp:368
float vref()
Get the VREF from SoCs designated internal ADC channel.
Definition bsp.cpp:239
float vbat()
Get the VBAT from SoCs designated internal ADC channel.
Definition bsp.cpp:219
sensor_bsp(const struct device *dev)
Definition bsp.cpp:210
spi_bsp_exception(string_type file_name, numeric_type line)
Definition bsp.hpp:175
void read(uint8_t *rx, const uint8_t *tx, size_t tx_len, size_t rx_len) override
Performs an SPI read operation.
Definition bsp.cpp:38
spi_bsp(const struct device *dev, const struct spi_config &spi_cfg)
Definition bsp.cpp:31
void write(const uint8_t *tx, size_t len) override
Performs an SPI write operation.
Definition bsp.cpp:60
lib::bsp::gpio & cs() override
Returns a GPIO control handle for the CS of the SPI. If this is performed automatically by the hardwa...
Definition bsp.hpp:213
spi_manual_cs_bsp(const struct device *dev, const struct spi_config &spi_cfg, const struct gpio_dt_spec *cs)
Definition bsp.hpp:206
v_bat_exception(string_type file_name, numeric_type line)
Definition bsp.hpp:85
watchdog_exception(string_type file_name, numeric_type line)
Definition bsp.hpp:53
#define ESPI
Error in SPI.
#define EI2C
Error in I2C.
#define EWDT
Watchdog error.
#define EVBAT
Error in VBAT readings.
#define EADCINIT
Error in ADC readings.
#define EDEVNOTREADY
Device not ready.
#define EDEVNOTCONF
Device not configured.