DUDS
Distributed Update of Data from Something
DigitalPinMasterSyncSerial.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/hardware/interface/DigitalPinMasterSyncSerial.hpp>
13 #include <chrono>
14 #include <thread>
15 
16 // nanos: the time of fate
17 static void nanodelay(int nanos) {
18  std::this_thread::sleep_for(std::chrono::nanoseconds(nanos));
19 }
20 
21 namespace duds { namespace hardware { namespace interface {
22 
24 clk(-1), dat(-1), datI(-1) { }
25 
27 MasterSyncSerial(flags, period) { }
28 
30  const DigitalPinSet &pset,
31  Flags flags,
32  int period
33 ) : MasterSyncSerial(flags, period), pins(pset) { }
34 
36  DigitalPinSet &&pset,
37  Flags flags,
38  int period
39 ) : MasterSyncSerial(flags, period), pins(std::move(pset)) { }
40 
42  forceClose();
43 }
44 
46  // there must be 2 pins for half-duplex, 3 for full duplex
47  if (((cfg & MssFullDuplex) && (ps.size() != 3)) || (ps.size() != 2)) {
49  }
50  // get the capabilities for inspection
51  std::vector<DigitalPinCap> caps = ps.capabilities();
52  // clock
53  if (!caps[ClockPin].canBeOutput()) {
56  );
57  }
58  if (cfg & MssFullDuplex) {
59  if (!caps[OutputPin].canBeOutput()) {
61  PinErrorName("output") << PinErrorId(ps.globalId(OutputPin))
62  );
63  }
64  if (!caps[InputPin].canBeInput()) {
66  PinErrorName("input") << PinErrorId(ps.globalId(InputPin))
67  );
68  }
69  } else { // half-duplex
70  if (!caps[DataPin].canBeInput() || !caps[DataPin].canBeOutput()) {
72  PinErrorName("data") << PinErrorId(ps.globalId(DataPin))
73  );
74  }
75  }
76 }
77 
78 // ----- old below this line -----
79 
80 void DigitalPinMasterSyncSerial::setPins(const PinIndex &pi) {
81  if (flags & MssOpen) {
83  }
84  static const std::string names[4] = {
85  std::string("clock"),
86  std::string("data"),
87  std::string("output"),
88  std::string("input"),
89  };
90  std::string find[3];
91  find[0] = names[0];
92  if (flags & MssFullDuplex) {
93  find[1] = names[2];
94  find[2] = names[3];
95  pi.pinNumbers(find + 0, find + 3, pins, 3);
96  } else {
97  find[1] = names[1];
98  pi.pinNumbers(find + 0, find + 2, pins, 2);
99  pins[2] = -1;
100  }
101  std::shared_ptr<PinStore> nps = pi.store();
102  try {
103  // assure usable pins
104  checkPins(nps, clk, dat, datI);
105  } catch (...) {
106  // remove pin IDs
107  clk = dat = datI = -1;
108  throw;
109  }
110  store = std::move(nps);
111  // ready?
112  if ((flags & MssUseSelect) && sel.usable()) {
113  flags |= MssReady;
114  }
115 }
116 
118  const std::shared_ptr<PinStore> &ps,
119  unsigned int clock,
120  unsigned int data
121 ) {
122  // this function is for half-duplex operation; fail on full-duplex
123  if (flags & MssFullDuplex) {
125  }
126  if (flags & MssOpen) {
128  }
129  checkPins(ps, clock, data, -1);
130  clk = clock;
131  dat = data;
132  datI = -1;
133  store = ps;
134  // ready?
135  if ((flags & MssUseSelect) && sel.usable()) {
136  flags |= MssReady;
137  }
138 }
139 
141  const std::shared_ptr<PinStore> &ps,
142  unsigned int clock,
143  unsigned int output,
144  unsigned int input
145 ) {
146  // this function is for full-duplex operation; fail on half-duplex
147  if (~flags & MssFullDuplex) {
149  }
150  if (flags & MssOpen) {
152  }
153  checkPins(ps, clock, output, input);
154  clk = clock;
155  dat = output;
156  datI = input;
157  store = ps;
158  // ready?
159  if ((flags & MssUseSelect) && sel.usable()) {
160  flags |= MssReady;
161  }
162 }
163 
165  if (~flags & MssUseSelect) {
167  ChipSelectIdError(cs.chipId()));
168  }
169  if (flags & MssOpen) {
171  }
172  if (!cs.haveManager()) {
174  ChipSelectIdError(cs.chipId()));
175  }
176  if (!cs.configured()) {
178  ChipSelectIdError(cs.chipId()));
179  }
180  sel = cs;
181  // ready?
182  if ((clk != -1) && (dat != -1) &&
183  ((~flags & MssFullDuplex) || (datI != -1))) {
184  flags |= MssReady;
185  }
186 }
187 
190 }
191 
192 void DigitalPinMasterSyncSerial::clockPeriod(unsigned int nanos) {
194 }
195 
197  // obtain access to pins
198  store->access(acc, pins, 3);
199  // obtain select
200  if (sel) {
201  sel.access(chipAcc);
202  }
203  // set clock idle state
204  acc[0].setOutput();
205  acc[0].setState(flags & MssClockIdleHigh);
206  // for full-duplex . . .
207  if (flags & MssFullDuplex) {
208  // . . . set I/O direction for data pins
209  acc[1].setOutput();
210  acc[2].setInput();
211  }
212 }
213 
215  for (int loop = 2; loop >= 0; loop--) {
216  acc[loop].retire();
217  }
218  chipAcc.retire();
219 }
220 
222  // using a select line?
223  if (sel) {
224  // select the gizmo-thingy
225  chipAcc.select();
227  }
228 }
229 
231  // using a select line?
232  if (sel) {
233  // deselect the gizmo-thingy
234  chipAcc.deselect();
235  }
236  // set clock idle state
237  acc[0].setState(flags & MssClockIdleHigh);
239 }
240 
242  const std::uint8_t * __restrict__ out,
243  std::uint8_t * __restrict__ in,
244  int bits
245 ) {
246  if (sel && (~flags & MssCommunicating)) {
248  }
249  DigitalPinAccess &inpin = (flags & MssFullDuplex) ? acc[2] : acc[1];
250  const std::uint8_t *outpos = out;
251  int extrabits = 0;
252  std::uint8_t *inpos = in;
253  std::uint8_t bitpos;
254  bool inbit;
255  // half-duplex?
256  if (~flags & MssFullDuplex) {
257  // either full duplex communication is used, or one of the buffers is NULL
258  if (in && out) {
260  }
261  // set data pin I/O direction
262  if (out) {
263  acc[1].setOutput();
264  } else {
265  acc[1].setInput();
266  }
267  }
268  // MSb first?
269  if (flags & MssMSbFirst) {
270  bitpos = 0x80;
271  } else { // LSb first
272  inpos += bits / 8;
273  outpos += bits / 8;
274  extrabits = bits % 8;
275  if (extrabits == 0) {
276  inpos--;
277  outpos--;
278  bitpos = 1;
279  } else {
280  bitpos = 0x80 >> (extrabits - 1);
281  }
282  }
283  for (; bits; bits--) {
284  // output next bit
285  if (out) {
286  acc[1].setState(*outpos & bitpos);
287  }
288  // transition the clock
289  acc[0].setState(~flags & MssOutFallInRise);
290  // provide time
292  // in case of input
293  if (in) {
294  // check input state
295  if (inpin.getState()) { // set bit
296  *inpos |= bitpos;
297  } else { // clear bit
298  *inpos &= ~bitpos;
299  }
300  }
301  // transition the clock
302  acc[0].setState(flags & MssOutFallInRise);
303  // provide time
305  // advance to next bit
306  if (flags & MssMSbFirst) {
307  if (!(bitpos >>= 1)) {
308  bitpos = 0x80;
309  inpos++;
310  outpos++;
311  }
312  } else {
313  if (!(bitpos <<= 1)) {
314  bitpos = 1;
315  inpos--;
316  outpos--;
317  }
318  }
319  }
320  // in case of LSb first extra bits . . .
321  if (in && extrabits) {
322  // . . . shift down the MSB so the MSb's are not used and the LSb's are
323  // all received bits
324  in[0] >>= 8 - extrabits;
325  }
326 }
327 
328 } } } // namespaces
329 
unsigned int clockFrequency() const noexcept
Computes and returns the maximum clock frequency in Hertz.
A full-duplex configuration or data transfer operation was requested on a half-duplex serial interfac...
A chip select object was specified on a serial interface that does not use a chip select...
int chipId() const
Returns the chip ID of the chip this object will select.
Definition: ChipSelect.hpp:125
unsigned int dat
The pin ID for data, output if full-duplex.
boost::error_info< struct Info_PinName, std::string > PinErrorName
A name or function associated with the pin(s).
Definition: PinErrors.hpp:89
boost::error_info< struct Info_ChipId, int > ChipSelectIdError
The chip select ID relavent to the error.
static constexpr Flags MssMSbFirst
Send data MSb first, little endian.
static constexpr Flags MssFullDuplex
Communication is full duplex.
static constexpr Flags MssCommunicating
Indicates that communication is underway.
void setPins(const PinIndex &pi)
Sets the pins to use based on names already set in the PinIndex.
The operation has too few or much data to work on the pins, which can alternately be stated as having...
Definition: PinErrors.hpp:50
unsigned int clockPeriod() const noexcept
Returns the minimum clock period in nanoseconds.
STL namespace.
move_impl move(unsigned int c, unsigned int r)
Display stream manipulator that moves the display cursor to the given location.
The requested operation is not supported by the specific pin.
Definition: PinErrors.hpp:38
virtual void open()
Gets the required access objects.
boost::error_info< struct Info_PinId, unsigned int > PinErrorId
The pin global ID involved in the error.
Definition: PinErrors.hpp:97
DigitalPinCap capabilities(unsigned int pos) const
Returns the capabilities of the specified pin.
bool configured() const
Returns true if this object was configured with a chip to select.
Definition: ChipSelect.hpp:112
static constexpr Flags MssUseSelect
Use a select line to tell a device to pay attention to the master.
An object to wrap together a ChipSelectManager and chip ID to simplify code that needs to repeatedly ...
Definition: ChipSelect.hpp:24
virtual void stop()
Deselects the device and assures the clock is in the idle state.
unsigned int minHalfPeriod
The minimum time between changing the clock edge in nanoseconds.
bool haveManager() const
Returns true if this object has an associated manager.
Definition: ChipSelect.hpp:100
unsigned int size() const
Returns the number of pins in this object.
A half-duplex configuration was requested on a full-duplex serial interface.
Represents a set of pins on a single DigitalPort.
static constexpr Flags MssOpen
Indicates that all required resources for communication have been acquired.
virtual void close()
Relinquishes the access objects.
A ChipSelectManager is required for the operation but is not set.
virtual void start()
Selects the device, which may be the same as doing nothing.
Provides access to a single pin on a DigitalPort.
void deselect()
Deselects the chip.
Definition: ChipAccess.hpp:69
ChipSelect sel
Chip selection for serial interfaces that require it.
virtual void transfer(const std::uint8_t *__restrict__ out, std::uint8_t *__restrict__ in, int bits)
Moves data about.
std::unique_ptr< ChipAccess > access()
Obtains a ChipAccess object.
Definition: ChipSelect.cpp:32
An abstraction for the master side of a simple synchronous serial communication connection to some de...
void retire()
Relinquish access.
Definition: ChipAccess.hpp:54
static void nanodelay(int nanos)
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 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.
std::shared_ptr< PinStore > store
The store of pins that manages the pins used by this serial interface.
static constexpr Flags MssClockIdleHigh
Before communication begins, and after it ends, the clock line should have a high logic level...
unsigned int globalId(unsigned int pos) const
Returns the global pin ID of the pin at the given position inside this set of pins.
ChipAccess chipAcc
Chip access for for serial interfaces that require chip selection.
static void checkPins(const DigitalPinSet &ps, Flags cfg)
Checks the pins&#39; capabilities to assure they can be used in the intended role.
Indicates an attempt to select a non-existant chip.
void setChipSelect(const ChipSelect &cs)
Sets the ChipSelect object to use for selections.
unsigned int datI
The pin ID for data input if full-duplex.
void select()
Selects the chip.
Definition: ChipAccess.hpp:63
#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