This repository has been archived on 2018-05-28. You can view files and clone it, but cannot push or open issues or pull requests.
BBB-Simple-ACS/client/lib/spi_device.cpp

148 lines
4.3 KiB
C++

/*
* SPIDevice.cpp Created on: 22 May 2014
* Copyright (c) 2014 Derek Molloy (www.derekmolloy.ie)
* Made available for the book "Exploring BeagleBone"
* See: www.exploringbeaglebone.com
* Licensed under the EUPL V.1.1
*
* This Software is provided to You under the terms of the European
* Union Public License (the "EUPL") version 1.1 as published by the
* European Union. Any use of this Software, other than as authorized
* under this License is strictly prohibited (to the extent such use
* is covered by a right of the copyright holder of this Software).
*
* This Software is provided under the License on an "AS IS" basis and
* without warranties of any kind concerning the Software, including
* without limitation merchantability, fitness for a particular purpose,
* absence of defects or errors, accuracy, and non-infringement of
* intellectual property rights other than copyright. This disclaimer
* of warranty is an essential part of the License and a condition for
* the grant of any rights to this Software.
*
* For more details, see http://www.derekmolloy.ie/
*/
#include "spi_device.hpp"
#include <iostream>
#include <string>
#include <cstdlib>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
spi_device::spi_device(unsigned int bus, unsigned int device) : bus_(bus), device_(device)
{
filename_ = std::string(base_path) + std::to_string(bus) + '.' + std::to_string(device);
if ((fd_ = open(filename_.c_str(), O_RDWR)) < 0 ||
set_mode(mode_) == -1 ||
set_speed(speed_) == -1 ||
set_speed(speed_) == -1 ||
set_bits_per_word(bits_) == -1)
{
std::cerr << "Failed to open SPI device: " <<
base_path << bus << '.' << device << std::endl;
exit(1);
}
}
int spi_device::transfer(unsigned char send[], unsigned char receive[], unsigned length)
{
spi_ioc_transfer transfer = {
reinterpret_cast<unsigned long>(send),
reinterpret_cast<unsigned long>(receive),
length, speed_, delay_, bits_
};
auto status = ioctl(this->fd_, SPI_IOC_MESSAGE(1), &transfer);
if (status < 0)
std::cerr << "SPI: SPI_IOC_MESSAGE Failed" << std::endl;
return status;
}
unsigned char spi_device::read_register(unsigned char register_address)
{
unsigned char send[2] = { 0 }, receive[2] = { 0 };
send[0] = static_cast<unsigned char>(0x80 | register_address);
transfer(send, receive, 2);
return receive[1];
}
unsigned char spi_device::read(unsigned char register_address)
{
unsigned char send[2] = { register_address };
unsigned char receive[2] = { 0 };
transfer(send, receive, 2);
return receive[1];
}
int spi_device::write(unsigned char value)
{
this->transfer(&value, nullptr, 1);
return 0;
}
int spi_device::write(unsigned char value[], unsigned length)
{
this->transfer(value, nullptr, length);
return 0;
}
int spi_device::write_register(unsigned char register_address, unsigned char value)
{
unsigned char send[2] = { register_address, value };
unsigned char receive[2] = { 0 };
this->transfer(send, receive, 2);
return 0;
}
int spi_device::set_speed(uint32_t speed)
{
speed_ = speed;
if (ioctl(fd_, SPI_IOC_WR_MAX_SPEED_HZ, &speed_) == -1) {
std::cerr << "SPI: Can't set max speed HZ" << std::endl;
return -1;
}
if (ioctl(fd_, SPI_IOC_RD_MAX_SPEED_HZ, &speed_) == -1) {
std::cerr << "SPI: Can't get max speed HZ." << std::endl;
return -1;
}
return 0;
}
int spi_device::set_mode(mode mode)
{
mode_ = mode;
if (ioctl(fd_, SPI_IOC_WR_MODE, &mode_) == -1) {
std::cerr << "SPI: Can't set SPI mode." << std::endl;
return -1;
}
if (ioctl(fd_, SPI_IOC_RD_MODE, &mode_) == -1) {
std::cerr << "SPI: Can't get SPI mode." << std::endl;
return -1;
}
return 0;
}
int spi_device::set_bits_per_word(uint8_t bits)
{
bits_ = bits;
if (ioctl(fd_, SPI_IOC_WR_BITS_PER_WORD, &bits_) == -1) {
std::cerr << "SPI: Can't set bits per word." << std::endl;
return -1;
}
if (ioctl(fd_, SPI_IOC_RD_BITS_PER_WORD, &bits_) == -1) {
std::cerr << "SPI: Can't get bits per word." << std::endl;
return -1;
}
return 0;
}
spi_device::~spi_device()
{
close(fd_);
}