001    /*----------------------------------------------------------------------------*/
002    /* Copyright (c) FIRST 2008-2012. 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    /*----------------------------------------------------------------------------*/
007    
008    package edu.wpi.first.wpilibj;
009    
010    import edu.wpi.first.wpilibj.fpga.tInterrupt;
011    import edu.wpi.first.wpilibj.fpga.tInterruptManager;
012    
013    /**
014     * Base for sensors to be used with interrupts
015     */
016    public abstract class InterruptableSensorBase extends SensorBase {
017    
018        /**
019         * The interrupt resource
020         */
021        protected tInterrupt m_interrupt;
022        /**
023         * The interrupt manager resource
024         */
025        protected tInterruptManager m_manager;
026        /**
027         * The index of the interrupt
028         */
029        protected int m_interruptIndex;
030        /**
031         * Resource manager
032         */
033        protected static Resource interrupts = new Resource(8);
034    
035        /**
036         * Create a new InterrupatableSensorBase
037         */
038        public InterruptableSensorBase() {
039            m_manager = null;
040            m_interrupt = null;
041        }
042    
043        /**
044         * Allocate the interrupt
045         * @param watcher
046         */
047        public void allocateInterrupts(boolean watcher) {
048            if (!watcher) {
049                throw new IllegalArgumentException("Interrupt callbacks not yet supported");
050            }
051            // Expects the calling leaf class to allocate an interrupt index.
052            m_interrupt = new tInterrupt((byte) m_interruptIndex);
053            m_interrupt.writeConfig_WaitForAck(false);
054            m_manager = new tInterruptManager(1 << m_interruptIndex, watcher);
055        }
056    
057        /**
058         * Cancel interrupts on this device.
059         * This deallocates all the chipobject structures and disables any interrupts.
060         */
061        public void cancelInterrupts() {
062            if (m_interrupt == null || m_manager == null) {
063                throw new IllegalStateException();
064            }
065            m_interrupt.Release();
066            m_interrupt = null;
067            m_manager.Release();
068            m_manager = null;
069        }
070    
071        /**
072         * In synchronous mode, wait for the defined interrupt to occur.
073         * @param timeout Timeout in seconds
074         */
075        public void waitForInterrupt(double timeout) {
076            m_manager.watch((int) (timeout * 1e3));
077        }
078    
079        /**
080         * Enable interrupts to occur on this input.
081         * Interrupts are disabled when the RequestInterrupt call is made. This gives time to do the
082         * setup of the other options before starting to field interrupts.
083         */
084        public void enableInterrupts() {
085            throw new IllegalArgumentException("Interrupt callbacks not yet supported");
086        }
087    
088        /**
089         * Disable Interrupts without without deallocating structures.
090         */
091        public void disableInterrupts() {
092            throw new IllegalArgumentException("Interrupt callbacks not yet supported");
093        }
094    
095        /**
096         * Return the timestamp for the interrupt that occurred most recently.
097         * This is in the same time domain as getClock().
098         * @return Timestamp in seconds since boot.
099         */
100        public double readInterruptTimestamp() {
101            return m_interrupt.readTimeStamp() * 1e-6;
102        }
103    }