예제 #1
0
파일: PWM.cpp 프로젝트: FRC3238/allwpilib
/**
 * Set the PWM value based on a speed.
 *
 * This is intended to be used by speed controllers.
 *
 * @pre SetMaxPositivePwm() called.
 * @pre SetMinPositivePwm() called.
 * @pre SetCenterPwm() called.
 * @pre SetMaxNegativePwm() called.
 * @pre SetMinNegativePwm() called.
 *
 * @param speed The speed to set the speed controller between -1.0 and 1.0.
 */
void PWM::SetSpeed(float speed) {
  if (StatusIsFatal()) return;
  // clamp speed to be in the range 1.0 >= speed >= -1.0
  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();
  } else if (speed > 0.0) {
    rawValue = (int32_t)(speed * ((float)GetPositiveScaleFactor()) +
                         ((float)GetMinPositivePwm()) + 0.5);
  } else {
    rawValue = (int32_t)(speed * ((float)GetNegativeScaleFactor()) +
                         ((float)GetMaxNegativePwm()) + 0.5);
  }

  // the above should result in a pwm_value in the valid range
  wpi_assert((rawValue >= GetMinNegativePwm()) &&
             (rawValue <= GetMaxPositivePwm()));
  wpi_assert(rawValue != kPwmDisabled);

  // send the computed pwm value to the FPGA
  SetRaw(rawValue);
}
예제 #2
0
파일: PWM.cpp 프로젝트: FRC980/FRC-Team-980
/**
 * Set the PWM value based on a position.
 *
 * This is intended to be used by servos.
 *
 * @pre SetMaxPositivePwm() called.
 * @pre SetMinNegativePwm() called.
 *
 * @param pos The position to set the servo between 0.0 and 1.0.
 */
void PWM::SetPosition(float pos)
{
    if (pos < 0.0)
    {
        pos = 0.0;
    }
    else if (pos > 1.0)
    {
        pos = 1.0;
    }

    INT32 rawValue;
    // note, need to perform the multiplication below as floating point
    // before converting to int
    rawValue =
        (INT32) ((pos * (float)GetFullRangeScaleFactor()) +
                 GetMinNegativePwm());

    wpi_assert((rawValue >= GetMinNegativePwm())
               && (rawValue <= GetMaxPositivePwm()));
    wpi_assert(rawValue != kPwmDisabled);

    // send the computed pwm value to the FPGA
    SetRaw((UINT8) rawValue);
}
예제 #3
0
/**
 * Set the relay state.
 * 
 * Valid values depend on which directions of the relay are controlled by the object.
 * 
 * When set to kBothDirections, the relay can only be one of the three reasonable
 *    values, 0v-0v, 0v-12v, or 12v-0v.
 * 
 * When set to kForwardOnly or kReverseOnly, you can specify the constant for the
 *    direction or you can simply specify kOff and kOn.  Using only kOff and kOn is
 *    recommended.
 * 
 * @param value The state to set the relay.
 */
void Relay::Set(Relay::Value value)
{
	switch (value)
	{
	case kOff:
		if (m_direction == kBothDirections || m_direction == kForwardOnly)
		{
			m_module->SetRelayForward(m_channel, false);
		}
		if (m_direction == kBothDirections || m_direction == kReverseOnly)
		{
			m_module->SetRelayReverse(m_channel, false);
		}
		break;
	case kOn:
		wpi_assert(m_direction != kBothDirections);
		if (m_direction == kForwardOnly)
		{
			m_module->SetRelayForward(m_channel, true);
		}
		else if (m_direction == kReverseOnly)
		{
			m_module->SetRelayReverse(m_channel, true);
		}
		break;
	case kForward:
		wpi_assert(m_direction != kReverseOnly);
		if (m_direction == kBothDirections || m_direction == kForwardOnly)
		{
			m_module->SetRelayForward(m_channel, true);
		}
		if (m_direction == kBothDirections)
		{
			m_module->SetRelayReverse(m_channel, false);
		}
		break;
	case kReverse:
		wpi_assert(m_direction != kForwardOnly);
		if (m_direction == kBothDirections)
		{
			m_module->SetRelayForward(m_channel, false);
		}
		if (m_direction == kBothDirections || m_direction == kReverseOnly)
		{
			m_module->SetRelayReverse(m_channel, true);
		}
		break;
	default:
		wpi_assert(false);
	}
}
예제 #4
0
/**
 * @brief Unregister a button to track the number of times it was pressed.
 * @param joystick_id Which joystick to track a button on
 * @param button_idd Which button on the joystick to track
 */
void Proxy166::UnregisterCounter(int joystick_id, int button_id) {
	wpi_assert(joystick_id < NUMBER_OF_JOYSTICKS && joystick_id >= 0);
	wpi_assert(button_id < NUMBER_OF_JOY_BUTTONS && button_id >= 0);
	
	if(tracker.size() == 0)
		return;
	vector<int>::iterator it = tracker.begin();
	while((it+=3) != tracker.end())
	{
		if(*it == joystick_id && *(it+1) == button_id) {
			tracker.erase(it, it+2);
		}
	}
}
/**
 * Set the source object that causes the counter to count down.
 * Set the down counting DigitalSource.
 */
void Counter::SetDownSource(DigitalSource *source)
{
	wpi_assert(m_downSource == NULL);
	unsigned char mode = m_counter->readConfig_Mode(&status);
	wpi_assert(mode == kTwoPulse || mode == kExternalDirection);
	m_downSource = source;
	m_counter->writeConfig_DownSource_Module(source->GetModuleForRouting(), &status);
	m_counter->writeConfig_DownSource_Channel(source->GetChannelForRouting(), &status);
	m_counter->writeConfig_DownSource_AnalogTrigger(source->GetAnalogTriggerForRouting(), &status);

	SetDownSourceEdge(true, false);
	m_counter->strobeReset(&status);
	wpi_assertCleanStatus(status);
}
예제 #6
0
/**
 * @brief Whether a joystick is registered for tracking
 * @param joystick_id What joystick to check
 * @param button_id What button on the joystick to check.
 * @return Whether it is registered.
 */
bool Proxy166::IsRegistered(int joystick_id, int button_id) {
	wpi_assert(joystick_id < NUMBER_OF_JOYSTICKS && joystick_id >= 0);
	wpi_assert(button_id < NUMBER_OF_JOY_BUTTONS && button_id >= 0);
	
	if(tracker.size() == 0)
		return false;
	vector<int>::iterator it = tracker.begin();
	while((it+=3) != tracker.end())
	{
		if(*it == joystick_id && *(it+1) == button_id) {
			return true;
		}
	}
	return false;
}
예제 #7
0
/**
 * Delete this Notifier from the timer queue.
 * WARNING: this method does not do synchronization! It must be called from somewhere
 * that is taking care of synchronizing access to the queue.
 * Remove this Notifier from the timer queue and adjust the next interrupt time to reflect
 * the current top of the queue.
 */
void Notifier::DeleteFromQueue()
{
    if (m_queued)
    {
        m_queued = false;
        wpi_assert(timerQueueHead != NULL);
        if (timerQueueHead == this)
        {
            // remove the first item in the list - update the alarm
            timerQueueHead = this->m_nextEvent;
            UpdateAlarm();
        }
        else
        {
            for (Notifier *n = timerQueueHead; n != NULL; n = n->m_nextEvent)
            {
                if (n->m_nextEvent == this)
                {
                    // this element is the next element from *n from the queue
                    n->m_nextEvent = this->m_nextEvent;    // point around this one
                }
            }
        }
    }
}
예제 #8
0
/**
 * @brief Sets the cache value of a button on a joystick.
 * @param joy_id Which joystick to set the button status for.
 * @param button_id Which button on the joystick to set the status for.
 * @param newval What to set the button's value to.
 */
void Proxy166::SetButton(int joy_id, int button_id, bool newval)
{
	wpi_assert(joy_id < NUMBER_OF_JOY_BUTTONS && joy_id >= 0);
	//semTake(JoystickLocks[joy_id], WAIT_FOREVER);
	Joysticks[joy_id].button[button_id] = newval;
	//semGive(JoystickLocks[joy_id]);
}
예제 #9
0
/**
 * Turn Automatic mode on/off.
 * When in Automatic mode, all sensors will fire in round robin, waiting a set
 * time between each sensor.
 * @param enabling Set to true if round robin scheduling should start for all the ultrasonic sensors. This
 * scheduling method assures that the sensors are non-interfering because no two sensors fire at the same time.
 * If another scheduling algorithm is preffered, it can be implemented by pinging the sensors manually and waiting
 * for the results to come back.
 */
void Ultrasonic::SetAutomaticMode(bool enabling)
{
	if (enabling == m_automaticEnabled)
		return; // ignore the case of no change

	m_automaticEnabled = enabling;
	if (enabling)
	{
		// enabling automatic mode.
		// Clear all the counters so no data is valid
		for (Ultrasonic *u = m_firstSensor; u != NULL; u = u->m_nextSensor)
		{
			u->m_counter->Reset();
		}
		// Start round robin task
		wpi_assert(m_task.Verify() == false);	// should be false since was previously disabled
		m_task.Start();
	}
	else
	{
		// disabling automatic mode. Wait for background task to stop running.
		while (m_task.Verify())
			Wait(0.15);	// just a little longer than the ping time for round-robin to stop

		// clear all the counters (data now invalid) since automatic mode is stopped
		for (Ultrasonic *u = m_firstSensor; u != NULL; u = u->m_nextSensor)
		{
			u->m_counter->Reset();
		}
		m_task.Stop();
	}
}
예제 #10
0
void InterruptableSensorBase::AllocateInterrupts(bool watcher) {
  wpi_assert(m_interrupt == nullptr);
  // Expects the calling leaf class to allocate an interrupt index.
  int32_t status = 0;
  m_interrupt = initializeInterrupts(m_interruptIndex, watcher, &status);
  wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
예제 #11
0
/**
 * Get values from the digital inputs on the Driver Station.
 * Return digital values from the Drivers Station. These values are
 * typically used for buttons and switches on advanced operator
 * interfaces.
 * @param channel The digital input to get. Valid range is 1 - 8.
 */
bool DriverStation::GetDigitalIn(UINT32 channel)
{
    wpi_assert((channel >= 1) && (channel <= 8));
    GetData();
    return ((m_controlData->
             dsDigitalIn >> (channel - 1)) & 0x1) ? true : false;
}
예제 #12
0
/**
 * Create a Notifier for timer event notification.
 * @param handler The handler is called at the notification time which is set
 * using StartSingle or StartPeriodic.
 */
Notifier::Notifier(TimerEventHandler handler, void *param)
{
    tRioStatusCode status = 0;
    wpi_assert(handler != NULL);
    m_handler = handler;
    m_param = param;
    m_periodic = false;
    m_expirationTime = 0;
    m_period = 0;
    m_nextEvent = NULL;
    m_queued = false;
    CRITICAL_REGION(m_semaphore)
    {
        // do the first time intialization of static variables
        if (talarm == NULL)
        {
            manager =
                new tInterruptManager(1 << kTimerInterruptNumber, false,
                                      &status);
            manager->registerHandler(ProcessQueue, NULL, &status);
            manager->enable(&status);
            talarm = new tAlarm(&status);
        }
    }
    END_REGION;
    wpi_assertCleanStatus(status);
}
예제 #13
0
/**
 * Disable Interrupts without without deallocating structures.
 */
void InterruptableSensorBase::DisableInterrupts() {
  if (StatusIsFatal()) return;
  wpi_assert(m_interrupt != nullptr);
  int32_t status = 0;
  disableInterrupts(m_interrupt, &status);
  wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
예제 #14
0
/**
 * @brief Register a button to track the number of times it was pressed.
 * @param joystick_id Which joystick to track a button on
 * @param button_idd Which button on the joystick to track
 */
void Proxy166::RegisterCounter(int joystick_id, int button_id) {
	wpi_assert(joystick_id < NUMBER_OF_JOYSTICKS && joystick_id >= 0);
	wpi_assert(button_id < NUMBER_OF_JOY_BUTTONS && button_id >= 0);
	
	if(tracker.size() != 0) {
		vector<int>::iterator it = tracker.begin();
		while((it+=3) != tracker.end())
		{
			if(*it == joystick_id && *(it+1) == button_id) {
				return;
			}
		}
	}
	tracker.push_back(joystick_id);
	tracker.push_back(button_id);
	tracker.push_back(0);
}
예제 #15
0
/**
 * Return the timestamp for the falling interrupt that occurred most recently.
 * This is in the same time domain as GetClock().
 * The falling-edge interrupt should be enabled with
 * {@link #DigitalInput.SetUpSourceEdge}
 * @return Timestamp in seconds since boot.
*/
double InterruptableSensorBase::ReadFallingTimestamp() {
  if (StatusIsFatal()) return 0.0;
  wpi_assert(m_interrupt != nullptr);
  int32_t status = 0;
  double timestamp = readFallingTimestamp(m_interrupt, &status);
  wpi_setErrorWithContext(status, getHALErrorMessage(status));
  return timestamp;
}
예제 #16
0
/**
 * @brief Gets the cached Z axis value of a joystick.
 * @param joy_id Which joystick to get the cached Z axis value for.
 * @return Float equal to the cached Z axis value.
 */
float Proxy166::GetJoystickZ(int joy_id) {
	wpi_assert(joy_id < NUMBER_OF_JOYSTICKS && joy_id >= 0);
	float value = 0;
	//semTake(JoystickLocks[joy_id], WAIT_FOREVER);
	value = Joysticks[joy_id].Z;
	//semGive(JoystickLocks[joy_id]);
	return value;
}
예제 #17
0
/**
 * @brief Gets a cached switch value.
 * @param switch_id Which switch to retrieve the cached value of.
 * @return The int value of the cached switch value.
 */
int Proxy166::GetSwitch(int switch_id) {
	wpi_assert(switch_id < NUMBER_OF_SWITCHES && switch_id >= 0);
	int value = 0;
	//semTake(SwitchLocks[switch_id], WAIT_FOREVER);
	value = Switches[switch_id];
	//semGive(SwitchLocks[switch_id]);
	return value;
}
예제 #18
0
/**
 * @brief Gets the pending amount of times a button was pressed and released since last call.
 * @param joystick_id Which joystick to check
 * @param button_id Which button on the joystick to check
 * @return How many times the button was pressed and released since last call.
 */
int Proxy166::GetPendingCount(int joystick_id, int button_id) {
	wpi_assert(joystick_id < NUMBER_OF_JOYSTICKS && joystick_id >= 0);
	wpi_assert(button_id < NUMBER_OF_JOY_BUTTONS && button_id >= 0);
	
	if(tracker.size() == 0)
		wpi_assertWithMessage(false, "Tried to fetch pending count for a non-registered button.");
	vector<int>::iterator it = tracker.begin();
	while(it != tracker.end())
	{
		if(*it == joystick_id && *(it+1) == button_id) {
			return *(it+2);
		}
		it += 3;
	}
	wpi_assertWithMessage(false, "Tried to fetch pending count for a non-registered button.");
	return 0;
}
예제 #19
0
/**
 * Single ping to ultrasonic sensor.
 * Send out a single ping to the ultrasonic sensor. This only works if automatic (round robin)
 * mode is disabled. A single ping is sent out, and the counter should count the semi-period
 * when it comes in. The counter is reset to make the current value invalid.
 */
void Ultrasonic::Ping()
{
	// TODO: Either assert or disable, not both.
	wpi_assert(!m_automaticEnabled);
	SetAutomaticMode(false); // turn off automatic round robin if pinging single sensor
	m_counter->Reset(); // reset the counter to zero (invalid data now)
	m_pingChannel->Pulse(kPingTime); // do the ping to start getting a single range
}
예제 #20
0
/**
 * Helper function to determine the size of a jpeg. The general structure of
 * how to parse a jpeg for length can be found in this stackoverflow article:
 * http://stackoverflow.com/a/1602428. Be sure to also read the comments for
 * the SOS flag explanation.
 */
unsigned int USBCamera::GetJpegSize(void* buffer, unsigned int buffSize) {
    uint8_t* data = (uint8_t*)buffer;
    if (!wpi_assert(data[0] == 0xff && data[1] == 0xd8)) return 0;
    unsigned int pos = 2;
    while (pos < buffSize) {
        // All control markers start with 0xff, so if this isn't present,
        // the JPEG is not valid
        if (!wpi_assert(data[pos] == 0xff)) return 0;
        unsigned char t = data[pos + 1];
        // These are RST markers. We just skip them and move onto the next marker
        if (t == 0x01 || (t >= 0xd0 && t <= 0xd7)) {
            pos += 2;
        } else if (t == 0xd9) {
            // End of Image, add 2 for this and 0-indexed
            return pos + 2;
        } else if (!wpi_assert(t != 0xd8)) {
            // Another start of image, invalid image
            return 0;
        } else if (t == 0xda) {
            // SOS marker. The next two bytes are a 16-bit big-endian int that is
            // the length of the SOS header, skip that
            unsigned int len = (((unsigned int)(data[pos + 2] & 0xff)) << 8 |
                                ((unsigned int)data[pos + 3] & 0xff));
            pos += len + 2;
            // The next marker is the first marker that is 0xff followed by a non-RST
            // element. 0xff followed by 0x00 is an escaped 0xff. 0xd0-0xd7 are RST
            // markers
            while (data[pos] != 0xff || data[pos + 1] == 0x00 ||
                    (data[pos + 1] >= 0xd0 && data[pos + 1] <= 0xd7)) {
                pos += 1;
                if (pos >= buffSize) return 0;
            }
        } else {
            // This is one of several possible markers. The next two bytes are a
            // 16-bit
            // big-endian int with the length of the marker header, skip that then
            // continue searching
            unsigned int len = (((unsigned int)(data[pos + 2] & 0xff)) << 8 |
                                ((unsigned int)data[pos + 3] & 0xff));
            pos += len + 2;
        }
    }

    return 0;
}
예제 #21
0
DriverStation::Alliance DriverStation::GetAlliance()
{
    if (m_controlData->dsID_Alliance == 'R')
        return kRed;
    if (m_controlData->dsID_Alliance == 'B')
        return kBlue;
    wpi_assert(false);
    return kInvalid;
}
예제 #22
0
/**
 * @brief Gets the cache value of the trigger (button 1) of a joystick. 
 * @param joy_id Which joystick to retrieve the trigger status for.
 * @param reset Whether to reset the button's value after being called.
 * @return The last read current value
 */
bool Proxy166::GetTrigger(int joy_id, bool reset) { 
	wpi_assert(joy_id < NUMBER_OF_JOYSTICKS && joy_id >= 0);
	bool bid = GetButton(joy_id,1); 
	// reset the button so actions are triggered only once
	if (reset) {
		SetButton(joy_id, 1, 0);
	}
	return bid;
}
예제 #23
0
/**
 * Read the battery voltage from the specified AnalogChannel.
 *
 * This accessor assumes that the battery voltage is being measured
 * through the voltage divider on an analog breakout.
 *
 * @return The battery voltage.
 */
float DriverStation::GetBatteryVoltage()
{
    wpi_assert(m_batteryChannel != NULL);

    // The Analog bumper has a voltage divider on the battery source.
    // Vbatt *--/\/\/\--* Vsample *--/\/\/\--* Gnd
    //         680 Ohms            1000 Ohms
    return m_batteryChannel->GetAverageVoltage() * (1680.0 / 1000.0);
}
예제 #24
0
/**
 * Cancel interrupts on this device.
 * This deallocates all the chipobject structures and disables any interrupts.
 */
void InterruptableSensorBase::CancelInterrupts() {
  if (StatusIsFatal()) return;
  wpi_assert(m_interrupt != nullptr);
  int32_t status = 0;
  cleanInterrupts(m_interrupt, &status);
  wpi_setErrorWithContext(status, getHALErrorMessage(status));
  m_interrupt = nullptr;
  m_interrupts->Free(m_interruptIndex);
}
예제 #25
0
/**
 * Get buttons based on an enumerated type.
 * 
 * The button type will be looked up in the list of buttons and then read.
 * 
 * @param button The type of button to read.
 * @return The state of the button.
 */
bool Joystick::GetButton(ButtonType button)
{
	switch (button)
	{
	case kTriggerButton: return GetTrigger();
	case kTopButton: return GetTop();
	default:
		wpi_assert(false);
		return false;
	}
}
예제 #26
0
DigitalGlitchFilter::DigitalGlitchFilter() {
  std::lock_guard<priority_mutex> sync(m_mutex);
  auto index =
      std::find(m_filterAllocated.begin(), m_filterAllocated.end(), false);
  wpi_assert(index != m_filterAllocated.end());

  m_channelIndex = std::distance(m_filterAllocated.begin(), index);
  *index = true;

  HALReport(HALUsageReporting::kResourceType_DigitalFilter, m_channelIndex);
}
/**
 * In synchronous mode, wait for the defined interrupt to occur. You should <b>NOT</b> attempt to read the
 * sensor from another thread while waiting for an interrupt. This is not threadsafe, and can cause 
 * memory corruption
 * @param timeout Timeout in seconds
 * @param ignorePrevious If true, ignore interrupts that happened before
 * WaitForInterrupt was called.
 * @return What interrupts fired
 */
InterruptableSensorBase::WaitResult InterruptableSensorBase::WaitForInterrupt(float timeout, bool ignorePrevious)
{
	if (StatusIsFatal()) return InterruptableSensorBase::kTimeout;
	wpi_assert(m_interrupt != NULL);
	int32_t status = 0;
	uint32_t result;

	result = waitForInterrupt(m_interrupt, timeout, ignorePrevious, &status);
	wpi_setErrorWithContext(status, getHALErrorMessage(status));

	return static_cast<WaitResult>(result);
}
예제 #28
0
/**
 * @brief Sets a cached joystick value.
 * @param joy_id Which joystick to set the cached value for.
 * @param stick A Joystick object with the X, Y, and Z axes set, as well as each of the buttons.
 */
void Proxy166::SetJoystick(int joy_id, Joystick & stick)
{
	wpi_assert(joy_id < NUMBER_OF_JOYSTICKS && joy_id >= 0);
	//semTake(JoystickLocks[joy_id], WAIT_FOREVER);
	Joysticks[joy_id].X = stick.GetX();
	Joysticks[joy_id].Y = stick.GetY();
	Joysticks[joy_id].Z = stick.GetZ();
	Joysticks[joy_id].throttle = stick.GetThrottle();
	for(unsigned i=0;i<NUMBER_OF_JOY_BUTTONS;i++) {
		Joysticks[joy_id].button[i] = stick.GetRawButton(i);
	}
	//semGive(JoystickLocks[joy_id]);
}
예제 #29
0
/**
 * Set the speed of the right and left motors.
 *
 * This is used once an appropriate drive setup function is called such as
 * TwoWheelDrive(). The motors are set to "leftOutput" and "rightOutput"
 * and includes flipping the direction of one side for opposing motors.
 *
 * @param leftOutput  The speed to send to the left side of the robot.
 * @param rightOutput The speed to send to the right side of the robot.
 */
void RobotDrive::SetLeftRightMotorOutputs(float leftOutput, float rightOutput) {
  wpi_assert(m_rearLeftMotor != nullptr && m_rearRightMotor != nullptr);

  if (m_frontLeftMotor != nullptr)
    m_frontLeftMotor->Set(Limit(leftOutput) * m_maxOutput);
  m_rearLeftMotor->Set(Limit(leftOutput) * m_maxOutput);

  if (m_frontRightMotor != nullptr)
    m_frontRightMotor->Set(-Limit(rightOutput) * m_maxOutput);
  m_rearRightMotor->Set(-Limit(rightOutput) * m_maxOutput);

  m_safetyHelper->Feed();
}
예제 #30
0
/**
 * Get dynamic data from the driver station buffer
 */
void KinectStick::GetData()
{
	uint32_t packetNumber = DriverStation::GetInstance()->GetPacketNumber();
	if (_recentPacketNumber != packetNumber)
	{
		_recentPacketNumber = packetNumber;
		int retVal = getDynamicControlData(kJoystickBundleID, _sticks.data, sizeof(_sticks.data), 5);
		if (retVal == 0)
		{
			wpi_assert(_sticks.formatted.size == sizeof(_sticks.data) - 1);
		}
	}
}