Now you can download a copy of these docs so you can use them offline! Download now
Counter.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 "Counter.h"
8 #include "AnalogTrigger.h"
9 #include "DigitalInput.h"
10 #include "NetworkCommunication/UsageReporting.h"
11 #include "Resource.h"
12 #include "WPIErrors.h"
13 
14 static Resource *counters = NULL;
15 
20 void Counter::InitCounter(Mode mode)
21 {
22  m_table = NULL;
23  Resource::CreateResourceObject(&counters, tCounter::kNumSystems);
24  uint32_t index = counters->Allocate("Counter");
25  if (index == ~0ul)
26  {
27  CloneError(counters);
28  return;
29  }
30  m_index = index;
31  tRioStatusCode localStatus = NiFpga_Status_Success;
32  m_counter = tCounter::create(m_index, &localStatus);
33  m_counter->writeConfig_Mode(mode, &localStatus);
34  m_upSource = NULL;
35  m_downSource = NULL;
36  m_allocatedUpSource = false;
37  m_allocatedDownSource = false;
38  m_counter->writeTimerConfig_AverageSize(1, &localStatus);
39  wpi_setError(localStatus);
40 
41  nUsageReporting::report(nUsageReporting::kResourceType_Counter, index, mode);
42 }
43 
50  m_upSource(NULL),
51  m_downSource(NULL),
52  m_counter(NULL)
53 {
54  InitCounter();
55 }
56 
63  m_upSource(NULL),
64  m_downSource(NULL),
65  m_counter(NULL)
66 {
67  InitCounter();
68  SetUpSource(source);
70 }
71 
73  m_upSource(NULL),
74  m_downSource(NULL),
75  m_counter(NULL)
76 {
77  InitCounter();
78  SetUpSource(&source);
80 }
81 
86 Counter::Counter(uint32_t channel) :
87  m_upSource(NULL),
88  m_downSource(NULL),
89  m_counter(NULL)
90 {
91  InitCounter();
92  SetUpSource(channel);
94 }
95 
102 Counter::Counter(uint8_t moduleNumber, uint32_t channel) :
103  m_upSource(NULL),
104  m_downSource(NULL),
105  m_counter(NULL)
106 {
107  InitCounter();
108  SetUpSource(moduleNumber, channel);
109  ClearDownSource();
110 }
111 
118  m_upSource(NULL),
119  m_downSource(NULL),
120  m_counter(NULL)
121 {
122  InitCounter();
123  SetUpSource(trigger->CreateOutput(AnalogTriggerOutput::kState));
124  ClearDownSource();
125  m_allocatedUpSource = true;
126 }
127 
129  m_upSource(NULL),
130  m_downSource(NULL),
131  m_counter(NULL)
132 {
133  InitCounter();
134  SetUpSource(trigger.CreateOutput(AnalogTriggerOutput::kState));
135  ClearDownSource();
136  m_allocatedUpSource = true;
137 }
138 
139 Counter::Counter(EncodingType encodingType, DigitalSource *upSource, DigitalSource *downSource, bool inverted) :
140  m_upSource(NULL),
141  m_downSource(NULL),
142  m_counter(NULL)
143 {
144  if (encodingType != k1X && encodingType != k2X)
145  {
146  wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports 1X and 2X quadrature decoding.");
147  return;
148  }
149  InitCounter(kExternalDirection);
150  SetUpSource(upSource);
151  SetDownSource(downSource);
152  tRioStatusCode localStatus = NiFpga_Status_Success;
153 
154  if (encodingType == k1X)
155  {
156  SetUpSourceEdge(true, false);
157  m_counter->writeTimerConfig_AverageSize(1, &localStatus);
158  }
159  else
160  {
161  SetUpSourceEdge(true, true);
162  m_counter->writeTimerConfig_AverageSize(2, &localStatus);
163  }
164 
165  wpi_setError(localStatus);
166  SetDownSourceEdge(inverted, true);
167 }
168 
173 {
174  SetUpdateWhenEmpty(true);
175  if (m_allocatedUpSource)
176  {
177  delete m_upSource;
178  m_upSource = NULL;
179  }
180  if (m_allocatedDownSource)
181  {
182  delete m_downSource;
183  m_downSource = NULL;
184  }
185  delete m_counter;
186  m_counter = NULL;
187  counters->Free(m_index);
188 }
189 
196 void Counter::SetUpSource(uint8_t moduleNumber, uint32_t channel)
197 {
198  if (StatusIsFatal()) return;
199  SetUpSource(new DigitalInput(moduleNumber, channel));
200  m_allocatedUpSource = true;
201 }
202 
207 void Counter::SetUpSource(uint32_t channel)
208 {
209  if (StatusIsFatal()) return;
210  SetUpSource(GetDefaultDigitalModule(), channel);
211  m_allocatedUpSource = true;
212 }
213 
219 void Counter::SetUpSource(AnalogTrigger *analogTrigger, AnalogTriggerOutput::Type triggerType)
220 {
221  if (StatusIsFatal()) return;
222  SetUpSource(analogTrigger->CreateOutput(triggerType));
223  m_allocatedUpSource = true;
224 }
225 
231 void Counter::SetUpSource(AnalogTrigger &analogTrigger, AnalogTriggerOutput::Type triggerType)
232 {
233  SetUpSource(&analogTrigger, triggerType);
234 }
235 
241 {
242  if (StatusIsFatal()) return;
243  if (m_allocatedUpSource)
244  {
245  delete m_upSource;
246  m_upSource = NULL;
247  m_allocatedUpSource = false;
248  }
249  m_upSource = source;
250  if (m_upSource->StatusIsFatal())
251  {
252  CloneError(m_upSource);
253  }
254  else
255  {
256  tRioStatusCode localStatus = NiFpga_Status_Success;
257  m_counter->writeConfig_UpSource_Module(source->GetModuleForRouting(), &localStatus);
258  m_counter->writeConfig_UpSource_Channel(source->GetChannelForRouting(), &localStatus);
259  m_counter->writeConfig_UpSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &localStatus);
260 
261  if(m_counter->readConfig_Mode(&localStatus) == kTwoPulse ||
262  m_counter->readConfig_Mode(&localStatus) == kExternalDirection)
263  {
264  SetUpSourceEdge(true, false);
265  }
266  m_counter->strobeReset(&localStatus);
267  wpi_setError(localStatus);
268  }
269 }
270 
276 {
277  SetUpSource(&source);
278 }
279 
284 void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge)
285 {
286  if (StatusIsFatal()) return;
287  if (m_upSource == NULL)
288  {
289  wpi_setWPIErrorWithContext(NullParameter, "Must set non-NULL UpSource before setting UpSourceEdge");
290  }
291  tRioStatusCode localStatus = NiFpga_Status_Success;
292  m_counter->writeConfig_UpRisingEdge(risingEdge, &localStatus);
293  m_counter->writeConfig_UpFallingEdge(fallingEdge, &localStatus);
294  wpi_setError(localStatus);
295 }
296 
301 {
302  if (StatusIsFatal()) return;
303  if (m_allocatedUpSource)
304  {
305  delete m_upSource;
306  m_upSource = NULL;
307  m_allocatedUpSource = false;
308  }
309  tRioStatusCode localStatus = NiFpga_Status_Success;
310  bool state = m_counter->readConfig_Enable(&localStatus);
311  m_counter->writeConfig_Enable(false, &localStatus);
312  m_counter->writeConfig_UpFallingEdge(false, &localStatus);
313  m_counter->writeConfig_UpRisingEdge(false, &localStatus);
314  // Index 0 of digital is always 0.
315  m_counter->writeConfig_UpSource_Channel(0, &localStatus);
316  m_counter->writeConfig_UpSource_AnalogTrigger(false, &localStatus);
317  m_counter->writeConfig_Enable(state, &localStatus);
318  wpi_setError(localStatus);
319 }
320 
325 void Counter::SetDownSource(uint32_t channel)
326 {
327  if (StatusIsFatal()) return;
328  SetDownSource(new DigitalInput(channel));
329  m_allocatedDownSource = true;
330 }
331 
338 void Counter::SetDownSource(uint8_t moduleNumber, uint32_t channel)
339 {
340  if (StatusIsFatal()) return;
341  SetDownSource(new DigitalInput(moduleNumber, channel));
342  m_allocatedDownSource = true;
343 }
344 
350 void Counter::SetDownSource(AnalogTrigger *analogTrigger, AnalogTriggerOutput::Type triggerType)
351 {
352  if (StatusIsFatal()) return;
353  SetDownSource(analogTrigger->CreateOutput(triggerType));
354  m_allocatedDownSource = true;
355 }
356 
362 void Counter::SetDownSource(AnalogTrigger &analogTrigger, AnalogTriggerOutput::Type triggerType)
363 {
364  SetDownSource(&analogTrigger, triggerType);
365 }
366 
372 {
373  if (StatusIsFatal()) return;
374  if (m_allocatedDownSource)
375  {
376  delete m_downSource;
377  m_downSource = NULL;
378  m_allocatedDownSource = false;
379  }
380  m_downSource = source;
382  {
383  CloneError(m_downSource);
384  }
385  else
386  {
387  tRioStatusCode localStatus = NiFpga_Status_Success;
388  unsigned char mode = m_counter->readConfig_Mode(&localStatus);
389  if (mode != kTwoPulse && mode != kExternalDirection)
390  {
391  wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports DownSource in TwoPulse and ExternalDirection modes.");
392  return;
393  }
394  m_counter->writeConfig_DownSource_Module(source->GetModuleForRouting(), &localStatus);
395  m_counter->writeConfig_DownSource_Channel(source->GetChannelForRouting(), &localStatus);
396  m_counter->writeConfig_DownSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &localStatus);
397 
398  SetDownSourceEdge(true, false);
399  m_counter->strobeReset(&localStatus);
400  wpi_setError(localStatus);
401  }
402 }
403 
409 {
410  SetDownSource(&source);
411 }
412 
417 void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge)
418 {
419  if (StatusIsFatal()) return;
420  if (m_downSource == NULL)
421  {
422  wpi_setWPIErrorWithContext(NullParameter, "Must set non-NULL DownSource before setting DownSourceEdge");
423  }
424  tRioStatusCode localStatus = NiFpga_Status_Success;
425  m_counter->writeConfig_DownRisingEdge(risingEdge, &localStatus);
426  m_counter->writeConfig_DownFallingEdge(fallingEdge, &localStatus);
427  wpi_setError(localStatus);
428 }
429 
434 {
435  if (StatusIsFatal()) return;
436  if (m_allocatedDownSource)
437  {
438  delete m_downSource;
439  m_downSource = NULL;
440  m_allocatedDownSource = false;
441  }
442  tRioStatusCode localStatus = NiFpga_Status_Success;
443  bool state = m_counter->readConfig_Enable(&localStatus);
444  m_counter->writeConfig_Enable(false, &localStatus);
445  m_counter->writeConfig_DownFallingEdge(false, &localStatus);
446  m_counter->writeConfig_DownRisingEdge(false, &localStatus);
447  // Index 0 of digital is always 0.
448  m_counter->writeConfig_DownSource_Channel(0, &localStatus);
449  m_counter->writeConfig_DownSource_AnalogTrigger(false, &localStatus);
450  m_counter->writeConfig_Enable(state, &localStatus);
451  wpi_setError(localStatus);
452 }
453 
459 {
460  if (StatusIsFatal()) return;
461  tRioStatusCode localStatus = NiFpga_Status_Success;
462  m_counter->writeConfig_Mode(kTwoPulse, &localStatus);
463  wpi_setError(localStatus);
464 }
465 
472 {
473  if (StatusIsFatal()) return;
474  tRioStatusCode localStatus = NiFpga_Status_Success;
475  m_counter->writeConfig_Mode(kExternalDirection, &localStatus);
476  wpi_setError(localStatus);
477 }
478 
483 void Counter::SetSemiPeriodMode(bool highSemiPeriod)
484 {
485  if (StatusIsFatal()) return;
486  tRioStatusCode localStatus = NiFpga_Status_Success;
487  m_counter->writeConfig_Mode(kSemiperiod, &localStatus);
488  m_counter->writeConfig_UpRisingEdge(highSemiPeriod, &localStatus);
489  SetUpdateWhenEmpty(false);
490  wpi_setError(localStatus);
491 }
492 
498 void Counter::SetPulseLengthMode(float threshold)
499 {
500  if (StatusIsFatal()) return;
501  tRioStatusCode localStatus = NiFpga_Status_Success;
502  m_counter->writeConfig_Mode(kPulseLength, &localStatus);
503  m_counter->writeConfig_PulseLengthThreshold((uint32_t)(threshold * 1.0e6) * kSystemClockTicksPerMicrosecond, &localStatus);
504  wpi_setError(localStatus);
505 }
506 
507 
515  {
516  tRioStatusCode localStatus = NiFpga_Status_Success;
517  return m_counter->readTimerConfig_AverageSize(&localStatus);
518  wpi_setError(localStatus);
519  }
520 
527  void Counter::SetSamplesToAverage (int samplesToAverage) {
528  tRioStatusCode localStatus = NiFpga_Status_Success;
529  if (samplesToAverage < 1 || samplesToAverage > 127)
530  {
531  wpi_setWPIErrorWithContext(ParameterOutOfRange, "Average counter values must be between 1 and 127");
532  }
533  m_counter->writeTimerConfig_AverageSize(samplesToAverage, &localStatus);
534  wpi_setError(localStatus);
535  }
536 
543 {
544  if (StatusIsFatal()) return;
545  tRioStatusCode localStatus = NiFpga_Status_Success;
546  m_counter->writeConfig_Enable(1, &localStatus);
547  wpi_setError(localStatus);
548 }
549 
555 int32_t Counter::Get()
556 {
557  if (StatusIsFatal()) return 0;
558  tRioStatusCode localStatus = NiFpga_Status_Success;
559  int32_t value = m_counter->readOutput_Value(&localStatus);
560  wpi_setError(localStatus);
561  return value;
562 }
563 
570 {
571  if (StatusIsFatal()) return;
572  tRioStatusCode localStatus = NiFpga_Status_Success;
573  m_counter->strobeReset(&localStatus);
574  wpi_setError(localStatus);
575 }
576 
582 {
583  if (StatusIsFatal()) return;
584  tRioStatusCode localStatus = NiFpga_Status_Success;
585  m_counter->writeConfig_Enable(0, &localStatus);
586  wpi_setError(localStatus);
587 }
588 
589 /*
590  * Get the Period of the most recent count.
591  * Returns the time interval of the most recent count. This can be used for velocity calculations
592  * to determine shaft speed.
593  * @returns The period of the last two pulses in units of seconds.
594  */
595 double Counter::GetPeriod()
596 {
597  if (StatusIsFatal()) return 0.0;
598  tRioStatusCode localStatus = NiFpga_Status_Success;
599  tCounter::tTimerOutput output = m_counter->readTimerOutput(&localStatus);
600  double period;
601  if (output.Stalled)
602  {
603  // Return infinity
604  double zero = 0.0;
605  period = 1.0 / zero;
606  }
607  else
608  {
609  // output.Period is a fixed point number that counts by 2 (24 bits, 25 integer bits)
610  period = (double)(output.Period << 1) / (double)output.Count;
611  }
612  wpi_setError(localStatus);
613  return period * 1.0e-6;
614 }
615 
623 void Counter::SetMaxPeriod(double maxPeriod)
624 {
625  if (StatusIsFatal()) return;
626  tRioStatusCode localStatus = NiFpga_Status_Success;
627  m_counter->writeTimerConfig_StallPeriod((uint32_t)(maxPeriod * 1.0e6), &localStatus);
628  wpi_setError(localStatus);
629 }
630 
643 void Counter::SetUpdateWhenEmpty(bool enabled)
644 {
645  if (StatusIsFatal()) return;
646  tRioStatusCode localStatus = NiFpga_Status_Success;
647  m_counter->writeTimerConfig_UpdateWhenEmpty(enabled, &localStatus);
648  wpi_setError(localStatus);
649 }
650 
660 {
661  if (StatusIsFatal()) return false;
662  tRioStatusCode localStatus = NiFpga_Status_Success;
663  return m_counter->readTimerOutput_Stalled(&localStatus);
664  wpi_setError(localStatus);
665 }
666 
672 {
673  if (StatusIsFatal()) return false;
674  tRioStatusCode localStatus = NiFpga_Status_Success;
675  bool value = m_counter->readOutput_Direction(&localStatus);
676  wpi_setError(localStatus);
677  return value;
678 }
679 
686 void Counter::SetReverseDirection(bool reverseDirection)
687 {
688  if (StatusIsFatal()) return;
689  tRioStatusCode localStatus = NiFpga_Status_Success;
690  if (m_counter->readConfig_Mode(&localStatus) == kExternalDirection)
691  {
692  if (reverseDirection)
693  SetDownSourceEdge(true, true);
694  else
695  SetDownSourceEdge(false, true);
696  }
697  wpi_setError(localStatus);
698 }
699 
700 
702  if (m_table != NULL) {
703  m_table->PutNumber("Value", Get());
704  }
705 }
706 
708 
709 }
710 
712 
713 }
714 
716  return "Counter";
717 }
718 
719 void Counter::InitTable(ITable *subTable) {
720  m_table = subTable;
721  UpdateTable();
722 }
723 
725  return m_table;
726 }
727 
AnalogTriggerOutput * CreateOutput(AnalogTriggerOutput::Type type)
void Start()
Definition: Counter.cpp:542
void ClearDownSource()
Definition: Counter.cpp:433
virtual void PutNumber(std::string key, double value)=0
void Reset()
Definition: Counter.cpp:569
void SetExternalDirectionMode()
Definition: Counter.cpp:471
Definition: ITable.h:26
void SetDownSource(uint32_t channel)
Definition: Counter.cpp:325
Counter()
Definition: Counter.cpp:49
void StartLiveWindowMode()
Definition: Counter.cpp:707
void SetReverseDirection(bool reverseDirection)
Definition: Counter.cpp:686
void SetUpdateWhenEmpty(bool enabled)
Definition: Counter.cpp:643
tCounter * m_counter
The FPGA counter object.
Definition: Counter.h:85
void Free(uint32_t index)
Definition: Resource.cpp:105
uint32_t Allocate(const char *resourceDesc)
Definition: Resource.cpp:62
bool GetStopped()
Definition: Counter.cpp:659
void SetUpSourceEdge(bool risingEdge, bool fallingEdge)
Definition: Counter.cpp:284
void SetMaxPeriod(double maxPeriod)
Definition: Counter.cpp:623
void SetUpDownCounterMode()
Definition: Counter.cpp:458
void InitTable(ITable *subTable)
Definition: Counter.cpp:719
DigitalSource * m_downSource
What makes the counter count down.
Definition: Counter.h:84
bool GetDirection()
Definition: Counter.cpp:671
virtual bool StatusIsFatal() const
Check if the current error code represents a fatal error.
Definition: ErrorBase.cpp:178
void SetSemiPeriodMode(bool highSemiPeriod)
Definition: Counter.cpp:483
void SetSamplesToAverage(int samplesToAverage)
Definition: Counter.cpp:527
int32_t Get()
Definition: Counter.cpp:555
ITable * GetTable()
Definition: Counter.cpp:724
virtual std::string GetSmartDashboardType()
Definition: Counter.cpp:715
static void CreateResourceObject(Resource **r, uint32_t elements)
Definition: Resource.cpp:39
void SetDownSourceEdge(bool risingEdge, bool fallingEdge)
Definition: Counter.cpp:417
virtual ~Counter()
Definition: Counter.cpp:172
void StopLiveWindowMode()
Definition: Counter.cpp:711
void SetUpSource(uint32_t channel)
Definition: Counter.cpp:207
void SetPulseLengthMode(float threshold)
Definition: Counter.cpp:498
void Stop()
Definition: Counter.cpp:581
DigitalSource * m_upSource
What makes the counter count up.
Definition: Counter.h:83
void UpdateTable()
Definition: Counter.cpp:701
void ClearUpSource()
Definition: Counter.cpp:300
int GetSamplesToAverage()
Definition: Counter.cpp:514

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