Skip to content

Commit

Permalink
fix SPIDEV interface (#315)
Browse files Browse the repository at this point in the history
* fix SPIDEV interface
* cleanup SPIDEV
  • Loading branch information
plasticassius committed Jan 4, 2017
1 parent ab738fd commit e234ba7
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 146 deletions.
173 changes: 65 additions & 108 deletions utility/SPIDEV/spi.cpp
Original file line number Diff line number Diff line change
@@ -1,45 +1,42 @@
/*
/*
* File: spi.cpp
* Author: Purinda Gunasekara <purinda@gmail.com>
*
*
* Created on 24 June 2012, 11:00 AM
*
*
* 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 <pthread.h>
static pthread_mutex_t spiMutex;
#include <fcntl.h>
#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) {
}

void SPI::begin(int busNo){

this->device = "/dev/spidev0.0";
/* set spidev accordingly to busNo like:
* busNo = 23 -> /dev/spidev2.3
*
* a bit messy but simple
* */
this->device[11] += (busNo / 10) % 10;
this->device[13] += busNo % 10;
this->bits = 8;
this->speed = RF24_SPIDEV_SPEED;
this->mode=0;
//this->mode |= SPI_NO_CS;
this->init();
}
char device[] = "/dev/spidev0.0";
device[11] += (busNo / 10) % 10;
device[13] += busNo % 10;

void SPI::init()
{
int ret;

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)
{
Expand All @@ -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
*/
ret = ioctl(this->fd, SPI_IOC_WR_MODE, &this->mode);
ret = ioctl(this->fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
{
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)
{
perror("can't set spi mode");
abort();
abort();
}

/*
* 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)
{
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)
{
perror("can't set bits per word");
abort();
abort();
}
/*
* 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)
{
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)
{
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;
tr.tx_buf = (unsigned long)tx;
tr.rx_buf = (unsigned long)rx;
tr.len = ARRAY_SIZE(tx);
memset(&tr, 0, sizeof(tr));
tr.tx_buf = (unsigned long)&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.cs_change = 1;
tr.speed_hz = this->speed;
tr.bits_per_word = this->bits;*/
tr.bits_per_word = RF24_SPIDEV_BITS;
tr.cs_change = 0;

int ret;
ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
{
pthread_mutex_unlock (&spiMutex);
perror("can't send spi message");
abort();
abort();
}

pthread_mutex_unlock (&spiMutex);
return rx[0];
return rx;
}

//void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len)
{

pthread_mutex_lock (&spiMutex);
int ret;
this->init();
struct spi_ioc_transfer tr = {
tr.tx_buf = (unsigned long)tbuf,
tr.rx_buf = (unsigned long)rbuf,
tr.len = len,//ARRAY_SIZE(tx),
tr.cs_change=1,
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;*/
struct spi_ioc_transfer tr;
memset(&tr, 0, sizeof(tr));
tr.tx_buf = (unsigned long)tbuf;
tr.rx_buf = (unsigned long)rbuf;
tr.len = len;
tr.speed_hz = RF24_SPIDEV_SPEED;
tr.delay_usecs = 0;
tr.bits_per_word = RF24_SPIDEV_BITS;
tr.cs_change = 0;

int ret;
ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
{
pthread_mutex_unlock (&spiMutex);
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() {
if (!(this->fd < 0))
close(this->fd);
if (!(this->fd < 0))
close(this->fd);
}

56 changes: 18 additions & 38 deletions utility/SPIDEV/spi.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
/*
* File: spi.h
* Author: Purinda Gunasekara <purinda@gmail.com>
*
*
* Created on 24 June 2012, 11:00 AM
*/

Expand All @@ -13,7 +13,7 @@
* \cond HIDDEN_SYMBOLS
* Class declaration for SPI helper files
*/

/**
* Example GPIO.h file
*
Expand All @@ -22,48 +22,34 @@
* 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 <linux/types.h>
#include <linux/spi/spidev.h>

#ifndef RF24_SPIDEV_SPEED
/* 8MHz as default */
#define RF24_SPIDEV_SPEED 8000000
#endif

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

using namespace std;

class SPI {
public:

/**
* SPI constructor
*/
*/
SPI();

/**
* Start SPI
*/
void begin(int busNo);

/**
* Transfer a single byte
* @param tx_ Byte to send
* @param tx Byte to send
* @return Data returned via spi
*/
uint8_t transfer(uint8_t tx_);
uint8_t transfer(uint8_t tx);

/**
* Transfer a buffer of data
* @param tbuf Transmit buffer
Expand All @@ -76,24 +62,18 @@ class SPI {
* Transfer a buffer of data without an rx buffer
* @param buf Pointer to a buffer of data
* @param len Length of the data
*/
void transfern(char* buf, uint32_t len);

virtual ~SPI();
*/
void transfern(char* buf, uint32_t len) {
transfernb(buf, buf, len);
}

~SPI();

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;

void init();
void init();
};

/**
Expand Down

0 comments on commit e234ba7

Please sign in to comment.