void CTextMessage::SetText(const string& strMessage, const _BINARY biToggleBit) { int i, j; int iNumBodyBytes; _BINARY biFirstFlag; _BINARY biLastFlag; CCRC CRCObject; /* Get length of text message. TODO: take care of multiple byte characters (UTF-8 coding)! */ int iLenBytesOfText = strMessage.length(); /* Calculate required number of segments. The body shall contain 16 bytes of character data */ iNumSeg = (int) ceil((_REAL) iLenBytesOfText / BYTES_PER_SEG_TEXT_MESS); /* The text message may comprise up to 8 segments. Check the number of segments, if number is larger, cut message */ if (iNumSeg > 8) { iNumSeg = 8; iLenBytesOfText = iNumSeg * BYTES_PER_SEG_TEXT_MESS; } /* Allocate memory for segment pointer */ vvbiSegment.Init(iNumSeg); /* Generate segments ---------------------------------------------------- */ /* Reset position in string */ int iPosInStr = 0; for (i = 0; i < iNumSeg; i++) { /* Calculate number of bytes for body */ const int iRemainingBytes = iLenBytesOfText - iPosInStr; /* All segments should have the maximum number of bytes per segment except the last one which takes the remaining bytes */ if (iRemainingBytes > BYTES_PER_SEG_TEXT_MESS) iNumBodyBytes = BYTES_PER_SEG_TEXT_MESS; else iNumBodyBytes = iRemainingBytes; /* Init segment vector: "Beginning of segment" 4 * 8 bits, Header 16 bits, body n * 8 bits, CRC 16 bits */ vvbiSegment[i].Init(4 * 8 + 16 + iNumBodyBytes * 8 + 16); /* Reset enqueue function */ vvbiSegment[i].ResetBitAccess(); /* Generate "beginning of segment" identification by "all 0xFF" ----- */ for (j = 0; j < NUM_BYTES_TEXT_MESS_IN_AUD_STR; j++) vvbiSegment[i].Enqueue((uint32_t) 0xFF, SIZEOF__BYTE); /* Header ----------------------------------------------------------- */ /* Toggle bit */ vvbiSegment[i].Enqueue((uint32_t) biToggleBit, 1); /* Determine position of segment */ if (i == 0) biFirstFlag = 1; else biFirstFlag = 0; if (iLenBytesOfText - iPosInStr <= BYTES_PER_SEG_TEXT_MESS) biLastFlag = 1; else biLastFlag = 0; /* Enqueue first flag */ vvbiSegment[i].Enqueue((uint32_t) biFirstFlag, 1); /* Enqueue last flag */ vvbiSegment[i].Enqueue((uint32_t) biLastFlag, 1); /* Command flag. This is a data block -> command flag = 0 */ vvbiSegment[i].Enqueue((uint32_t) 0, 1); /* Field 1: specify the number of bytes in the body minus 1 (It shall normally take the value 15 except in the last segment) */ vvbiSegment[i].Enqueue((uint32_t) iNumBodyBytes - 1, 4); /* Field 2. If First flag = "1", this field shall contain the value "1111" */ if (biFirstFlag == 1) vvbiSegment[i].Enqueue((uint32_t) 15 /* 1111 */, 4); else { /* Rfa. The bit shall be set to zero until it is defined */ vvbiSegment[i].Enqueue((uint32_t) 0, 1); /* SegNum: specify the sequence number of the current segment minus 1. The value 0 is reserved for future use */ vvbiSegment[i].Enqueue((uint32_t) i, 3); } /* Rfa. These bits shall be set to zero until they are defined */ vvbiSegment[i].Enqueue((uint32_t) 0, 4); /* Body ------------------------------------------------------------- */ /* Set body bytes */ for (j = 0; j < iNumBodyBytes; j++) { vvbiSegment[i].Enqueue((uint32_t) strMessage.at(iPosInStr), SIZEOF__BYTE); iPosInStr++; } /* CRC -------------------------------------------------------------- */ /* Reset bit access and skip segment beginning piece (all 0xFFs) */ vvbiSegment[i].ResetBitAccess(); vvbiSegment[i].Separate(SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR); /* Calculate the CRC and put it at the end of the segment */ CRCObject.Reset(16); /* "byLengthBody" was defined in the header */ for (j = 0; j < iNumBodyBytes + 2 /* Header */; j++) CRCObject.AddByte((_BYTE) vvbiSegment[i].Separate(SIZEOF__BYTE)); /* Now, pointer in "enqueue"-function is back at the same place, add CRC */ vvbiSegment[i].Enqueue(CRCObject.GetCRC(), 16); /* Reset bit access for using segment in encoder function */ vvbiSegment[i].ResetBitAccess(); } }
/* Actual MDI protocol implementation *****************************************/ CVector<_BINARY> CMDI::GenAFPacket(const _BOOLEAN bWithSDC) { /* The AF layer encapsulates a single TAG Packet. Mandatory TAG items: *ptr, dlfc, fac_, sdc_, sdci, robm, str0-3 */ int i; CVector<_BINARY> vecbiAFPkt; /* Increment MDI packet counter and generate counter tag */ GenTagLoFrCnt(); /* Payload length in bytes */ // TODO: check if padding bits are needed to get byte alignment!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! const int iPayloadLenBytes = (vecbiTagProTy.Size() + vecbiTagLoFrCnt.Size() + vecbiTagFAC.Size() + vecbiTagSDC.Size() + vecbiTagSDCChanInf.Size() + vecbiTagRobMod.Size() + vecbiTagStr[0].Size() + vecbiTagStr[1].Size() + vecbiTagStr[2].Size() + vecbiTagStr[3].Size()) / SIZEOF__BYTE; /* 10 bytes AF header, 2 bytes CRC, payload */ const int iAFPktLenBits = iPayloadLenBytes * SIZEOF__BYTE + 12 * SIZEOF__BYTE; /* Init vector length */ vecbiAFPkt.Init(iAFPktLenBits); vecbiAFPkt.ResetBitAccess(); /* SYNC: two-byte ASCII representation of "AF" */ vecbiAFPkt.Enqueue((uint32_t) 'A', SIZEOF__BYTE); vecbiAFPkt.Enqueue((uint32_t) 'F', SIZEOF__BYTE); /* LEN: length of the payload, in bytes (4 bytes long -> 32 bits) */ vecbiAFPkt.Enqueue((uint32_t) iPayloadLenBytes, 32); /* SEQ: sequence number. Each AF Packet shall increment the sequence number by one for each packet sent, regardless of content. There shall be no requirement that the first packet received shall have a specific value. The counter shall wrap from FFFF_[16] to 0000_[16], thus the value shall count, FFFE_[16], FFFF_[16], 0000_[16], 0001_[16], etc. (2 bytes long -> 16 bits) */ vecbiAFPkt.Enqueue((uint32_t) iSeqNumber, 16); iSeqNumber++; if (iSeqNumber > 0xFFFF) iSeqNumber = 0; /* AR: AF protocol Revision - a field combining the CF, MAJ and MIN fields */ /* CF: CRC Flag, 0 if the CRC field is not used (CRC value shall be 0000_[16]) or 1 if the CRC field contains a valid CRC (1 bit long) */ if (bUseAFCRC == TRUE) vecbiAFPkt.Enqueue((uint32_t) 1, 1); else vecbiAFPkt.Enqueue((uint32_t) 0, 1); /* MAJ: major revision of the AF protocol in use (3 bits long) */ vecbiAFPkt.Enqueue((uint32_t) AF_MAJOR_REVISION, 3); /* MIN: minor revision of the AF protocol in use (4 bits long) */ vecbiAFPkt.Enqueue((uint32_t) AF_MINOR_REVISION, 4); /* Protocol Type (PT): single byte encoding the protocol of the data carried in the payload. For TAG Packets, the value shall be the ASCII representation of "T" */ vecbiAFPkt.Enqueue((uint32_t) 'T', SIZEOF__BYTE); /* Payload -------------------------------------------------------------- */ // TODO: copy data byte wise -> check if possible to do that... /* *ptr tag */ vecbiTagProTy.ResetBitAccess(); for (i = 0; i < vecbiTagProTy.Size(); i++) vecbiAFPkt.Enqueue(vecbiTagProTy.Separate(1), 1); /* dlfc tag */ vecbiTagLoFrCnt.ResetBitAccess(); for (i = 0; i < vecbiTagLoFrCnt.Size(); i++) vecbiAFPkt.Enqueue(vecbiTagLoFrCnt.Separate(1), 1); /* fac_ tag */ vecbiTagFAC.ResetBitAccess(); for (i = 0; i < vecbiTagFAC.Size(); i++) vecbiAFPkt.Enqueue(vecbiTagFAC.Separate(1), 1); /* SDC tag must be delayed in some cases */ if (bWithSDC == TRUE) { /* sdc_ tag */ vecbiTagSDC.ResetBitAccess(); for (i = 0; i < vecbiTagSDC.Size(); i++) vecbiAFPkt.Enqueue(vecbiTagSDC.Separate(1), 1); } /* sdci tag */ vecbiTagSDCChanInf.ResetBitAccess(); for (i = 0; i < vecbiTagSDCChanInf.Size(); i++) vecbiAFPkt.Enqueue(vecbiTagSDCChanInf.Separate(1), 1); /* robm tag */ vecbiTagRobMod.ResetBitAccess(); for (i = 0; i < vecbiTagRobMod.Size(); i++) vecbiAFPkt.Enqueue(vecbiTagRobMod.Separate(1), 1); /* strx tag */ for (int j = 0; j < MAX_NUM_STREAMS; j++) { vecbiTagStr[j].ResetBitAccess(); for (i = 0; i < vecbiTagStr[j].Size(); i++) vecbiAFPkt.Enqueue(vecbiTagStr[j].Separate(1), 1); } /* CRC: CRC calculated as described in annex A if the CF field is 1, otherwise 0000_[16] */ if (bUseAFCRC == TRUE) { CCRC CRCObject; /* CRC -------------------------------------------------------------- */ /* Calculate the CRC and put at the end of the stream */ CRCObject.Reset(16); vecbiAFPkt.ResetBitAccess(); /* 2 bytes CRC -> "- 2" */ for (int i = 0; i < iAFPktLenBits / SIZEOF__BYTE - 2; i++) CRCObject.AddByte((_BYTE) vecbiAFPkt.Separate(SIZEOF__BYTE)); /* Now, pointer in "enqueue"-function is back at the same place, add CRC */ vecbiAFPkt.Enqueue(CRCObject.GetCRC(), 16); } else vecbiAFPkt.Enqueue((uint32_t) 0, 16); return vecbiAFPkt; }
/******************************************************************************\ * Encoder * \******************************************************************************/ void CDataEncoder::GeneratePacket(CVector<_BINARY>& vecbiPacket) { int i; _BOOLEAN bLastFlag; /* Init size for whole packet, not only body */ vecbiPacket.Init(iTotalPacketSize); vecbiPacket.ResetBitAccess(); /* Calculate remaining data size to be transmitted */ const int iRemainSize = vecbiCurDataUnit.Size() - iCurDataPointer; /* Header --------------------------------------------------------------- */ /* First flag */ if (iCurDataPointer == 0) vecbiPacket.Enqueue((uint32_t) 1, 1); else vecbiPacket.Enqueue((uint32_t) 0, 1); /* Last flag */ if (iRemainSize > iPacketLen) { vecbiPacket.Enqueue((uint32_t) 0, 1); bLastFlag = FALSE; } else { vecbiPacket.Enqueue((uint32_t) 1, 1); bLastFlag = TRUE; } /* Packet Id */ vecbiPacket.Enqueue((uint32_t) iPacketID, 2); /* Padded packet indicator (PPI) */ if (iRemainSize < iPacketLen) vecbiPacket.Enqueue((uint32_t) 1, 1); else vecbiPacket.Enqueue((uint32_t) 0, 1); /* Continuity index (CI) */ vecbiPacket.Enqueue((uint32_t) iContinInd, 3); /* Increment index modulo 8 (1 << 3) */ iContinInd++; if (iContinInd == 8) iContinInd = 0; /* Body ----------------------------------------------------------------- */ if (iRemainSize >= iPacketLen) { if (iRemainSize == iPacketLen) { /* Last packet */ for (i = 0; i < iPacketLen; i++) vecbiPacket.Enqueue(vecbiCurDataUnit.Separate(1), 1); } else { for (i = 0; i < iPacketLen; i++) { vecbiPacket.Enqueue(vecbiCurDataUnit.Separate(1), 1); iCurDataPointer++; } } } else { /* Padded packet. If the PPI is 1 then the first byte shall indicate the number of useful bytes that follow, and the data field is completed with padding bytes of value 0x00 */ vecbiPacket.Enqueue((uint32_t) (iRemainSize / SIZEOF__BYTE), SIZEOF__BYTE); /* Data */ for (i = 0; i < iRemainSize; i++) vecbiPacket.Enqueue(vecbiCurDataUnit.Separate(1), 1); /* Padding */ for (i = 0; i < iPacketLen - iRemainSize; i++) vecbiPacket.Enqueue(vecbiCurDataUnit.Separate(1), 1); } /* If this was the last packet, get data for next data unit */ if (bLastFlag == TRUE) { /* Generate new data unit */ MOTSlideShowEncoder.GetDataUnit(vecbiCurDataUnit); vecbiCurDataUnit.ResetBitAccess(); /* Reset data pointer and continuity index */ iCurDataPointer = 0; } /* CRC ------------------------------------------------------------------ */ CCRC CRCObject; /* Reset bit access */ vecbiPacket.ResetBitAccess(); /* Calculate the CRC and put it at the end of the segment */ CRCObject.Reset(16); /* "byLengthBody" was defined in the header */ for (i = 0; i < (iTotalPacketSize / SIZEOF__BYTE - 2); i++) CRCObject.AddByte(vecbiPacket.Separate(SIZEOF__BYTE)); /* Now, pointer in "enqueue"-function is back at the same place, add CRC */ vecbiPacket.Enqueue(CRCObject.GetCRC(), 16); }