Now you can download a copy of these docs so you can use them offline! Download now
Counter.cpp
00001 /*----------------------------------------------------------------------------*/ 00002 /* Copyright (c) FIRST 2008. All Rights Reserved. */ 00003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00004 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00005 /*----------------------------------------------------------------------------*/ 00006 00007 #include "Counter.h" 00008 #include "AnalogTrigger.h" 00009 #include "DigitalInput.h" 00010 #include "Resource.h" 00011 #include "WPIErrors.h" 00012 00013 static Resource *counters = NULL; 00014 00019 void Counter::InitCounter(Mode mode) 00020 { 00021 Resource::CreateResourceObject(&counters, tCounter::kNumSystems); 00022 UINT32 index = counters->Allocate("Counter"); 00023 if (index == ~0ul) 00024 { 00025 CloneError(counters); 00026 return; 00027 } 00028 m_index = index; 00029 tRioStatusCode localStatus = NiFpga_Status_Success; 00030 m_counter = tCounter::create(m_index, &localStatus); 00031 m_counter->writeConfig_Mode(mode, &localStatus); 00032 m_upSource = NULL; 00033 m_downSource = NULL; 00034 m_allocatedUpSource = false; 00035 m_allocatedDownSource = false; 00036 m_counter->writeTimerConfig_AverageSize(1, &localStatus); 00037 wpi_setError(localStatus); 00038 } 00039 00045 Counter::Counter() : 00046 m_upSource(NULL), 00047 m_downSource(NULL), 00048 m_counter(NULL) 00049 { 00050 InitCounter(); 00051 } 00052 00058 Counter::Counter(DigitalSource *source) : 00059 m_upSource(NULL), 00060 m_downSource(NULL), 00061 m_counter(NULL) 00062 { 00063 InitCounter(); 00064 SetUpSource(source); 00065 ClearDownSource(); 00066 } 00067 00068 Counter::Counter(DigitalSource &source) : 00069 m_upSource(NULL), 00070 m_downSource(NULL), 00071 m_counter(NULL) 00072 { 00073 InitCounter(); 00074 SetUpSource(&source); 00075 ClearDownSource(); 00076 } 00077 00082 Counter::Counter(UINT32 channel) : 00083 m_upSource(NULL), 00084 m_downSource(NULL), 00085 m_counter(NULL) 00086 { 00087 InitCounter(); 00088 SetUpSource(channel); 00089 ClearDownSource(); 00090 } 00091 00098 Counter::Counter(UINT8 moduleNumber, UINT32 channel) : 00099 m_upSource(NULL), 00100 m_downSource(NULL), 00101 m_counter(NULL) 00102 { 00103 InitCounter(); 00104 SetUpSource(moduleNumber, channel); 00105 ClearDownSource(); 00106 } 00107 00113 Counter::Counter(AnalogTrigger *trigger) : 00114 m_upSource(NULL), 00115 m_downSource(NULL), 00116 m_counter(NULL) 00117 { 00118 InitCounter(); 00119 SetUpSource(trigger->CreateOutput(AnalogTriggerOutput::kState)); 00120 ClearDownSource(); 00121 m_allocatedUpSource = true; 00122 } 00123 00124 Counter::Counter(AnalogTrigger &trigger) : 00125 m_upSource(NULL), 00126 m_downSource(NULL), 00127 m_counter(NULL) 00128 { 00129 InitCounter(); 00130 SetUpSource(trigger.CreateOutput(AnalogTriggerOutput::kState)); 00131 ClearDownSource(); 00132 m_allocatedUpSource = true; 00133 } 00134 00135 Counter::Counter(EncodingType encodingType, DigitalSource *upSource, DigitalSource *downSource, bool inverted) : 00136 m_upSource(NULL), 00137 m_downSource(NULL), 00138 m_counter(NULL) 00139 { 00140 if (encodingType != k1X && encodingType != k2X) 00141 { 00142 wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports 1X and 2X quadrature decoding."); 00143 return; 00144 } 00145 InitCounter(kExternalDirection); 00146 SetUpSource(upSource); 00147 SetDownSource(downSource); 00148 tRioStatusCode localStatus = NiFpga_Status_Success; 00149 00150 if (encodingType == k1X) 00151 { 00152 SetUpSourceEdge(true, false); 00153 m_counter->writeTimerConfig_AverageSize(1, &localStatus); 00154 } 00155 else 00156 { 00157 SetUpSourceEdge(true, true); 00158 m_counter->writeTimerConfig_AverageSize(2, &localStatus); 00159 } 00160 00161 wpi_setError(localStatus); 00162 SetDownSourceEdge(inverted, true); 00163 } 00164 00168 Counter::~Counter() 00169 { 00170 SetUpdateWhenEmpty(true); 00171 if (m_allocatedUpSource) 00172 { 00173 delete m_upSource; 00174 m_upSource = NULL; 00175 } 00176 if (m_allocatedDownSource) 00177 { 00178 delete m_downSource; 00179 m_downSource = NULL; 00180 } 00181 delete m_counter; 00182 m_counter = NULL; 00183 counters->Free(m_index); 00184 } 00185 00192 void Counter::SetUpSource(UINT8 moduleNumber, UINT32 channel) 00193 { 00194 if (StatusIsFatal()) return; 00195 SetUpSource(new DigitalInput(moduleNumber, channel)); 00196 m_allocatedUpSource = true; 00197 } 00198 00203 void Counter::SetUpSource(UINT32 channel) 00204 { 00205 if (StatusIsFatal()) return; 00206 SetUpSource(GetDefaultDigitalModule(), channel); 00207 m_allocatedUpSource = true; 00208 } 00209 00215 void Counter::SetUpSource(AnalogTrigger *analogTrigger, AnalogTriggerOutput::Type triggerType) 00216 { 00217 if (StatusIsFatal()) return; 00218 SetUpSource(analogTrigger->CreateOutput(triggerType)); 00219 m_allocatedUpSource = true; 00220 } 00221 00227 void Counter::SetUpSource(AnalogTrigger &analogTrigger, AnalogTriggerOutput::Type triggerType) 00228 { 00229 SetUpSource(&analogTrigger, triggerType); 00230 } 00231 00236 void Counter::SetUpSource(DigitalSource *source) 00237 { 00238 if (StatusIsFatal()) return; 00239 if (m_allocatedUpSource) 00240 { 00241 delete m_upSource; 00242 m_upSource = NULL; 00243 m_allocatedUpSource = false; 00244 } 00245 m_upSource = source; 00246 if (m_upSource->StatusIsFatal()) 00247 { 00248 CloneError(m_upSource); 00249 } 00250 else 00251 { 00252 tRioStatusCode localStatus = NiFpga_Status_Success; 00253 m_counter->writeConfig_UpSource_Module(source->GetModuleForRouting(), &localStatus); 00254 m_counter->writeConfig_UpSource_Channel(source->GetChannelForRouting(), &localStatus); 00255 m_counter->writeConfig_UpSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &localStatus); 00256 00257 if(m_counter->readConfig_Mode(&localStatus) == kTwoPulse || 00258 m_counter->readConfig_Mode(&localStatus) == kExternalDirection) 00259 { 00260 SetUpSourceEdge(true, false); 00261 } 00262 m_counter->strobeReset(&localStatus); 00263 wpi_setError(localStatus); 00264 } 00265 } 00266 00271 void Counter::SetUpSource(DigitalSource &source) 00272 { 00273 SetUpSource(&source); 00274 } 00275 00280 void Counter::SetUpSourceEdge(bool risingEdge, bool fallingEdge) 00281 { 00282 if (StatusIsFatal()) return; 00283 if (m_upSource == NULL) 00284 { 00285 wpi_setWPIErrorWithContext(NullParameter, "Must set non-NULL UpSource before setting UpSourceEdge"); 00286 } 00287 tRioStatusCode localStatus = NiFpga_Status_Success; 00288 m_counter->writeConfig_UpRisingEdge(risingEdge, &localStatus); 00289 m_counter->writeConfig_UpFallingEdge(fallingEdge, &localStatus); 00290 wpi_setError(localStatus); 00291 } 00292 00296 void Counter::ClearUpSource() 00297 { 00298 if (StatusIsFatal()) return; 00299 if (m_allocatedUpSource) 00300 { 00301 delete m_upSource; 00302 m_upSource = NULL; 00303 m_allocatedUpSource = false; 00304 } 00305 tRioStatusCode localStatus = NiFpga_Status_Success; 00306 bool state = m_counter->readConfig_Enable(&localStatus); 00307 m_counter->writeConfig_Enable(false, &localStatus); 00308 m_counter->writeConfig_UpFallingEdge(false, &localStatus); 00309 m_counter->writeConfig_UpRisingEdge(false, &localStatus); 00310 // Index 0 of digital is always 0. 00311 m_counter->writeConfig_UpSource_Channel(0, &localStatus); 00312 m_counter->writeConfig_UpSource_AnalogTrigger(false, &localStatus); 00313 m_counter->writeConfig_Enable(state, &localStatus); 00314 wpi_setError(localStatus); 00315 } 00316 00321 void Counter::SetDownSource(UINT32 channel) 00322 { 00323 if (StatusIsFatal()) return; 00324 SetDownSource(new DigitalInput(channel)); 00325 m_allocatedDownSource = true; 00326 } 00327 00334 void Counter::SetDownSource(UINT8 moduleNumber, UINT32 channel) 00335 { 00336 if (StatusIsFatal()) return; 00337 SetDownSource(new DigitalInput(moduleNumber, channel)); 00338 m_allocatedDownSource = true; 00339 } 00340 00346 void Counter::SetDownSource(AnalogTrigger *analogTrigger, AnalogTriggerOutput::Type triggerType) 00347 { 00348 if (StatusIsFatal()) return; 00349 SetDownSource(analogTrigger->CreateOutput(triggerType)); 00350 m_allocatedDownSource = true; 00351 } 00352 00358 void Counter::SetDownSource(AnalogTrigger &analogTrigger, AnalogTriggerOutput::Type triggerType) 00359 { 00360 SetDownSource(&analogTrigger, triggerType); 00361 } 00362 00367 void Counter::SetDownSource(DigitalSource *source) 00368 { 00369 if (StatusIsFatal()) return; 00370 if (m_allocatedDownSource) 00371 { 00372 delete m_downSource; 00373 m_downSource = NULL; 00374 m_allocatedDownSource = false; 00375 } 00376 m_downSource = source; 00377 if (m_downSource->StatusIsFatal()) 00378 { 00379 CloneError(m_downSource); 00380 } 00381 else 00382 { 00383 tRioStatusCode localStatus = NiFpga_Status_Success; 00384 unsigned char mode = m_counter->readConfig_Mode(&localStatus); 00385 if (mode != kTwoPulse && mode != kExternalDirection) 00386 { 00387 wpi_setWPIErrorWithContext(ParameterOutOfRange, "Counter only supports DownSource in TwoPulse and ExternalDirection modes."); 00388 return; 00389 } 00390 m_counter->writeConfig_DownSource_Module(source->GetModuleForRouting(), &localStatus); 00391 m_counter->writeConfig_DownSource_Channel(source->GetChannelForRouting(), &localStatus); 00392 m_counter->writeConfig_DownSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &localStatus); 00393 00394 SetDownSourceEdge(true, false); 00395 m_counter->strobeReset(&localStatus); 00396 wpi_setError(localStatus); 00397 } 00398 } 00399 00404 void Counter::SetDownSource(DigitalSource &source) 00405 { 00406 SetDownSource(&source); 00407 } 00408 00413 void Counter::SetDownSourceEdge(bool risingEdge, bool fallingEdge) 00414 { 00415 if (StatusIsFatal()) return; 00416 if (m_downSource == NULL) 00417 { 00418 wpi_setWPIErrorWithContext(NullParameter, "Must set non-NULL DownSource before setting DownSourceEdge"); 00419 } 00420 tRioStatusCode localStatus = NiFpga_Status_Success; 00421 m_counter->writeConfig_DownRisingEdge(risingEdge, &localStatus); 00422 m_counter->writeConfig_DownFallingEdge(fallingEdge, &localStatus); 00423 wpi_setError(localStatus); 00424 } 00425 00429 void Counter::ClearDownSource() 00430 { 00431 if (StatusIsFatal()) return; 00432 if (m_allocatedDownSource) 00433 { 00434 delete m_downSource; 00435 m_downSource = NULL; 00436 m_allocatedDownSource = false; 00437 } 00438 tRioStatusCode localStatus = NiFpga_Status_Success; 00439 bool state = m_counter->readConfig_Enable(&localStatus); 00440 m_counter->writeConfig_Enable(false, &localStatus); 00441 m_counter->writeConfig_DownFallingEdge(false, &localStatus); 00442 m_counter->writeConfig_DownRisingEdge(false, &localStatus); 00443 // Index 0 of digital is always 0. 00444 m_counter->writeConfig_DownSource_Channel(0, &localStatus); 00445 m_counter->writeConfig_DownSource_AnalogTrigger(false, &localStatus); 00446 m_counter->writeConfig_Enable(state, &localStatus); 00447 wpi_setError(localStatus); 00448 } 00449 00454 void Counter::SetUpDownCounterMode() 00455 { 00456 if (StatusIsFatal()) return; 00457 tRioStatusCode localStatus = NiFpga_Status_Success; 00458 m_counter->writeConfig_Mode(kTwoPulse, &localStatus); 00459 wpi_setError(localStatus); 00460 } 00461 00467 void Counter::SetExternalDirectionMode() 00468 { 00469 if (StatusIsFatal()) return; 00470 tRioStatusCode localStatus = NiFpga_Status_Success; 00471 m_counter->writeConfig_Mode(kExternalDirection, &localStatus); 00472 wpi_setError(localStatus); 00473 } 00474 00479 void Counter::SetSemiPeriodMode(bool highSemiPeriod) 00480 { 00481 if (StatusIsFatal()) return; 00482 tRioStatusCode localStatus = NiFpga_Status_Success; 00483 m_counter->writeConfig_Mode(kSemiperiod, &localStatus); 00484 m_counter->writeConfig_UpRisingEdge(highSemiPeriod, &localStatus); 00485 SetUpdateWhenEmpty(false); 00486 wpi_setError(localStatus); 00487 } 00488 00494 void Counter::SetPulseLengthMode(float threshold) 00495 { 00496 if (StatusIsFatal()) return; 00497 tRioStatusCode localStatus = NiFpga_Status_Success; 00498 m_counter->writeConfig_Mode(kPulseLength, &localStatus); 00499 m_counter->writeConfig_PulseLengthThreshold((UINT32)(threshold * 1.0e6) * kSystemClockTicksPerMicrosecond, &localStatus); 00500 wpi_setError(localStatus); 00501 } 00502 00508 void Counter::Start() 00509 { 00510 if (StatusIsFatal()) return; 00511 tRioStatusCode localStatus = NiFpga_Status_Success; 00512 m_counter->writeConfig_Enable(1, &localStatus); 00513 wpi_setError(localStatus); 00514 } 00515 00521 INT32 Counter::Get() 00522 { 00523 if (StatusIsFatal()) return 0; 00524 tRioStatusCode localStatus = NiFpga_Status_Success; 00525 INT32 value = m_counter->readOutput_Value(&localStatus); 00526 wpi_setError(localStatus); 00527 return value; 00528 } 00529 00535 void Counter::Reset() 00536 { 00537 if (StatusIsFatal()) return; 00538 tRioStatusCode localStatus = NiFpga_Status_Success; 00539 m_counter->strobeReset(&localStatus); 00540 wpi_setError(localStatus); 00541 } 00542 00547 void Counter::Stop() 00548 { 00549 if (StatusIsFatal()) return; 00550 tRioStatusCode localStatus = NiFpga_Status_Success; 00551 m_counter->writeConfig_Enable(0, &localStatus); 00552 wpi_setError(localStatus); 00553 } 00554 00555 /* 00556 * Get the Period of the most recent count. 00557 * Returns the time interval of the most recent count. This can be used for velocity calculations 00558 * to determine shaft speed. 00559 * @returns The period of the last two pulses in units of seconds. 00560 */ 00561 double Counter::GetPeriod() 00562 { 00563 if (StatusIsFatal()) return 0.0; 00564 tRioStatusCode localStatus = NiFpga_Status_Success; 00565 tCounter::tTimerOutput output = m_counter->readTimerOutput(&localStatus); 00566 double period; 00567 if (output.Stalled) 00568 { 00569 // Return infinity 00570 double zero = 0.0; 00571 period = 1.0 / zero; 00572 } 00573 else 00574 { 00575 // output.Period is a fixed point number that counts by 2 (24 bits, 25 integer bits) 00576 period = (double)(output.Period << 1) / (double)output.Count; 00577 } 00578 wpi_setError(localStatus); 00579 return period * 1.0e-6; 00580 } 00581 00589 void Counter::SetMaxPeriod(double maxPeriod) 00590 { 00591 if (StatusIsFatal()) return; 00592 tRioStatusCode localStatus = NiFpga_Status_Success; 00593 m_counter->writeTimerConfig_StallPeriod((UINT32)(maxPeriod * 1.0e6), &localStatus); 00594 wpi_setError(localStatus); 00595 } 00596 00609 void Counter::SetUpdateWhenEmpty(bool enabled) 00610 { 00611 if (StatusIsFatal()) return; 00612 tRioStatusCode localStatus = NiFpga_Status_Success; 00613 m_counter->writeTimerConfig_UpdateWhenEmpty(enabled, &localStatus); 00614 wpi_setError(localStatus); 00615 } 00616 00625 bool Counter::GetStopped() 00626 { 00627 if (StatusIsFatal()) return false; 00628 tRioStatusCode localStatus = NiFpga_Status_Success; 00629 return m_counter->readTimerOutput_Stalled(&localStatus); 00630 wpi_setError(localStatus); 00631 } 00632 00637 bool Counter::GetDirection() 00638 { 00639 if (StatusIsFatal()) return false; 00640 tRioStatusCode localStatus = NiFpga_Status_Success; 00641 bool value = m_counter->readOutput_Direction(&localStatus); 00642 wpi_setError(localStatus); 00643 return value; 00644 } 00645 00652 void Counter::SetReverseDirection(bool reverseDirection) 00653 { 00654 if (StatusIsFatal()) return; 00655 tRioStatusCode localStatus = NiFpga_Status_Success; 00656 if (m_counter->readConfig_Mode(&localStatus) == kExternalDirection) 00657 { 00658 if (reverseDirection) 00659 SetDownSourceEdge(true, true); 00660 else 00661 SetDownSourceEdge(false, true); 00662 } 00663 wpi_setError(localStatus); 00664 }
Generated on Thu Jan 12 2012 22:35:19 for WPILibC++ by
1.7.1