| /* |
| * Copyright (c) 2016 Audi AG |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| */ |
| |
| package org.eclipse.mdm.mdfsorter.mdf4; |
| |
| import java.io.IOException; |
| import java.math.BigInteger; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.eclipse.mdm.mdfsorter.MDFParser; |
| |
| /** |
| * The Channel Group Block |
| * |
| * @author Christian Rechner, Tobias Leemann |
| * |
| */ |
| public class CGBLOCK extends MDF4GenBlock { |
| |
| /** Data section */ |
| |
| // Record ID, value must be less than maximum unsigned integer value allowed |
| // by dg_rec_id_size in parent DGBLOCK. |
| // UINT64 |
| private long recordId; |
| |
| // Number of cycles, i.e. number of samples for this channel group. |
| // This specifies the number of records of this type in the data block. |
| // UINT64 |
| private long cycleCount; |
| |
| // Flags |
| // The value contains the following bit flags (Bit 0 = LSB): |
| // Bit 0: VLSD channel group flag. |
| // Bit 1: Bus event channel group flag |
| // Bit 2: Plain bus event channel group flag |
| // UINT16 |
| private int flags; |
| |
| // Value of character to be used as path separator, 0 if no path separator |
| // specified. |
| // UINT16 |
| private int pathSeparator; |
| |
| // Normal CGBLOCK: |
| // Number of data Bytes (after record ID) used for signal values in record, |
| // i.e. size of plain data for each |
| // recorded sample of this channel group. |
| // VLSD CGBLOCK: |
| // Low part of a UINT64 value that specifies the total size in Bytes of all |
| // variable length signal values for the |
| // recorded samples of this channel group. |
| // UINT32 |
| private long dataBytes; |
| |
| // Normal CGBLOCK: |
| // Number of additional Bytes for record used for invalidation bits. Can be |
| // zero if no invalidation bits are used at |
| // all. Invalidation bits may only occur in the specified number of Bytes |
| // after the data Bytes, not within the data |
| // Bytes that contain the signal values. |
| // VLSD CGBLOCK: |
| // High part of UINT64 value that specifies the total size in Bytes of all |
| // variable length signal values for the |
| // recorded samples of this channel group, i.e. the total size in Bytes can |
| // be calculated by cg_data_bytes + |
| // (cg_inval_bytes << 32) |
| // Note: this value does not include the Bytes used to specify the length of |
| // each VLSD value! |
| private long invalBytes; |
| |
| /** |
| * Parse a HLBLOCK from an existing MDFGenBlock |
| * |
| * @param parent |
| * The already existing MDF Generic Block. |
| */ |
| public CGBLOCK(MDF4GenBlock parent) { |
| super(parent.getPos()); |
| setLength(parent.getLength()); |
| setLinkCount(parent.getLinkCount()); |
| setId(parent.getId()); |
| setLinks(parent.getLinks()); |
| parent.setPrec(this); |
| } |
| |
| public MDF4GenBlock getLnkCgNext() { |
| return links[0]; |
| } |
| |
| public MDF4GenBlock getLnkCnFirst() { |
| return links[1]; |
| } |
| |
| public MDF4GenBlock getLnkTxAcqName() { |
| return links[2]; |
| } |
| |
| public MDF4GenBlock getLnkSiAcqSource() { |
| return links[3]; |
| } |
| |
| public MDF4GenBlock getLnkSrFirst() { |
| return links[4]; |
| } |
| |
| public MDF4GenBlock getLnkMdComment() { |
| return links[5]; |
| } |
| |
| public long getRecordId() { |
| return recordId; |
| } |
| |
| public long getCycleCount() { |
| return cycleCount; |
| } |
| |
| public int getFlags() { |
| return flags; |
| } |
| |
| public int getPathSeparator() { |
| return pathSeparator; |
| } |
| |
| public long getDataBytes() { |
| return dataBytes; |
| } |
| |
| public long getInvalBytes() { |
| return invalBytes; |
| } |
| |
| public void setRecordId(long recordId) { |
| this.recordId = recordId; |
| } |
| |
| public void setCycleCount(long cycleCount) { |
| this.cycleCount = cycleCount; |
| } |
| |
| private void setFlags(int flags) { |
| this.flags = flags; |
| } |
| |
| public void setPathSeparator(int pathSeparator) { |
| this.pathSeparator = pathSeparator; |
| } |
| |
| private void setDataBytes(long dataBytes) { |
| this.dataBytes = dataBytes; |
| } |
| |
| private void setInvalBytes(long invalBytes) { |
| this.invalBytes = invalBytes; |
| } |
| |
| public boolean isVLSDChannel() { |
| return BigInteger.valueOf(flags).testBit(0); |
| } |
| |
| /** |
| * Get the number of Bytes that are used in Variable Length Signal Data |
| * (VLSD) values This value is calculated from dataBytes and invalBytes. |
| * (see Specification) |
| * |
| * @return The value. |
| */ |
| public long getVLSDlength() { |
| return dataBytes + (invalBytes << 32); |
| } |
| |
| public void setIsVlSD(boolean isVLSD) { |
| if (isVLSD) { |
| flags = flags | 0x1; |
| } else { |
| flags = flags & -2; |
| } |
| } |
| |
| /** |
| * Returns a list with all VLSDChannels in this group |
| * |
| * @return The list of CNBLOCKs. |
| */ |
| public List<CNBLOCK> getVLSDChannels() { |
| LinkedList<CNBLOCK> ret = new LinkedList<CNBLOCK>(); |
| CNBLOCK next = (CNBLOCK) getLnkCnFirst(); |
| while (next != null) { |
| // check if vlsd channel |
| if (next.getChannelType() == 1) { |
| ret.add(next); |
| } |
| next = (CNBLOCK) next.getLnkCnNext(); |
| } |
| return ret; |
| } |
| |
| @Override |
| public String toString() { |
| return "CGBLOCK [recordId=" + recordId + ", cycleCount=" + cycleCount |
| + ", flags=" + flags + ", pathSeparator=" + pathSeparator |
| + ", dataBytes=" + dataBytes + ", invalBytes=" + invalBytes |
| + "]"; |
| } |
| |
| /** |
| * @see MDF4GenBlock#parse(byte[]) |
| */ |
| @Override |
| public void parse(byte[] content) throws IOException { |
| |
| // UINT64: Record ID |
| setRecordId( |
| MDF4Util.readUInt64(MDFParser.getDataBuffer(content, 0, 8))); |
| |
| // UINT64: Number of cycles |
| setCycleCount( |
| MDF4Util.readUInt64(MDFParser.getDataBuffer(content, 8, 16))); |
| |
| // UINT16: Flags |
| setFlags(MDF4Util.readUInt16(MDFParser.getDataBuffer(content, 16, 18))); |
| |
| // UINT16: Value of character to be used as path separator, 0 if no path |
| // separator specified. |
| setPathSeparator( |
| MDF4Util.readUInt16(MDFParser.getDataBuffer(content, 18, 20))); |
| |
| // UINT32: Number of data Bytes (after record ID) used for signal values |
| // in record. |
| setDataBytes( |
| MDF4Util.readUInt32(MDFParser.getDataBuffer(content, 24, 28))); |
| |
| // UINT32: Number of additional Bytes for record used for invalidation |
| // bits. |
| setInvalBytes( |
| MDF4Util.readUInt32(MDFParser.getDataBuffer(content, 28, 32))); |
| } |
| |
| @Override |
| public byte[] getBodyBytes() { |
| int arraylen = 32; |
| byte[] ret = new byte[arraylen]; |
| |
| byte[] recID = MDF4Util.getBytesUInt64(getRecordId()); |
| System.arraycopy(recID, 0, ret, 0, 8); |
| |
| byte[] cyccount = MDF4Util.getBytesUInt64(getCycleCount()); |
| System.arraycopy(cyccount, 0, ret, 8, 8); |
| |
| byte[] flags = MDF4Util.getBytesUInt16(getFlags()); |
| System.arraycopy(flags, 0, ret, 16, 2); |
| |
| byte[] pathsep = MDF4Util.getBytesUInt16(getPathSeparator()); |
| System.arraycopy(pathsep, 0, ret, 18, 2); |
| |
| // 4 Spacer bytes |
| |
| byte[] databytes = MDF4Util.getBytesUInt32(getDataBytes()); |
| System.arraycopy(databytes, 0, ret, 24, 4); |
| |
| byte[] invalbytes = MDF4Util.getBytesUInt32(getInvalBytes()); |
| System.arraycopy(invalbytes, 0, ret, 28, 4); |
| |
| return ret; |
| } |
| |
| } |