Now you can download a copy of these docs so you can use them offline! Download now
SPI.cpp
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) FIRST 2008. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5 /*----------------------------------------------------------------------------*/
6 
7 #include "SPI.h"
8 
9 #include "ChipObject/tSPI.h"
10 #include "DigitalModule.h"
11 #include "DigitalInput.h"
12 #include "DigitalOutput.h"
13 #include "NetworkCommunication/UsageReporting.h"
14 #include "Synchronized.h"
15 #include "WPIErrors.h"
16 
17 #include <math.h>
18 #include <usrLib.h>
19 
20 SEM_ID SPI::m_semaphore = NULL;
21 
32 {
33  Init(&clk, &mosi, &miso);
34 }
35 
46 {
47  Init(clk, mosi, miso);
48 }
49 
58 {
59  Init(&clk, &mosi, NULL);
60 }
61 
70 {
71  Init(clk, mosi, NULL);
72 }
73 
82 {
83  Init(&clk, NULL, &miso);
84 }
85 
94 {
95  Init(clk, NULL, miso);
96 }
97 
102 {
103  delete m_spi;
104 }
105 
115 void SPI::Init(DigitalOutput *clk, DigitalOutput *mosi, DigitalInput *miso)
116 {
117  if (m_semaphore == NULL)
118  {
119  m_semaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
120  }
121 
122  tRioStatusCode localStatus = NiFpga_Status_Success;
123  m_spi = tSPI::create(&localStatus);
124  wpi_setError(localStatus);
125 
126  m_config.BusBitWidth = 8;
127  m_config.ClockHalfPeriodDelay = 0;
128  m_config.MSBfirst = 0;
129  m_config.DataOnFalling = 0;
130  m_config.LatchFirst = 0;
131  m_config.LatchLast = 0;
132  m_config.FramePolarity = 0;
133  m_config.WriteOnly = miso ? 0 : 1;
134  m_config.ClockPolarity = 0;
135 
136  m_channels.SCLK_Channel = clk->GetChannelForRouting();
137  m_channels.SCLK_Module = clk->GetModuleForRouting();
138  m_channels.SS_Channel = 0;
139  m_channels.SS_Module = 0;
140 
141  if (mosi)
142  {
143  m_channels.MOSI_Channel = mosi->GetChannelForRouting();
144  m_channels.MOSI_Module = mosi->GetModuleForRouting();
145  }
146  else
147  {
148  m_channels.MOSI_Channel = 0;
149  m_channels.MOSI_Module = 0;
150  }
151 
152  if (miso)
153  {
154  m_channels.MISO_Channel = miso->GetChannelForRouting();
155  m_channels.MISO_Module = miso->GetModuleForRouting();
156  }
157  else
158  {
159  m_channels.MISO_Channel = 0;
160  m_channels.MISO_Module = 0;
161  }
162 
163  m_ss = NULL;
164 
165  static int32_t instances = 0;
166  instances++;
167  nUsageReporting::report(nUsageReporting::kResourceType_SPI, instances);
168 }
169 
176 void SPI::SetBitsPerWord(uint32_t bits)
177 {
178  m_config.BusBitWidth = bits;
179 }
180 
188 {
189  return m_config.BusBitWidth;
190 }
191 
198 void SPI::SetClockRate(double hz)
199 {
200  int delay = 0;
201  tRioStatusCode localStatus = NiFpga_Status_Success;
202  int loopTiming = DigitalModule::GetInstance(m_spi->readChannels_SCLK_Module(&localStatus))->GetLoopTiming();
203  wpi_setError(localStatus);
204  double v = (1.0 / hz) / (2 * loopTiming / (kSystemClockTicksPerMicrosecond * 1e6));
205  if (v < 1) {
206  wpi_setWPIErrorWithContext(ParameterOutOfRange, "SPI Clock too high");
207  }
208  delay = (int) (v + .5);
209  if (delay > 255) {
210  wpi_setWPIErrorWithContext(ParameterOutOfRange, "SPI Clock too low");
211  }
212 
213  m_config.ClockHalfPeriodDelay = delay;
214 }
215 
221 {
222  m_config.MSBfirst = 1;
223 }
224 
230 {
231  m_config.MSBfirst = 0;
232 }
233 
239 {
240  m_config.DataOnFalling = 1;
241 }
242 
248 {
249  m_config.DataOnFalling = 0;
250 }
251 
263 void SPI::SetSlaveSelect(DigitalOutput *ss, tFrameMode mode, bool activeLow)
264 {
265  if (ss)
266  {
267  m_channels.SS_Channel = ss->GetChannelForRouting();
268  m_channels.SS_Module = ss->GetModuleForRouting();
269  }
270  else
271  {
272  m_channels.SS_Channel = 0;
273  m_channels.SS_Module = 0;
274  }
275  m_ss = ss;
276 
277  switch (mode)
278  {
279  case kChipSelect:
280  m_config.LatchFirst = 0;
281  m_config.LatchLast = 0;
282  break;
283  case kPreLatchPulse:
284  m_config.LatchFirst = 1;
285  m_config.LatchLast = 0;
286  break;
287  case kPostLatchPulse:
288  m_config.LatchFirst = 0;
289  m_config.LatchLast = 1;
290  break;
291  case kPreAndPostLatchPulse:
292  m_config.LatchFirst = 1;
293  m_config.LatchLast = 1;
294  break;
295  }
296 
297  m_config.FramePolarity = activeLow ? 1 : 0;
298 }
299 
311 void SPI::SetSlaveSelect(DigitalOutput &ss, tFrameMode mode, bool activeLow)
312 {
313  SetSlaveSelect(&ss, mode, activeLow);
314 }
315 
327 DigitalOutput *SPI::GetSlaveSelect(tFrameMode *mode, bool *activeLow)
328 {
329  if (mode != NULL)
330  {
331  *mode = (tFrameMode) (m_config.LatchFirst | (m_config.LatchLast << 1));
332  }
333  if (activeLow != NULL)
334  {
335  *activeLow = m_config.FramePolarity != 0;
336  }
337  return m_ss;
338 }
339 
345 {
346  m_config.ClockPolarity = 1;
347 }
348 
354 {
355  m_config.ClockPolarity = 0;
356 }
357 
362 {
363  Synchronized sync(m_semaphore);
364 
365  tRioStatusCode localStatus = NiFpga_Status_Success;
366  m_spi->writeConfig(m_config, &localStatus);
367  m_spi->writeChannels(m_channels, &localStatus);
368  m_spi->strobeReset(&localStatus);
369  wpi_setError(localStatus);
370 }
371 
379 {
380  tRioStatusCode localStatus = NiFpga_Status_Success;
381  uint16_t result = m_spi->readAvailableToLoad(&localStatus);
382  wpi_setError(localStatus);
383  return result;
384 }
385 
393 {
394  tRioStatusCode localStatus = NiFpga_Status_Success;
395  uint16_t result = m_spi->readReceivedElements(&localStatus);
396  wpi_setError(localStatus);
397  return result;
398 }
399 
406 {
407  tRioStatusCode localStatus = NiFpga_Status_Success;
408  bool result = m_spi->readStatus_Idle(&localStatus);
409  wpi_setError(localStatus);
410  return result;
411 }
412 
420 {
421  tRioStatusCode localStatus = NiFpga_Status_Success;
422  bool result = m_spi->readStatus_ReceivedDataOverflow(&localStatus);
423  wpi_setError(localStatus);
424  return result;
425 }
426 
434 void SPI::Write(uint32_t data)
435 {
436  if (m_channels.MOSI_Channel == 0 && m_channels.MOSI_Module == 0)
437  {
438  wpi_setWPIError(SPIWriteNoMOSI);
439  return;
440  }
441 
442  Synchronized sync(m_semaphore);
443 
444  while (GetOutputFIFOAvailable() == 0)
445  taskDelay(NO_WAIT);
446 
447  tRioStatusCode localStatus = NiFpga_Status_Success;
448  m_spi->writeDataToLoad(data, &localStatus);
449  m_spi->strobeLoad(&localStatus);
450  wpi_setError(localStatus);
451 }
452 
466 uint32_t SPI::Read(bool initiate)
467 {
468  if (m_channels.MISO_Channel == 0 && m_channels.MISO_Module == 0)
469  {
470  wpi_setWPIError(SPIReadNoMISO);
471  return 0;
472  }
473 
474  tRioStatusCode localStatus = NiFpga_Status_Success;
475  uint32_t data;
476  {
477  Synchronized sync(m_semaphore);
478 
479  if (initiate)
480  {
481  m_spi->writeDataToLoad(0, &localStatus);
482  m_spi->strobeLoad(&localStatus);
483  }
484 
485  // Do we have anything ready to read?
486  if (GetNumReceived() == 0)
487  {
488  if (!initiate && IsDone() && GetOutputFIFOAvailable() == kTransmitFIFODepth)
489  {
490  // Nothing to read: error out
491  wpi_setWPIError(SPIReadNoData);
492  return 0;
493  }
494 
495  // Wait for the transaction to complete
496  while (GetNumReceived() == 0)
497  taskDelay(NO_WAIT);
498  }
499 
500  m_spi->strobeReadReceivedData(&localStatus);
501  data = m_spi->readReceivedData(&localStatus);
502  }
503  wpi_setError(localStatus);
504 
505  return data;
506 }
507 
512 {
513  tRioStatusCode localStatus = NiFpga_Status_Success;
514  m_spi->strobeReset(&localStatus);
515  wpi_setError(localStatus);
516 }
517 
522 {
523  tRioStatusCode localStatus = NiFpga_Status_Success;
524  m_spi->strobeClearReceivedData(&localStatus);
525  wpi_setError(localStatus);
526 }
virtual void Reset()
Definition: SPI.cpp:511
virtual bool IsDone()
Definition: SPI.cpp:405
uint32_t GetBitsPerWord()
Definition: SPI.cpp:187
void SetSampleDataOnFalling()
Definition: SPI.cpp:238
SPI(DigitalOutput &clk, DigitalOutput &mosi, DigitalInput &miso)
Definition: SPI.cpp:31
virtual uint32_t GetModuleForRouting()
virtual uint16_t GetNumReceived()
Definition: SPI.cpp:392
void SetClockActiveHigh()
Definition: SPI.cpp:353
virtual ~SPI()
Definition: SPI.cpp:101
virtual uint32_t GetModuleForRouting()
void SetSlaveSelect(DigitalOutput *ss, tFrameMode mode=kChipSelect, bool activeLow=false)
Definition: SPI.cpp:263
void SetSampleDataOnRising()
Definition: SPI.cpp:247
virtual uint32_t Read(bool initiate=false)
Definition: SPI.cpp:466
bool HadReceiveOverflow()
Definition: SPI.cpp:419
virtual void ClearReceivedData()
Definition: SPI.cpp:521
virtual void Write(uint32_t data)
Definition: SPI.cpp:434
void SetClockActiveLow()
Definition: SPI.cpp:344
void SetBitsPerWord(uint32_t bits)
Definition: SPI.cpp:176
virtual uint32_t GetChannelForRouting()
static DigitalModule * GetInstance(uint8_t moduleNumber)
void SetClockRate(double hz)
Definition: SPI.cpp:198
virtual uint32_t GetChannelForRouting()
virtual void ApplyConfig()
Definition: SPI.cpp:361
virtual uint16_t GetOutputFIFOAvailable()
Definition: SPI.cpp:378
DigitalOutput * GetSlaveSelect(tFrameMode *mode=NULL, bool *activeLow=NULL)
Definition: SPI.cpp:327
void SetLSBFirst()
Definition: SPI.cpp:229
void SetMSBFirst()
Definition: SPI.cpp:220

Generated on Sat Apr 26 2014 12:26:45 for WPILibC++ by doxygen 1.8.6