Move PWM allocation to HAL to allow for checking against DIO allocation

Re-number MXP DIO to match pinout (include SPI and I2C pins) (fixes artf2664)
Change PWM MXP mapping to accommodate DIO re-mapping
This re-implementation also fixes artf2668 for C++ and Java
Change the test bench to reflect this change also

Change-Id: If30bd6a85a9f1f619fbde06a4ecd595a15fd28f7
This commit is contained in:
Kevin O'Connor
2014-08-05 17:27:43 -04:00
committed by Thomas Clark
parent deb335d96d
commit 59473ab7a7
9 changed files with 105 additions and 41 deletions

View File

@@ -21,6 +21,8 @@ extern "C"
bool checkRelayChannel(void* digital_port_pointer);
void setPWM(void* digital_port_pointer, unsigned short value, int32_t *status);
bool allocatePWMChannel(void* digital_port_pointer, int32_t *status);
void freePWMChannel(void* digital_port_pointer, int32_t *status);
unsigned short getPWM(void* digital_port_pointer, int32_t *status);
void setPWMPeriodScale(void* digital_port_pointer, uint32_t squelchMask, int32_t *status);
void* allocatePWM(int32_t *status);

View File

@@ -62,6 +62,7 @@ tRelay* relaySystem = NULL;
tPWM* pwmSystem = NULL;
Resource *DIOChannels = NULL;
Resource *DO_PWMGenerators = NULL;
Resource *PWMChannels = NULL;
bool digitalSystemsInitialized = false;
@@ -99,6 +100,7 @@ void initializeDigital(int32_t *status) {
Resource::CreateResourceObject(&DIOChannels, tDIO::kNumSystems * kDigitalPins);
Resource::CreateResourceObject(&DO_PWMGenerators, tDIO::kNumPWMDutyCycleAElements + tDIO::kNumPWMDutyCycleBElements);
Resource::CreateResourceObject(&PWMChannels, tPWM::kNumSystems * kPwmPins);
digitalSystem = tDIO::create(status);
// Relay Setup
@@ -165,15 +167,19 @@ bool checkRelayChannel(void* digital_port_pointer) {
}
/**
* Map DIO pin numbers from their physical number (10 to 19) to their position
* Map DIO pin numbers from their physical number (10 to 26) to their position
* in the bit field.
*/
uint32_t remapMXPChannel(uint32_t pin) {
if(pin < 14) {
return pin - 10; // First four digital headers
} else {
return pin - 6; // Last 8 digital headers, not counting the SPI pins
}
return pin - 10;
}
uint32_t remapMXPPWMChannel(uint32_t pin) {
if(pin < 14) {
return pin - 10; //first block of 4 pwms (MXP 0-3)
} else {
return pin - 6; //block of PWMs after SPI
}
}
/**
@@ -191,11 +197,6 @@ void setPWM(void* digital_port_pointer, unsigned short value, int32_t *status) {
pwmSystem->writeHdr(port->port.pin, value, status);
} else {
pwmSystem->writeMXP(port->port.pin - tPWM::kNumHdrRegisters, value, status);
// Enable special functions on this pin
uint32_t bitToSet = 1 << remapMXPChannel(port->port.pin);
short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status);
digitalSystem->writeEnableMXPSpecialFunction(specialFunctions | bitToSet, status);
}
}
@@ -426,6 +427,32 @@ bool allocateDIO(void* digital_port_pointer, bool input, int32_t *status) {
return true;
}
bool allocatePWMChannel(void* digital_port_pointer, int32_t *status) {
DigitalPort* port = (DigitalPort*) digital_port_pointer;
char buf[64];
snprintf(buf, 64, "PWM %d", port->port.pin);
if (PWMChannels->Allocate(port->port.pin, buf) == ~0ul) return false;
if (port->port.pin > tPWM::kNumHdrRegisters-1) {
snprintf(buf, 64, "PWM %d and DIO %d", port->port.pin, remapMXPPWMChannel(port->port.pin) + 10);
if (DIOChannels->Allocate(remapMXPPWMChannel(port->port.pin) + 10, buf) == ~0ul) return false;
uint32_t bitToSet = 1 << remapMXPPWMChannel(port->port.pin);
short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status);
digitalSystem->writeEnableMXPSpecialFunction(specialFunctions | bitToSet, status);
}
return true;
}
void freePWMChannel(void* digital_port_pointer, int32_t *status) {
DigitalPort* port = (DigitalPort*) digital_port_pointer;
PWMChannels->Free(port->port.pin);
if(port->port.pin > tPWM::kNumHdrRegisters-1) {
DIOChannels->Free(remapMXPPWMChannel(port->port.pin) + 10);
uint32_t bitToUnset = 1 << remapMXPPWMChannel(port->port.pin);
short specialFunctions = digitalSystem->readEnableMXPSpecialFunction(status);
digitalSystem->writeEnableMXPSpecialFunction(specialFunctions & ~bitToUnset, status);
}
}
/**
* Free the resource associated with a digital I/O channel.
*

View File

@@ -15,7 +15,6 @@ constexpr float PWM::kDefaultPwmPeriod;
constexpr float PWM::kDefaultPwmCenter;
const int32_t PWM::kDefaultPwmStepsDown;
const int32_t PWM::kPwmDisabled;
static Resource *allocated = NULL;
/**
* Initialize PWMs given a channel.
@@ -28,7 +27,6 @@ void PWM::InitPWM(uint32_t channel)
{
m_table = NULL;
char buf[64];
Resource::CreateResourceObject(&allocated, kPwmChannels);
if (!CheckPWMChannel(channel))
{
@@ -37,16 +35,12 @@ void PWM::InitPWM(uint32_t channel)
return;
}
snprintf(buf, 64, "PWM %d", channel);
if (allocated->Allocate(channel, buf) == ~0ul)
{
CloneError(allocated);
return;
}
int32_t status = 0;
allocatePWMChannel(m_pwm_ports[channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
m_channel = channel;
int32_t status = 0;
setPWM(m_pwm_ports[m_channel], kPwmDisabled, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
@@ -73,10 +67,12 @@ PWM::PWM(uint32_t channel)
PWM::~PWM()
{
int32_t status = 0;
setPWM(m_pwm_ports[m_channel], kPwmDisabled, &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
allocated->Free(m_channel);
freePWMChannel(m_pwm_ports[m_channel], &status);
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/**

View File

@@ -43,10 +43,10 @@ public:
static const uint32_t kFakePressureSwitchChannel = 11;
static const uint32_t kFakeSolenoid1Channel = 12;
static const uint32_t kFakeSolenoid2Channel = 13;
static const uint32_t kFakeRelayForward = 14;
static const uint32_t kFakeRelayReverse = 15;
static const uint32_t kFakeJaguarForwardLimit = 16;
static const uint32_t kFakeJaguarReverseLimit = 17;
static const uint32_t kFakeRelayForward = 18;
static const uint32_t kFakeRelayReverse = 19;
static const uint32_t kFakeJaguarForwardLimit = 20;
static const uint32_t kFakeJaguarReverseLimit = 21;
/* Relay channels */
static const uint32_t kRelayChannel = 0;

View File

@@ -37,8 +37,6 @@ import edu.wpi.first.wpilibj.hal.HALUtil;
* 0 = disabled (i.e. PWM output is held low)
*/
public class PWM extends SensorBase implements LiveWindowSendable {
private static Resource allocated = new Resource( kPwmChannels);
/**
* Represents the amount to multiply the minimum servo-pulse pwm period by.
*/
@@ -113,12 +111,6 @@ public class PWM extends SensorBase implements LiveWindowSendable {
*/
private void initPWM(final int channel) {
checkPWMChannel(channel);
try {
allocated.allocate(channel);
} catch (CheckedAllocationException e) {
throw new AllocationException(
"PWM channel " + channel + " is already allocated");
}
m_channel = channel;
ByteBuffer status = ByteBuffer.allocateDirect(4);
@@ -127,6 +119,13 @@ public class PWM extends SensorBase implements LiveWindowSendable {
m_port = DIOJNI.initializeDigitalPort(DIOJNI.getPort((byte) m_channel), status.asIntBuffer());
HALUtil.checkStatus(status.asIntBuffer());
if (!PWMJNI.allocatePWMChannel(m_port, status.asIntBuffer()))
{
throw new AllocationException(
"PWM channel " + channel + " is already allocated");
}
HALUtil.checkStatus(status.asIntBuffer());
PWMJNI.setPWM(m_port, (short) 0, status.asIntBuffer());
HALUtil.checkStatus(status.asIntBuffer());
@@ -156,10 +155,11 @@ public class PWM extends SensorBase implements LiveWindowSendable {
PWMJNI.setPWM(m_port, (short) 0, status.asIntBuffer());
HALUtil.checkStatus(status.asIntBuffer());
PWMJNI.freeDIO(m_port, status.asIntBuffer());
PWMJNI.freePWMChannel(m_port, status.asIntBuffer());
HALUtil.checkStatus(status.asIntBuffer());
allocated.free(m_channel);
PWMJNI.freeDIO(m_port, status.asIntBuffer());
HALUtil.checkStatus(status.asIntBuffer());
}
/**

View File

@@ -7,6 +7,8 @@ import edu.wpi.first.wpilibj.SensorBase;
public class PWMJNI extends DIOJNI {
public static native boolean allocatePWMChannel(ByteBuffer digital_port_pointer, IntBuffer status);
public static native void freePWMChannel(ByteBuffer digital_port_pointer, IntBuffer status);
public static native void setPWM(ByteBuffer digital_port_pointer, short value, IntBuffer status);
public static native short getPWM(ByteBuffer digital_port_pointer, IntBuffer status);
public static native void setPWMPeriodScale(ByteBuffer digital_port_pointer, int squelchMask, IntBuffer status);

View File

@@ -54,8 +54,8 @@ public class PCMTest extends AbstractComsSetup {
fakePressureSwitch = new DigitalOutput(11);
fakeCompressor = new AnalogInput(1);
solenoid1 = new Solenoid(0);
solenoid2 = new Solenoid(1);
solenoid1 = new Solenoid(7);
solenoid2 = new Solenoid(6);
fakeSolenoid1 = new DigitalInput(12);
fakeSolenoid2 = new DigitalInput(13);

View File

@@ -68,8 +68,8 @@ public final class TestBench {
/* CAN ASSOICATED CHANNELS */
public static final int kCANRelayPowerCycler = 1;
public static final int kFakeJaguarPotentiometer = 1;
public static final int kFakeJaguarForwardLimit = 16;
public static final int kFakeJaguarReverseLimit = 17;
public static final int kFakeJaguarForwardLimit = 20;
public static final int kFakeJaguarReverseLimit = 21;
public static final int kCANJaguarID = 2;
//THESE MUST BE IN INCREMENTING ORDER
@@ -310,12 +310,12 @@ public final class TestBench {
@Override
protected DigitalInput giveInputTwo() {
return new DigitalInput(14);
return new DigitalInput(18);
}
@Override
protected DigitalInput giveInputOne() {
return new DigitalInput(15);
return new DigitalInput(19);
}
};
return relay;

View File

@@ -14,6 +14,43 @@ TLogLevel pwmJNILogLevel = logWARNING;
else Log().Get(level)
/*
* Class: edu_wpi_first_wpilibj_hal_PWMJNI
* Method: allocatePWMChannel
* Signature: (Ljava/nio/ByteBuffer;Ljava/nio/IntBuffer;)Z
*/
JNIEXPORT jboolean JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_allocatePWMChannel
(JNIEnv * env, jclass, jobject id, jobject status)
{
PWMJNI_LOG(logDEBUG) << "Calling DIOJNI allocatePWMChannel";
void ** javaId = (void**)env->GetDirectBufferAddress(id);
PWMJNI_LOG(logDEBUG) << "Port Ptr = " << *javaId;
jint * statusPtr = (jint*)env->GetDirectBufferAddress(status);
PWMJNI_LOG(logDEBUG) << "Status Ptr = " << statusPtr;
jbyte returnValue = allocatePWMChannel(*javaId, statusPtr);
PWMJNI_LOG(logDEBUG) << "Status = " << *statusPtr;
PWMJNI_LOG(logDEBUG) << "allocatePWMChannelResult = " << (jint)returnValue;
return returnValue;
}
/*
* Class: edu_wpi_first_wpilibj_hal_PWMJNI
* Method: freePWMChannel
* Signature: (Ljava/nio/ByteBuffer;Ljava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_PWMJNI_freePWMChannel
(JNIEnv * env, jclass, jobject id, jobject status)
{
PWMJNI_LOG(logDEBUG) << "Calling DIOJNI freePWMChannel";
void ** javaId = (void**)env->GetDirectBufferAddress(id);
PWMJNI_LOG(logDEBUG) << "Port Ptr = " << *javaId;
jint * statusPtr = (jint*)env->GetDirectBufferAddress(status);
PWMJNI_LOG(logDEBUG) << "Status Ptr = " << statusPtr;
freePWMChannel(*javaId, statusPtr);
PWMJNI_LOG(logDEBUG) << "Status = " << *statusPtr;
}
/*
* Class: edu_wpi_first_wpilibj_hal_PWMJNI
* Method: setPWM