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 static edu.wpi.first.util.ErrorMessages.requireNonNullParam; 008 009import edu.wpi.first.hal.CounterJNI; 010import edu.wpi.first.hal.FRCNetComm.tResourceType; 011import edu.wpi.first.hal.HAL; 012import edu.wpi.first.util.sendable.Sendable; 013import edu.wpi.first.util.sendable.SendableBuilder; 014import edu.wpi.first.util.sendable.SendableRegistry; 015import edu.wpi.first.wpilibj.DigitalSource; 016import java.nio.ByteBuffer; 017import java.nio.ByteOrder; 018 019/** 020 * Counter using external direction. 021 * 022 * <p>This counts on an edge from one digital input and the whether it counts up or down based on 023 * the state of a second digital input. 024 */ 025public class ExternalDirectionCounter implements Sendable, AutoCloseable { 026 private final DigitalSource m_countSource; 027 private final DigitalSource m_directionSource; 028 029 private final int m_handle; 030 031 /** 032 * Constructs a new ExternalDirectionCounter. 033 * 034 * @param countSource The source for counting. 035 * @param directionSource The source for selecting count direction. 036 */ 037 @SuppressWarnings("this-escape") 038 public ExternalDirectionCounter(DigitalSource countSource, DigitalSource directionSource) { 039 m_countSource = requireNonNullParam(countSource, "countSource", "ExternalDirectionCounter"); 040 m_directionSource = 041 requireNonNullParam(directionSource, "directionSource", "ExternalDirectionCounter"); 042 043 ByteBuffer index = ByteBuffer.allocateDirect(4); 044 // set the byte order 045 index.order(ByteOrder.LITTLE_ENDIAN); 046 m_handle = CounterJNI.initializeCounter(CounterJNI.EXTERNAL_DIRECTION, index.asIntBuffer()); 047 048 CounterJNI.setCounterUpSource( 049 m_handle, 050 countSource.getPortHandleForRouting(), 051 countSource.getAnalogTriggerTypeForRouting()); 052 CounterJNI.setCounterUpSourceEdge(m_handle, true, false); 053 054 CounterJNI.setCounterDownSource( 055 m_handle, 056 directionSource.getPortHandleForRouting(), 057 directionSource.getAnalogTriggerTypeForRouting()); 058 CounterJNI.setCounterDownSourceEdge(m_handle, false, true); 059 CounterJNI.resetCounter(m_handle); 060 061 int intIndex = index.getInt(); 062 HAL.report(tResourceType.kResourceType_Counter, intIndex + 1); 063 SendableRegistry.addLW(this, "External Direction Counter", intIndex); 064 } 065 066 /** 067 * Gets the current count. 068 * 069 * @return The current count. 070 */ 071 public int getCount() { 072 return CounterJNI.getCounter(m_handle); 073 } 074 075 /** 076 * Sets to reverse the counter direction. 077 * 078 * @param reverseDirection True to reverse counting direction. 079 */ 080 public void setReverseDirection(boolean reverseDirection) { 081 CounterJNI.setCounterReverseDirection(m_handle, reverseDirection); 082 } 083 084 /** Resets the current count. */ 085 public void reset() { 086 CounterJNI.resetCounter(m_handle); 087 } 088 089 /** 090 * Sets the edge configuration for counting. 091 * 092 * @param configuration The counting edge configuration. 093 */ 094 public void setEdgeConfiguration(EdgeConfiguration configuration) { 095 CounterJNI.setCounterUpSourceEdge(m_handle, configuration.rising, configuration.falling); 096 } 097 098 @Override 099 public void close() { 100 SendableRegistry.remove(this); 101 CounterJNI.freeCounter(m_handle); 102 CounterJNI.suppressUnused(m_countSource); 103 CounterJNI.suppressUnused(m_directionSource); 104 } 105 106 @Override 107 public void initSendable(SendableBuilder builder) { 108 builder.setSmartDashboardType("External Direction Counter"); 109 builder.addDoubleProperty("Count", this::getCount, null); 110 } 111}