#include "pispi.h" #include "piincludes_p.h" #if !defined(WINDOWS) && !defined(MAC_OS) # define PISPI #endif #ifdef PISPI # include # include # include #endif PRIVATE_DEFINITION_START(PISPI) #ifdef PISPI int fd; spi_ioc_transfer spi_ioc_tr; #endif PRIVATE_DEFINITION_END(PISPI) REGISTER_DEVICE(PISPI) PISPI::PISPI(const PIString & path, uint speed, PIIODevice::DeviceMode mode) : PIIODevice(path, mode) { setThreadedReadBufferSize(1024); setPath(path); setSpeed(speed); setBits(8); spi_mode = 0; if (mode == ReadOnly) piCoutObj << "error, SPI can't work in ReadOnly mode"; #ifdef PISPI PRIVATE->fd = 0; #endif } void PISPI::setSpeed(uint speed_hz) { spi_speed = speed_hz; } void PISPI::setBits(uchar bits) { spi_bits = bits; } void PISPI::setParameter(PISPI::Parameters parameter, bool on) { PIFlags cp = (PIFlags)spi_mode; cp.setFlag(parameter, on); spi_mode = (int)cp; } bool PISPI::isParameterSet(PISPI::Parameters parameter) const { PIFlags cp = (PIFlags)spi_mode; return cp[parameter]; } bool PISPI::openDevice() { #ifdef PISPI int ret = 0; //piCoutObj << "open device" << path(); PRIVATE->fd = ::open(path().dataAscii(), O_RDWR); if (PRIVATE->fd < 0) {piCoutObj << "can't open device";return false;} //piCoutObj << "set mode" << spi_mode; ret = ioctl(PRIVATE->fd, SPI_IOC_WR_MODE, &spi_mode); if (ret == -1) {piCoutObj << "can't set spi write mode";return false;} //piCoutObj << "set bits" << spi_bits; ret = ioctl(PRIVATE->fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits); if (ret == -1) {piCoutObj << "can't set bits per word";return false;} //piCoutObj << "set speed" << spi_speed; ret = ioctl(PRIVATE->fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed); if (ret == -1) {piCoutObj << "can't set max write speed hz";return false;} piCoutObj << "SPI open" << path() << "speed:" << spi_speed/1000 << "KHz" << "mode" << spi_mode << "bits" << spi_bits; PRIVATE->spi_ioc_tr.delay_usecs = 0; PRIVATE->spi_ioc_tr.speed_hz = 0; PRIVATE->spi_ioc_tr.bits_per_word = spi_bits; return true; #else piCoutObj << "PISPI not implemented on windows"; return false; #endif } bool PISPI::closeDevice() { #ifdef PISPI if (PRIVATE->fd) ::close(PRIVATE->fd); #endif return true; } int PISPI::readDevice(void * read_to, int max_size) { int sz = piMini(recv_buf.size_s(), max_size); memcpy(read_to, recv_buf.data(), sz); recv_buf.resize(recv_buf.size_s() - sz); return sz; } int PISPI::writeDevice(const void * data, int max_size) { #ifdef PISPI if (max_size > 0) { if (tx_buf.size_s() != max_size) { tx_buf.resize(max_size); rx_buf.resize(max_size); PRIVATE->spi_ioc_tr.tx_buf = (ulong)(tx_buf.data()); PRIVATE->spi_ioc_tr.rx_buf = (ulong)(rx_buf.data()); PRIVATE->spi_ioc_tr.len = max_size; } memcpy(tx_buf.data(), data, max_size); int ret; //piCoutObj << "write" << max_size << tx_buf.size(); ret = ioctl(PRIVATE->fd, SPI_IOC_MESSAGE(1), &PRIVATE->spi_ioc_tr); if (ret < 1) {piCoutObj << "can't send spi message" << ret; return -1;} if (canRead()) recv_buf.append(rx_buf); if (recv_buf.size_s() > threadedReadBufferSize()) recv_buf.resize(threadedReadBufferSize()); return max_size; } #endif return 0; } PIString PISPI::constructFullPathDevice() const { PIString ret; ret << path() << ":" << int(speed()) << ":" << int(bits()) << ":" << (int)parameters(); return ret; } void PISPI::configureFromFullPathDevice(const PIString & full_path) { PIStringList pl = full_path.split(":"); for (int i = 0; i < pl.size_s(); ++i) { PIString p(pl[i]); switch (i) { case 0: setPath(p); break; case 1: setSpeed(p.toInt()); break; case 2: setBits(p.toInt()); break; case 3: setParameters(p.toInt()); break; default: break; } } }