diff --git a/ChangeLog b/ChangeLog index df00a50227c7797257a53c68bcebfa71f5df2119..c78cfc152f54402c9f2663ecba480f4d0f7d2e97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2014-05-10 +------------------------------------------------------------------------ + +Added initial Linux SPI implementation to use the library on a +Raspberry Pi or other Linux based SPI-capable platforms. + ------------------------------------------------------------------------ 2012-01-28 @@ -5,7 +11,7 @@ * included rfm12_read_interrupt_flags_inline() again for performance reasons (interrupt handler might be to slow on 115200 Baud otherwise) * clear interrupt flag before checking status (there is a glitch sometimes - while the int line goes high, which triggers another interrupt otherweise, + while the int line goes high, which triggers another interrupt otherwise, which also hurts performance * LNA controllable over rfm12_livectrl diff --git a/src/include/rfm12_spi.c b/src/include/rfm12_spi.c index de0833742d7d5d9c2ead4a5f7946876b14ebe7cb..d2a56f5e1de13bc03cb3371c68de5d55960182e4 100644 --- a/src/include/rfm12_spi.c +++ b/src/include/rfm12_spi.c @@ -27,6 +27,7 @@ #define SS_ASSERT() PORT_SS &= ~(1<<BIT_SS) #define SS_RELEASE() PORT_SS |= (1<<BIT_SS) +#ifdef __PLATFORM_AVR__ #if RFM12_SPI_SOFTWARE /* @description Actual sending function to send raw data to the Module @@ -135,3 +136,5 @@ static void spi_init(void) { SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0); //SPI Master, clk/16 #endif } + +#endif diff --git a/src/include/rfm12_spi_linux.c b/src/include/rfm12_spi_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..8b3b2d7c70b8328461f5cde43353aa97dcacc0a5 --- /dev/null +++ b/src/include/rfm12_spi_linux.c @@ -0,0 +1,107 @@ +#ifdef __PLATFORM_LINUX__ +#include <linux/spi/spidev.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <stdlib.h> +#include <getopt.h> +#include <stdio.h> +#include <byteswap.h> +#include <unistd.h> + +static const char *device = "/dev/spidev0.1"; +static int fd; +static uint8_t mode = 0; +static uint8_t bits = 8; +static uint32_t speed = 250000; + +static void pabort(const char *s) +{ + perror(s); + abort(); +} + + +static void spi_init(void) { + int ret = 0; + + fd = open(device, O_RDWR); + + if (fd < 0) { + pabort("driver not loaded? can't open device"); + } + ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); + if (ret == -1) + pabort("can't set spi mode"); + + ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); + if (ret == -1) + pabort("can't get spi mode"); + + /* + * bits per word + */ + ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); + if (ret == -1) + pabort("can't set bits per word"); + + ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); + if (ret == -1) + pabort("can't get bits per word"); + + /* + * max speed hz + */ + ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + if (ret == -1) + pabort("can't set max speed hz"); + + ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); + if (ret == -1) + pabort("can't get max speed hz"); +} + +static uint16_t rfm12_read(uint16_t address) { + int ret; + + uint8_t rx[2]; + uint8_t tx[2]; + + tx[0] = (uint8_t) (address >> 8); + tx[1] = (uint8_t) (address & 0xFF); + + rx[0] = 0; + rx[1] = 0; + + struct spi_ioc_transfer tr = { + .tx_buf = (unsigned long)tx, + .rx_buf = (unsigned long)rx, + .len = 2, + .delay_usecs = 0, + .speed_hz = speed, + .bits_per_word = bits, + }; + + ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); + + if (ret < 1) + pabort("can't send spi message"); + + + return ((uint16_t)rx[0] << 8) + rx[1]; +} + +static void rfm12_data(uint16_t d) { + uint8_t buffer[2]; + buffer[0] = (uint8_t) (d >> 8); + buffer[1] = (uint8_t) (d & 0xff); + + write(fd, buffer, sizeof(buffer)); +} + +static uint8_t rfm12_read_int_flags_inline(void) { + uint16_t ret = rfm12_read(0x0000); + + return ret >> 8; +} + +#endif diff --git a/src/rfm12.c b/src/rfm12.c index 8e696b316d68308f94423688736e9242168705f5..90c9473b295903a016d5f39ccb44754f5fe22346 100644 --- a/src/rfm12.c +++ b/src/rfm12.c @@ -34,10 +34,14 @@ /************************ * standard includes */ +#ifdef __PLATFORM_AVR__ #include <avr/io.h> #include <avr/interrupt.h> -#include <string.h> #include <avr/pgmspace.h> +#endif + +#include <string.h> + /************************ @@ -85,6 +89,7 @@ rfm12_control_t ctrl; /* include spi functions into here */ #include "include/rfm12_spi.c" +#include "include/rfm12_spi_linux.c" /* * include control / init functions into here @@ -142,7 +147,9 @@ ISR(RFM12_INT_VECT, ISR_NOBLOCK) do { //clear AVR int flag +#ifdef __PLATFORM_AVR__ RFM12_INT_FLAG = (1<<RFM12_FLAG_BIT); +#endif //first we read the first byte of the status register //to get the interrupt flags @@ -646,7 +653,11 @@ rfm12_start_tx(uint8_t type, uint8_t length) { //set TX Power, frequency shift #define RFM12_CMD_TXCONF_DEFAULT (RFM12_CMD_TXCONF | RFM12_POWER | RFM12_TXCONF_FS_CALC(FSK_SHIFT) ) +#ifdef __PLATFORM_AVR__ static const uint16_t init_cmds[] PROGMEM = { +#else +static const uint16_t init_cmds[] = { +#endif //defined above (so shadow register is inited with same value) RFM12_CMD_CFG_DEFAULT, @@ -708,8 +719,10 @@ static const uint16_t init_cmds[] PROGMEM = { */ void rfm12_init(void) { //initialize spi +#ifdef __PLATFORM_AVR__ SS_RELEASE(); DDR_SS |= (1<<BIT_SS); +#endif spi_init(); //typically sets DDR registers for RFM12BP TX/RX pin @@ -756,9 +769,17 @@ void rfm12_init(void) { //write all the initialisation values to rfm12 uint8_t x; - for (x = 0; x < ( sizeof(init_cmds) / 2) ; x++) { - rfm12_data(pgm_read_word(&init_cmds[x])); - } + + #ifdef __PLATFORM_AVR__ + + for (x = 0; x < ( sizeof(init_cmds) / 2) ; x++) { + rfm12_data(pgm_read_word(&init_cmds[x])); + } + #else + for (x = 0; x < ( sizeof(init_cmds) / 2) ; x++) { + rfm12_data(init_cmds[x]); + } + #endif #ifdef RX_ENTER_HOOK RX_ENTER_HOOK; @@ -774,11 +795,16 @@ void rfm12_init(void) { #endif //setup interrupt for falling edge trigger +#ifdef __PLATFORM_AVR__ RFM12_INT_SETUP(); +#endif //clear int flag rfm12_read(RFM12_CMD_STATUS); + +#ifdef __PLATFORM_AVR__ RFM12_INT_FLAG = (1<<RFM12_FLAG_BIT); +#endif //init receiver fifo, we now begin receiving. rfm12_data(CLEAR_FIFO); diff --git a/src/rfm12.h b/src/rfm12.h index 5b13b5ad31a767d0d852313601eda3c004549923..ff7e1d219f226bc9f51816aae42899c1d75466bb 100644 --- a/src/rfm12.h +++ b/src/rfm12.h @@ -40,6 +40,10 @@ #ifndef _RFM12_H #define _RFM12_H +#ifdef __PLATFORM_LINUX__ +#include <stdint.h> +#endif + //this was missing, but is very important to set the config options for structs and such #include "include/rfm12_core.h"