<commit_before>/*
 * USBAEMon.java
 *
 * Created on February 17, 2005, 7:54 AM
 */

package net.sf.jaer.hardwareinterface.usb.silabs;

import net.sf.jaer.biasgen.*;
import net.sf.jaer.biasgen.VDAC.VPot;
import net.sf.jaer.aemonitor.*;
import net.sf.jaer.chip.*;
import net.sf.jaer.hardwareinterface.*;
import net.sf.jaer.hardwareinterface.usb.USBInterface;

import java.beans.*;
import java.io.*;
import java.util.*;
import java.util.logging.*;


/**
 *  Acquires data from the UNI-USE simple USB AER board that uses 
 Silicon Labs (http://www.silabs.com)
 * C8051F320 controller and SiLabs USBXPress device and host driver firmware and software.
 *<p>
 * The DLL's USBAEMonitor.dll and SiUSBXp.dll must be 
 accessible for windows programs.   Generally, this means they must be
 * somewhere on the PATH, for example, in <code>WINNT\system32</code>, 
 or they can be in the directory the program is started.
 *It is generally simplest to just put the folders on the PATH variable.
 *<p>
 *Events are captured as 16 bit addresses and 32 bit timestamps with 1us 
 tick. To use this class, construct an instance of <code>USB1AEMonitor</code>,
 *then {@link #open} it. Each time you want to capture available events, 
 call {@link #acquireAvailableEventsFromDriver}, which returns the packet of events.
 * <p>
 * {@link #overrunOccurred} can be used to see if there was a driver overrun.
 *<p>
 *NOTE: only supports a single device at a time now. (JNI limitations).
 *
 *
 * @author  tobi
 */
public class SiLabsC8051F320 implements AEMonitorInterface,  BiasgenHardwareInterface, USBInterface {
    
    static Logger log=Logger.getLogger("SiLabsC8051F320");
    
    protected AEChip chip;
    
    public void setChip(AEChip chip) {
        this.chip=chip;
    }
    
    public AEChip getChip() {
        return chip;
    }
    
    static boolean libLoaded=false;
    public static final String NATIVE_DLL_FILENAME="SiLabsC8051F320";
    public static final String USBXPRESS_DLL_FILENAME="SiUSBXp";
    boolean isOpened=false;
    public boolean eventAcquisitionEnabled=false;
    public static final int MAX_BYTES_PER_BIAS=4;
    int numEvents=0, lastNumEvents=0;
    int lastdt=0;
    AEPacketRaw events;
    
    static{
//        if(System.getProperty("os.name").startsWith("Windows")){
            try {
                System.loadLibrary(USBXPRESS_DLL_FILENAME); // you need to load this dependent DLL *first* if SiLabsC8051F320 is not on the Windows PATH
                    // see http://forum.java.sun.com/thread.jspa?threadID=679534&messageID=3963962
                System.loadLibrary(NATIVE_DLL_FILENAME);// Load Library for interfacing to Eco-Link
                libLoaded=true;
    //            log.info("SiLabsC8051F320: loaded dynamic link library "+ NATIVE_DLL_FILENAME+".dll");
            } catch (UnsatisfiedLinkError e) {
                //logging is special here because this one is static
                log.warning("Couldn't load JNI DLL for SiLabs: "+e);
                String path=null;
                try{
                    path=System.getenv("PATH");
                    path=path.replace(File.pathSeparatorChar,'\n');
                }catch(Exception e2){
                    log.warning("Couldn't read PATH from environment:" +e2.getMessage());
                }
//                log.warning(e.getMessage()+
//                        "\nSiLabsC8051F320: can't load "+NATIVE_DLL_FILENAME+".dll"+
//                        "\nNot found in " + System.getProperty("java.ext.dirs")+" or "+System.getProperty("java.library.path")+
//                        "\n user.dir="+System.getProperty("user.dir")+
//                        "\nYou will not be able to use this type of hardware interface"+
//                        "\nCould it be that you still need the SiLabsC8051F320.dll folder on the Windows PATH \n (and not just in java.library.path) because of dependent DLLs?"+
//                        "\nPATH="+path);
            }
//        }
        //        if(libLoaded){
        //            log.info("Registering static shutdown hook to close USBAEMonitor");
        //            Runtime.getRuntime().addShutdownHook(new Thread(){
        //                public void run(){ log.info("USBAEMonitor shutdown hook");}
        //            });
        //        }
//        System.loadLibrary(NATIVE_DLL_FILENAME);
        //        if(initIDs()!=0){ throw new USBAEMonitorException("can't init object field IDs");}
    }
    
    /** Creates a new instance of USB1AEMonitor. Note that it is possible but probably bad to construct several instances
     * and use each of them to open and read from the same device.
     * This class would probably better be a singleton until multiple devices are supported.
     */
    public SiLabsC8051F320() {
    }
    
    //    private static native int initIDs();
    PropertyChangeSupport support=new PropertyChangeSupport(this);
    
    private native short[] nativeGetAddresses();
    private native int[] nativeGetTimestamps();
    private native boolean nativeOverrunOccured();
    private native int nativeOpen();
    private native int nativeClose();
    private native int nativeAcquireAvailableEventsFromDriver();
    private native int nativeGetNumEventsAcquired();
    private native int nativeSetEventAcquisitionEnabled(boolean eventAcquisitionEnabled);
    private native int nativeGetNumDevices();
    private native int nativeOpen(int n);
    private native int nativeSetPowerdown(boolean powerDownEnabled);
    private native int nativeSendBiases(byte[] bytes);
    private native int nativeFlashBiases(byte[] bytes);
    public native int nativeResetTimestamps();
    
    private int interfaceNumber=0; // this is the number of the interface to actually open (we can only open one)
    
    /** Opens the device driver and starts acquiring events.
     *
     * @see #close
     *@throws USBAEMonitorException if there is a problem. Diagnostics are printed to stdout in the native code.
     */
    public void open() throws HardwareInterfaceException {
        if(!libLoaded) return;
        int status=nativeOpen(getInterfaceNumber());
        if(status==0) {
            isOpened=true;
            setEventAcquisitionEnabled(true);
//            log.info("SiLabsC8051F320.open(): device opened");
            HardwareInterfaceException.clearException();
            return;
        }else {
            isOpened=false;
            //close(); // not opened, so don't need to close
            throw new HardwareInterfaceException("nativeOpen: can't open device, device returned status "+errorText(status));
        }
    }
    
    public String toString() {
        return (getTypeName() + ": Interface " + getInterfaceNumber());
    }
    
    void ensureOpen() throws HardwareInterfaceException{
        if(!isOpen()){
//            log.info("SiLabsC8051F320.acquireAvailableEventsFromDriver(): device not open, opening it");
            open();
        }
    }
    
    
    /** Gets available events from driver and return them in a new AEPacketRaw.
     *{@link #overrunOccurred} will be true if these was an overrun of the host USBXPress driver buffers (>16k events).
     *<p>
     *AEListeners are called if new events have been collected.
     *
     * @return packet of raw events
     *@throws USBAEMonitorException
     *@see #addAEListener
     * .
     */
    public AEPacketRaw acquireAvailableEventsFromDriver() throws HardwareInterfaceException {
        try{
            if(!libLoaded) return null;
            ensureOpen();
            numEvents=nativeAcquireAvailableEventsFromDriver();
            if (numEvents<0) {
                close();
                throw new HardwareInterfaceException("nativeAcquireAvailableEventsFromDriver, device returned "+errorText(numEvents));
            }
            events=new AEPacketRaw(numEvents);
            if(numEvents==0){
                return new AEPacketRaw(0);
            }
            short[] shortAddr=nativeGetAddresses(); // returns null when device is disconnected
            // add copy to handle change to int[] raw addresses
            int[] addr=new int[shortAddr.length];
            for(int i=0;i<shortAddr.length;i++){
                addr[i]=shortAddr[i];
            }
//        int[] addr=nativeGetAddresses();
            int[] t=nativeGetTimestamps();
            if(addr==null || t==null){
                System.err.println("SiLabsC8051F320.acquireAvailableEventsFromDriver(): should have gotten "+numEvents+" events but got null array");
                return new AEPacketRaw(0);
            }
            events.setAddresses(addr);
            events.setTimestamps(t);
            events.setNumEvents(numEvents);
            if(numEvents>0){
                support.firePropertyChange(newEventPropertyChange);
                lastdt=t[numEvents-1]-t[0];
            }
            lastNumEvents=numEvents;
            HardwareInterfaceException.clearException();
            return events;<commit_msg>changed handling of address and timestamp buffers to copy data to the arrays in the new AEPacketRaw that is allocated for each received packet. Really this should reuse the packets to avoid heap cleanup.<commit_after>/*
 * USBAEMon.java
 *
 * Created on February 17, 2005, 7:54 AM
 */

package net.sf.jaer.hardwareinterface.usb.silabs;

import net.sf.jaer.biasgen.*;
import net.sf.jaer.biasgen.VDAC.VPot;
import net.sf.jaer.aemonitor.*;
import net.sf.jaer.chip.*;
import net.sf.jaer.hardwareinterface.*;
import net.sf.jaer.hardwareinterface.usb.USBInterface;

import java.beans.*;
import java.io.*;
import java.util.*;
import java.util.logging.*;


/**
 *  Acquires data from the UNI-USE simple USB AER board that uses 
 Silicon Labs (http://www.silabs.com)
 * C8051F320 controller and SiLabs USBXPress device and host driver firmware and software.
 *<p>
 * The DLL's USBAEMonitor.dll and SiUSBXp.dll must be 
 accessible for windows programs.   Generally, this means they must be
 * somewhere on the PATH, for example, in <code>WINNT\system32</code>, 
 or they can be in the directory the program is started.
 *It is generally simplest to just put the folders on the PATH variable.
 *<p>
 *Events are captured as 16 bit addresses and 32 bit timestamps with 1us 
 tick. To use this class, construct an instance of <code>USB1AEMonitor</code>,
 *then {@link #open} it. Each time you want to capture available events, 
 call {@link #acquireAvailableEventsFromDriver}, which returns the packet of events.
 * <p>
 * {@link #overrunOccurred} can be used to see if there was a driver overrun.
 *<p>
 *NOTE: only supports a single device at a time now. (JNI limitations).
 *
 *
 * @author  tobi
 */
public class SiLabsC8051F320 implements AEMonitorInterface,  BiasgenHardwareInterface, USBInterface {
     // TODO should be using thesycon usbio driver instead of lame SiLabs USBXPress driver.
    
    static Logger log=Logger.getLogger("SiLabsC8051F320");
    
    protected AEChip chip;
    
    public void setChip(AEChip chip) {
        this.chip=chip;
    }
    
    public AEChip getChip() {
        return chip;
    }
    
    static boolean libLoaded=false;
    public static final String NATIVE_DLL_FILENAME="SiLabsC8051F320";
    public static final String USBXPRESS_DLL_FILENAME="SiUSBXp";
    boolean isOpened=false;
    public boolean eventAcquisitionEnabled=false;
    public static final int MAX_BYTES_PER_BIAS=4;
    int numEvents=0, lastNumEvents=0;
    int lastdt=0;
    AEPacketRaw events;
    
    static{
//        if(System.getProperty("os.name").startsWith("Windows")){
            try {
                System.loadLibrary(USBXPRESS_DLL_FILENAME); // you need to load this dependent DLL *first* if SiLabsC8051F320 is not on the Windows PATH
                    // see http://forum.java.sun.com/thread.jspa?threadID=679534&messageID=3963962
                System.loadLibrary(NATIVE_DLL_FILENAME);// Load Library for interfacing to Eco-Link
                libLoaded=true;
    //            log.info("SiLabsC8051F320: loaded dynamic link library "+ NATIVE_DLL_FILENAME+".dll");
            } catch (UnsatisfiedLinkError e) {
                //logging is special here because this one is static
                log.warning("Couldn't load JNI DLL for SiLabs: "+e);
                String path=null;
                try{
                    path=System.getenv("PATH");
                    path=path.replace(File.pathSeparatorChar,'\n');
                }catch(Exception e2){
                    log.warning("Couldn't read PATH from environment:" +e2.getMessage());
                }
//                log.warning(e.getMessage()+
//                        "\nSiLabsC8051F320: can't load "+NATIVE_DLL_FILENAME+".dll"+
//                        "\nNot found in " + System.getProperty("java.ext.dirs")+" or "+System.getProperty("java.library.path")+
//                        "\n user.dir="+System.getProperty("user.dir")+
//                        "\nYou will not be able to use this type of hardware interface"+
//                        "\nCould it be that you still need the SiLabsC8051F320.dll folder on the Windows PATH \n (and not just in java.library.path) because of dependent DLLs?"+
//                        "\nPATH="+path);
            }
//        }
        //        if(libLoaded){
        //            log.info("Registering static shutdown hook to close USBAEMonitor");
        //            Runtime.getRuntime().addShutdownHook(new Thread(){
        //                public void run(){ log.info("USBAEMonitor shutdown hook");}
        //            });
        //        }
//        System.loadLibrary(NATIVE_DLL_FILENAME);
        //        if(initIDs()!=0){ throw new USBAEMonitorException("can't init object field IDs");}
    }
    
    /** Creates a new instance of USB1AEMonitor. Note that it is possible but probably bad to construct several instances
     * and use each of them to open and read from the same device.
     * This class would probably better be a singleton until multiple devices are supported.
     */
    public SiLabsC8051F320() {
    }
    
    //    private static native int initIDs();
    PropertyChangeSupport support=new PropertyChangeSupport(this);
    
    private native short[] nativeGetAddresses();
    private native int[] nativeGetTimestamps();
    private native boolean nativeOverrunOccured();
    private native int nativeOpen();
    private native int nativeClose();
    private native int nativeAcquireAvailableEventsFromDriver();
    private native int nativeGetNumEventsAcquired();
    private native int nativeSetEventAcquisitionEnabled(boolean eventAcquisitionEnabled);
    private native int nativeGetNumDevices();
    private native int nativeOpen(int n);
    private native int nativeSetPowerdown(boolean powerDownEnabled);
    private native int nativeSendBiases(byte[] bytes);
    private native int nativeFlashBiases(byte[] bytes);
    public native int nativeResetTimestamps();
    
    private int interfaceNumber=0; // this is the number of the interface to actually open (we can only open one)
    
    /** Opens the device driver and starts acquiring events.
     *
     * @see #close
     *@throws USBAEMonitorException if there is a problem. Diagnostics are printed to stdout in the native code.
     */
    public void open() throws HardwareInterfaceException {
        if(!libLoaded) return;
        int status=nativeOpen(getInterfaceNumber());
        if(status==0) {
            isOpened=true;
            setEventAcquisitionEnabled(true);
//            log.info("SiLabsC8051F320.open(): device opened");
            HardwareInterfaceException.clearException();
            return;
        }else {
            isOpened=false;
            //close(); // not opened, so don't need to close
            throw new HardwareInterfaceException("nativeOpen: can't open device, device returned status "+errorText(status));
        }
    }
    
    public String toString() {
        return (getTypeName() + ": Interface " + getInterfaceNumber());
    }
    
    void ensureOpen() throws HardwareInterfaceException{
        if(!isOpen()){
//            log.info("SiLabsC8051F320.acquireAvailableEventsFromDriver(): device not open, opening it");
            open();
        }
    }
    
    
    /** Gets available events from driver and return them in a new AEPacketRaw.
     *{@link #overrunOccurred} will be true if these was an overrun of the host USBXPress driver buffers (>16k events).
     *<p>
     *AEListeners are called if new events have been collected.
     *
     * @return packet of raw events
     *@throws USBAEMonitorException
     *@see #addAEListener
     * .
     */
    public AEPacketRaw acquireAvailableEventsFromDriver() throws HardwareInterfaceException {
        try{
            if(!libLoaded) return null;
            ensureOpen();
            numEvents=nativeAcquireAvailableEventsFromDriver();
            if (numEvents<0) {
                close();
                throw new HardwareInterfaceException("nativeAcquireAvailableEventsFromDriver, device returned "+errorText(numEvents));
            }
            events=new AEPacketRaw(numEvents); // TODO should reuse packet
            if(numEvents==0){
                return new AEPacketRaw(0);
            }
            short[] shortAddr=nativeGetAddresses(); // returns null when device is disconnected
            if(shortAddr==null){
                throw new NullPointerException("array of short[] addresses returned was null, probably device was unplugged");
            }
            // add copy to handle change from original short[] addresses to new int[] raw addresses
            int[] addr=events.addresses;
            for(int i=0;i<shortAddr.length;i++){
                addr[i]=shortAddr[i]&0xFFFF;
            }
            int[] t=nativeGetTimestamps();
            if(t==null){
               throw new NullPointerException("should have gotten "+numEvents+" events but got null array. Probably device was unplugged");
            }
            int[] ts=events.timestamps;
            System.arraycopy(t, 0, ts, 0, ts.length);
            events.setNumEvents(numEvents);
            if(numEvents>0){
                support.firePropertyChange(newEventPropertyChange);
                lastdt=t[numEvents-1]-t[0];
            }
            lastNumEvents=numEvents;
            HardwareInterfaceException.clearException();
            return events;
{'fraction_non_alphanumeric': 0.09476769431176726, 'fraction_numerical': 0.014274858879722102, 'mean_word_length': 2.4613939507796356, 'pattern_counts': {'":': 2, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4555346', 'n_tokens_mistral': 5215, 'n_tokens_neox': 4903, 'n_words': 1509}