Skip to content
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

fix SPIDEV interface #315

Merged
merged 2 commits into from
Jan 4, 2017
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
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