blob: 0bdc57c40a27a89572ff735d11c6e145c6f38eb2 [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
Austin Schuh1e69f942020-11-14 15:06:14 -08002/* Copyright (c) 2008-2020 FIRST. All Rights Reserved. */
Brian Silverman8fce7482020-01-05 13:18:21 -08003/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "frc/DigitalOutput.h"
9
10#include <limits>
Brian Silverman8fce7482020-01-05 13:18:21 -080011
12#include <hal/DIO.h>
13#include <hal/FRCUsageReporting.h>
14#include <hal/HALBase.h>
15#include <hal/Ports.h>
16
17#include "frc/SensorUtil.h"
18#include "frc/WPIErrors.h"
19#include "frc/smartdashboard/SendableBuilder.h"
20#include "frc/smartdashboard/SendableRegistry.h"
21
22using namespace frc;
23
24DigitalOutput::DigitalOutput(int channel) {
25 m_pwmGenerator = HAL_kInvalidHandle;
26 if (!SensorUtil::CheckDigitalChannel(channel)) {
27 wpi_setWPIErrorWithContext(ChannelIndexOutOfRange,
28 "Digital Channel " + wpi::Twine(channel));
29 m_channel = std::numeric_limits<int>::max();
30 return;
31 }
32 m_channel = channel;
33
34 int32_t status = 0;
35 m_handle = HAL_InitializeDIOPort(HAL_GetPort(channel), false, &status);
36 if (status != 0) {
37 wpi_setHALErrorWithRange(status, 0, HAL_GetNumDigitalChannels(), channel);
38 m_channel = std::numeric_limits<int>::max();
39 m_handle = HAL_kInvalidHandle;
40 return;
41 }
42
43 HAL_Report(HALUsageReporting::kResourceType_DigitalOutput, channel + 1);
44 SendableRegistry::GetInstance().AddLW(this, "DigitalOutput", channel);
45}
46
47DigitalOutput::~DigitalOutput() {
48 if (StatusIsFatal()) return;
49 // Disable the PWM in case it was running.
50 DisablePWM();
51
52 HAL_FreeDIOPort(m_handle);
53}
54
55void DigitalOutput::Set(bool value) {
56 if (StatusIsFatal()) return;
57
58 int32_t status = 0;
59 HAL_SetDIO(m_handle, value, &status);
60 wpi_setHALError(status);
61}
62
63bool DigitalOutput::Get() const {
64 if (StatusIsFatal()) return false;
65
66 int32_t status = 0;
67 bool val = HAL_GetDIO(m_handle, &status);
68 wpi_setHALError(status);
69 return val;
70}
71
72HAL_Handle DigitalOutput::GetPortHandleForRouting() const { return m_handle; }
73
74AnalogTriggerType DigitalOutput::GetAnalogTriggerTypeForRouting() const {
75 return (AnalogTriggerType)0;
76}
77
78bool DigitalOutput::IsAnalogTrigger() const { return false; }
79
80int DigitalOutput::GetChannel() const { return m_channel; }
81
82void DigitalOutput::Pulse(double length) {
83 if (StatusIsFatal()) return;
84
85 int32_t status = 0;
86 HAL_Pulse(m_handle, length, &status);
87 wpi_setHALError(status);
88}
89
90bool DigitalOutput::IsPulsing() const {
91 if (StatusIsFatal()) return false;
92
93 int32_t status = 0;
94 bool value = HAL_IsPulsing(m_handle, &status);
95 wpi_setHALError(status);
96 return value;
97}
98
99void DigitalOutput::SetPWMRate(double rate) {
100 if (StatusIsFatal()) return;
101
102 int32_t status = 0;
103 HAL_SetDigitalPWMRate(rate, &status);
104 wpi_setHALError(status);
105}
106
107void DigitalOutput::EnablePWM(double initialDutyCycle) {
108 if (m_pwmGenerator != HAL_kInvalidHandle) return;
109
110 int32_t status = 0;
111
112 if (StatusIsFatal()) return;
113 m_pwmGenerator = HAL_AllocateDigitalPWM(&status);
114 wpi_setHALError(status);
115
116 if (StatusIsFatal()) return;
117 HAL_SetDigitalPWMDutyCycle(m_pwmGenerator, initialDutyCycle, &status);
118 wpi_setHALError(status);
119
120 if (StatusIsFatal()) return;
121 HAL_SetDigitalPWMOutputChannel(m_pwmGenerator, m_channel, &status);
122 wpi_setHALError(status);
123}
124
125void DigitalOutput::DisablePWM() {
126 if (StatusIsFatal()) return;
127 if (m_pwmGenerator == HAL_kInvalidHandle) return;
128
129 int32_t status = 0;
130
131 // Disable the output by routing to a dead bit.
132 HAL_SetDigitalPWMOutputChannel(m_pwmGenerator, SensorUtil::kDigitalChannels,
133 &status);
134 wpi_setHALError(status);
135
136 HAL_FreeDigitalPWM(m_pwmGenerator, &status);
137 wpi_setHALError(status);
138
139 m_pwmGenerator = HAL_kInvalidHandle;
140}
141
142void DigitalOutput::UpdateDutyCycle(double dutyCycle) {
143 if (StatusIsFatal()) return;
144
145 int32_t status = 0;
146 HAL_SetDigitalPWMDutyCycle(m_pwmGenerator, dutyCycle, &status);
147 wpi_setHALError(status);
148}
149
150void DigitalOutput::SetSimDevice(HAL_SimDeviceHandle device) {
151 HAL_SetDIOSimDevice(m_handle, device);
152}
153
154void DigitalOutput::InitSendable(SendableBuilder& builder) {
155 builder.SetSmartDashboardType("Digital Output");
Austin Schuh1e69f942020-11-14 15:06:14 -0800156 builder.AddBooleanProperty(
157 "Value", [=]() { return Get(); }, [=](bool value) { Set(value); });
Brian Silverman8fce7482020-01-05 13:18:21 -0800158}