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.wpilibj.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 public ExternalDirectionCounter(DigitalSource countSource, DigitalSource directionSource) { 038 m_countSource = requireNonNullParam(countSource, "countSource", "ExternalDirectionCounter"); 039 m_directionSource = 040 requireNonNullParam(directionSource, "directionSource", "ExternalDirectionCounter"); 041 042 ByteBuffer index = ByteBuffer.allocateDirect(4); 043 // set the byte order 044 index.order(ByteOrder.LITTLE_ENDIAN); 045 m_handle = CounterJNI.initializeCounter(CounterJNI.EXTERNAL_DIRECTION, index.asIntBuffer()); 046 047 CounterJNI.setCounterUpSource( 048 m_handle, 049 countSource.getPortHandleForRouting(), 050 countSource.getAnalogTriggerTypeForRouting()); 051 CounterJNI.setCounterUpSourceEdge(m_handle, true, false); 052 053 CounterJNI.setCounterDownSource( 054 m_handle, 055 directionSource.getPortHandleForRouting(), 056 directionSource.getAnalogTriggerTypeForRouting()); 057 CounterJNI.setCounterDownSourceEdge(m_handle, false, true); 058 CounterJNI.resetCounter(m_handle); 059 060 int intIndex = index.getInt(); 061 HAL.report(tResourceType.kResourceType_Counter, intIndex + 1); 062 SendableRegistry.addLW(this, "External Direction Counter", intIndex); 063 } 064 065 /** 066 * Gets the current count. 067 * 068 * @return The current count. 069 */ 070 public int getCount() { 071 return CounterJNI.getCounter(m_handle); 072 } 073 074 /** 075 * Sets to revese the counter direction. 076 * 077 * @param reverseDirection True to reverse counting direction. 078 */ 079 public void setReverseDirection(boolean reverseDirection) { 080 CounterJNI.setCounterReverseDirection(m_handle, reverseDirection); 081 } 082 083 /** Resets the current count. */ 084 public void reset() { 085 CounterJNI.resetCounter(m_handle); 086 } 087 088 /** 089 * Sets the edge configuration for counting. 090 * 091 * @param configuration The counting edge configuration. 092 */ 093 public void setEdgeConfiguration(EdgeConfiguration configuration) { 094 CounterJNI.setCounterUpSourceEdge(m_handle, configuration.rising, configuration.falling); 095 } 096 097 @Override 098 public void close() throws Exception { 099 SendableRegistry.remove(this); 100 CounterJNI.freeCounter(m_handle); 101 CounterJNI.suppressUnused(m_countSource); 102 CounterJNI.suppressUnused(m_directionSource); 103 } 104 105 @Override 106 public void initSendable(SendableBuilder builder) { 107 builder.setSmartDashboardType("External Direction Counter"); 108 builder.addDoubleProperty("Count", this::getCount, null); 109 } 110}