2016-05-26 12:56:39 -07:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
/* Copyright (c) FIRST 2016. 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 the root directory of */
|
|
|
|
|
/* the project. */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "HAL/PWM.h"
|
|
|
|
|
|
2016-07-08 21:29:29 -07:00
|
|
|
#include "ConstantsInternal.h"
|
2016-05-26 12:56:39 -07:00
|
|
|
#include "DigitalInternal.h"
|
2016-07-13 20:29:28 -07:00
|
|
|
#include "HAL/handles/HandlesInternal.h"
|
2016-07-02 23:19:14 -07:00
|
|
|
#include "PortsInternal.h"
|
2016-05-26 12:56:39 -07:00
|
|
|
|
|
|
|
|
using namespace hal;
|
|
|
|
|
|
2016-07-08 21:29:29 -07:00
|
|
|
static inline int32_t GetMaxPositivePwm(DigitalPort* port) {
|
|
|
|
|
return port->maxPwm;
|
|
|
|
|
}
|
|
|
|
|
static inline int32_t GetMinPositivePwm(DigitalPort* port) {
|
|
|
|
|
return port->eliminateDeadband ? port->deadbandMaxPwm : port->centerPwm + 1;
|
|
|
|
|
}
|
|
|
|
|
static inline int32_t GetCenterPwm(DigitalPort* port) {
|
|
|
|
|
return port->centerPwm;
|
|
|
|
|
}
|
|
|
|
|
static inline int32_t GetMaxNegativePwm(DigitalPort* port) {
|
|
|
|
|
return port->eliminateDeadband ? port->deadbandMinPwm : port->centerPwm - 1;
|
|
|
|
|
}
|
|
|
|
|
static inline int32_t GetMinNegativePwm(DigitalPort* port) {
|
|
|
|
|
return port->minPwm;
|
|
|
|
|
}
|
|
|
|
|
static inline int32_t GetPositiveScaleFactor(DigitalPort* port) {
|
|
|
|
|
return GetMaxPositivePwm(port) - GetMinPositivePwm(port);
|
|
|
|
|
} ///< The scale for positive speeds.
|
|
|
|
|
static inline int32_t GetNegativeScaleFactor(DigitalPort* port) {
|
|
|
|
|
return GetMaxNegativePwm(port) - GetMinNegativePwm(port);
|
|
|
|
|
} ///< The scale for negative speeds.
|
|
|
|
|
static inline int32_t GetFullRangeScaleFactor(DigitalPort* port) {
|
|
|
|
|
return GetMaxPositivePwm(port) - GetMinNegativePwm(port);
|
|
|
|
|
} ///< The scale for positions.
|
|
|
|
|
|
2016-05-26 12:56:39 -07:00
|
|
|
extern "C" {
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
HAL_DigitalHandle HAL_InitializePWMPort(HAL_PortHandle portHandle,
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t* status) {
|
2016-06-30 21:39:09 -07:00
|
|
|
initializeDigital(status);
|
|
|
|
|
|
2016-07-09 00:24:26 -07:00
|
|
|
if (*status != 0) return HAL_kInvalidHandle;
|
2016-06-30 21:39:09 -07:00
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
int16_t channel = getPortHandleChannel(portHandle);
|
|
|
|
|
if (channel == InvalidHandleIndex) {
|
2016-05-26 12:56:39 -07:00
|
|
|
*status = PARAMETER_OUT_OF_RANGE;
|
2016-07-09 00:24:26 -07:00
|
|
|
return HAL_kInvalidHandle;
|
2016-06-30 21:39:09 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
uint8_t origChannel = static_cast<uint8_t>(channel);
|
2016-06-30 21:39:09 -07:00
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
if (origChannel < kNumPWMHeaders) {
|
|
|
|
|
channel += kNumDigitalChannels; // remap Headers to end of allocations
|
2016-05-26 12:56:39 -07:00
|
|
|
} else {
|
2016-08-12 13:45:28 -07:00
|
|
|
channel = remapMXPPWMChannel(channel) + 10; // remap MXP to proper channel
|
2016-06-30 21:39:09 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
auto handle =
|
|
|
|
|
digitalChannelHandles.Allocate(channel, HAL_HandleEnum::PWM, status);
|
2016-06-30 21:39:09 -07:00
|
|
|
|
|
|
|
|
if (*status != 0)
|
2016-07-09 00:24:26 -07:00
|
|
|
return HAL_kInvalidHandle; // failed to allocate. Pass error back.
|
2016-06-30 21:39:09 -07:00
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(handle, HAL_HandleEnum::PWM);
|
2016-06-30 21:39:09 -07:00
|
|
|
if (port == nullptr) { // would only occur on thread issue.
|
2016-07-03 17:27:06 -07:00
|
|
|
*status = HAL_HANDLE_ERROR;
|
2016-07-09 00:24:26 -07:00
|
|
|
return HAL_kInvalidHandle;
|
2016-05-26 12:56:39 -07:00
|
|
|
}
|
2016-06-30 21:39:09 -07:00
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
port->channel = origChannel;
|
2016-06-30 21:39:09 -07:00
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
int32_t bitToSet = 1 << remapMXPPWMChannel(port->channel);
|
2016-07-13 20:16:45 -07:00
|
|
|
uint16_t specialFunctions =
|
2016-07-10 17:47:44 -07:00
|
|
|
digitalSystem->readEnableMXPSpecialFunction(status);
|
2016-06-30 21:39:09 -07:00
|
|
|
digitalSystem->writeEnableMXPSpecialFunction(specialFunctions | bitToSet,
|
|
|
|
|
status);
|
|
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
|
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-06-30 21:39:09 -07:00
|
|
|
if (port == nullptr) {
|
2016-07-03 17:27:06 -07:00
|
|
|
*status = HAL_HANDLE_ERROR;
|
2016-06-30 21:39:09 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
if (port->channel > tPWM::kNumHdrRegisters - 1) {
|
|
|
|
|
int32_t bitToUnset = 1 << remapMXPPWMChannel(port->channel);
|
2016-07-13 20:16:45 -07:00
|
|
|
uint16_t specialFunctions =
|
2016-06-30 21:39:09 -07:00
|
|
|
digitalSystem->readEnableMXPSpecialFunction(status);
|
|
|
|
|
digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToUnset,
|
|
|
|
|
status);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
digitalChannelHandles.Free(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-05-26 12:56:39 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
HAL_Bool HAL_CheckPWMChannel(int32_t channel) {
|
|
|
|
|
return channel < kNumPWMChannels && channel >= 0;
|
2016-07-12 10:45:14 -07:00
|
|
|
}
|
2016-06-30 21:39:09 -07:00
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_SetPWMConfig(HAL_DigitalHandle pwmPortHandle, double max,
|
2016-07-09 00:24:26 -07:00
|
|
|
double deadbandMax, double center, double deadbandMin,
|
|
|
|
|
double min, int32_t* status) {
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// calculate the loop time in milliseconds
|
|
|
|
|
double loopTime =
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_GetLoopTiming(status) / (kSystemClockTicksPerMicrosecond * 1e3);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (*status != 0) return;
|
|
|
|
|
|
2016-08-11 23:38:45 -07:00
|
|
|
int32_t maxPwm = static_cast<int32_t>((max - kDefaultPwmCenter) / loopTime +
|
|
|
|
|
kDefaultPwmStepsDown - 1);
|
|
|
|
|
int32_t deadbandMaxPwm = static_cast<int32_t>(
|
2016-07-08 21:29:29 -07:00
|
|
|
(deadbandMax - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
|
2016-08-11 23:38:45 -07:00
|
|
|
int32_t centerPwm = static_cast<int32_t>(
|
|
|
|
|
(center - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
|
|
|
|
|
int32_t deadbandMinPwm = static_cast<int32_t>(
|
2016-07-08 21:29:29 -07:00
|
|
|
(deadbandMin - kDefaultPwmCenter) / loopTime + kDefaultPwmStepsDown - 1);
|
2016-08-11 23:38:45 -07:00
|
|
|
int32_t minPwm = static_cast<int32_t>((min - kDefaultPwmCenter) / loopTime +
|
|
|
|
|
kDefaultPwmStepsDown - 1);
|
2016-07-08 21:29:29 -07:00
|
|
|
|
|
|
|
|
port->maxPwm = maxPwm;
|
|
|
|
|
port->deadbandMaxPwm = deadbandMaxPwm;
|
|
|
|
|
port->deadbandMinPwm = deadbandMinPwm;
|
|
|
|
|
port->centerPwm = centerPwm;
|
|
|
|
|
port->minPwm = minPwm;
|
|
|
|
|
port->configSet = true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_SetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t maxPwm,
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t deadbandMaxPwm, int32_t centerPwm,
|
|
|
|
|
int32_t deadbandMinPwm, int32_t minPwm,
|
|
|
|
|
int32_t* status) {
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
port->maxPwm = maxPwm;
|
|
|
|
|
port->deadbandMaxPwm = deadbandMaxPwm;
|
|
|
|
|
port->deadbandMinPwm = deadbandMinPwm;
|
|
|
|
|
port->centerPwm = centerPwm;
|
|
|
|
|
port->minPwm = minPwm;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_GetPWMConfigRaw(HAL_DigitalHandle pwmPortHandle, int32_t* maxPwm,
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t* deadbandMaxPwm, int32_t* centerPwm,
|
|
|
|
|
int32_t* deadbandMinPwm, int32_t* minPwm,
|
|
|
|
|
int32_t* status) {
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
*maxPwm = port->maxPwm;
|
|
|
|
|
*deadbandMaxPwm = port->deadbandMaxPwm;
|
|
|
|
|
*deadbandMinPwm = port->deadbandMinPwm;
|
|
|
|
|
*centerPwm = port->centerPwm;
|
|
|
|
|
*minPwm = port->minPwm;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_SetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
|
2016-07-12 10:45:14 -07:00
|
|
|
HAL_Bool eliminateDeadband, int32_t* status) {
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
port->eliminateDeadband = eliminateDeadband;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
HAL_Bool HAL_GetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
|
2016-07-12 10:45:14 -07:00
|
|
|
int32_t* status) {
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return port->eliminateDeadband;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-26 12:56:39 -07:00
|
|
|
/**
|
|
|
|
|
* Set a PWM channel to the desired value. The values range from 0 to 255 and
|
|
|
|
|
* the period is controlled
|
|
|
|
|
* by the PWM Period and MinHigh registers.
|
|
|
|
|
*
|
|
|
|
|
* @param channel The PWM channel to set.
|
|
|
|
|
* @param value The PWM value to set.
|
|
|
|
|
*/
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_SetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t value,
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t* status) {
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-06-30 21:39:09 -07:00
|
|
|
if (port == nullptr) {
|
2016-07-03 17:27:06 -07:00
|
|
|
*status = HAL_HANDLE_ERROR;
|
2016-05-26 12:56:39 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
if (port->channel < tPWM::kNumHdrRegisters) {
|
|
|
|
|
pwmSystem->writeHdr(port->channel, value, status);
|
2016-05-26 12:56:39 -07:00
|
|
|
} else {
|
2016-08-12 13:45:28 -07:00
|
|
|
pwmSystem->writeMXP(port->channel - tPWM::kNumHdrRegisters, value, status);
|
2016-05-26 12:56:39 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-08 21:29:29 -07:00
|
|
|
/**
|
|
|
|
|
* Set a PWM channel to the desired scaled value. The values range from -1 to 1
|
|
|
|
|
* and
|
|
|
|
|
* the period is controlled
|
|
|
|
|
* by the PWM Period and MinHigh registers.
|
|
|
|
|
*
|
|
|
|
|
* @param channel The PWM channel to set.
|
|
|
|
|
* @param value The scaled PWM value to set.
|
|
|
|
|
*/
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_SetPWMSpeed(HAL_DigitalHandle pwmPortHandle, double speed,
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t* status) {
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!port->configSet) {
|
|
|
|
|
*status = INCOMPATIBLE_STATE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DigitalPort* dPort = port.get();
|
|
|
|
|
|
|
|
|
|
if (speed < -1.0) {
|
|
|
|
|
speed = -1.0;
|
|
|
|
|
} else if (speed > 1.0) {
|
|
|
|
|
speed = 1.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// calculate the desired output pwm value by scaling the speed appropriately
|
|
|
|
|
int32_t rawValue;
|
|
|
|
|
if (speed == 0.0) {
|
|
|
|
|
rawValue = GetCenterPwm(dPort);
|
|
|
|
|
} else if (speed > 0.0) {
|
2016-07-10 17:47:44 -07:00
|
|
|
rawValue = static_cast<int32_t>(
|
2016-07-12 10:45:14 -07:00
|
|
|
speed * static_cast<double>(GetPositiveScaleFactor(dPort)) +
|
|
|
|
|
static_cast<double>(GetMinPositivePwm(dPort)) + 0.5);
|
2016-07-08 21:29:29 -07:00
|
|
|
} else {
|
2016-07-10 17:47:44 -07:00
|
|
|
rawValue = static_cast<int32_t>(
|
2016-07-12 10:45:14 -07:00
|
|
|
speed * static_cast<double>(GetNegativeScaleFactor(dPort)) +
|
|
|
|
|
static_cast<double>(GetMaxNegativePwm(dPort)) + 0.5);
|
2016-07-08 21:29:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!((rawValue >= GetMinNegativePwm(dPort)) &&
|
|
|
|
|
(rawValue <= GetMaxPositivePwm(dPort))) ||
|
|
|
|
|
rawValue == kPwmDisabled) {
|
|
|
|
|
*status = HAL_PWM_SCALE_ERROR;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
HAL_SetPWMRaw(pwmPortHandle, rawValue, status);
|
2016-07-08 21:29:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set a PWM channel to the desired position value. The values range from 0 to 1
|
|
|
|
|
* and
|
|
|
|
|
* the period is controlled
|
|
|
|
|
* by the PWM Period and MinHigh registers.
|
|
|
|
|
*
|
|
|
|
|
* @param channel The PWM channel to set.
|
|
|
|
|
* @param value The scaled PWM value to set.
|
|
|
|
|
*/
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_SetPWMPosition(HAL_DigitalHandle pwmPortHandle, double pos,
|
2016-07-09 00:24:26 -07:00
|
|
|
int32_t* status) {
|
2016-08-12 13:45:28 -07:00
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!port->configSet) {
|
|
|
|
|
*status = INCOMPATIBLE_STATE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
DigitalPort* dPort = port.get();
|
|
|
|
|
|
|
|
|
|
if (pos < 0.0) {
|
|
|
|
|
pos = 0.0;
|
|
|
|
|
} else if (pos > 1.0) {
|
|
|
|
|
pos = 1.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// note, need to perform the multiplication below as floating point before
|
|
|
|
|
// converting to int
|
2016-07-12 10:45:14 -07:00
|
|
|
int32_t rawValue = static_cast<int32_t>(
|
|
|
|
|
(pos * static_cast<double>(GetFullRangeScaleFactor(dPort))) +
|
2016-07-10 17:47:44 -07:00
|
|
|
GetMinNegativePwm(dPort));
|
2016-07-08 21:29:29 -07:00
|
|
|
|
|
|
|
|
if (rawValue == kPwmDisabled) {
|
|
|
|
|
*status = HAL_PWM_SCALE_ERROR;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
HAL_SetPWMRaw(pwmPortHandle, rawValue, status);
|
2016-07-08 21:29:29 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_SetPWMDisabled(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
|
|
|
|
HAL_SetPWMRaw(pwmPortHandle, kPwmDisabled, status);
|
2016-07-08 21:29:29 -07:00
|
|
|
}
|
|
|
|
|
|
2016-05-26 12:56:39 -07:00
|
|
|
/**
|
|
|
|
|
* Get a value from a PWM channel. The values range from 0 to 255.
|
|
|
|
|
*
|
|
|
|
|
* @param channel The PWM channel to read from.
|
|
|
|
|
* @return The raw PWM value.
|
|
|
|
|
*/
|
2016-08-12 13:45:28 -07:00
|
|
|
int32_t HAL_GetPWMRaw(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
|
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-06-30 21:39:09 -07:00
|
|
|
if (port == nullptr) {
|
2016-07-03 17:27:06 -07:00
|
|
|
*status = HAL_HANDLE_ERROR;
|
2016-05-26 12:56:39 -07:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
if (port->channel < tPWM::kNumHdrRegisters) {
|
|
|
|
|
return pwmSystem->readHdr(port->channel, status);
|
2016-05-26 12:56:39 -07:00
|
|
|
} else {
|
2016-08-12 13:45:28 -07:00
|
|
|
return pwmSystem->readMXP(port->channel - tPWM::kNumHdrRegisters, status);
|
2016-05-26 12:56:39 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-08 21:29:29 -07:00
|
|
|
/**
|
|
|
|
|
* Get a scaled value from a PWM channel. The values range from -1 to 1.
|
|
|
|
|
*
|
|
|
|
|
* @param channel The PWM channel to read from.
|
|
|
|
|
* @return The scaled PWM value.
|
|
|
|
|
*/
|
2016-08-12 13:45:28 -07:00
|
|
|
double HAL_GetPWMSpeed(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
|
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (!port->configSet) {
|
|
|
|
|
*status = INCOMPATIBLE_STATE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
int32_t value = HAL_GetPWMRaw(pwmPortHandle, status);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (*status != 0) return 0;
|
|
|
|
|
DigitalPort* dPort = port.get();
|
|
|
|
|
|
|
|
|
|
if (value == kPwmDisabled) {
|
|
|
|
|
return 0.0;
|
|
|
|
|
} else if (value > GetMaxPositivePwm(dPort)) {
|
|
|
|
|
return 1.0;
|
|
|
|
|
} else if (value < GetMinNegativePwm(dPort)) {
|
|
|
|
|
return -1.0;
|
|
|
|
|
} else if (value > GetMinPositivePwm(dPort)) {
|
2016-07-12 10:45:14 -07:00
|
|
|
return static_cast<double>(value - GetMinPositivePwm(dPort)) /
|
|
|
|
|
static_cast<double>(GetPositiveScaleFactor(dPort));
|
2016-07-08 21:29:29 -07:00
|
|
|
} else if (value < GetMaxNegativePwm(dPort)) {
|
2016-07-12 10:45:14 -07:00
|
|
|
return static_cast<double>(value - GetMaxNegativePwm(dPort)) /
|
|
|
|
|
static_cast<double>(GetNegativeScaleFactor(dPort));
|
2016-07-08 21:29:29 -07:00
|
|
|
} else {
|
|
|
|
|
return 0.0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get a position value from a PWM channel. The values range from 0 to 1.
|
|
|
|
|
*
|
|
|
|
|
* @param channel The PWM channel to read from.
|
|
|
|
|
* @return The scaled PWM value.
|
|
|
|
|
*/
|
2016-08-12 13:45:28 -07:00
|
|
|
double HAL_GetPWMPosition(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
|
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (port == nullptr) {
|
|
|
|
|
*status = HAL_HANDLE_ERROR;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (!port->configSet) {
|
|
|
|
|
*status = INCOMPATIBLE_STATE;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
int32_t value = HAL_GetPWMRaw(pwmPortHandle, status);
|
2016-07-08 21:29:29 -07:00
|
|
|
if (*status != 0) return 0;
|
|
|
|
|
DigitalPort* dPort = port.get();
|
|
|
|
|
|
|
|
|
|
if (value < GetMinNegativePwm(dPort)) {
|
|
|
|
|
return 0.0;
|
|
|
|
|
} else if (value > GetMaxPositivePwm(dPort)) {
|
|
|
|
|
return 1.0;
|
|
|
|
|
} else {
|
2016-07-12 10:45:14 -07:00
|
|
|
return static_cast<double>(value - GetMinNegativePwm(dPort)) /
|
|
|
|
|
static_cast<double>(GetFullRangeScaleFactor(dPort));
|
2016-07-08 21:29:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_LatchPWMZero(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
|
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-06-30 21:39:09 -07:00
|
|
|
if (port == nullptr) {
|
2016-07-03 17:27:06 -07:00
|
|
|
*status = HAL_HANDLE_ERROR;
|
2016-05-26 12:56:39 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
pwmSystem->writeZeroLatch(port->channel, true, status);
|
|
|
|
|
pwmSystem->writeZeroLatch(port->channel, false, status);
|
2016-05-26 12:56:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set how how often the PWM signal is squelched, thus scaling the period.
|
|
|
|
|
*
|
|
|
|
|
* @param channel The PWM channel to configure.
|
|
|
|
|
* @param squelchMask The 2-bit mask of outputs to squelch.
|
|
|
|
|
*/
|
2016-08-12 13:45:28 -07:00
|
|
|
void HAL_SetPWMPeriodScale(HAL_DigitalHandle pwmPortHandle, int32_t squelchMask,
|
|
|
|
|
int32_t* status) {
|
|
|
|
|
auto port = digitalChannelHandles.Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
2016-06-30 21:39:09 -07:00
|
|
|
if (port == nullptr) {
|
2016-07-03 17:27:06 -07:00
|
|
|
*status = HAL_HANDLE_ERROR;
|
2016-05-26 12:56:39 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 13:45:28 -07:00
|
|
|
if (port->channel < tPWM::kNumPeriodScaleHdrElements) {
|
|
|
|
|
pwmSystem->writePeriodScaleHdr(port->channel, squelchMask, status);
|
2016-05-26 12:56:39 -07:00
|
|
|
} else {
|
2016-08-12 13:45:28 -07:00
|
|
|
pwmSystem->writePeriodScaleMXP(
|
|
|
|
|
port->channel - tPWM::kNumPeriodScaleHdrElements, squelchMask, status);
|
2016-05-26 12:56:39 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the loop timing of the PWM system
|
|
|
|
|
*
|
|
|
|
|
* @return The loop time
|
|
|
|
|
*/
|
2016-07-12 10:45:14 -07:00
|
|
|
int32_t HAL_GetLoopTiming(int32_t* status) {
|
2016-05-26 12:56:39 -07:00
|
|
|
return pwmSystem->readLoopTiming(status);
|
|
|
|
|
}
|
|
|
|
|
}
|