001/*----------------------------------------------------------------------------*/
002/* Copyright (c) FIRST 2008-2014. All Rights Reserved.                        */
003/* Open Source Software - may be modified and shared by FRC teams. The code   */
004/* must be accompanied by the FIRST BSD license file in the root directory of */
005/* the project.                                                               */
006/*----------------------------------------------------------------------------*/
007package edu.wpi.first.wpilibj;
008import java.nio.ByteBuffer;
009import java.nio.IntBuffer;
010
011import edu.wpi.first.wpilibj.hal.HALUtil;
012import edu.wpi.first.wpilibj.hal.PowerJNI;
013import edu.wpi.first.wpilibj.interfaces.Potentiometer;
014import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
015import edu.wpi.first.wpilibj.tables.ITable;
016
017/**
018 * Class for reading analog potentiometers. Analog potentiometers read
019 * in an analog voltage that corresponds to a position. The position is
020 * in whichever units you choose, by way of the scaling and offset
021 * constants passed to the constructor. 
022 *
023 * @author Alex Henning
024 * @author Colby Skeggs (rail voltage)
025 */
026public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
027    private double m_fullRange, m_offset;
028    private AnalogInput m_analog_input;
029    private boolean m_init_analog_input;
030
031    /**
032     * Common initialization code called by all constructors.
033     * @param input The {@link AnalogInput} this potentiometer is plugged into.
034     * @param fullRange The scaling to multiply the voltage by to get a meaningful unit.
035     * @param offset The offset to add to the scaled value for controlling the zero value
036     */
037    private void initPot(final AnalogInput input, double fullRange, double offset) {
038        this.m_fullRange = fullRange;
039        this.m_offset = offset;
040        m_analog_input = input;
041    }
042
043    /**
044     * AnalogPotentiometer constructor.
045     *
046     * Use the fullRange and offset values so that the output produces
047     * meaningful values. I.E: you have a 270 degree potentiometer and
048     * you want the output to be degrees with the halfway point as 0
049     * degrees. The fullRange value is 270.0(degrees) and the offset is
050     * -135.0 since the halfway point after scaling is 135 degrees.
051     * 
052     * This will calculate the result from the fullRange times the
053     * fraction of the supply voltage, plus the offset.
054     *
055     * @param channel The analog channel this potentiometer is plugged into.
056     * @param fullRange The scaling to multiply the fraction by to get a meaningful unit.
057     * @param offset The offset to add to the scaled value for controlling the zero value
058     */
059    public AnalogPotentiometer(final int channel, double fullRange, double offset) {
060        AnalogInput input = new AnalogInput(channel);
061        m_init_analog_input = true;
062        initPot(input, fullRange, offset);
063    }
064
065    /**
066     * AnalogPotentiometer constructor.
067     *
068     * Use the fullRange and offset values so that the output produces
069     * meaningful values. I.E: you have a 270 degree potentiometer and
070     * you want the output to be degrees with the halfway point as 0
071     * degrees. The fullRange value is 270.0(degrees) and the offset is
072     * -135.0 since the halfway point after scaling is 135 degrees.
073     * 
074     * This will calculate the result from the fullRange times the
075     * fraction of the supply voltage, plus the offset.
076     *
077     * @param input The {@link AnalogInput} this potentiometer is plugged into.
078     * @param fullRange The scaling to multiply the fraction by to get a meaningful unit.
079     * @param offset The offset to add to the scaled value for controlling the zero value
080     */
081    public AnalogPotentiometer(final AnalogInput input, double fullRange, double offset) {
082        m_init_analog_input = false;
083        initPot(input, fullRange, offset);
084    }
085
086    /**
087     * AnalogPotentiometer constructor.
088     *
089     * Use the fullRange and offset values so that the output produces
090     * meaningful values. I.E: you have a 270 degree potentiometer and
091     * you want the output to be degrees with the halfway point as 0
092     * degrees. The fullRange value is 270.0(degrees) and the offset is
093     * -135.0 since the halfway point after scaling is 135 degrees.
094     *
095     * @param channel The analog channel this potentiometer is plugged into.
096     * @param scale The scaling to multiply the voltage by to get a meaningful unit.
097     */
098    public AnalogPotentiometer(final int channel, double scale) {
099        this(channel, scale, 0);
100    }
101    
102    /**
103     * AnalogPotentiometer constructor.
104     *
105     * Use the fullRange and offset values so that the output produces
106     * meaningful values. I.E: you have a 270 degree potentiometer and
107     * you want the output to be degrees with the halfway point as 0
108     * degrees. The fullRange value is 270.0(degrees) and the offset is
109     * -135.0 since the halfway point after scaling is 135 degrees.
110     *
111     * @param input The {@link AnalogInput} this potentiometer is plugged into.
112     * @param scale The scaling to multiply the voltage by to get a meaningful unit.
113     */
114    public AnalogPotentiometer(final AnalogInput input, double scale) {
115        this(input, scale, 0);
116    }
117
118    /**
119     * AnalogPotentiometer constructor.
120     *
121     * @param channel The analog channel this potentiometer is plugged into.
122     */
123    public AnalogPotentiometer(final int channel) {
124        this(channel, 1, 0);
125    }
126
127    /**
128     * AnalogPotentiometer constructor.
129     *
130     * @param input The {@link AnalogInput} this potentiometer is plugged into.
131     */
132    public AnalogPotentiometer(final AnalogInput input) {
133        this(input, 1, 0);
134    }
135
136    /**
137     * Get the current reading of the potentiometer.
138     *
139     * @return The current position of the potentiometer.
140     */
141    public double get() {
142        return (m_analog_input.getVoltage() / ControllerPower.getVoltage5V()) * m_fullRange + m_offset;
143    }
144
145    /**
146     * Implement the PIDSource interface.
147     *
148     * @return The current reading.
149     */
150    public double pidGet() {
151        return get();
152    }
153
154
155    /**
156     * Live Window code, only does anything if live window is activated.
157     */
158    public String getSmartDashboardType(){
159        return "Analog Input";
160    }
161    private ITable m_table;
162
163    /**
164     * {@inheritDoc}
165     */
166    public void initTable(ITable subtable) {
167        m_table = subtable;
168        updateTable();
169    }
170
171    /**
172     * {@inheritDoc}
173     */
174    public void updateTable() {
175        if (m_table != null) {
176            m_table.putNumber("Value", get());
177        }
178    }
179
180    /**
181     * {@inheritDoc}
182     */
183    public ITable getTable(){
184        return m_table;
185    }
186    
187    public void free(){
188        if(m_init_analog_input){
189                m_analog_input.free();
190                m_analog_input = null;
191                m_init_analog_input = false;
192        }
193    }
194
195    /**
196     * Analog Channels don't have to do anything special when entering the LiveWindow.
197     * {@inheritDoc}
198     */
199    public void startLiveWindowMode() {}
200
201    /**
202     * Analog Channels don't have to do anything special when exiting the LiveWindow.
203     * {@inheritDoc}
204     */
205    public void stopLiveWindowMode() {}
206}