001/*----------------------------------------------------------------------------*/
002/* Copyright (c) FIRST 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;
008
009import java.nio.ByteOrder;
010import java.nio.IntBuffer;
011import java.nio.LongBuffer;
012import java.nio.ByteBuffer;
013
014//import com.sun.jna.Pointer;
015
016
017import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
018import edu.wpi.first.wpilibj.communication.UsageReporting;
019import edu.wpi.first.wpilibj.hal.AnalogJNI;
020import edu.wpi.first.wpilibj.hal.HALUtil;
021import edu.wpi.first.wpilibj.livewindow.LiveWindow;
022import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
023import edu.wpi.first.wpilibj.tables.ITable;
024import edu.wpi.first.wpilibj.util.AllocationException;
025import edu.wpi.first.wpilibj.util.CheckedAllocationException;
026
027/**
028 * Analog output class.
029 */
030public class AnalogOutput extends SensorBase implements LiveWindowSendable {
031        private static Resource channels = new Resource(kAnalogOutputChannels);
032        private ByteBuffer m_port;
033        private int m_channel;
034
035        /**
036         * Construct an analog output on a specified MXP channel.
037         *
038         * @param channel
039         *                      The channel number to represent.
040         */
041        public AnalogOutput(final int channel) {
042                m_channel = channel;
043
044                if (AnalogJNI.checkAnalogOutputChannel(channel) == 0) {
045                        throw new AllocationException("Analog output channel " + m_channel
046                                        + " cannot be allocated. Channel is not present.");
047                }
048                try {
049                        channels.allocate(channel);
050                } catch (CheckedAllocationException e) {
051                        throw new AllocationException("Analog output channel " + m_channel
052                                        + " is already allocated");
053                }
054
055                ByteBuffer port_pointer = AnalogJNI.getPort((byte)channel);
056                ByteBuffer status = ByteBuffer.allocateDirect(4);
057                // set the byte order
058                status.order(ByteOrder.LITTLE_ENDIAN);
059                m_port = AnalogJNI.initializeAnalogOutputPort(port_pointer, status.asIntBuffer());
060                HALUtil.checkStatus(status.asIntBuffer());
061
062                LiveWindow.addSensor("AnalogOutput", channel, this);
063                UsageReporting.report(tResourceType.kResourceType_AnalogChannel, channel, 1);
064        }
065
066        /**
067         * Channel destructor.
068         */
069        public void free() {
070                channels.free(m_channel);
071                m_channel = 0;
072        }
073
074        public void setVoltage(double voltage) {
075                ByteBuffer status = ByteBuffer.allocateDirect(4);
076                status.order(ByteOrder.LITTLE_ENDIAN);
077
078                AnalogJNI.setAnalogOutput(m_port, voltage, status.asIntBuffer());
079
080                HALUtil.checkStatus(status.asIntBuffer());
081        }
082
083        public double getVoltage() {
084                ByteBuffer status = ByteBuffer.allocateDirect(4);
085                status.order(ByteOrder.LITTLE_ENDIAN);
086
087                double voltage = AnalogJNI.getAnalogOutput(m_port, status.asIntBuffer());
088
089                HALUtil.checkStatus(status.asIntBuffer());
090
091                return voltage;
092        }
093
094        /*
095         * Live Window code, only does anything if live window is activated.
096         */
097        public String getSmartDashboardType() {
098                return "Analog Output";
099        }
100
101        private ITable m_table;
102
103        /**
104         * {@inheritDoc}
105         */
106        public void initTable(ITable subtable) {
107                m_table = subtable;
108                updateTable();
109        }
110
111        /**
112         * {@inheritDoc}
113         */
114        public void updateTable() {
115                if (m_table != null) {
116                        m_table.putNumber("Value", getVoltage());
117                }
118        }
119
120        /**
121         * {@inheritDoc}
122         */
123        public ITable getTable() {
124                return m_table;
125        }
126
127        /**
128         * Analog Channels don't have to do anything special when entering the
129         * LiveWindow. {@inheritDoc}
130         */
131        public void startLiveWindowMode() {
132        }
133
134        /**
135         * Analog Channels don't have to do anything special when exiting the
136         * LiveWindow. {@inheritDoc}
137         */
138        public void stopLiveWindowMode() {
139        }
140}