/* * 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 #include #include #include #include #include #include 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(send), reinterpret_cast(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(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_); }