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 DigitalSource m_upSource; 025 private 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 } 047 048 if (downSource != null) { 049 m_downSource = downSource; 050 CounterJNI.setCounterDownSource( 051 m_handle, 052 downSource.getPortHandleForRouting(), 053 downSource.getAnalogTriggerTypeForRouting()); 054 CounterJNI.setCounterDownSourceEdge(m_handle, true, false); 055 } 056 057 reset(); 058 059 int intIndex = index.getInt(); 060 HAL.report(tResourceType.kResourceType_Counter, intIndex + 1); 061 SendableRegistry.addLW(this, "UpDown Counter", intIndex); 062 } 063 064 @Override 065 public void close() throws Exception { 066 SendableRegistry.remove(this); 067 CounterJNI.freeCounter(m_handle); 068 CounterJNI.suppressUnused(m_upSource); 069 CounterJNI.suppressUnused(m_downSource); 070 } 071 072 /** 073 * Sets the configuration for the up source. 074 * 075 * @param configuration The up source configuration. 076 */ 077 public void setUpEdgeConfiguration(EdgeConfiguration configuration) { 078 CounterJNI.setCounterUpSourceEdge(m_handle, configuration.rising, configuration.falling); 079 } 080 081 /** 082 * Sets the configuration for the down source. 083 * 084 * @param configuration The down source configuration. 085 */ 086 public void setDownEdgeConfiguration(EdgeConfiguration configuration) { 087 CounterJNI.setCounterDownSourceEdge(m_handle, configuration.rising, configuration.falling); 088 } 089 090 /** Resets the current count. */ 091 public void reset() { 092 CounterJNI.resetCounter(m_handle); 093 } 094 095 /** 096 * Sets to reverse the counter direction. 097 * 098 * @param reverseDirection True to reverse counting direction. 099 */ 100 public void setReverseDirection(boolean reverseDirection) { 101 CounterJNI.setCounterReverseDirection(m_handle, reverseDirection); 102 } 103 104 /** 105 * Gets the current count. 106 * 107 * @return The current count. 108 */ 109 public int getCount() { 110 return CounterJNI.getCounter(m_handle); 111 } 112 113 @Override 114 public void initSendable(SendableBuilder builder) { 115 builder.setSmartDashboardType("UpDown Counter"); 116 builder.addDoubleProperty("Count", this::getCount, null); 117 } 118}