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 }