package scd_micro;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* Cyclic buffer of frames. Used for frames generated by simulator, but not yet processed by detector.
* The memory is allocated at construction time and always re-used (frame data is copied in the same locations).
* The frames, as well as the buffer, live in immortal memory. The constructor runs in immortal memory.
* Note that the buffer is (intentionally) not synchronized. In a weird combination of priorities that is not
* intended to be used, buffer frames could be overwritten.
*/
public class FrameBuffer {
// empty buffer ... first == last
// full buffer .... last + 1 == first
// - so there is still one empty slot, but we don't want to use it,
// because we would not then recognize empty from full buffer
//
// last .. where the next frame will be stored
// first .. where the next frame will be read
public int first, last;
public RawFrame[] frames;
public FrameBuffer() {
frames = new RawFrame[Constants.BUFFER_FRAMES];
for (int i = 0; i < Constants.BUFFER_FRAMES; i++) {
frames[i] = new RawFrame();
}
}
public void putFrameInternal(final float[] positions_, final int[] lengths_, final byte[] callsigns_) {
if ( (last + 1) % Constants.BUFFER_FRAMES == first) {
ImmortalEntry.droppedFrames ++;
return;
}
frames[last].copy(lengths_, callsigns_, positions_);
last = (last + 1) % Constants.BUFFER_FRAMES;
}
static int frameno = 0;
public void putFrame(final float[] positions_, final int[] lengths_, final byte[] callsigns_) {
if (Constants.SYNCHRONOUS_DETECTOR || Constants.DUMP_SENT_FRAMES) {
String prefix = "S-FRAME " + frameno + " ";
int offset = 0;
for (int i=0;i<lengths_.length;i++) {
int cslen = lengths_[i];
System.out.println(prefix+new String( callsigns_, offset, cslen )+" "+
positions_[3*i]+" "+
positions_[3*i+1]+" "+
positions_[3*i+2]+" ");
offset += cslen;
}
frameno++;
}
// if (Constants.FRAMES_BINARY_DUMP) {
// // the binary format:
// // nframes <INT>
// //
// // nplanes <INT> 1
// // positions <FLOAT> nplanes*3
// // lengths <INT> nplanes
// // callsigns_length <INT> 1
// // callsigns <BYTE> callsigns_length
//
// DataOutputStream ds = ImmortalEntry.binaryDumpStream;
//
// try {
// ds.writeInt(lengths_.length);
//
// for(int i=0; i<lengths_.length; i++) {
// ds.writeFloat(positions_[3*i]);
// ds.writeFloat(positions_[3*i+1]);
// ds.writeFloat(positions_[3*i+2]);
// }
//
// for(int i=0;i<lengths_.length; i++) {
// ds.writeInt(lengths_[i]);
// }
//
// ds.writeInt(callsigns_.length);
// ds.write(callsigns_);
//
// } catch (IOException e) {
// throw new RuntimeException("Error dumping frames to binary file "+e);
// }
//
// }
// if (Constants.SYNCHRONOUS_DETECTOR) {
// FrameSynchronizer.produceFrame();
// }
putFrameInternal(positions_, lengths_, callsigns_);
// if (Constants.SYNCHRONOUS_DETECTOR) {
// FrameSynchronizer.waitForConsumer();
// }
}
public RawFrame getFrame() {
if (last == first) {
return null;
} else {
final int f = first;
first = (first + 1) % Constants.BUFFER_FRAMES;
return frames[f]; // NOTE: if the simulator could run between this and the previous line,
// it could corrupt the present frame
}
}
}