Skip to content

Add SUBGHZSPI support to SPI library. #1839

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 60 additions & 15 deletions CI/update/stm32variant.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
uartrx_list = [] # ['PIN','name','UARTrx', ['af']]
uartcts_list = [] # ['PIN','name','UARTcts', ['af']]
uartrts_list = [] # ['PIN','name','UARTrts', ['af']]
spimosi_list = [] # ['PIN','name','SPIMOSI', ['af']]
spimiso_list = [] # ['PIN','name','SPIMISO', ['af']]
spissel_list = [] # ['PIN','name','SPISSEL', ['af']]
spisclk_list = [] # ['PIN','name','SPISCLK', ['af']]
spimosi_list = [] # ['PIN','name','SPIMOSI', 'sort name', ['af']]
spimiso_list = [] # ['PIN','name','SPIMISO', 'sort name', ['af']]
spissel_list = [] # ['PIN','name','SPISSEL', 'sort name', ['af']]
spisclk_list = [] # ['PIN','name','SPISCLK', 'sort name', ['af']]
cantd_list = [] # ['PIN','name','CANTD', ['af']]
canrd_list = [] # ['PIN','name','CANRD', ['af']]
eth_list = [] # ['PIN','name','ETH', ['af']]
Expand Down Expand Up @@ -464,14 +464,14 @@ def store_uart(pin, name, signal):

# Store SPI pins
def store_spi(pin, name, signal):
if "_MISO" in signal:
spimiso_list.append([pin, name, signal])
if "_MOSI" in signal:
spimosi_list.append([pin, name, signal])
if "_SCK" in signal:
spisclk_list.append([pin, name, signal])
if "_NSS" in signal:
spissel_list.append([pin, name, signal])
if re.search("[-_]MISO", signal):
spimiso_list.append([pin, name, signal, signal.removeprefix("DEBUG_")])
if re.search("[-_]MOSI", signal):
spimosi_list.append([pin, name, signal, signal.removeprefix("DEBUG_")])
if re.search("[-_]SCK", signal):
spisclk_list.append([pin, name, signal, signal.removeprefix("DEBUG_")])
if re.search("[-_]NSS", signal):
spissel_list.append([pin, name, signal, signal.removeprefix("DEBUG_")])


# Store CAN pins
Expand Down Expand Up @@ -749,6 +749,7 @@ def spi_pinmap(lst):
spi_pins_list = []
winst = []
wpin = []
sp = re.compile(r"-|_")
if lst == spimosi_list:
aname = "SPI_MOSI"
elif lst == spimiso_list:
Expand All @@ -759,16 +760,18 @@ def spi_pinmap(lst):
aname = "SPI_SSEL"
for p in lst:
# 2nd element is the SPI_XXXX signal
inst = p[2].split("_")[0]
# but using 3rd which contains the stripped one
# used to properly sort them
inst = sp.split(p[3])[0]
winst.append(len(inst))
wpin.append(len(p[0]))
spi_pins_list.append(
{
"pin": p[0],
"inst": inst,
"mode": "STM_MODE_AF_PP",
"pull": "GPIO_PULLUP",
"af": p[3],
"pull": "GPIO_PULLUP" if inst != "SUBGHZSPI" else "GPIO_NOPULL",
"af": p[4],
}
)
return dict(
Expand Down Expand Up @@ -1278,6 +1281,36 @@ def timer_variant():
return dict(tone=tone, servo=servo)


def alias_definition():
# alias for STM32WL
alias_list = []
if mcu_family == "STM32WL":
mosi = [
mosi[0].replace("_", "", 1)
for mosi in spimosi_list
if "SUBGHZSPI" in mosi[2]
]
miso = [
miso[0].replace("_", "", 1)
for miso in spimiso_list
if "SUBGHZSPI" in miso[2]
]
sck = [
sck[0].replace("_", "", 1) for sck in spisclk_list if "SUBGHZSPI" in sck[2]
]
ssel = [
ssel[0].replace("_", "", 1)
for ssel in spissel_list
if "SUBGHZSPI" in ssel[2]
]
if mosi and miso and sck and ssel:
alias_list.append(("DEBUG_SUBGHZSPI_MOSI", mosi[0]))
alias_list.append(("DEBUG_SUBGHZSPI_MISO", miso[0]))
alias_list.append(("DEBUG_SUBGHZSPI_SCLK", sck[0]))
alias_list.append(("DEBUG_SUBGHZSPI_SS", ssel[0]))
return alias_list


def print_variant(generic_list, alt_syswkup_list):
variant_h_template = j2_env.get_template(variant_h_filename)
variant_cpp_template = j2_env.get_template(variant_cpp_filename)
Expand All @@ -1299,6 +1332,9 @@ def print_variant(generic_list, alt_syswkup_list):
# Timers definition
timer = timer_variant()

# Alias to ease some usage
alias_list = alias_definition()

# Manage all pins number, PinName and analog pins
analog_index = 0
pins_number_list = []
Expand Down Expand Up @@ -1379,6 +1415,7 @@ def print_variant(generic_list, alt_syswkup_list):
timer=timer,
serial=serial,
hal_modules_list=hal_modules_list,
alias_list=alias_list,
)
)

Expand Down Expand Up @@ -1536,6 +1573,10 @@ def natural_sortkey2(list_2_elem):
return tuple(int(num) if num else alpha for num, alpha in tokenize(list_2_elem[2]))


def natural_sortkey3(list_2_elem):
return tuple(int(num) if num else alpha for num, alpha in tokenize(list_2_elem[3]))


def sort_my_lists():
io_list.sort(key=natural_sortkey)
dualpad_list.sort(key=natural_sortkey)
Expand All @@ -1550,9 +1591,13 @@ def sort_my_lists():
uartrx_list.sort(key=natural_sortkey)
uartcts_list.sort(key=natural_sortkey)
uartrts_list.sort(key=natural_sortkey)
spimosi_list.sort(key=natural_sortkey3)
spimosi_list.sort(key=natural_sortkey)
spimiso_list.sort(key=natural_sortkey3)
spimiso_list.sort(key=natural_sortkey)
spissel_list.sort(key=natural_sortkey3)
spissel_list.sort(key=natural_sortkey)
spisclk_list.sort(key=natural_sortkey3)
spisclk_list.sort(key=natural_sortkey)
cantd_list.sort(key=natural_sortkey)
canrd_list.sort(key=natural_sortkey)
Expand Down
9 changes: 9 additions & 0 deletions CI/update/templates/variant_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@
#define PIN_SERIAL_TX {{serial.tx}}
#endif

{% if alias_list %}
// Alias
{% for alias in alias_list %}
#ifndef {{alias[0]}}
#define {{"%-21s %s"|format(alias[0], alias[1])}}
#endif
{% endfor %}

{% endif %}
{% if hal_modules_list %}
// Extra HAL modules
{% for hal_module in hal_modules_list %}
Expand Down
75 changes: 75 additions & 0 deletions libraries/SPI/src/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,78 @@ void SPIClass::detachInterrupt(void)
{
// Should be disableInterrupt()
}

#if defined(SUBGHZSPI_BASE)
void SUBGHZSPIClass::begin(uint8_t _pin)
{
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
SPIClass::begin(CS_PIN_CONTROLLED_BY_USER);
}

void SUBGHZSPIClass::beginTransaction(uint8_t _pin, SPISettings settings)
{
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
SPIClass::beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
}

byte SUBGHZSPIClass::transfer(uint8_t _pin, uint8_t _data, SPITransferMode _mode)
{
byte res;
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_SelectSUBGHZSPI_NSS();
}
res = SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
return res;
}

uint16_t SUBGHZSPIClass::transfer16(uint8_t _pin, uint16_t _data, SPITransferMode _mode)
{
uint16_t rx_buffer = 0;
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_SelectSUBGHZSPI_NSS();
}
SPIClass::transfer16(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
return rx_buffer;
}

void SUBGHZSPIClass::transfer(uint8_t _pin, void *_buf, size_t _count, SPITransferMode _mode)
{
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_SelectSUBGHZSPI_NSS();
}
SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _buf, _count, _mode);
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
}

void SUBGHZSPIClass::transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode)
{
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_SelectSUBGHZSPI_NSS();
}
SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _bufout, _bufin, _count, _mode);
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
}

void SUBGHZSPIClass::enableDebugPins(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel)
{
/* Configure SPI GPIO pins */
pinmap_pinout(digitalPinToPinName(mosi), PinMap_SPI_MOSI);
pinmap_pinout(digitalPinToPinName(miso), PinMap_SPI_MISO);
pinmap_pinout(digitalPinToPinName(sclk), PinMap_SPI_SCLK);
pinmap_pinout(digitalPinToPinName(ssel), PinMap_SPI_SSEL);
}
#endif
86 changes: 53 additions & 33 deletions libraries/SPI/src/SPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,29 +74,26 @@ enum SPITransferMode {

class SPISettings {
public:
SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE)
{
clk = clock;
bOrder = bitOrder;
noReceive = noRecv;

if (SPI_MODE0 == dataMode) {
dMode = SPI_MODE_0;
} else if (SPI_MODE1 == dataMode) {
dMode = SPI_MODE_1;
} else if (SPI_MODE2 == dataMode) {
dMode = SPI_MODE_2;
} else if (SPI_MODE3 == dataMode) {
dMode = SPI_MODE_3;
}
}
SPISettings()
{
pinCS = -1;
clk = SPI_SPEED_CLOCK_DEFAULT;
bOrder = MSBFIRST;
dMode = SPI_MODE_0;
}
constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE)
: pinCS(-1),
clk(clock),
bOrder(bitOrder),
dMode((spi_mode_e)(
(SPI_MODE0 == dataMode) ? SPI_MODE_0 :
(SPI_MODE1 == dataMode) ? SPI_MODE_1 :
(SPI_MODE2 == dataMode) ? SPI_MODE_2 :
(SPI_MODE3 == dataMode) ? SPI_MODE_3 :
SPI_MODE0
)),
noReceive(noRecv)
{ }
constexpr SPISettings()
: pinCS(-1),
clk(SPI_SPEED_CLOCK_DEFAULT),
bOrder(MSBFIRST),
dMode(SPI_MODE_0),
noReceive(SPI_TRANSMITRECEIVE)
{ }
private:
int16_t pinCS; //CS pin associated to the configuration
uint32_t clk; //specifies the spi bus maximum clock speed
Expand Down Expand Up @@ -151,15 +148,15 @@ class SPIClass {
_spi.pin_ssel = (ssel);
};

void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
virtual void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
void end(void);

/* This function should be used to configure the SPI instance in case you
* don't use default parameters.
* You can attach another CS pin to the SPI instance and each CS pin can be
* attach with specific SPI settings.
*/
void beginTransaction(uint8_t pin, SPISettings settings);
virtual void beginTransaction(uint8_t pin, SPISettings settings);
void beginTransaction(SPISettings settings)
{
beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
Expand All @@ -175,10 +172,10 @@ class SPIClass {
* instance with begin() or beginTransaction().
* You can specify the CS pin to use.
*/
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
virtual byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
virtual uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
virtual void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
virtual void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);

// Transfer functions when user controls himself the CS pin.
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST)
Expand Down Expand Up @@ -233,6 +230,10 @@ class SPIClass {
return &(_spi.handle);
}

protected:
// spi instance
spi_t _spi;

private:
/* Contains various spiSettings for the same spi instance. Each spi spiSettings
is associated to a CS pin. */
Expand All @@ -241,10 +242,6 @@ class SPIClass {
// Use to know which configuration is selected.
int16_t _CSPinConfig;

// spi instance
spi_t _spi;


typedef enum {
GET_IDX = 0,
ADD_NEW_PIN = 1
Expand Down Expand Up @@ -304,4 +301,27 @@ class SPIClass {

extern SPIClass SPI;

#if defined(SUBGHZSPI_BASE)
class SUBGHZSPIClass : public SPIClass {
public:
SUBGHZSPIClass(): SPIClass{NC, NC, NC, NC}
{
_spi.spi = SUBGHZSPI;
}

void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
void beginTransaction(uint8_t pin, SPISettings settings);
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
void enableDebugPins(uint32_t mosi = DEBUG_SUBGHZSPI_MOSI, uint32_t miso = DEBUG_SUBGHZSPI_MISO, uint32_t sclk = DEBUG_SUBGHZSPI_SCLK, uint32_t ssel = DEBUG_SUBGHZSPI_SS);

using SPIClass::beginTransaction;
using SPIClass::transfer;
using SPIClass::transfer16;
};

#endif

#endif /* _SPI_H_INCLUDED */
Loading