Skip to content

Commit

Permalink
[driver] Adding Semtech SX1280/SX1281 driver
Browse files Browse the repository at this point in the history
  • Loading branch information
rasmuskleist committed Aug 15, 2023
1 parent d214fb7 commit 194f3bc
Show file tree
Hide file tree
Showing 7 changed files with 2,200 additions and 2 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -802,17 +802,18 @@ your specific needs.
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stts22h">STTS22H</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stusb4500">STUSB4500</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx1276">SX1276</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx128x">SX128X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3414">TCS3414</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3472">TCS3472</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tlc594x">TLC594x</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tlc594x">TLC594x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp102">TMP102</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp12x">TMP12x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-touch2046">TOUCH2046</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl53l0">VL53L0</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ws2812">WS2812</a></td>
</tr>
</table>
Expand Down
247 changes: 247 additions & 0 deletions src/modm/driver/radio/sx128x.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/*
* Copyright (c) 2023, Lasse Alexander Jensen
* Copyright (c) 2023, Rasmus Kleist Hørlyck Sørensen
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_SX128X_HPP
#define MODM_SX128X_HPP

#include "sx128x_definitions.hpp"
#include "sx128x_transport.hpp"

#include <modm/processing/timer.hpp>

namespace modm
{

/**
* @tparam Transport Transpot Layer for SX128x
*
* @ingroup modm_driver_sx128x
* @author Lasse Alexander Jensen
* @author Rasmus Kleist Hørlyck Sørensen
*/
template< class Transport, class Reset, class Busy >
class Sx128x : public sx128x, public Transport
{
using Command = Transport::Command;

public:
Sx128x() = default;

/// Determine if radio is busy
bool
isBusy();

/// Reset the transceiver
/// @attention It is necessary to reset each radio on a shared bus prior to starting the first SPI communicatio
modm::ResumableResult<void>
reset();

public:
/// Get the transceiver status directly.
/// @attention this command can be issued at any time as long as it is not the very first command send over the interface
modm::ResumableResult<bool>
getStatus(Status *status);

/// Writes a single byte in a data memory space at the specified address
modm::ResumableResult<bool>
writeRegister(Register reg, uint8_t data);

/// Writes a block of bytes in a data memory space starting at a specific address
modm::ResumableResult<bool>
writeRegister(Register reg, std::span<const uint8_t> data);

/// Read a single byte of data at the given address
modm::ResumableResult<bool>
readRegister(Register reg, uint8_t *data);

/// Read a block of data starting at a given address
modm::ResumableResult<bool>
readRegister(Register reg, std::span<uint8_t> data);

/// This function is used to write the data payload to be transmitted
/// @attention When the address exceeds 255 it wraps back to 0 due to the circular nature of data buffer
modm::ResumableResult<bool>
writeBuffer(uint8_t offset, std::span<const uint8_t> data);

/// This function is used to read the received data payload
modm::ResumableResult<bool>
readBuffer(uint8_t offset, std::span<uint8_t> data);

/// Set the transceiver to Sleep mode with the lowest current consumption possible
/// @warning Depending on the specified level of memory retention not all instruction will be retained
modm::ResumableResult<bool>
setSleep(SleepConfig_t sleepConfig);

/// Set the device in either STDBY_RC or STDBY_XOSC mode which are intermediate levels of power consumption
/// By default in this state, the system is clocked by the 13 MHz RC oscillator to reduce power consumption.
/// However if the application is time critical, the XOSC block can be turned or left ON.
/// @attention In this Standby mode, the transceiver may be configured for future RF operations
modm::ResumableResult<bool>
setStandby(StandbyConfig standbyConfig = StandbyConfig::StdbyRc);

/// Set the device in Frequency Synthesizer mode where the PLL is locked to the carrier frequency
/// @attention In normal operation of the transceiver, the user does not normally need to use FS mode
modm::ResumableResult<bool>
setFs();

/// Set the device in Transmit mode
/// @warning The IRQ status must be cleared before using this command
modm::ResumableResult<bool>
setTx(PeriodBase periodBase, uint16_t periodBaseCount);

/// Set the device in Receiver mode
/// @warning The IRQ status must be cleared before using this command
/// @attention Setting periodBaseCount = 0 puts the transceiver in RX Single Mode
/// @attention Setting periodBaseCount = 0xFFFF puts the transceiver in Rx Continuous mode
modm::ResumableResult<bool>
setRx(PeriodBase periodBase, uint16_t periodBaseCount);

/// Set the transceiver in sniff mode, so that it regularly looks for new packets
/// @warning RxDone interrupt must be configured prior to enter Duty cycled operations
/// @warning SetLongPreamble must be issued prior to setRxDutyCycle
modm::ResumableResult<bool>
setRxDutyCycle(PeriodBase periodBase, uint16_t rxPeriodBaseCount, uint16_t sleepPeriodBaseCount);

/// Set the transceiver to use CAD (Channel Activity Detection) mode
/// @warning The Channel Activity Detection is a LoRa specific mode of operation
modm::ResumableResult<bool>
setCad();

/// Set the transceiver to generate a Continuous Wave (RF tone) at a selected frequency and output power
/// @attention The device remains in Tx Continuous Wave until the host sends a mode confiquration command.
modm::ResumableResult<bool>
setTxContinuousWave();

/// Set the transceiver to generate an infinite sequence of alternating 'O's and '1's in GFSK modulation and symbol 0 in LoRa
/// @attention The device remains in transmit until the host sends a mode confiquration command
modm::ResumableResult<bool>
setTxContinuousPreamble();

/// Set the transceiver radio frame out of a choice of 5 different packet types
/// @attention the packet type must be set first in the radio configuration sequence
modm::ResumableResult<bool>
setPacketType(PacketType packetType);

/// Get the current operating packet type of the radio
modm::ResumableResult<bool>
getPacketType(PacketType *packetType);

/// Set the frequency of the RF frequency mode.
/// @warning This must be called after SetPacket type.
/// @attention The LSB of rfFrequency is equal to the PLL step i.e. 52e6/2^18 Hz, where 52e6 is the crystal frequency in Hz
modm::ResumableResult<bool>
setRfFrequency(uint32_t rfFrequency);

/// Set the Tx output power and the Tx ramp time
/// @attention The output power (Pout) is defined by the parameter power. Pout = -18 + power
/// @attention PoutMin = -18 dBm (power = 0) and PoutMax = 13 dBm (power = 31)
modm::ResumableResult<bool>
setTxParams(uint8_t power, RampTime rampTime);

/// Set the number of symbols on which which Channel Activity Detected (CAD) operates
modm::ResumableResult<bool>
setCadParams(CadSymbolNumber cadSymbolNumber);

/// Set the base address for the packet handling operation in Tx and Rx mode for all packet types
modm::ResumableResult<bool>
setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress);

/// Set the modulation parameters of the radio
/// @attention The modulation parameters will be interpreted depending on the frame type
modm::ResumableResult<bool>
setModulationParams(ModulationParams modulationParams);

/// Set the parameters of the packet handling block
/// @warning Interpretation by the transceiver of the packet parameters depends upon the chosen packet type
modm::ResumableResult<bool>
setPacketParams(PacketParams packetParams);

/// Get length of the last received packet and the address of the first byte received
modm::ResumableResult<bool>
getRxBufferStatus(RxBufferStatus *rxBufferStatus);

/// Retrieve information about the last received packet
/// @attention The returned parameters are frame-dependent
/// @attention Actual signal power is -(rssiSync) / 2 (dBm)
/// @attention Actual SNR is (snr) / 4 (dBm)
modm::ResumableResult<bool>
getPacketStatus(PacketStatus *packetStatus);

/// Get the instantaneous RSSI value during reception of the packet
/// @attention Actual signal power is -(rssiSync) / 2 (dBm)
modm::ResumableResult<bool>
getRssiInst(uint8_t *rssiInst);

/// Enable IRQs and to route IRQs to DIO pins.
modm::ResumableResult<bool>
setDioIrqParams(Irq_t irqMask, Irq_t dio1Mask = Irq_t(), Irq_t dio2Mask = Irq_t(), Irq_t dio3Mask = Irq_t());

/// Get the value of the IRQ register
modm::ResumableResult<bool>
getIrqStatus(Irq_t *irqStatus);

/// Clear IRQ flags in the IRQ register
modm::ResumableResult<bool>
clearIrqStatus(Irq_t irqMask);

/// Specify if DC-DC or LDO is used for power regulation
modm::ResumableResult<bool>
setRegulatorMode(RegulatorMode regModeParam);

/// Save the present context of the radio register values to the Data RAM
modm::ResumableResult<bool>
setSaveContext();

/// Set the chip so that the state following a Rx or Tx operation is FS and not STDBY
/// This feature is to be used to reduce the switching time between consecutive Rx and/or Tx operations
modm::ResumableResult<bool>
setAutoFs(bool enable = true);

/// Set the device to be able to send back a response 150 us after a packet reception
/// @attention The delay between the packet reception end and the next packet transmission start is defined by TxDelay = time + 33 us
modm::ResumableResult<bool>
setAutoTx(uint16_t time);

/// Set the transceiver into Long Preamble mode
/// @warning Long Preamble mode can only be used with either LoRa mode and GFSK mode
modm::ResumableResult<bool>
setLongPreamble(bool enable = true);

/// Set UART speed
/// @warning UART only
/// @attention UART communication must be initiated with 115.2 kbps
/// @attention The UartDividerRatio is given by UartDividerRatio = (Baud Rate * 2^20) / fClk
modm::ResumableResult<bool>
setUartSpeed(UartDividerRatio uartDividerRatio);

/// Set the role of the radio in ranging operation
modm::ResumableResult<bool>
setRangingRole(RangingRole rangingRole);

/// Enable advanced ranging
modm::ResumableResult<bool>
setAdvancedRanging(bool enable = true);

public:
// The LSB of rfFrequency is equal to the PLL step i.e. 52e6/2^18 Hz, where 52e6 is the crystal frequency in Hz
static constexpr float frequencyLsb = float(52_MHz) / 262144.f;

private:
ShortPreciseTimeout timeout;
uint8_t buffer[8];
};

}

#include "sx128x_impl.hpp"

#endif
40 changes: 40 additions & 0 deletions src/modm/driver/radio/sx128x.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2023, Rasmus Kleist Hørlyck Sørensen
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------


def init(module):
module.name = ":driver:sx128x"
module.description = """\
Semtech SX1280/SX1281 Driver
Long Range, Low Power, 2.4 GHz Transceiver with Ranging Capability
!!! warning "The SX128x driver UART transport layer is untested"
"""

def prepare(module, options):
module.depends(
":architecture:gpio",
":architecture:spi.device",
":architecture:uart.device",
":math:utils",
":processing:resumable",
":processing:timer")
return True

def build(env):
env.outbasepath = "modm/src/modm/driver/radio"
env.copy("sx128x.hpp")
env.copy("sx128x_impl.hpp")
env.copy("sx128x_definitions.hpp")
env.copy("sx128x_transport.hpp")
env.copy("sx128x_transport_impl.hpp")
Loading

0 comments on commit 194f3bc

Please sign in to comment.