forked from rbmj/wpilib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Counter.cpp
727 lines (667 loc) · 21.9 KB
/
Counter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
#include "Counter.h"
#include "AnalogTrigger.h"
#include "DigitalInput.h"
#include "NetworkCommunication/UsageReporting.h"
#include "Resource.h"
#include "WPIErrors.h"
static Resource *counters = NULL;
/**
* Create an instance of a counter object.
* This creates a ChipObject counter and initializes status variables appropriately
*/
void Counter::InitCounter(Mode mode)
{
m_table = NULL;
Resource::CreateResourceObject(&counters, tCounter::kNumSystems);
uint32_t index = counters->Allocate("Counter");
if (index == ~0ul)
{
CloneError(counters);
return;
}
m_index = index;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter = tCounter::create(m_index, &localStatus);
m_counter->writeConfig_Mode(mode, &localStatus);
m_upSource = NULL;
m_downSource = NULL;
m_allocatedUpSource = false;
m_allocatedDownSource = false;
m_counter->writeTimerConfig_AverageSize(1, &localStatus);
wpi_setError(localStatus);
nUsageReporting::report(nUsageReporting::kResourceType_Counter, index, mode);
}
/**
* Create an instance of a counter where no sources are selected.
* Then they all must be selected by calling functions to specify the upsource and the downsource
* independently.
*/
Counter::Counter() :
m_upSource(NULL),
m_downSource(NULL),
m_counter(NULL)
{
InitCounter();
}
/**
* Create an instance of a counter from a Digital Input.
* This is used if an existing digital input is to be shared by multiple other objects such
* as encoders.
*/
Counter::Counter(DigitalSource *source) :
m_upSource(NULL),
m_downSource(NULL),
m_counter(NULL)
{
InitCounter();
SetUpSource(source);
ClearDownSource();
}
Counter::Counter(DigitalSource &source) :
m_upSource(NULL),
m_downSource(NULL),
m_counter(NULL)
{
InitCounter();
SetUpSource(&source);
ClearDownSource();
}
/**
* Create an instance of a Counter object.
* Create an up-Counter instance given a channel. The default digital module is assumed.
*/
Counter::Counter(uint32_t channel) :
m_upSource(NULL),
m_downSource(NULL),
m_counter(NULL)
{
InitCounter();
SetUpSource(channel);
ClearDownSource();
}
/**
* Create an instance of a Counter object.
* Create an instance of an up-Counter given a digital module and a channel.
* @param moduleNumber The digital module (1 or 2).
* @param channel The channel in the digital module
*/
Counter::Counter(uint8_t moduleNumber, uint32_t channel) :
m_upSource(NULL),
m_downSource(NULL),
m_counter(NULL)
{
InitCounter();
SetUpSource(moduleNumber, channel);
ClearDownSource();
}
/**
* Create an instance of a Counter object.
* Create an instance of a simple up-Counter given an analog trigger.
* Use the trigger state output from the analog trigger.
*/
Counter::Counter(AnalogTrigger *trigger) :
m_upSource(NULL),
m_downSource(NULL),
m_counter(NULL)
{
InitCounter();
SetUpSource(trigger->CreateOutput(AnalogTriggerOutput::kState));
ClearDownSource();
m_allocatedUpSource = true;
}
Counter::Counter(AnalogTrigger &trigger) :
m_upSource(NULL),
m_downSource(NULL),
m_counter(NULL)
{
InitCounter();
SetUpSource(trigger.CreateOutput(AnalogTriggerOutput::kState));
ClearDownSource();
m_allocatedUpSource = true;
}
Counter::Counter(EncodingType encodingType, DigitalSource *upSource, DigitalSource *downSource, bool inverted) :
m_upSource(NULL),
m_downSource(NULL),
m_counter(NULL)
{
if (encodingType != k1X && encodingType != k2X)
{
wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports 1X and 2X quadrature decoding.");
return;
}
InitCounter(kExternalDirection);
SetUpSource(upSource);
SetDownSource(downSource);
tRioStatusCode localStatus = NiFpga_Status_Success;
if (encodingType == k1X)
{
SetUpSourceEdge(true, false);
m_counter->writeTimerConfig_AverageSize(1, &localStatus);
}
else
{
SetUpSourceEdge(true, true);
m_counter->writeTimerConfig_AverageSize(2, &localStatus);
}
wpi_setError(localStatus);
SetDownSourceEdge(inverted, true);
}
/**
* Delete the Counter object.
*/
Counter::~Counter()
{
SetUpdateWhenEmpty(true);
if (m_allocatedUpSource)
{
delete m_upSource;
m_upSource = NULL;
}
if (m_allocatedDownSource)
{
delete m_downSource;
m_downSource = NULL;
}
delete m_counter;
m_counter = NULL;
counters->Free(m_index);
}
/**
* Set the up source for the counter as digital input channel and slot.
*
* @param moduleNumber The digital module (1 or 2).
* @param channel The digital channel (1..14).
*/
void Counter::SetUpSource(uint8_t moduleNumber, uint32_t channel)
{
if (StatusIsFatal()) return;
SetUpSource(new DigitalInput(moduleNumber, channel));
m_allocatedUpSource = true;
}
/**
* Set the upsource for the counter as a digital input channel.
* The slot will be the default digital module slot.
*/
void Counter::SetUpSource(uint32_t channel)
{
if (StatusIsFatal()) return;
SetUpSource(GetDefaultDigitalModule(), channel);
m_allocatedUpSource = true;
}
/**
* Set the up counting source to be an analog trigger.
* @param analogTrigger The analog trigger object that is used for the Up Source
* @param triggerType The analog trigger output that will trigger the counter.
*/
void Counter::SetUpSource(AnalogTrigger *analogTrigger, AnalogTriggerOutput::Type triggerType)
{
if (StatusIsFatal()) return;
SetUpSource(analogTrigger->CreateOutput(triggerType));
m_allocatedUpSource = true;
}
/**
* Set the up counting source to be an analog trigger.
* @param analogTrigger The analog trigger object that is used for the Up Source
* @param triggerType The analog trigger output that will trigger the counter.
*/
void Counter::SetUpSource(AnalogTrigger &analogTrigger, AnalogTriggerOutput::Type triggerType)
{
SetUpSource(&analogTrigger, triggerType);
}
/**
* Set the source object that causes the counter to count up.
* Set the up counting DigitalSource.
*/
void Counter::SetUpSource(DigitalSource *source)
{
if (StatusIsFatal()) return;
if (m_allocatedUpSource)
{
delete m_upSource;
m_upSource = NULL;
m_allocatedUpSource = false;
}
m_upSource = source;
if (m_upSource->StatusIsFatal())
{
CloneError(m_upSource);
}
else
{
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_UpSource_Module(source->GetModuleForRouting(), &localStatus);
m_counter->writeConfig_UpSource_Channel(source->GetChannelForRouting(), &localStatus);
m_counter->writeConfig_UpSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &localStatus);
if(m_counter->readConfig_Mode(&localStatus) == kTwoPulse ||
m_counter->readConfig_Mode(&localStatus) == kExternalDirection)
{
SetUpSourceEdge(true, false);
}
m_counter->strobeReset(&localStatus);
wpi_setError(localStatus);
}
}
/**
* Set the source object that causes the counter to count up.
* Set the up counting DigitalSource.
*/
void Counter::SetUpSource(DigitalSource &source)
{
SetUpSource(&source);
}
/**
* Set the edge sensitivity on an up counting source.
* Set the up source to either detect rising edges or falling edges.
*/
void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge)
{
if (StatusIsFatal()) return;
if (m_upSource == NULL)
{
wpi_setWPIErrorWithContext(NullParameter, "Must set non-NULL UpSource before setting UpSourceEdge");
}
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_UpRisingEdge(risingEdge, &localStatus);
m_counter->writeConfig_UpFallingEdge(fallingEdge, &localStatus);
wpi_setError(localStatus);
}
/**
* Disable the up counting source to the counter.
*/
void Counter::ClearUpSource()
{
if (StatusIsFatal()) return;
if (m_allocatedUpSource)
{
delete m_upSource;
m_upSource = NULL;
m_allocatedUpSource = false;
}
tRioStatusCode localStatus = NiFpga_Status_Success;
bool state = m_counter->readConfig_Enable(&localStatus);
m_counter->writeConfig_Enable(false, &localStatus);
m_counter->writeConfig_UpFallingEdge(false, &localStatus);
m_counter->writeConfig_UpRisingEdge(false, &localStatus);
// Index 0 of digital is always 0.
m_counter->writeConfig_UpSource_Channel(0, &localStatus);
m_counter->writeConfig_UpSource_AnalogTrigger(false, &localStatus);
m_counter->writeConfig_Enable(state, &localStatus);
wpi_setError(localStatus);
}
/**
* Set the down counting source to be a digital input channel.
* The slot will be set to the default digital module slot.
*/
void Counter::SetDownSource(uint32_t channel)
{
if (StatusIsFatal()) return;
SetDownSource(new DigitalInput(channel));
m_allocatedDownSource = true;
}
/**
* Set the down counting source to be a digital input slot and channel.
*
* @param moduleNumber The digital module (1 or 2).
* @param channel The digital channel (1..14).
*/
void Counter::SetDownSource(uint8_t moduleNumber, uint32_t channel)
{
if (StatusIsFatal()) return;
SetDownSource(new DigitalInput(moduleNumber, channel));
m_allocatedDownSource = true;
}
/**
* Set the down counting source to be an analog trigger.
* @param analogTrigger The analog trigger object that is used for the Down Source
* @param triggerType The analog trigger output that will trigger the counter.
*/
void Counter::SetDownSource(AnalogTrigger *analogTrigger, AnalogTriggerOutput::Type triggerType)
{
if (StatusIsFatal()) return;
SetDownSource(analogTrigger->CreateOutput(triggerType));
m_allocatedDownSource = true;
}
/**
* Set the down counting source to be an analog trigger.
* @param analogTrigger The analog trigger object that is used for the Down Source
* @param triggerType The analog trigger output that will trigger the counter.
*/
void Counter::SetDownSource(AnalogTrigger &analogTrigger, AnalogTriggerOutput::Type triggerType)
{
SetDownSource(&analogTrigger, triggerType);
}
/**
* Set the source object that causes the counter to count down.
* Set the down counting DigitalSource.
*/
void Counter::SetDownSource(DigitalSource *source)
{
if (StatusIsFatal()) return;
if (m_allocatedDownSource)
{
delete m_downSource;
m_downSource = NULL;
m_allocatedDownSource = false;
}
m_downSource = source;
if (m_downSource->StatusIsFatal())
{
CloneError(m_downSource);
}
else
{
tRioStatusCode localStatus = NiFpga_Status_Success;
unsigned char mode = m_counter->readConfig_Mode(&localStatus);
if (mode != kTwoPulse && mode != kExternalDirection)
{
wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports DownSource in TwoPulse and ExternalDirection modes.");
return;
}
m_counter->writeConfig_DownSource_Module(source->GetModuleForRouting(), &localStatus);
m_counter->writeConfig_DownSource_Channel(source->GetChannelForRouting(), &localStatus);
m_counter->writeConfig_DownSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &localStatus);
SetDownSourceEdge(true, false);
m_counter->strobeReset(&localStatus);
wpi_setError(localStatus);
}
}
/**
* Set the source object that causes the counter to count down.
* Set the down counting DigitalSource.
*/
void Counter::SetDownSource(DigitalSource &source)
{
SetDownSource(&source);
}
/**
* Set the edge sensitivity on a down counting source.
* Set the down source to either detect rising edges or falling edges.
*/
void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge)
{
if (StatusIsFatal()) return;
if (m_downSource == NULL)
{
wpi_setWPIErrorWithContext(NullParameter, "Must set non-NULL DownSource before setting DownSourceEdge");
}
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_DownRisingEdge(risingEdge, &localStatus);
m_counter->writeConfig_DownFallingEdge(fallingEdge, &localStatus);
wpi_setError(localStatus);
}
/**
* Disable the down counting source to the counter.
*/
void Counter::ClearDownSource()
{
if (StatusIsFatal()) return;
if (m_allocatedDownSource)
{
delete m_downSource;
m_downSource = NULL;
m_allocatedDownSource = false;
}
tRioStatusCode localStatus = NiFpga_Status_Success;
bool state = m_counter->readConfig_Enable(&localStatus);
m_counter->writeConfig_Enable(false, &localStatus);
m_counter->writeConfig_DownFallingEdge(false, &localStatus);
m_counter->writeConfig_DownRisingEdge(false, &localStatus);
// Index 0 of digital is always 0.
m_counter->writeConfig_DownSource_Channel(0, &localStatus);
m_counter->writeConfig_DownSource_AnalogTrigger(false, &localStatus);
m_counter->writeConfig_Enable(state, &localStatus);
wpi_setError(localStatus);
}
/**
* Set standard up / down counting mode on this counter.
* Up and down counts are sourced independently from two inputs.
*/
void Counter::SetUpDownCounterMode()
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_Mode(kTwoPulse, &localStatus);
wpi_setError(localStatus);
}
/**
* Set external direction mode on this counter.
* Counts are sourced on the Up counter input.
* The Down counter input represents the direction to count.
*/
void Counter::SetExternalDirectionMode()
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_Mode(kExternalDirection, &localStatus);
wpi_setError(localStatus);
}
/**
* Set Semi-period mode on this counter.
* Counts up on both rising and falling edges.
*/
void Counter::SetSemiPeriodMode(bool highSemiPeriod)
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_Mode(kSemiperiod, &localStatus);
m_counter->writeConfig_UpRisingEdge(highSemiPeriod, &localStatus);
SetUpdateWhenEmpty(false);
wpi_setError(localStatus);
}
/**
* Configure the counter to count in up or down based on the length of the input pulse.
* This mode is most useful for direction sensitive gear tooth sensors.
* @param threshold The pulse length beyond which the counter counts the opposite direction. Units are seconds.
*/
void Counter::SetPulseLengthMode(float threshold)
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_Mode(kPulseLength, &localStatus);
m_counter->writeConfig_PulseLengthThreshold((uint32_t)(threshold * 1.0e6) * kSystemClockTicksPerMicrosecond, &localStatus);
wpi_setError(localStatus);
}
/**
* Get the Samples to Average which specifies the number of samples of the timer to
* average when calculating the period. Perform averaging to account for
* mechanical imperfections or as oversampling to increase resolution.
* @return SamplesToAverage The number of samples being averaged (from 1 to 127)
*/
int Counter::GetSamplesToAverage()
{
tRioStatusCode localStatus = NiFpga_Status_Success;
return m_counter->readTimerConfig_AverageSize(&localStatus);
wpi_setError(localStatus);
}
/**
* Set the Samples to Average which specifies the number of samples of the timer to
* average when calculating the period. Perform averaging to account for
* mechanical imperfections or as oversampling to increase resolution.
* @param samplesToAverage The number of samples to average from 1 to 127.
*/
void Counter::SetSamplesToAverage (int samplesToAverage) {
tRioStatusCode localStatus = NiFpga_Status_Success;
if (samplesToAverage < 1 || samplesToAverage > 127)
{
wpi_setWPIErrorWithContext(ParameterOutOfRange, "Average counter values must be between 1 and 127");
}
m_counter->writeTimerConfig_AverageSize(samplesToAverage, &localStatus);
wpi_setError(localStatus);
}
/**
* Start the Counter counting.
* This enables the counter and it starts accumulating counts from the associated
* input channel. The counter value is not reset on starting, and still has the previous value.
*/
void Counter::Start()
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_Enable(1, &localStatus);
wpi_setError(localStatus);
}
/**
* Read the current counter value.
* Read the value at this instant. It may still be running, so it reflects the current value. Next
* time it is read, it might have a different value.
*/
int32_t Counter::Get()
{
if (StatusIsFatal()) return 0;
tRioStatusCode localStatus = NiFpga_Status_Success;
int32_t value = m_counter->readOutput_Value(&localStatus);
wpi_setError(localStatus);
return value;
}
/**
* Reset the Counter to zero.
* Set the counter value to zero. This doesn't effect the running state of the counter, just sets
* the current value to zero.
*/
void Counter::Reset()
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->strobeReset(&localStatus);
wpi_setError(localStatus);
}
/**
* Stop the Counter.
* Stops the counting but doesn't effect the current value.
*/
void Counter::Stop()
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeConfig_Enable(0, &localStatus);
wpi_setError(localStatus);
}
/*
* Get the Period of the most recent count.
* Returns the time interval of the most recent count. This can be used for velocity calculations
* to determine shaft speed.
* @returns The period of the last two pulses in units of seconds.
*/
double Counter::GetPeriod()
{
if (StatusIsFatal()) return 0.0;
tRioStatusCode localStatus = NiFpga_Status_Success;
tCounter::tTimerOutput output = m_counter->readTimerOutput(&localStatus);
double period;
if (output.Stalled)
{
// Return infinity
double zero = 0.0;
period = 1.0 / zero;
}
else
{
// output.Period is a fixed point number that counts by 2 (24 bits, 25 integer bits)
period = (double)(output.Period << 1) / (double)output.Count;
}
wpi_setError(localStatus);
return period * 1.0e-6;
}
/**
* Set the maximum period where the device is still considered "moving".
* Sets the maximum period where the device is considered moving. This value is used to determine
* the "stopped" state of the counter using the GetStopped method.
* @param maxPeriod The maximum period where the counted device is considered moving in
* seconds.
*/
void Counter::SetMaxPeriod(double maxPeriod)
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeTimerConfig_StallPeriod((uint32_t)(maxPeriod * 1.0e6), &localStatus);
wpi_setError(localStatus);
}
/**
* Select whether you want to continue updating the event timer output when there are no samples captured.
* The output of the event timer has a buffer of periods that are averaged and posted to
* a register on the FPGA. When the timer detects that the event source has stopped
* (based on the MaxPeriod) the buffer of samples to be averaged is emptied. If you
* enable the update when empty, you will be notified of the stopped source and the event
* time will report 0 samples. If you disable update when empty, the most recent average
* will remain on the output until a new sample is acquired. You will never see 0 samples
* output (except when there have been no events since an FPGA reset) and you will likely not
* see the stopped bit become true (since it is updated at the end of an average and there are
* no samples to average).
*/
void Counter::SetUpdateWhenEmpty(bool enabled)
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
m_counter->writeTimerConfig_UpdateWhenEmpty(enabled, &localStatus);
wpi_setError(localStatus);
}
/**
* Determine if the clock is stopped.
* Determine if the clocked input is stopped based on the MaxPeriod value set using the
* SetMaxPeriod method. If the clock exceeds the MaxPeriod, then the device (and counter) are
* assumed to be stopped and it returns true.
* @return Returns true if the most recent counter period exceeds the MaxPeriod value set by
* SetMaxPeriod.
*/
bool Counter::GetStopped()
{
if (StatusIsFatal()) return false;
tRioStatusCode localStatus = NiFpga_Status_Success;
return m_counter->readTimerOutput_Stalled(&localStatus);
wpi_setError(localStatus);
}
/**
* The last direction the counter value changed.
* @return The last direction the counter value changed.
*/
bool Counter::GetDirection()
{
if (StatusIsFatal()) return false;
tRioStatusCode localStatus = NiFpga_Status_Success;
bool value = m_counter->readOutput_Direction(&localStatus);
wpi_setError(localStatus);
return value;
}
/**
* Set the Counter to return reversed sensing on the direction.
* This allows counters to change the direction they are counting in the case of 1X and 2X
* quadrature encoding only. Any other counter mode isn't supported.
* @param reverseDirection true if the value counted should be negated.
*/
void Counter::SetReverseDirection(bool reverseDirection)
{
if (StatusIsFatal()) return;
tRioStatusCode localStatus = NiFpga_Status_Success;
if (m_counter->readConfig_Mode(&localStatus) == kExternalDirection)
{
if (reverseDirection)
SetDownSourceEdge(true, true);
else
SetDownSourceEdge(false, true);
}
wpi_setError(localStatus);
}
void Counter::UpdateTable() {
if (m_table != NULL) {
m_table->PutNumber("Value", Get());
}
}
void Counter::StartLiveWindowMode() {
}
void Counter::StopLiveWindowMode() {
}
std::string Counter::GetSmartDashboardType() {
return "Counter";
}
void Counter::InitTable(ITable *subTable) {
m_table = subTable;
UpdateTable();
}
ITable * Counter::GetTable() {
return m_table;
}