DUDS
Distributed Update of Data from Something
SpiMasterSyncSerial.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the DUDS project. It is subject to the BSD-style
3  * license terms in the LICENSE file found in the top-level directory of this
4  * distribution and at https://github.com/jjackowski/duds/blob/master/LICENSE.
5  * No part of DUDS, including this file, may be copied, modified, propagated,
6  * or distributed except according to the terms contained in the LICENSE file.
7  *
8  * Copyright (C) 2017 Jeff Jackowski
9  */
11 #include <duds/general/Errors.hpp>
12 #include <boost/exception/errinfo_file_name.hpp>
13 #include <fcntl.h>
14 #include <sys/ioctl.h>
16 #include <cstring>
17 
18 namespace duds { namespace hardware { namespace interface { namespace linux {
19 
21 
23  const std::string &path,
24  Flags flags,
25  int freq
26 ) : MasterSyncSerial(flags, 0) {
27  open(path);
28  setClockFrequency(freq);
29 }
30 
32 MasterSyncSerial(flags, 0), spifd(-1) { }
33 
35  forceClose();
36  ::close(spifd);
37 }
38 
40  const std::string &path,
41  Flags newflags,
42  int freq
43 ) {
44  // do not open when in use
45  if (flags & MssOpen) {
47  }
48  // close an open SPI device file
49  if (spifd >= 0) {
50  ::close(spifd);
51  }
52  if (newflags != 0) {
53  flags = newflags;
54  }
55  // open the SPI device file
56  spifd = ::open(path.c_str(), O_RDWR);
57  if (spifd < 0) {
59  boost::errinfo_file_name(path));
60  }
61  std::uint8_t byte = 0;
62  // figure out SPI mode flags
63  if (flags & MssClockIdleHigh) {
64  byte = SPI_CPOL;
65  if (flags & MssOutFallInRise) {
66  byte |= SPI_CPHA;
67  }
68  } else if (~flags & MssOutFallInRise) {
69  byte |= SPI_CPHA;
70  }
71  // set SPI mode flags
72  if (ioctl(spifd, SPI_IOC_WR_MODE, &byte) < 0) {
74  boost::errinfo_file_name(path));
75  }
76  // set bit order
77  if (flags & MssMSbFirst) {
78  byte = 0;
79  } else {
80  byte = 1;
81  }
82  if (ioctl(spifd, SPI_IOC_WR_LSB_FIRST, &byte) < 0) {
84  boost::errinfo_file_name(path));
85  }
86  // only 8 bits per word supported
87  byte = 8;
88  if (ioctl(spifd, SPI_IOC_WR_BITS_PER_WORD, &byte) < 0) {
90  boost::errinfo_file_name(path));
91  }
92  // set clock
93  setClockFrequency(freq);
94  // clear out struct used to describe transfers
95  std::memset(&xfer, 0, sizeof xfer);
96  // ready for use
97  flags |= MssReady;
98 }
99 
100 void SpiMasterSyncSerial::setClockFrequency(unsigned int freq) {
101  if (flags & MssCommunicating) {
103  }
104  if (ioctl(spifd, SPI_IOC_WR_MAX_SPEED_HZ, &freq) < 0) {
106  }
108 }
109 
110 void SpiMasterSyncSerial::setClockPeriod(unsigned int nanos) {
111  if (flags & MssCommunicating) {
113  }
114  // hold the current clock period in case of error
115  unsigned int prev = minHalfPeriod;
116  // change the clock period
118  // get the resultant frequency
119  nanos = clockFrequency();
120  // atempt to change the frequency
121  if (ioctl(spifd, SPI_IOC_WR_MAX_SPEED_HZ, &nanos) < 0) {
122  // revert the stored clock period
123  minHalfPeriod = prev;
124  // issue error
126  }
127 }
128 
130 
132 
134 
136 
138  const std::uint8_t * __restrict__ out,
139  std::uint8_t * __restrict__ in,
141 ) {
142  if (~flags & MssCommunicating) {
144  }
145  // only full bytes may be transfered; no partial bytes
146  if (bits.blocks() & 7) {
148  }
149  xfer.tx_buf = (ptrdiff_t)out;
150  xfer.rx_buf = (ptrdiff_t)in;
151  xfer.len = duds::general::Bytes(bits).blocks();
152  if (ioctl(spifd, SPI_IOC_MESSAGE(1), &xfer) < 0) {
154  }
155 }
156 
157 } } } } // namespaces
158 
unsigned int clockFrequency() const noexcept
Computes and returns the maximum clock frequency in Hertz.
static constexpr Flags MssMSbFirst
Send data MSb first, little endian.
static constexpr Flags MssCommunicating
Indicates that communication is underway.
virtual void transfer(const std::uint8_t *__restrict__ out, std::uint8_t *__restrict__ in, duds::general::Bits bits)
Moves data about.
unsigned int clockPeriod() const noexcept
Returns the minimum clock period in nanoseconds.
virtual void close()
Transitions the object from the open (MssOpen) to the ready (MssReady) state.
void setClockFrequency(unsigned int freq)
Changes the maximum clock frequency.
SpiMasterSyncSerial()
Creates the object without a SPI device to use.
unsigned int minHalfPeriod
The minimum time between changing the clock edge in nanoseconds.
static constexpr Flags MssOpen
Indicates that all required resources for communication have been acquired.
The requested mode of operation is unsupported; intended for use by implementing classes that must im...
spi_ioc_transfer xfer
Data for telling the kernel what to send and receive.
constexpr std::size_t blocks() const
Returns the size specified as a multuple of Bits.
Definition: DataSize.hpp:162
An abstraction for the master side of a simple synchronous serial communication connection to some de...
virtual void stop()
Denotes the end of a conversation; transitions from the communicating state to the open state...
static constexpr Flags MssReady
Indictates that all required resources for communication have been identified and passed a validity c...
static constexpr Flags MssOutFallInRise
Output on the falling edge of the clock and read on the rising edge.
A class to assist with specifiying the sizes of data with scaling units, much like std::chrono::durat...
Definition: DataSize.hpp:106
A transfer operation was requested when not in the communicating state.
void forceClose()
Attempts to forcibly cease communications by calling condStop() and close().
The requested operation requires communication to not already be in use.
virtual void open()
Transitions the object from the ready (MssReady) to the open (MssOpen) state.
static constexpr Flags MssClockIdleHigh
Before communication begins, and after it ends, the clock line should have a high logic level...
void setClockPeriod(unsigned int nanos)
Changes the minimum clock period.
General errors.
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
Definition: Errors.hpp:48
virtual void start()
Denotes the start of a conversation; transitions from the open state to the communicating state...
DataSize< 8 > Bytes
DataSize type for a size in bytes.
Definition: DataSize.hpp:384