DUDS
Distributed Update of Data from Something
MasterSyncSerial.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  */
13 #include <duds/general/Errors.hpp>
14 
15 namespace duds { namespace hardware { namespace interface {
16 
35 
36 MasterSyncSerial::MasterSyncSerial(Flags f, int p) : minHalfPeriod(p >> 1) {
37  flags = f & MssConfigMask;
38 }
39 
41 
43  if (flags & MssOpen) {
44  condStop();
45  }
46  close();
47 }
48 
50  if (acc == mssacc) {
51  // don't retire the access object more than once
52  acc->mss.reset();
53  // end communication
54  condStop();
55  close();
57  // lose the access object; it should be destructing
58  mssacc = nullptr;
59  } else {
60  // panic! maybe limit this to debug builds
62  }
63 }
64 
65 unsigned int MasterSyncSerial::clockFrequency() const noexcept {
66  return minHalfPeriod ? 500000000 / minHalfPeriod : 0;
67 }
68 
69 void MasterSyncSerial::clockFrequency(unsigned int freq) {
70  clockPeriod(freq ? 500000000 / freq : 0);
71 }
72 
73 void MasterSyncSerial::clockPeriod(unsigned int period) {
74  // this object must not be communicating
75  if (flags & MssCommunicating) {
77  }
78  minHalfPeriod = period;
79 }
80 
81 std::unique_ptr<MasterSyncSerialAccess> MasterSyncSerial::access() {
82  if (~flags & MssReady) {
84  }
85  if ((flags & MssOpen) || mssacc) {
87  }
88  open();
89  flags |= MssOpen;
90  return std::unique_ptr<MasterSyncSerialAccess>(mssacc =
91  new MasterSyncSerialAccess(shared_from_this()));
92 }
93 
95  if (~flags & MssReady) {
97  }
98  if ((flags & MssOpen) || mssacc) {
100  }
101  if (acc.mss) {
103  }
104  open();
105  flags |= MssOpen;
106  acc.mss = shared_from_this();
107  mssacc = &acc;
108 }
109 
110 std::unique_ptr<MasterSyncSerialAccess> MasterSyncSerial::accessStart() {
111  std::unique_ptr<MasterSyncSerialAccess> acc = access();
112  condStart();
113  return acc;
114 }
115 
117  access(acc);
118  condStart();
119 }
120 
122  /*
123  if (~flags & MssReady()) {
124  DUDS_THROW_EXCEPTION(SyncSerialNotReady());
125  }
126  */
127  if (~flags & MssOpen) {
129  }
130  if (~flags & MssCommunicating) {
131  start();
133  }
134 }
135 
137  /*
138  if (~flags & MssReady()) {
139  DUDS_THROW_EXCEPTION(SyncSerialNotReady());
140  }
141  */
142  if (~flags & MssOpen) {
144  }
145  if (flags & MssCommunicating) {
146  stop();
147  flags.clear(MssCommunicating);
148  }
149 }
150 
152  const std::uint8_t *buff,
154 ) {
155  transfer(buff, nullptr, bits);
156 }
157 
158 void MasterSyncSerial::receive(std::uint8_t *buff, duds::general::Bits bits) {
159  transfer(nullptr, buff, bits);
160 }
161 
163  // visit each conversation part
164  Conversation::PartVector::iterator iter = conv.begin();
165  for (; iter != conv.end(); ++iter) {
166  ConversationPart &cp = *(*iter);
167  // check for need to provide a break in chip selection, or similar detail
168  if (cp.flags() & ConversationPart::MpfBreak) {
169  // deselect
170  condStop();
171  }
172  // select chip if needed
173  condStart();
174  // input part?
175  if (cp.input()) {
176  receive((std::uint8_t*)cp.start(), cp.length() << 3);
177  } else {
178  transmit((std::uint8_t*)cp.start(), cp.length() << 3);
179  }
180  }
181  // all done
182  condStop();
183 }
184 
186  if (~flags & MssReady) {
188  }
189  if ((flags & MssOpen) || mssacc) {
191  }
192  open();
193  // mark as in use without memory allocations or shared pointers
194  flags |= MssOpen;
195  //mssacc = (MasterSyncSerialAccess*)(-1); // just needs to not be zero
196  // do the communication
197  try {
198  converseAlreadyOpen(conv);
199  } catch (...) {
200  // close stuff and rethrow
201  forceClose();
202  flags.clear(MssOpen);
203  throw;
204  }
205  // always close
206  close();
207  flags.clear(MssOpen);
208 }
209 
210 } } } // namespaces
unsigned int clockFrequency() const noexcept
Computes and returns the maximum clock frequency in Hertz.
static constexpr Flags MpfBreak
True/set to indicate that any kind of selection signal should be toggled, or a stop condition should ...
MasterSyncSerial()
Builds a MasterSyncSerial with an invalid clock period and all configuration flags clear...
static constexpr Flags MssSpiMode2LSb
Flags for SPI mode 2 with the LSb transfered first.
virtual void open()=0
Transitions the object from the ready (MssReady) to the open (MssOpen) state.
virtual void close()=0
Transitions the object from the open (MssOpen) to the ready (MssReady) state.
void condStop()
Calls stop() if currently communicating (set MssCommunicating flag).
static constexpr Flags MssSpiMode2
Flags for SPI mode 2.
The requested operation requires communication to be in the ready state.
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.
static constexpr Flags MssSpiMode1
Flags for SPI mode 1.
std::unique_ptr< MasterSyncSerialAccess > access()
Obtain access for communication; transitions the object from the ready (MssReady) to the open (MssOpe...
static constexpr Flags MssSpiMode1LSb
Flags for SPI mode 1 with the LSb transfered first.
duds::general::BitFlags< struct MssFlags > Flags
Configuration flags for various synchronous serial options.
unsigned int clockPeriod() const noexcept
Returns the minimum clock period in nanoseconds.
virtual void transmit(const std::uint8_t *buff, duds::general::Bits bits)
Sends bits of data.
BitFlags clear()
Clear all bits.
Definition: BitFlags.hpp:245
static constexpr Flags MssConfigMask
All the flags that are used for configuration rather than the current state.
void converseAlreadyOpen(Conversation &conv)
Has a half-duplex Conversation with the connected device.
static constexpr Flags MssSpiMode3
Flags for SPI mode 3.
virtual void converse(Conversation &conv)
Has a half-duplex Conversation with the connected device.
static constexpr Flags MssUseSelect
Use a select line to tell a device to pay attention to the master.
Represents a section of a half-duplex conversation with a device.
unsigned int minHalfPeriod
The minimum time between changing the clock edge in nanoseconds.
virtual ~MasterSyncSerial()=0
Derived class destructors should assure that communication has stopped by calling forceClose()...
static constexpr Flags MssSpiMode0
Flags for SPI mode 0.
std::unique_ptr< MasterSyncSerialAccess > accessStart()
Obtain access for communication; transitions the object from the ready (MssReady) to the communicatin...
static constexpr Flags MssOpen
Indicates that all required resources for communication have been acquired.
static constexpr Flags MssSpiMode0LSb
Flags for SPI mode 0 with the LSb transfered first.
virtual void stop()=0
Denotes the end of a conversation; transitions from the communicating state to the open state...
static std::wstring_convert< std::codecvt_utf8< char32_t >, char32_t > conv
String converter; UTF-8 to/from UTF-32.
Definition: BppFont.cpp:165
static constexpr Flags MssSpiMode3LSb
Flags for SPI mode 3 with the LSb transfered first.
Flags flags() const
Returns the flags.
virtual std::size_t length() const =0
Returns the length of the buffer following the start pointer.
virtual char * start() const =0
Returns a pointer to the begining of the conversation part&#39;s buffer.
Provides access for communicating using a MasterSyncSerial object.
std::shared_ptr< MasterSyncSerial > mss
The serial interface used by this access object.
Header for Conversarion; includes ConversationVector.hpp and ConversationExternal.hpp.
PartVector::iterator begin()
An iterator to the first ConversationPart that allows modification.
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
void forceClose()
Attempts to forcibly cease communications by calling condStop() and close().
virtual void start()=0
Denotes the start of a conversation; transitions from the open state to the communicating state...
The requested operation requires communication to not already be in use.
The requested operation requires communication to be in the open state.
MasterSyncSerialAccess * mssacc
A pointer to the current access object or nullptr.
PartVector::iterator end()
An iterator to the end of ConversationPart vector.
virtual void transfer(const std::uint8_t *__restrict__ out, std::uint8_t *__restrict__ in, duds::general::Bits bits)=0
Sends and/or receives bits of data.
static constexpr Flags MssClockIdleHigh
Before communication begins, and after it ends, the clock line should have a high logic level...
virtual void receive(std::uint8_t *buff, duds::general::Bits bits)
Receives bits of data.
static constexpr Flags MssFirstDerivedClassFlag
The first flag that may be defined by a derived class.
void condStart()
Calls start() if not currently communicating (clear MssCommunicating flag).
void retire(MasterSyncSerialAccess *acc)
Removes the access object from use.
General errors.
bool input() const
True if this part is flagged for input use.
#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
friend class MasterSyncSerialAccess
The access object calls select(), deselect(), and retire(MasterSyncSerialAccess *).
The given MasterSyncSerialAccess object already provides access to a MasterSyncSerial object...
An attempt was made to retire a MasterSyncSerialAccess object that does not belong to the serial inte...
Represents a two-way conversation with a device.