All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yamcs.tctm.CcsdsPacket Maven / Gradle / Ivy

There is a newer version: 5.10.7
Show newest version
package org.yamcs.tctm;

import java.nio.ByteBuffer;

import org.yamcs.utils.ByteArrayUtils;

/**
 * CCSDS Packet as per CCSDS 133.0-B-2 https://public.ccsds.org/Pubs/133x0b2e1.pdf
 *
 * 
 * primary header (6 bytes):
 *  3 bit = version - 0
 *  1 bit = type (0 = TM, 1= TC)
 *  1 bit = 2nd header present
 *  11 bit = apid
 *
 *  2 bit = grouping, 01 = first, 00 = cont, 10 = last packet of group, 11 = unsegmented data
 *  14 bit = seq
 *
 *  16 bit = packet length (excluding primary header) minus 1
 * 
* */ public class CcsdsPacket { protected ByteBuffer bb; public CcsdsPacket(byte[] packet) { bb = ByteBuffer.wrap(packet); } public CcsdsPacket(ByteBuffer bb) { this.bb = bb; } public static CcsdsPacket wrap(byte[] pkt) { return new CcsdsPacket(pkt); } public int getSecondaryHeaderFlag() { return (bb.getShort(0) >> 11) & 1; } static public boolean getSecondaryHeaderFlag(byte[] packet) { return (packet[0] & 0x8) == 0x8; } public int getSequenceCount() { return bb.getShort(2) & 0x3FFF; } public static int getSequenceCount(byte[] packet) { return ByteArrayUtils.decodeUnsignedShort(packet, 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; } /** * Write the header. The grouping is set to 10b = last packet in the group and the length to the capacity of the * buffer (minus 7) * * @param apid * @param secHeaderPresent * 1 = present, 0 = absent * @param tmtc * 0 = tm, 1 = tc * @param seqFlags * grouping: 01 = first packet, 00 = continuation packet, 10 = last packet of group, 11 = unsegmented * data * @param seq */ public void setHeader(int apid, int tmtc, int secHeaderPresent, int seqFlags, int seq) { secHeaderPresent &= 1; tmtc &= 1; seq &= 0x3FFF; seqFlags &= 3; short w = (short) ((tmtc << 12) | (secHeaderPresent << 11) | apid); bb.putShort(0, w); w = (short) ((seqFlags << 14) | seq); bb.putShort(2, w); bb.putShort(4, (short) (bb.capacity() - 7)); } 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 getCcsdsPacketLength(ByteBuffer bb) { return bb.getShort(4) & 0xFFFF; } /* returns the length written in the ccsds header */ public int getCcsdsPacketLength() { return getCcsdsPacketLength(bb); } public void setCcsdsPacketLength(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 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 boolean getChecksumIndicator() { return (bb.get(11) & 0x20) == 0x20; } static public boolean getChecksumIndicator(byte[] packet) { return (packet[11] & 0x20) == 0x20; } public byte[] getBytes() { if (bb.hasArray() && bb.array().length == bb.capacity() && !bb.isReadOnly()) { return bb.array(); } byte[] b = new byte[bb.capacity()]; int pos = bb.position(); bb.get(b); bb.position(0); bb.position(pos); return b; } public ByteBuffer getByteBuffer() { return bb; } public static short getAPID(byte[] packet) { return (short) (ByteArrayUtils.decodeUnsignedShort(packet, 0) & 0x07FF); } public static int getCcsdsPacketLength(byte[] buf) { return getCcsdsPacketLength(ByteBuffer.wrap(buf)); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("apid: ").append(getAPID()).append("\n"); appendBinaryData(sb); return sb.toString(); } protected void appendBinaryData(StringBuilder sb) { StringBuilder text = new StringBuilder(); int len = bb.limit(); int lengthRoundedUpToNextMultipleOf16 = (int) Math.ceil(len / 16.0) * 16; byte c; for (int i = 0; i < lengthRoundedUpToNextMultipleOf16; ++i) { // If we are at the beginning of a 16 byte multiple if (i % 16 == 0) { sb.append(String.format("%04x:", i)); text.setLength(0); } // For every 2 bytes, insert an extra space if ((i & 1) == 0) { sb.append(" "); } // If we did not reach the end of the buffer if (i < len) { c = bb.get(i); // Add 2 byte hexadecimal translation of the byte sb.append(String.format("%02x", 0xFF & c)); // Add printable characters or a dot to the ASCII buffer of the line being parsed text.append(((c >= ' ') && (c <= 127)) ? String.format("%c", c) : "."); } else { // If we reached the end of the buffer // Pad with spaces sb.append(" "); text.append(" "); } // If we reached the end of a 16 byte multiple if ((i + 1) % 16 == 0) { // Append the ASCII buffer of the parsed line sb.append(" "); sb.append(text); sb.append("\n"); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy