// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. #include "hal/DutyCycle.h" #include #include "ConstantsInternal.h" #include "DigitalInternal.h" #include "DutyCycleInternal.h" #include "HALInitializer.h" #include "PortsInternal.h" #include "hal/ChipObject.h" #include "hal/Errors.h" #include "hal/handles/HandlesInternal.h" #include "hal/handles/LimitedHandleResource.h" using namespace hal; namespace hal { LimitedHandleResource* dutyCycleHandles; namespace init { void InitializeDutyCycle() { static LimitedHandleResource dcH; dutyCycleHandles = &dcH; } } // namespace init } // namespace hal extern "C" { HAL_DutyCycleHandle HAL_InitializeDutyCycle(HAL_Handle digitalSourceHandle, HAL_AnalogTriggerType triggerType, int32_t* status) { hal::init::CheckInit(); bool routingAnalogTrigger = false; uint8_t routingChannel = 0; uint8_t routingModule = 0; bool success = remapDigitalSource(digitalSourceHandle, triggerType, routingChannel, routingModule, routingAnalogTrigger); if (!success) { *status = HAL_HANDLE_ERROR; return HAL_kInvalidHandle; } HAL_DutyCycleHandle handle = dutyCycleHandles->Allocate(); if (handle == HAL_kInvalidHandle) { *status = NO_AVAILABLE_RESOURCES; return HAL_kInvalidHandle; } auto dutyCycle = dutyCycleHandles->Get(handle); uint32_t index = static_cast(getHandleIndex(handle)); dutyCycle->dutyCycle.reset(tDutyCycle::create(index, status)); dutyCycle->dutyCycle->writeSource_AnalogTrigger(routingAnalogTrigger, status); dutyCycle->dutyCycle->writeSource_Channel(routingChannel, status); dutyCycle->dutyCycle->writeSource_Module(routingModule, status); dutyCycle->index = index; return handle; } void HAL_FreeDutyCycle(HAL_DutyCycleHandle dutyCycleHandle) { // Just free it, the unique ptr will take care of everything else dutyCycleHandles->Free(dutyCycleHandle); } void HAL_SetDutyCycleSimDevice(HAL_EncoderHandle handle, HAL_SimDeviceHandle device) {} int32_t HAL_GetDutyCycleFrequency(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) { auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle); if (!dutyCycle) { *status = HAL_HANDLE_ERROR; return 0; } // TODO Handle Overflow unsigned char overflow = 0; return dutyCycle->dutyCycle->readFrequency(&overflow, status); } double HAL_GetDutyCycleOutput(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) { auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle); if (!dutyCycle) { *status = HAL_HANDLE_ERROR; return 0; } // TODO Handle Overflow unsigned char overflow = 0; uint32_t output = dutyCycle->dutyCycle->readOutput(&overflow, status); return output / static_cast(kDutyCycleScaleFactor); } int32_t HAL_GetDutyCycleHighTime(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) { auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle); if (!dutyCycle) { *status = HAL_HANDLE_ERROR; return 0; } // TODO Handle Overflow unsigned char overflow = 0; uint32_t highTime = dutyCycle->dutyCycle->readHighTicks(&overflow, status); if (*status != 0) { return 0; } // Output will be at max 4e7, so x25 will still fit in a 32 bit signed int. return highTime * 25; } int32_t HAL_GetDutyCycleOutputScaleFactor(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) { return kDutyCycleScaleFactor; } int32_t HAL_GetDutyCycleFPGAIndex(HAL_DutyCycleHandle dutyCycleHandle, int32_t* status) { auto dutyCycle = dutyCycleHandles->Get(dutyCycleHandle); if (!dutyCycle) { *status = HAL_HANDLE_ERROR; return -1; } return dutyCycle->index; } } // extern "C"