001 // Class for handling interrupts.
002 // Copyright (c) National Instruments 2008. All Rights Reserved.
003
004 package edu.wpi.first.wpilibj.fpga;
005
006 import com.ni.rio.*;
007 import com.sun.cldc.jna.ptr.IntByReference;
008
009 public class tInterruptManager extends tSystem
010 {
011
012 private static final int kFPGA_INTERRUPT_BASE_ADDRESS = 0x8000;
013 private static final int kFPGA_INTERRUPT_ACKNOWLEDGE_ADDRESS = (kFPGA_INTERRUPT_BASE_ADDRESS + 0xC);
014
015 //tInterruptHandler m_handler;
016 private int m_interruptMask;
017 //int _taskId;
018 private IntByReference m_rioContext;
019 private boolean m_watcher;
020 private boolean m_enabled;
021 //void *m_userParam;
022
023 // maintain the interrupts that are already dealt with.
024 private static int m_globalInterruptMask = 0;
025 //static SEM_ID m_globalInterruptMaskSemaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
026
027 public tInterruptManager (int interruptMask, boolean watcher)
028 {
029 super();
030 if (status.isFatal()) return;
031
032 //m_handler = NULL;
033 m_interruptMask = interruptMask;
034 //m_taskId = INVALID_TASK_ID;
035 m_rioContext = new IntByReference(0);
036 m_watcher = watcher;
037 m_enabled = false;
038 //m_userParam = NULL;
039
040 // Allocate the appropriate resources in the RIO driver.
041 NiFpga.reserveIrqContext(m_DeviceHandle, m_rioContext, status);
042 }
043
044 protected void finalize()
045 {
046
047 // if (!m_watcher && isEnabled())
048 // {
049 // // Rendezvous with thread
050 // disable();
051 // }
052
053 // Free the resources in the RIO driver
054 NiFpga.unreserveIrqContext(m_DeviceHandle, m_rioContext, status);
055 super.finalize();
056 }
057
058 public int watch(int timeoutInMs)
059 {
060 if (!m_watcher)
061 {
062 status.setStatus(NiRioStatus.kRIOStatusIrrelevantAttribute);
063 return 0;
064 }
065
066 reserve();
067 if (status.isFatal()) return 0;
068
069 // Acknowldge any pending interrupts.
070 acknowledge();
071
072 int intsAsserted = NiFpga.waitOnIrqs(m_DeviceHandle, m_rioContext, m_interruptMask, timeoutInMs, status);
073 acknowledge();
074 unreserve();
075
076 return intsAsserted;
077 }
078
079 protected void acknowledge()
080 {
081 NiFpga.writeU32(m_DeviceHandle, kFPGA_INTERRUPT_ACKNOWLEDGE_ADDRESS, m_interruptMask, status);
082 }
083
084 protected void reserve()
085 {
086 // TODO: synchronize me
087 //semTake(_globalInterruptMaskSemaphore, WAIT_FOREVER);
088 if ((m_globalInterruptMask & m_interruptMask) != 0 || m_enabled)
089 {
090 // Don't look at this interrupt if someone else already is.
091 status.setStatus(NiRioStatus.kRIOStatusEventEnabled);
092 }
093 else
094 {
095 m_globalInterruptMask |= m_interruptMask;
096 m_enabled = true;
097 }
098 //semGive(_globalInterruptMaskSemaphore);
099 }
100
101 protected void unreserve()
102 {
103 // TODO: synchronize me
104 //semTake(_globalInterruptMaskSemaphore, WAIT_FOREVER);
105 if (!m_enabled)
106 {
107 // Don't try to disable if we were never enabled.
108 status.setStatus(NiRioStatus.kRIOStatusEventNotEnabled);
109 }
110 else
111 {
112 m_enabled = false;
113 m_globalInterruptMask &= ~m_interruptMask;
114 }
115 //semGive(_globalInterruptMaskSemaphore);
116 }
117
118 }