001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj; 006 007import edu.wpi.first.hal.DutyCycleJNI; 008import edu.wpi.first.hal.FRCNetComm.tResourceType; 009import edu.wpi.first.hal.HAL; 010import edu.wpi.first.util.sendable.Sendable; 011import edu.wpi.first.util.sendable.SendableBuilder; 012import edu.wpi.first.util.sendable.SendableRegistry; 013 014/** 015 * Class to read a duty cycle PWM input. 016 * 017 * <p>PWM input signals are specified with a frequency and a ratio of high to low in that frequency. 018 * There are 8 of these in the roboRIO, and they can be attached to any {@link DigitalSource}. 019 * 020 * <p>These can be combined as the input of an AnalogTrigger to a Counter in order to implement 021 * rollover checking. 022 */ 023public class DutyCycle implements Sendable, AutoCloseable { 024 // Explicitly package private 025 final int m_handle; 026 027 private final DigitalSource m_source; 028 029 /** 030 * Constructs a DutyCycle input from a DigitalSource input. 031 * 032 * <p>This class does not own the inputted source. 033 * 034 * @param digitalSource The DigitalSource to use. 035 */ 036 public DutyCycle(DigitalSource digitalSource) { 037 m_handle = 038 DutyCycleJNI.initialize( 039 digitalSource.getPortHandleForRouting(), 040 digitalSource.getAnalogTriggerTypeForRouting()); 041 042 m_source = digitalSource; 043 int index = getFPGAIndex(); 044 HAL.report(tResourceType.kResourceType_DutyCycle, index + 1); 045 SendableRegistry.addLW(this, "Duty Cycle", index); 046 } 047 048 /** Close the DutyCycle and free all resources. */ 049 @Override 050 public void close() { 051 SendableRegistry.remove(this); 052 DutyCycleJNI.free(m_handle); 053 } 054 055 /** 056 * Get the frequency of the duty cycle signal. 057 * 058 * @return frequency in Hertz 059 */ 060 public int getFrequency() { 061 return DutyCycleJNI.getFrequency(m_handle); 062 } 063 064 /** 065 * Get the output ratio of the duty cycle signal. 066 * 067 * <p>0 means always low, 1 means always high. 068 * 069 * @return output ratio between 0 and 1 070 */ 071 public double getOutput() { 072 return DutyCycleJNI.getOutput(m_handle); 073 } 074 075 /** 076 * Get the raw output ratio of the duty cycle signal. 077 * 078 * <p>0 means always low, an output equal to getOutputScaleFactor() means always high. 079 * 080 * @return output ratio in raw units 081 */ 082 public int getOutputRaw() { 083 return DutyCycleJNI.getOutputRaw(m_handle); 084 } 085 086 /** 087 * Get the scale factor of the output. 088 * 089 * <p>An output equal to this value is always high, and then linearly scales down to 0. Divide the 090 * result of getOutputRaw by this in order to get the percentage between 0 and 1. 091 * 092 * @return the output scale factor 093 */ 094 public int getOutputScaleFactor() { 095 return DutyCycleJNI.getOutputScaleFactor(m_handle); 096 } 097 098 /** 099 * Get the FPGA index for the DutyCycle. 100 * 101 * @return the FPGA index 102 */ 103 @SuppressWarnings("AbbreviationAsWordInName") 104 public final int getFPGAIndex() { 105 return DutyCycleJNI.getFPGAIndex(m_handle); 106 } 107 108 public int getSourceChannel() { 109 return m_source.getChannel(); 110 } 111 112 @Override 113 public void initSendable(SendableBuilder builder) { 114 builder.setSmartDashboardType("Duty Cycle"); 115 builder.addDoubleProperty("Frequency", this::getFrequency, null); 116 builder.addDoubleProperty("Output", this::getOutput, null); 117 } 118}