package com.proatech.examples; import com.proatech.bioera.external.ExternalInitIf; import com.proatech.bioera.external.ExternalSinkIf; import com.proatech.bioera.external.ExternalSourceIf; /** * This class is an example implementation of ExternalElement, it implements interfaces: ExternalSourceIf, ExternalSinkIf, ExternalInitIf. * * 1. It creates an element with one input and output channel. * 2. It multiplies input signal by 2. * */ public class ExternalElementExample implements ExternalSourceIf, ExternalInitIf, ExternalSinkIf { // This buffer will hold data provided to this element // This example has only one channel, so there is just one buffer private int scalarBuffer[]; // Must be implemented for Scalar element private float floatBuffer[]; // Must be implemented for Float element private double doubleBuffer[]; // Must be implemented for DoubleFloat element int available; // This variable will remember how many data is currently in our internal buffer ////////////// Definition of ExternalSourceIf interface ///////////////////////// /** * If your signal has constant rate it should be set here. * If it is set to -1, , then the information is taken from the element connected to input (in the design) */ public float getOutputDataRate() { return -1; } /** * If your signal has constant maximum digital value then it should be set here. * If it is set to Integer.MAX_VALUE, then the information is taken from the element connected to input (in the design) */ public int getDigitalMax() { return Integer.MAX_VALUE; } /** * If your signal has constant maximum digital value then it should be set here. * If it is set to Integer.MIN_VALUE, then the information is taken from the element connected to input (in design) */ public int getDigitalMin() { return Integer.MIN_VALUE; } /** * Define number of output channels. The design has to be restarted if this value changes. */ public int getOutputChannelCount() { return 1; } /** * If your signal has constant maximum physical value then it should be set here. * If it is set to Float.POSITIVE_INFINITY, then the information is taken from the element connected to input (in design) */ public float getPhysicalMax() { return Float.POSITIVE_INFINITY; } /** * If your signal has constant minimum physical value then it should be set here. * If it is set to Float.MIN_VALUE, then the information is taken from the element connected to input (in design) */ public float getPhysicalMin() { return Float.NEGATIVE_INFINITY; } /** * If your signal has a physical unit it should be set here. * If it is set to null, then the information is taken from the element connected to input (in design) */ public String getPhysicalUnit() { return null; } /** * You can set name of each channel. It will be visible on the element's pipe. * If not set (returns null), then a default name will be assigned. */ public String getOutputChannelName(int channel) { return "Channel " + (channel+1); } /** * You can set name of each input channel. It will be visible on the element's pipe. * If not set (returns null), then a default name will be assigned. */ public String getInputChannelName(int channel) { return "Input " + (channel+1); } /** * This method is described in the ExternalSourceIf interface */ public int processOutputData(int channel, int[] destinationBuffer) { // Just copy the data which has been already preprocessed in write() method System.arraycopy(scalarBuffer, 0, destinationBuffer, 0, available); int ret = available; // Reset internal buffer available = 0; return ret; } /** * This method is described in the ExternalSourceIf interface */ public int processOutputData(int channel, float[] destinationBuffer) { // Just copy the data which has been already preprocessed in write() method System.arraycopy(floatBuffer, 0, destinationBuffer, 0, available); int ret = available; // Reset internal buffer available = 0; return ret; } /** * This method is described in the ExternalSourceIf interface */ public int processOutputData(int channel, double[] destinationBuffer) { // Just copy the data which has been already preprocessed in write() method System.arraycopy(scalarBuffer, 0, destinationBuffer, 0, available); int ret = available; // Reset internal buffer available = 0; return ret; } /////////////////// Defiinition of the ExternalInitIf interface //////////////////// /** * Called one time when the element is created. */ public void init() throws java.io.IOException { } /** * Called whenever element is started. */ public void start() throws java.io.IOException { scalarBuffer = new int[65536]; // allocate buffer large enough to keep all incoming data floatBuffer = new float[65536]; // allocate buffer large enough to keep all incoming data doubleBuffer = new double[65536]; // allocate buffer large enough to keep all incoming data System.out.println("External element started"); } /** * Called whenever element is stopped. */ public void stop() throws java.io.IOException { System.out.println("External element stopped"); } /** * Called whenever element is paused. */ public void pause() throws java.io.IOException { System.out.println("External element paused"); } /** * Called whenever element is reinited. */ public void reinit() throws java.io.IOException { System.out.println("External element reinited"); } /** * Called whenever element is resumed. */ public void resume() throws java.io.IOException { System.out.println("External element resumed"); } /** * Called one time when element is removed from the design (or exit). */ public void destroy() { System.out.println("External element destroyed"); } /** * Define number of input channels. The design has to be restarted if this value changes. */ public int getInputChannelCount() { return 1; } /** * This method is called only in scalar ExternalElement when there is data delivered to input pipe * It must return the number of samples processed, or Integer.MAX_VALUE if all data should be dropped. */ public int processInputData(int channel, int[] source, int count) { // Remember how many data we read available = count; // Read all available data into our internal buffer System.arraycopy(source, 0, scalarBuffer, 0, count); // Process the data .... // Multiply all samples by 2 for (int i = 0; i < count; i++) { scalarBuffer[i] *= 2; } // This means that all data has been processed, it could also return the 'available' value. return Integer.MAX_VALUE; } /** * This method is called only in F_ExternalElement when there is data delivered to input pipe * It must return the number of samples processed, or Integer.MAX_VALUE if all data should be dropped. */ public int processInputData(int channel, float[] source, int count) { // Remember how many data we read available = count; // Read all available data into our internal buffer System.arraycopy(source, 0, floatBuffer, 0, count); // Process the data .... // Multiply all samples by 2 for (int i = 0; i < count; i++) { floatBuffer[i] *= 2; } // This means that all data has been processed, it could also return the 'available' value. return Integer.MAX_VALUE; } /** * This method is called only in D_ExternalElement when there is data delivered to input pipe * It must return the number of samples processed, or Integer.MAX_VALUE if all data should be dropped. */ public int processInputData(int channel, double[] source, int count) { // Remember how many data we read available = count; // Read all available data into our internal buffer System.arraycopy(source, 0, doubleBuffer, 0, count); // Process the data .... // Multiply all samples by 2 for (int i = 0; i < count; i++) { doubleBuffer[i] *= 2; } // This means that all data has been processed, it could also return the 'available' value. return Integer.MAX_VALUE; } }