7 #include "DigitalModule.h"
11 #include "Synchronized.h"
12 #include "WPIErrors.h"
17 static Resource *DO_PWMGenerators[tDIO::kNumSystems] = {NULL};
35 snprintf(buf, 64,
"Digital Module %d", moduleNumber);
36 wpi_setGlobalWPIErrorWithContext(ModuleIndexOutOfRange, buf);
52 :
Module(nLoadOut::kModuleType_Digital, moduleNumber)
57 tRioStatusCode localStatus = NiFpga_Status_Success;
59 wpi_setError(localStatus);
62 while(m_fpgaDIO->readLoopTiming(&localStatus) == 0) taskDelay(1);
64 if (m_fpgaDIO->readLoopTiming(&localStatus) != kExpectedLoopTiming)
67 sprintf(err,
"DIO LoopTiming: %d, expecting: %lu\n", m_fpgaDIO->readLoopTiming(&localStatus), kExpectedLoopTiming);
68 wpi_setWPIErrorWithContext(LoopTimingError, err);
72 double loopTime = m_fpgaDIO->readLoopTiming(&localStatus)/(kSystemClockTicksPerMicrosecond*1e3);
78 for (uint32_t pwm_index = 1; pwm_index <= kPwmChannels; pwm_index++)
80 SetPWM(pwm_index, PWM::kPwmDisabled);
85 m_fpgaDIO->writeSlowValue_RelayFwd(0, &localStatus);
86 m_fpgaDIO->writeSlowValue_RelayRev(0, &localStatus);
87 wpi_setError(localStatus);
90 m_digitalSemaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
93 m_relaySemaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
96 m_doPwmSemaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
101 DigitalModule::~DigitalModule()
103 semDelete(m_doPwmSemaphore);
104 m_doPwmSemaphore = NULL;
105 semDelete(m_relaySemaphore);
106 m_relaySemaphore = NULL;
107 semDelete(m_digitalSemaphore);
108 m_digitalSemaphore = NULL;
122 tRioStatusCode localStatus = NiFpga_Status_Success;
123 m_fpgaDIO->writePWMValue(channel - 1, value, &localStatus);
124 wpi_setError(localStatus);
136 tRioStatusCode localStatus = NiFpga_Status_Success;
137 return m_fpgaDIO->readPWMValue(channel - 1, &localStatus);
138 wpi_setError(localStatus);
150 tRioStatusCode localStatus = NiFpga_Status_Success;
151 m_fpgaDIO->writePWMPeriodScale(channel - 1, squelchMask, &localStatus);
152 wpi_setError(localStatus);
162 tRioStatusCode localStatus = NiFpga_Status_Success;
166 uint8_t forwardRelays = m_fpgaDIO->readSlowValue_RelayFwd(&localStatus);
168 forwardRelays |= 1 << (channel - 1);
170 forwardRelays &= ~(1 << (channel - 1));
171 m_fpgaDIO->writeSlowValue_RelayFwd(forwardRelays, &localStatus);
173 wpi_setError(localStatus);
183 tRioStatusCode localStatus = NiFpga_Status_Success;
187 uint8_t reverseRelays = m_fpgaDIO->readSlowValue_RelayRev(&localStatus);
189 reverseRelays |= 1 << (channel - 1);
191 reverseRelays &= ~(1 << (channel - 1));
192 m_fpgaDIO->writeSlowValue_RelayRev(reverseRelays, &localStatus);
194 wpi_setError(localStatus);
202 tRioStatusCode localStatus = NiFpga_Status_Success;
203 uint8_t forwardRelays = m_fpgaDIO->readSlowValue_RelayFwd(&localStatus);
204 wpi_setError(localStatus);
205 return (forwardRelays & (1 << (channel - 1))) != 0;
213 tRioStatusCode localStatus = NiFpga_Status_Success;
214 uint8_t forwardRelays = m_fpgaDIO->readSlowValue_RelayFwd(&localStatus);
215 wpi_setError(localStatus);
216 return forwardRelays;
224 tRioStatusCode localStatus = NiFpga_Status_Success;
225 uint8_t reverseRelays = m_fpgaDIO->readSlowValue_RelayRev(&localStatus);
226 wpi_setError(localStatus);
227 return (reverseRelays & (1 << (channel - 1))) != 0;
236 tRioStatusCode localStatus = NiFpga_Status_Success;
237 uint8_t reverseRelays = m_fpgaDIO->readSlowValue_RelayRev(&localStatus);
238 wpi_setError(localStatus);
239 return reverseRelays;
256 if (DIOChannels->
Allocate(kDigitalChannels * (
m_moduleNumber - 1) + channel - 1, buf) == ~0ul)
return false;
257 tRioStatusCode localStatus = NiFpga_Status_Success;
260 uint32_t bitToSet = 1 << (RemapDigitalChannel(channel - 1));
261 uint32_t outputEnable = m_fpgaDIO->readOutputEnable(&localStatus);
262 uint32_t outputEnableValue;
265 outputEnableValue = outputEnable & (~bitToSet);
269 outputEnableValue = outputEnable | bitToSet;
271 m_fpgaDIO->writeOutputEnable(outputEnableValue, &localStatus);
273 wpi_setError(localStatus);
296 if (value != 0 && value != 1)
298 wpi_setWPIError(NonBinaryDigitalValue);
302 tRioStatusCode localStatus = NiFpga_Status_Success;
305 uint16_t currentDIO = m_fpgaDIO->readDO(&localStatus);
308 currentDIO = currentDIO & ~(1 << RemapDigitalChannel(channel - 1));
312 currentDIO = currentDIO | (1 << RemapDigitalChannel(channel - 1));
314 m_fpgaDIO->writeDO(currentDIO, &localStatus);
316 wpi_setError(localStatus);
328 tRioStatusCode localStatus = NiFpga_Status_Success;
329 uint32_t currentDIO = m_fpgaDIO->readDI(&localStatus);
330 wpi_setError(localStatus);
336 return ((currentDIO >> RemapDigitalChannel(channel - 1)) & 1) != 0;
345 tRioStatusCode localStatus = NiFpga_Status_Success;
346 uint32_t currentDIO = m_fpgaDIO->readDI(&localStatus);
347 wpi_setError(localStatus);
360 tRioStatusCode localStatus = NiFpga_Status_Success;
361 uint32_t currentOutputEnable = m_fpgaDIO->readOutputEnable(&localStatus);
362 wpi_setError(localStatus);
368 return ((currentOutputEnable >> RemapDigitalChannel(channel - 1)) & 1) != 0;
378 tRioStatusCode localStatus = NiFpga_Status_Success;
379 uint32_t currentOutputEnable = m_fpgaDIO->readOutputEnable(&localStatus);
380 wpi_setError(localStatus);
381 return currentOutputEnable;
393 uint16_t mask = 1 << RemapDigitalChannel(channel - 1);
394 tRioStatusCode localStatus = NiFpga_Status_Success;
395 m_fpgaDIO->writePulseLength((uint8_t)(1.0e9 * pulseLength / (m_fpgaDIO->readLoopTiming(&localStatus) * 25)), &localStatus);
396 m_fpgaDIO->writePulse(mask, &localStatus);
397 wpi_setError(localStatus);
407 uint16_t mask = 1 << RemapDigitalChannel(channel - 1);
408 tRioStatusCode localStatus = NiFpga_Status_Success;
409 uint16_t pulseRegister = m_fpgaDIO->readPulse(&localStatus);
410 wpi_setError(localStatus);
411 return (pulseRegister & mask) != 0;
421 tRioStatusCode localStatus = NiFpga_Status_Success;
422 uint16_t pulseRegister = m_fpgaDIO->readPulse(&localStatus);
423 wpi_setError(localStatus);
424 return pulseRegister != 0;
447 if (pwmGenerator == ~0ul)
return;
462 tRioStatusCode localStatus = NiFpga_Status_Success;
463 uint8_t pwmPeriodPower = (uint8_t)(log(1.0 / (m_fpgaDIO->readLoopTiming(&localStatus) * 0.25E-6 * rate))/log(2.0) + 0.5);
464 m_fpgaDIO->writeDO_PWMConfig_PeriodPower(pwmPeriodPower, &localStatus);
465 wpi_setError(localStatus);
476 if (pwmGenerator == ~0ul)
return;
477 tRioStatusCode localStatus = NiFpga_Status_Success;
481 m_fpgaDIO->writeDO_PWMConfig_OutputSelect_0(RemapDigitalChannel(channel - 1), &localStatus);
484 m_fpgaDIO->writeDO_PWMConfig_OutputSelect_1(RemapDigitalChannel(channel - 1), &localStatus);
487 m_fpgaDIO->writeDO_PWMConfig_OutputSelect_2(RemapDigitalChannel(channel - 1), &localStatus);
490 m_fpgaDIO->writeDO_PWMConfig_OutputSelect_3(RemapDigitalChannel(channel - 1), &localStatus);
493 wpi_setError(localStatus);
504 if (pwmGenerator == ~0ul)
return;
505 if (dutyCycle > 1.0) dutyCycle = 1.0;
506 if (dutyCycle < 0.0) dutyCycle = 0.0;
507 float rawDutyCycle = 256.0 * dutyCycle;
508 if (rawDutyCycle > 255.5) rawDutyCycle = 255.5;
509 tRioStatusCode localStatus = NiFpga_Status_Success;
512 uint8_t pwmPeriodPower = m_fpgaDIO->readDO_PWMConfig_PeriodPower(&localStatus);
513 if (pwmPeriodPower < 4)
516 rawDutyCycle = rawDutyCycle / pow(2.0, 4 - pwmPeriodPower);
518 m_fpgaDIO->writeDO_PWMDutyCycle(pwmGenerator, (uint8_t)rawDutyCycle, &localStatus);
520 wpi_setError(localStatus);
530 tRioStatusCode localStatus = NiFpga_Status_Success;
531 uint16_t timing = m_fpgaDIO->readLoopTiming(&localStatus);
532 wpi_setError(localStatus);
546 return new I2C(
this, address);
void SetRelayReverse(uint32_t channel, bool on)
uint8_t GetPWM(uint32_t channel)
uint8_t GetRelayForward()
void SetDIO(uint32_t channel, short value)
static bool CheckPWMChannel(uint32_t channel)
void SetRelayForward(uint32_t channel, bool on)
void Pulse(uint32_t channel, float pulseLength)
void SetDO_PWMOutputChannel(uint32_t pwmGenerator, uint32_t channel)
DigitalModule(uint8_t moduleNumber)
void FreeDIO(uint32_t channel)
void SetDO_PWMDutyCycle(uint32_t pwmGenerator, float dutyCycle)
bool AllocateDIO(uint32_t channel, bool input)
static const int32_t kDefaultPwmStepsDown
void Free(uint32_t index)
void SetDO_PWMRate(float rate)
uint32_t Allocate(const char *resourceDesc)
uint8_t m_moduleNumber
The module index within the module type.
uint32_t AllocateDO_PWM()
static constexpr float kDefaultPwmCenter
static bool CheckDigitalModule(uint8_t moduleNumber)
void SetPWM(uint32_t channel, uint8_t value)
static DigitalModule * GetInstance(uint8_t moduleNumber)
static void CreateResourceObject(Resource **r, uint32_t elements)
static constexpr float kDefaultPwmPeriod
static Module * GetModule(nLoadOut::tModuleType type, uint8_t number)
static bool CheckRelayChannel(uint32_t channel)
I2C * GetI2C(uint32_t address)
void AddToSingletonList()
uint16_t GetDIODirection()
void SetPWMPeriodScale(uint32_t channel, uint32_t squelchMask)
uint8_t GetRelayReverse()
void FreeDO_PWM(uint32_t pwmGenerator)