package org.yamcs.utils; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import org.yamcs.utils.TimeEncoding; public class CcsdsPacket implements Comparable<CcsdsPacket>{ static public final int DATA_OFFSET=16; static public final int MAX_CCSDS_SIZE=1500; protected ByteBuffer bb; public CcsdsPacket( byte[] packet) { bb = ByteBuffer.wrap(packet); } public CcsdsPacket(ByteBuffer bb) { this.bb=bb; } public int getSecondaryHeaderFlag() { return (bb.getShort(0)>>11)&1; } public int getSequenceCount() { return bb.getShort(2)&0x3FFF; } public void setSequenceCount(short seqCount) { short oldSeqField = bb.getShort(2); short seqInd = (short)(oldSeqField&(~0x3FFF)); bb.putShort(2, (short)((seqCount&0x3FFF) + seqInd)); } public static short getSequenceCount(ByteBuffer bb) { return (short) (bb.getShort(2)&0x3FFF); } public int getAPID() { return bb.getShort(0)& 0x07FF; } public void setAPID(int apid) { int tmp=bb.getShort(0) & (~0x07FF); tmp=tmp|apid; bb.putShort(0,(short)tmp); } public static short getAPID(ByteBuffer bb) { return (short)(bb.getShort(0)& 0x07FF); } /*returns the length written in the ccsds header*/ public static int getCccsdsPacketLength(ByteBuffer bb) { return bb.getShort(4)&0xFFFF; } /*returns the length written in the ccsds header*/ public int getCccsdsPacketLength() { return getCccsdsPacketLength(bb); } public void setCccsdsPacketLength(short length) { //return bb.getShort(4)&0xFFFF; bb.putShort(4, length); } /**returns the length of the packet, normally equals ccsdslength+7*/ public int getLength() { return bb.capacity(); } /** * * @return instant */ public long getInstant() { return TimeEncoding.fromGpsCcsdsTime(bb.getInt(6), bb.get(10)) ; } public static long getInstant(ByteBuffer bb) { return TimeEncoding.fromGpsCcsdsTime(bb.getInt(6), bb.get(10)) ; } /** * @return time in seconds since 6 Jan 1980 */ public long getCoarseTime() { return bb.getInt(6)&0xFFFFFFFFL; } public int getTimeId() { return (bb.get(11) &0xFF)>>6; } public void setCoarseTime(int time) { bb.putInt(6, time); } public static long getCoarseTime(ByteBuffer bb) { return bb.getInt(6)&0xFFFFFFFFL; } public int getFineTime() { return bb.get(10)&0xFF; } public void setFineTime(short fineTime) { bb.put(10, (byte)(fineTime&0xFF)); } public static int getFineTime(ByteBuffer bb) { return bb.get(10)&0xFF; } public boolean getChecksumIndicator() { return (bb.get(11) & 0x20) == 0x20; } public int getPacketID() { if(getSecondaryHeaderFlag() != 0) return bb.getInt(12); else return 0; } public void setPacketID(int id) { bb.putInt(12, id); } public byte[] getBytes() { return bb.array(); } public ByteBuffer getByteBuffer() { return bb; } public int getPrivateHeaderClass() { return bb.get(18); } public int getPrivateHeaderType() { return bb.get(19); } public int getPrivateHeaderSource() { return ((int)bb.get(16))&0xFF; } public static CcsdsPacket getPacketFromStream(InputStream input) throws IOException { byte[] b=new byte[6]; ByteBuffer bb=ByteBuffer.wrap(b); if ( input.read(b) < 6 ) { throw new IOException("cannot read CCSDS primary header\n"); } int ccsdslen = bb.getShort(4)&0xFFFF; if ( ccsdslen > MAX_CCSDS_SIZE ) { throw new IOException("illegal CCSDS length "+ ccsdslen); } bb=ByteBuffer.allocate(ccsdslen+7); bb.put(b); if ( input.read(bb.array(), 6, ccsdslen+1) < ccsdslen+1 ) { throw new IOException("cannot read full packet"); } return new CcsdsPacket(bb); } public static long getInstant(byte[] pkt) { return getInstant(ByteBuffer.wrap(pkt)); } public static short getAPID(byte[] packet) { return getAPID(ByteBuffer.wrap(packet)); } public static int getCccsdsPacketLength(byte[] buf) { return getCccsdsPacketLength(ByteBuffer.wrap(buf)); } /*comparison based on time*/ @Override public int compareTo(CcsdsPacket p) { return Long.signum(this.getInstant()-p.getInstant()); } @Override public String toString() { StringBuffer sb=new StringBuffer(); StringBuffer text = new StringBuffer(); byte c; int len = bb.limit(); sb.append("apid: "+getAPID()+"\n"); sb.append("packetId: "+getPacketID()+"\n"); sb.append("time: "+ TimeEncoding.toCombinedFormat(getInstant())); sb.append("\n"); for(int i=0;i<len;++i) { if(i%16==0) { sb.append(String.format("%04x:",i)); text.setLength(0); } c = bb.get(i); if ( (i & 1) == 0 ) { sb.append(String.format(" %02x",0xFF&c)); } else { sb.append(String.format("%02x",0xFF&c)); } text.append(((c >= ' ') && (c <= 127)) ? String.format("%c",c) : "."); if((i+1)%16==0) { sb.append(" "); sb.append(text); sb.append("\n"); } } sb.append("\n\n"); return sb.toString(); } }