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.counter; 006 007import edu.wpi.first.hal.CounterJNI; 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; 013import edu.wpi.first.wpilibj.DigitalSource; 014import java.nio.ByteBuffer; 015import java.nio.ByteOrder; 016 017/** 018 * Up Down Counter. 019 * 020 * <p>This class can count edges on a single digital input or count up based on an edge from one 021 * digital input and down on an edge from another digital input. 022 */ 023public class UpDownCounter implements Sendable, AutoCloseable { 024 private final DigitalSource m_upSource; 025 private final DigitalSource m_downSource; 026 027 private final int m_handle; 028 029 /** 030 * Constructs a new UpDown Counter. 031 * 032 * @param upSource The up count source (can be null). 033 * @param downSource The down count source (can be null). 034 */ 035 public UpDownCounter(DigitalSource upSource, DigitalSource downSource) { 036 ByteBuffer index = ByteBuffer.allocateDirect(4); 037 // set the byte order 038 index.order(ByteOrder.LITTLE_ENDIAN); 039 m_handle = CounterJNI.initializeCounter(CounterJNI.TWO_PULSE, index.asIntBuffer()); 040 041 if (upSource != null) { 042 m_upSource = upSource; 043 CounterJNI.setCounterUpSource( 044 m_handle, upSource.getPortHandleForRouting(), upSource.getAnalogTriggerTypeForRouting()); 045 CounterJNI.setCounterUpSourceEdge(m_handle, true, false); 046 } else { 047 m_upSource = null; 048 } 049 050 if (downSource != null) { 051 m_downSource = downSource; 052 CounterJNI.setCounterDownSource( 053 m_handle, 054 downSource.getPortHandleForRouting(), 055 downSource.getAnalogTriggerTypeForRouting()); 056 CounterJNI.setCounterDownSourceEdge(m_handle, true, false); 057 } else { 058 m_downSource = null; 059 } 060 061 reset(); 062 063 int intIndex = index.getInt(); 064 HAL.report(tResourceType.kResourceType_Counter, intIndex + 1); 065 SendableRegistry.addLW(this, "UpDown Counter", intIndex); 066 } 067 068 @Override 069 public void close() { 070 SendableRegistry.remove(this); 071 CounterJNI.freeCounter(m_handle); 072 CounterJNI.suppressUnused(m_upSource); 073 CounterJNI.suppressUnused(m_downSource); 074 } 075 076 /** 077 * Sets the configuration for the up source. 078 * 079 * @param configuration The up source configuration. 080 */ 081 public void setUpEdgeConfiguration(EdgeConfiguration configuration) { 082 CounterJNI.setCounterUpSourceEdge(m_handle, configuration.rising, configuration.falling); 083 } 084 085 /** 086 * Sets the configuration for the down source. 087 * 088 * @param configuration The down source configuration. 089 */ 090 public void setDownEdgeConfiguration(EdgeConfiguration configuration) { 091 CounterJNI.setCounterDownSourceEdge(m_handle, configuration.rising, configuration.falling); 092 } 093 094 /** Resets the current count. */ 095 public void reset() { 096 CounterJNI.resetCounter(m_handle); 097 } 098 099 /** 100 * Sets to reverse the counter direction. 101 * 102 * @param reverseDirection True to reverse counting direction. 103 */ 104 public void setReverseDirection(boolean reverseDirection) { 105 CounterJNI.setCounterReverseDirection(m_handle, reverseDirection); 106 } 107 108 /** 109 * Gets the current count. 110 * 111 * @return The current count. 112 */ 113 public int getCount() { 114 return CounterJNI.getCounter(m_handle); 115 } 116 117 @Override 118 public void initSendable(SendableBuilder builder) { 119 builder.setSmartDashboardType("UpDown Counter"); 120 builder.addDoubleProperty("Count", this::getCount, null); 121 } 122}