blob: 6a9e9aec47eca61bb781ed14235859bcec387e68 [file] [log] [blame]
jerrymf1579332013-02-07 01:56:28 +00001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5/*----------------------------------------------------------------------------*/
6
7#include "MotorSafetyHelper.h"
8
9#include "DriverStation.h"
10#include "MotorSafety.h"
11#include "Timer.h"
12#include "WPIErrors.h"
13
14#include <stdio.h>
15
16MotorSafetyHelper *MotorSafetyHelper::m_headHelper = NULL;
17ReentrantSemaphore MotorSafetyHelper::m_listMutex;
18
19/**
20 * The constructor for a MotorSafetyHelper object.
21 * The helper object is constructed for every object that wants to implement the Motor
22 * Safety protocol. The helper object has the code to actually do the timing and call the
23 * motors Stop() method when the timeout expires. The motor object is expected to call the
24 * Feed() method whenever the motors value is updated.
25 * @param safeObject a pointer to the motor object implementing MotorSafety. This is used
26 * to call the Stop() method on the motor.
27 */
28MotorSafetyHelper::MotorSafetyHelper(MotorSafety *safeObject)
29{
30 m_safeObject = safeObject;
31 m_enabled = false;
32 m_expiration = DEFAULT_SAFETY_EXPIRATION;
33 m_stopTime = Timer::GetFPGATimestamp();
34
35 Synchronized sync(m_listMutex);
36 m_nextHelper = m_headHelper;
37 m_headHelper = this;
38}
39
40
41MotorSafetyHelper::~MotorSafetyHelper()
42{
43 Synchronized sync(m_listMutex);
44 if (m_headHelper == this)
45 {
46 m_headHelper = m_nextHelper;
47 }
48 else
49 {
50 MotorSafetyHelper *prev = NULL;
51 MotorSafetyHelper *cur = m_headHelper;
52 while (cur != this && cur != NULL)
53 prev = cur, cur = cur->m_nextHelper;
54 if (cur == this)
55 prev->m_nextHelper = cur->m_nextHelper;
56 }
57}
58
59/*
60 * Feed the motor safety object.
61 * Resets the timer on this object that is used to do the timeouts.
62 */
63void MotorSafetyHelper::Feed()
64{
65 Synchronized sync(m_syncMutex);
66 m_stopTime = Timer::GetFPGATimestamp() + m_expiration;
67}
68
69/*
70 * Set the expiration time for the corresponding motor safety object.
71 * @param expirationTime The timeout value in seconds.
72 */
73void MotorSafetyHelper::SetExpiration(float expirationTime)
74{
75 Synchronized sync(m_syncMutex);
76 m_expiration = expirationTime;
77}
78
79/**
80 * Retrieve the timeout value for the corresponding motor safety object.
81 * @returns the timeout value in seconds.
82 */
83float MotorSafetyHelper::GetExpiration()
84{
85 Synchronized sync(m_syncMutex);
86 return m_expiration;
87}
88
89/**
90 * Determine if the motor is still operating or has timed out.
91 * @returns a true value if the motor is still operating normally and hasn't timed out.
92 */
93bool MotorSafetyHelper::IsAlive()
94{
95 Synchronized sync(m_syncMutex);
96 return !m_enabled || m_stopTime > Timer::GetFPGATimestamp();
97}
98
99/**
100 * Check if this motor has exceeded its timeout.
101 * This method is called periodically to determine if this motor has exceeded its timeout
102 * value. If it has, the stop method is called, and the motor is shut down until its value is
103 * updated again.
104 */
105void MotorSafetyHelper::Check()
106{
107 if (!m_enabled) return;
108 if (DriverStation::GetInstance()->IsDisabled()) return;
109
110 Synchronized sync(m_syncMutex);
111 if (m_stopTime < Timer::GetFPGATimestamp())
112 {
113 char buf[128];
114 char desc[64];
115 m_safeObject->GetDescription(desc);
116 snprintf(buf, 128, "%s... Output not updated often enough.", desc);
117 wpi_setWPIErrorWithContext(Timeout, buf);
118 m_safeObject->StopMotor();
119 }
120}
121
122/**
123 * Enable/disable motor safety for this device
124 * Turn on and off the motor safety option for this PWM object.
125 * @param enabled True if motor safety is enforced for this object
126 */
127void MotorSafetyHelper::SetSafetyEnabled(bool enabled)
128{
129 Synchronized sync(m_syncMutex);
130 m_enabled = enabled;
131}
132
133/**
134 * Return the state of the motor safety enabled flag
135 * Return if the motor safety is currently enabled for this devicce.
136 * @returns True if motor safety is enforced for this device
137 */
138bool MotorSafetyHelper::IsSafetyEnabled()
139{
140 Synchronized sync(m_syncMutex);
141 return m_enabled;
142}
143
144/**
145 * Check the motors to see if any have timed out.
146 * This static method is called periodically to poll all the motors and stop any that have
147 * timed out.
148 */
149void MotorSafetyHelper::CheckMotors()
150{
151 Synchronized sync(m_listMutex);
152 for (MotorSafetyHelper *msh = m_headHelper; msh != NULL; msh = msh->m_nextHelper)
153 {
154 msh->Check();
155 }
156}