From c46ec5778d4d4d7be2b5041c6a83e321406f83c1 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Sun, 13 Feb 2022 18:40:30 -0500 Subject: [PATCH] Actually implement Linux SPI access --- LoRa.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++++- LoRa.h | 16 ++++++++++------ Makefile | 3 +++ 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/LoRa.cpp b/LoRa.cpp index 1ce035d..1b20596 100644 --- a/LoRa.cpp +++ b/LoRa.cpp @@ -11,6 +11,10 @@ #include // And we need to use the filesystem and IOCTLs instead of an SPI global #include + #include + #include + // And to have memset + #include // And we need to be able to report errors #include #include @@ -683,6 +687,7 @@ uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) uint8_t response; #if LIBRARY_TYPE == LIBRARY_ARDUINO + // Select chip, send address, and send/read data, the Arduino way digitalWrite(_ss, LOW); SPI.beginTransaction(_spiSettings); @@ -692,7 +697,47 @@ uint8_t ISR_VECT LoRaClass::singleTransfer(uint8_t address, uint8_t value) digitalWrite(_ss, HIGH); #elif LIBRARY_TYPE == LIBRARY_C - + // Select chip, send address, and send/read data, the Linux way + + // In Linux, chip select is automatically turned off outside of transactions. + + int status; + + // Configure SPI speed and mode to match settings + status = ioctl(_fd, SPI_IOC_WR_MODE, &_spiSettings.mode); + if (status < 0) { + perror("ioctl SPI_IOC_WR_MODE failed"); + exit(1); + } + status = ioctl(_fd, SPI_IOC_WR_LSB_FIRST, &_spiSettings.bitness); + if (status < 0) { + perror("ioctl SPI_IOC_WR_LSB_FIRST failed"); + exit(1); + } + status = ioctl(_fd, SPI_IOC_WR_MAX_SPEED_HZ, &_spiSettings.frequency); + if (status < 0) { + perror("ioctl SPI_IOC_WR_MAX_SPEED_HZ failed"); + exit(1); + } + + // We have two transfers: one send-only to send the address, and one + // send/receive, to send the value and get the response. + struct spi_ioc_transfer xfer[2]; + memset(xfer, 0, sizeof xfer); + + xfer[0].tx_buf = (unsigned long) &address; + xfer[0].len = 1; + + xfer[1].tx_buf = (unsigned long) &value; + xfer[1].rx_buf = (unsigned long) &response; + xfer[1].len = 1; + + // Do the transaction + status = ioctl(_fd, SPI_IOC_MESSAGE(2), xfer); + if (status < 0) { + perror("ioctl SPI_IOC_MESSAGE failed"); + exit(1); + } #else #error "SPI transfer not implemented for library type" #endif diff --git a/LoRa.h b/LoRa.h index 5793337..e57543a 100644 --- a/LoRa.h +++ b/LoRa.h @@ -22,16 +22,20 @@ typedef unsigned char byte; - // Arduino SPI is not available. + // Arduino SPI is not available, so make a Linux-ish version of SPISettings #define MSBFIRST 0 - #define SPI_MODE0 0 + #define LSBFIRST 1 + #define SPI_MODE0 SPI_MODE_0 + #define SPI_MODE1 SPI_MODE_1 + #define SPI_MODE2 SPI_MODE_2 + #define SPI_MODE3 SPI_MODE_3 class SPISettings { public: - inline SPISettings(int frequency, int bitness, int mode) : frequency(frequency), bitness(bitness), mode(mode) {}; + inline SPISettings(uint32_t frequency, byte bitness, byte mode) : frequency(frequency), bitness(bitness), mode(mode) {}; SPISettings& operator=(const SPISettings& other) = default; - int frequency; - int bitness; - int mode; + uint32_t frequency; + byte bitness; + byte mode; }; #endif diff --git a/Makefile b/Makefile index fda102b..b66d955 100644 --- a/Makefile +++ b/Makefile @@ -151,3 +151,6 @@ obj/MD5.o: MD5.cpp MD5.h Config.h ROM.h Platform.h prep-linux obj/LoRa.o: LoRa.cpp LoRa.h Platform.h prep-linux $(CC) -c -o $@ $< +obj/RNode_firmware.o: RNode_firmware.ino Utilities.h Config.h LoRa.h ROM.h Framing.h MD5.h Platform.h prep-linux + $(CC) -c -o $@ $< +