hps-java/src/main/java/org/lcsim/hps/recon/tracking/apv25
diff -N APV25Constants.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ APV25Constants.java 3 Jul 2012 00:34:12 -0000 1.1
@@ -0,0 +1,25 @@
+package org.lcsim.hps.recon.tracking.apv25;
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: APV25Constants.java,v 1.1 2012/07/03 00:34:12 omoreno Exp $
+ */
+public class APV25Constants {
+
+ // Total number of channels an APV25 asic contains
+ public static final int CHANNELS = 128;
+
+ // Number of electron-hole pairs created by a min. ionizing particle
+ // in 300 micrometers of Si
+ public static final int MIP = 25000;
+
+ //
+ public static final int SAMPLING_TIME = 24; // [ns]
+
+ //
+ public static final double FRONT_END_GAIN = 100.0;
+ public static final int ANALOG_PIPELINE_LENGTH = 192;
+
+
+}
hps-java/src/main/java/org/lcsim/hps/recon/tracking/apv25
diff -N APV25Full.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ APV25Full.java 3 Jul 2012 00:34:12 -0000 1.1
@@ -0,0 +1,231 @@
+package org.lcsim.hps.recon.tracking.apv25;
+
+//--- Constants ---//
+import static org.lcsim.hps.recon.tracking.apv25.APV25Constants.ANALOG_PIPELINE_LENGTH;
+import static org.lcsim.hps.recon.tracking.apv25.APV25Constants.FRONT_END_GAIN;
+import static org.lcsim.hps.recon.tracking.apv25.APV25Constants.MIP;
+import static org.lcsim.hps.recon.tracking.apv25.APV25Constants.SAMPLING_TIME;
+
+//--- hps-java ---//
+import org.lcsim.hps.util.ClockSingleton;
+import org.lcsim.hps.util.RingBuffer;
+
+/**
+ *
+ * @author Omar Moreno <[log in to unmask]>
+ * @version $Id: APV25Full.java,v 1.1 2012/07/03 00:34:12 omoreno Exp $
+ */
+public class APV25Full {
+
+ // APV25 Channels; An APV25 Readout Chip contains a total of 128 channels
+ private APV25Channel[] channels = new APV25Channel[128];
+ private String apv25Mode = "multi-peak";
+
+ public APV25Full(){
+
+ // Instantiate all APV25 channels
+ for(int channel = 0; channel < channels.length; channel++){
+ channels[channel] = new APV25Channel();
+ }
+
+ // TODO: Load channel constants from the conditions database. Channel
+ // constants need to be loaded on a run by run basis
+ this.loadChannelConstants();
+ }
+
+ /**
+ * Set the operating mode of the APV25 to either "peak",
+ * "deconvolution", or "multi-peak".
+ *
+ * @param mode : APV25 operating mode
+ */
+ public void setAPV25Mode(String mode) {
+ apv25Mode = mode;
+ }
+
+ /**
+ * Return an instance of an APV25 channel
+ *
+ * @return an instance of APV25Channel
+ */
+ public APV25Channel getChannel(int channel){
+ return channels[channel];
+ }
+
+ /**
+ * Inject charge into a channel and shape the signal. The resulting
+ * shaper signal is then sampled into the analog pipeline
+ *
+ * @param charge : Total charge being injected
+ * @param pipeline : Analog pipeline associated with a channel
+ */
+ public void injectCharge(int channel, double charge) {
+
+ // Shape the injected charge
+ this.getChannel(channel).shapeSignal(charge);
+
+ // Sample the resulting shaper signal
+ this.getChannel(channel).sampleShaperSignal();
+ }
+
+ /**
+ *
+ */
+ public void loadChannelConstants(){
+ }
+
+ //------------------------------------------//
+ // APV25 Channel //
+ //------------------------------------------//
+ public class APV25Channel {
+
+ private APV25ShaperSignal shaperSignal;
+ private APV25Pipeline pipeline;
+
+ private double shapingTime = 50; // [ns]
+
+ /**
+ * Default Constructor
+ */
+ public APV25Channel(){
+ }
+
+ /**
+ * Set the shaping time
+ *
+ * @param shapingTime : APV25 shaping time. The default Tp is set to 50 ns.
+ */
+ public void setShapingTime(int shapingTime) {
+ this.shapingTime = shapingTime;
+ }
+
+ /**
+ * Shape the injected charge
+ *
+ * @param charge
+ */
+ public void shapeSignal(double charge){
+ shaperSignal = new APV25ShaperSignal(charge);
+ }
+
+ public void sampleShaperSignal(){
+
+ // Obtain the beam time
+ double beamTime = ClockSingleton.getTime();
+
+ // Fill the analog pipeline starting with the cell to which the writer pointer is pointing
+ // to. Signals arriving within the same bucket of length <samplingTime> will be shifted in
+ // time depending on when they arrive.
+ for(int cell = 0; cell < ANALOG_PIPELINE_LENGTH; cell++){
+
+ // Time at which the shaper signal will be sampled
+ int sampleTime = cell*SAMPLING_TIME - ((int) beamTime)%SAMPLING_TIME;
+
+ // Sample the shaper signal
+ double sample = shaperSignal.getAmplitudeAtTime(sampleTime, shapingTime);
+
+ // Add the value to the pipeline
+ pipeline.addToCell(cell, sample);
+ }
+ }
+ }
+
+ //-------------------------------------//
+ // APV25 Analog Pipeline //
+ //-------------------------------------//
+ public class APV25Pipeline extends RingBuffer {
+
+ // TODO: Possibly store the pipeline in the event
+
+ // Note: ptr gives the position of the trigger pointer
+
+ private int triggerLatency = (int) Math.floor(200 /* ns */ / SAMPLING_TIME);
+ private int writerPointer = 0;
+
+ /**
+ * Constructor
+ */
+ public APV25Pipeline(){
+
+ // Initialize the pipeline to the APV25 pipeline length
+ super(ANALOG_PIPELINE_LENGTH);
+
+ // Initialize the position of the trigger pointer to a random position
+ this.ptr = (int) (Math.random()*(ANALOG_PIPELINE_LENGTH + 1));
+
+ // Set the position of the writer pointer
+ writerPointer = (ptr + triggerLatency)%ANALOG_PIPELINE_LENGTH;
+ }
+
+ /**
+ *
+ */
+ public void setLatency(int triggerLatency /*ns*/){
+ triggerLatency = (int) Math.floor(triggerLatency/SAMPLING_TIME);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void addToCell(int position, double element){
+ if((writerPointer + position)%ANALOG_PIPELINE_LENGTH == this.ptr) return;
+ super.addToCell(position, element);
+ }
+
+ /**
+ *
+ */
+ public double readout(){
+ double triggerPointerValue = this.currentValue();
+ array[ptr] = 0;
+ return triggerPointerValue;
+ }
+
+ /**
+ *
+ */
+ @Override
+ public String toString(){
+ String analogPipeline = "[ ";
+ for(int element = 0; element < ANALOG_PIPELINE_LENGTH; element++){
+ if(element == ptr) analogPipeline += " TP ===>";
+ else if(element == writerPointer) analogPipeline += " WP ===>";
+ analogPipeline += (array[element] + ", ");
+ }
+ analogPipeline += "] ";
+ return analogPipeline;
+ }
+ }
+
+ //-----------------------------------//
+ // APV25 Shaper Signal //
+ //-----------------------------------//
+ public class APV25ShaperSignal {
+
+ // Shaper signal maximum amplitude
+ private double maxAmp = 0;
+
+ /**
+ * Constructor
+ *
+ * @param charge: Charge injected into a channel
+ */
+ APV25ShaperSignal(double charge) {
+ // Find the maximum amplitude of the shaper signal
+ maxAmp = (charge/MIP)*FRONT_END_GAIN; // mV
+ }
+
+ /**
+ * Get the amplitude at a time t
+ *
+ * @param time: time at which the shaper signal is to be sampled
+ */
+ public double getAmplitudeAtTime(double time, double shapingTime) {
+ return maxAmp * (Math.max(0, time) / shapingTime) * Math.exp(1 - (time / shapingTime));
+ }
+
+ }
+
+
+}
\ No newline at end of file