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.hal;
006
007import java.util.HashMap;
008import java.util.Map;
009
010public class DMAJNISample {
011  private static final int kEnable_Accumulator0 = 8;
012  private static final int kEnable_Accumulator1 = 9;
013
014  static class BaseStore {
015    public final int m_valueType;
016    public final int m_index;
017
018    BaseStore(int valueType, int index) {
019      this.m_valueType = valueType;
020      this.m_index = index;
021    }
022  }
023
024  private final int[] m_dataBuffer = new int[100];
025  private final int[] m_storage = new int[100];
026  private long m_timeStamp;
027  private Map<Integer, BaseStore> m_propertyMap = new HashMap<>();
028
029  public int update(int dmaHandle, double timeoutSeconds) {
030    m_timeStamp = DMAJNI.readDMA(dmaHandle, timeoutSeconds, m_dataBuffer, m_storage);
031    return m_storage[25];
032  }
033
034  public int getCaptureSize() {
035    return m_storage[22];
036  }
037
038  public int getTriggerChannels() {
039    return m_storage[23];
040  }
041
042  public int getRemaining() {
043    return m_storage[24];
044  }
045
046  public long getTime() {
047    return m_timeStamp;
048  }
049
050  private BaseStore addSensorInternal(int handle) {
051    BaseStore sensorData = DMAJNI.getSensorReadData(handle);
052    m_propertyMap.put(handle, sensorData);
053    return sensorData;
054  }
055
056  public void addSensor(int handle) {
057    addSensorInternal(handle);
058  }
059
060  private int readValue(int valueType, int index) {
061    int offset = m_storage[valueType];
062    if (offset == -1) {
063      throw new RuntimeException("Resource not found in DMA capture");
064    }
065    return m_dataBuffer[offset + index];
066  }
067
068  public int getEncoder(int encoderHandle) {
069    BaseStore data = m_propertyMap.get(encoderHandle);
070    if (data == null) {
071      data = addSensorInternal(encoderHandle);
072    }
073    return readValue(data.m_valueType, data.m_index);
074  }
075
076  public int getEncoderPeriod(int encoderHandle) {
077    BaseStore data = m_propertyMap.get(encoderHandle);
078    if (data == null) {
079      data = addSensorInternal(encoderHandle);
080    }
081    // + 2 Hack, but needed to not have to call into JNI
082    return readValue(data.m_valueType + 2, data.m_index);
083  }
084
085  public int getCounter(int counterHandle) {
086    BaseStore data = m_propertyMap.get(counterHandle);
087    if (data == null) {
088      data = addSensorInternal(counterHandle);
089    }
090    return readValue(data.m_valueType, data.m_index);
091  }
092
093  public int getCounterPeriod(int counterHandle) {
094    BaseStore data = m_propertyMap.get(counterHandle);
095    if (data == null) {
096      data = addSensorInternal(counterHandle);
097    }
098    // Hack, but needed to not have to call into JNI
099    return readValue(data.m_valueType + 2, data.m_index);
100  }
101
102  public boolean getDigitalSource(int digitalSourceHandle) {
103    BaseStore data = m_propertyMap.get(digitalSourceHandle);
104    if (data == null) {
105      data = addSensorInternal(digitalSourceHandle);
106    }
107
108    int value = readValue(data.m_valueType, 0);
109
110    return ((value >> data.m_index) & 0x1) != 0;
111  }
112
113  public int getAnalogInput(int analogInputHandle) {
114    BaseStore data = m_propertyMap.get(analogInputHandle);
115    if (data == null) {
116      data = addSensorInternal(analogInputHandle);
117    }
118
119    int value = readValue(data.m_valueType, data.m_index / 2);
120    if ((data.m_index % 2) != 0) {
121      return (value >>> 16) & 0xFFFF;
122    } else {
123      return value & 0xFFFF;
124    }
125  }
126
127  public int getAnalogInputAveraged(int analogInputHandle) {
128    BaseStore data = m_propertyMap.get(analogInputHandle);
129    if (data == null) {
130      data = addSensorInternal(analogInputHandle);
131    }
132
133    // + 2 Hack, but needed to not have to call into JNI
134    return readValue(data.m_valueType + 2, data.m_index);
135  }
136
137  public void getAnalogAccumulator(int analogInputHandle, AccumulatorResult result) {
138    BaseStore data = m_propertyMap.get(analogInputHandle);
139    if (data == null) {
140      data = addSensorInternal(analogInputHandle);
141    }
142
143    if (data.m_index == 0) {
144      int val0 = readValue(kEnable_Accumulator0, 0);
145      int val1 = readValue(kEnable_Accumulator0, 1);
146      int val2 = readValue(kEnable_Accumulator0, 2);
147      result.count = val2;
148      result.value = ((long) val1 << 32) | val0;
149    } else if (data.m_index == 1) {
150      int val0 = readValue(kEnable_Accumulator1, 0);
151      int val1 = readValue(kEnable_Accumulator1, 1);
152      int val2 = readValue(kEnable_Accumulator1, 2);
153      result.count = val2;
154      result.value = ((long) val1 << 32) | val0;
155    } else {
156      throw new RuntimeException("Resource not found in DMA capture");
157    }
158  }
159
160  public int getDutyCycleOutput(int dutyCycleHandle) {
161    BaseStore data = m_propertyMap.get(dutyCycleHandle);
162    if (data == null) {
163      data = addSensorInternal(dutyCycleHandle);
164    }
165    return readValue(data.m_valueType, data.m_index);
166  }
167}