Commit e234ba71 authored by plasticassius's avatar plasticassius Committed by GitHub

fix SPIDEV interface (#315)

* fix SPIDEV interface
* cleanup SPIDEV
parent ab738fdf
/* /*
* File: spi.cpp * File: spi.cpp
* Author: Purinda Gunasekara <purinda@gmail.com> * Author: Purinda Gunasekara <purinda@gmail.com>
* *
* Created on 24 June 2012, 11:00 AM * Created on 24 June 2012, 11:00 AM
* *
* Inspired from spidev test in linux kernel documentation * Inspired from spidev test in linux kernel documentation
* www.kernel.org/doc/Documentation/spi/spidev_test.c * www.kernel.org/doc/Documentation/spi/spidev_test.c
*/ */
#include "spi.h" #include "spi.h"
#include <pthread.h> #include <fcntl.h>
static pthread_mutex_t spiMutex; #include <linux/spi/spidev.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define RF24_SPIDEV_BITS 8
SPI::SPI():fd(-1) { SPI::SPI():fd(-1) {
} }
void SPI::begin(int busNo){ void SPI::begin(int busNo){
this->device = "/dev/spidev0.0";
/* set spidev accordingly to busNo like: /* set spidev accordingly to busNo like:
* busNo = 23 -> /dev/spidev2.3 * busNo = 23 -> /dev/spidev2.3
* *
* a bit messy but simple * a bit messy but simple
* */ * */
this->device[11] += (busNo / 10) % 10; char device[] = "/dev/spidev0.0";
this->device[13] += busNo % 10; device[11] += (busNo / 10) % 10;
this->bits = 8; device[13] += busNo % 10;
this->speed = RF24_SPIDEV_SPEED;
this->mode=0;
//this->mode |= SPI_NO_CS;
this->init();
}
void SPI::init()
{
int ret;
if (this->fd < 0) // check whether spi is already open if (this->fd < 0) // check whether spi is already open
{ {
this->fd = open(this->device.c_str(), O_RDWR); this->fd = open(device, O_RDWR);
if (this->fd < 0) if (this->fd < 0)
{ {
...@@ -48,153 +45,113 @@ void SPI::init() ...@@ -48,153 +45,113 @@ void SPI::init()
} }
} }
init();
}
void SPI::init()
{
uint8_t bits = RF24_SPIDEV_BITS;
uint32_t speed = RF24_SPIDEV_SPEED;
uint8_t mode = 0;
int ret;
/* /*
* spi mode * spi mode
*/ */
ret = ioctl(this->fd, SPI_IOC_WR_MODE, &this->mode); ret = ioctl(this->fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1) if (ret == -1)
{ {
perror("can't set spi mode"); perror("can't set spi mode");
abort(); abort();
} }
ret = ioctl(this->fd, SPI_IOC_RD_MODE, &this->mode); ret = ioctl(this->fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1) if (ret == -1)
{ {
perror("can't set spi mode"); perror("can't set spi mode");
abort(); abort();
} }
/* /*
* bits per word * bits per word
*/ */
ret = ioctl(this->fd, SPI_IOC_WR_BITS_PER_WORD, &this->bits); ret = ioctl(this->fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1) if (ret == -1)
{ {
perror("can't set bits per word"); perror("can't set bits per word");
abort(); abort();
} }
ret = ioctl(this->fd, SPI_IOC_RD_BITS_PER_WORD, &this->bits); ret = ioctl(this->fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1) if (ret == -1)
{ {
perror("can't set bits per word"); perror("can't set bits per word");
abort(); abort();
} }
/* /*
* max speed hz * max speed hz
*/ */
ret = ioctl(this->fd, SPI_IOC_WR_MAX_SPEED_HZ, &this->speed); ret = ioctl(this->fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1) if (ret == -1)
{ {
perror("can't set max speed hz"); perror("can't set max speed hz");
abort(); abort();
} }
ret = ioctl(this->fd, SPI_IOC_RD_MAX_SPEED_HZ, &this->speed); ret = ioctl(this->fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1) if (ret == -1)
{ {
perror("can't set max speed hz"); perror("can't set max speed hz");
abort(); abort();
} }
} }
uint8_t SPI::transfer(uint8_t tx_) uint8_t SPI::transfer(uint8_t tx)
{ {
pthread_mutex_lock (&spiMutex);
int ret;
uint8_t tx[1] = {tx_};
uint8_t rx[1];
this->init();
struct spi_ioc_transfer tr = {
tr.tx_buf = (unsigned long)&tx[0],
tr.rx_buf = (unsigned long)&rx[0],
tr.len = 1,//ARRAY_SIZE(tx),
tr.delay_usecs = 0,
tr.cs_change=1,
tr.bits_per_word = this->bits,
};
tr.speed_hz = this->speed,
//Note: On RPi, for some reason I started getting 'bad message' errors, and changing the struct as below fixed it, until an update...??
//
/* // One byte is transfered at once
uint8_t rx[ARRAY_SIZE(tx)] = {0};
struct spi_ioc_transfer tr; struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long)tx; memset(&tr, 0, sizeof(tr));
tr.rx_buf = (unsigned long)rx; tr.tx_buf = (unsigned long)&tx;
tr.len = ARRAY_SIZE(tx); uint8_t rx;
tr.rx_buf = (unsigned long)&rx;
tr.len = sizeof(tx);
tr.speed_hz = RF24_SPIDEV_SPEED;
tr.delay_usecs = 0; tr.delay_usecs = 0;
tr.cs_change = 1; tr.bits_per_word = RF24_SPIDEV_BITS;
tr.speed_hz = this->speed; tr.cs_change = 0;
tr.bits_per_word = this->bits;*/
int ret;
ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr); ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) if (ret < 1)
{ {
pthread_mutex_unlock (&spiMutex);
perror("can't send spi message"); perror("can't send spi message");
abort(); abort();
} }
pthread_mutex_unlock (&spiMutex); return rx;
return rx[0];
} }
//void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len) void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len)
{ {
struct spi_ioc_transfer tr;
pthread_mutex_lock (&spiMutex); memset(&tr, 0, sizeof(tr));
int ret; tr.tx_buf = (unsigned long)tbuf;
this->init(); tr.rx_buf = (unsigned long)rbuf;
struct spi_ioc_transfer tr = { tr.len = len;
tr.tx_buf = (unsigned long)tbuf, tr.speed_hz = RF24_SPIDEV_SPEED;
tr.rx_buf = (unsigned long)rbuf, tr.delay_usecs = 0;
tr.len = len,//ARRAY_SIZE(tx), tr.bits_per_word = RF24_SPIDEV_BITS;
tr.cs_change=1, tr.cs_change = 0;
tr.delay_usecs = 0,
tr.bits_per_word = this->bits,
};
tr.speed_hz = this->speed,
//Note: On RPi, for some reason I started getting 'bad message' errors, and changing the struct as below fixed it, until an update...??
// One byte is transfered at once
//uint8_t tx[] = {0};
//tx[0] = tx_;
//uint8_t rx[ARRAY_SIZE(tx)] = {0};
/*struct spi_ioc_transfer tr;
tr.tx_buf = (unsigned long)tbuf;//(unsigned long)tx;
tr.rx_buf = (unsigned long)rbuf;//(unsigned long)rx;
tr.len = len;//ARRAY_SIZE(tx);
tr.delay_usecs = 0;
tr.cs_change = 1;
tr.speed_hz = this->speed;
tr.bits_per_word = this->bits;*/
int ret;
ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr); ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1) if (ret < 1)
{ {
pthread_mutex_unlock (&spiMutex);
perror("can't send spi message"); perror("can't send spi message");
abort(); abort();
} }
pthread_mutex_unlock (&spiMutex);
//return rx[0];
} }
void SPI::transfern(char* buf, uint32_t len)
{
transfernb(buf, buf, len);
}
SPI::~SPI() { SPI::~SPI() {
if (!(this->fd < 0)) if (!(this->fd < 0))
close(this->fd); close(this->fd);
} }
/* /*
* File: spi.h * File: spi.h
* Author: Purinda Gunasekara <purinda@gmail.com> * Author: Purinda Gunasekara <purinda@gmail.com>
* *
* Created on 24 June 2012, 11:00 AM * Created on 24 June 2012, 11:00 AM
*/ */
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* \cond HIDDEN_SYMBOLS * \cond HIDDEN_SYMBOLS
* Class declaration for SPI helper files * Class declaration for SPI helper files
*/ */
/** /**
* Example GPIO.h file * Example GPIO.h file
* *
...@@ -22,48 +22,34 @@ ...@@ -22,48 +22,34 @@
* See RF24_arch_config.h for additional information * See RF24_arch_config.h for additional information
* @{ * @{
*/ */
#include <string>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <inttypes.h> #include <inttypes.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#ifndef RF24_SPIDEV_SPEED #ifndef RF24_SPIDEV_SPEED
/* 8MHz as default */ /* 8MHz as default */
#define RF24_SPIDEV_SPEED 8000000 #define RF24_SPIDEV_SPEED 8000000
#endif #endif
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
using namespace std;
class SPI { class SPI {
public: public:
/** /**
* SPI constructor * SPI constructor
*/ */
SPI(); SPI();
/** /**
* Start SPI * Start SPI
*/ */
void begin(int busNo); void begin(int busNo);
/** /**
* Transfer a single byte * Transfer a single byte
* @param tx_ Byte to send * @param tx Byte to send
* @return Data returned via spi * @return Data returned via spi
*/ */
uint8_t transfer(uint8_t tx_); uint8_t transfer(uint8_t tx);
/** /**
* Transfer a buffer of data * Transfer a buffer of data
* @param tbuf Transmit buffer * @param tbuf Transmit buffer
...@@ -76,24 +62,18 @@ public: ...@@ -76,24 +62,18 @@ public:
* Transfer a buffer of data without an rx buffer * Transfer a buffer of data without an rx buffer
* @param buf Pointer to a buffer of data * @param buf Pointer to a buffer of data
* @param len Length of the data * @param len Length of the data
*/ */
void transfern(char* buf, uint32_t len); void transfern(char* buf, uint32_t len) {
transfernb(buf, buf, len);
virtual ~SPI(); }
~SPI();
private: private:
/** Default SPI device */
string device;
/** SPI Mode set */
uint8_t mode;
/** word size*/
uint8_t bits;
/** Set SPI speed*/
uint32_t speed;
int fd; int fd;
void init(); void init();
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment