summaryrefslogtreecommitdiff
path: root/cesar/maximus/channel/src/ChannelMapping.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/maximus/channel/src/ChannelMapping.cpp')
-rw-r--r--cesar/maximus/channel/src/ChannelMapping.cpp494
1 files changed, 494 insertions, 0 deletions
diff --git a/cesar/maximus/channel/src/ChannelMapping.cpp b/cesar/maximus/channel/src/ChannelMapping.cpp
new file mode 100644
index 0000000000..2013b07fc2
--- /dev/null
+++ b/cesar/maximus/channel/src/ChannelMapping.cpp
@@ -0,0 +1,494 @@
+/************************************************************************
+ ChannelMapping.cpp - Copyright buret
+
+Here you can write a license for your code, some comments or any other
+information you want to have in your generated code. To to this simply
+configure the "headings" directory in uml to point to a directory
+where you have your heading files.
+
+or you can just replace the contents of this file with your own.
+If you want to do this, this file is located at
+
+/usr/share/apps/umbrello/headings/heading.h
+
+-->Code Generators searches for heading files based on the file extension
+ i.e. it will look for a file name ending in ".h" to include in C++ header
+ files, and for a file name ending in ".java" to include in all generated
+ java code.
+ If you name the file "heading.<extension>", Code Generator will always
+ choose this file even if there are other files with the same extension in the
+ directory. If you name the file something else, it must be the only one with that
+ extension in the directory to guarantee that Code Generator will choose it.
+
+you can use variables in your heading files which are replaced at generation
+time. possible variables are : author, date, time, filename and filepath.
+just write %variable_name%
+
+This file was generated on %date% at %time%
+The original location of this file is /home/buret/eclipse/maximus/channel/src/ChannelMapping.cpp
+**************************************************************************/
+
+#include "ChannelMapping.h"
+
+#include "Error.h"
+#include "Logger.h"
+
+#include <math.h> // for 'pow()'
+
+#define NONE 0xFFFF
+
+/* Following tables are extracted from the HomePlug AV Specification Version 1.0.10 (March 20, 2007)
+ * Chapter 3.5.5 */
+
+// Table 3-18: Modulation Characteristics
+unsigned short int ChannelMapping::mNbOfBitsArray[MAXIMUS_CHANNEL_MOD_NB] = { 0, /* NONE */
+ 1, /* BPSK */
+ 2, /* QPSK */
+ 3, /* QAM8 */
+ 4, /* QAM16 */
+ 6, /* QAM64 */
+ 8, /* QAM256 */
+ 10 }; /* QAM1024 */
+
+// Table 3-22: Symbol Mapping (Except 8-QAM)
+// and Table 3-23: Symbol Mapping for 8-QAM
+short int ChannelMapping::mMappingArray[MAXIMUS_CHANNEL_VALUE_MAX_NB][MAXIMUS_CHANNEL_MOD_NB] =
+/* I/Q *//* code */
+ /*BPSK*//*QPSK*//*8*/ /*16*//*64*//*256*//*1024*/
+{ { 31, NONE, NONE, NONE, NONE, NONE, NONE, 0x18 },
+ { 29, NONE, NONE, NONE, NONE, NONE, NONE, 0x19 },
+ { 27, NONE, NONE, NONE, NONE, NONE, NONE, 0x1B },
+ { 25, NONE, NONE, NONE, NONE, NONE, NONE, 0x1A },
+ { 23, NONE, NONE, NONE, NONE, NONE, NONE, 0x1E },
+ { 21, NONE, NONE, NONE, NONE, NONE, NONE, 0x1F },
+ { 19, NONE, NONE, NONE, NONE, NONE, NONE, 0x1D },
+ { 17, NONE, NONE, NONE, NONE, NONE, NONE, 0x1C },
+ { 15, NONE, NONE, NONE, NONE, NONE, 0xC, 0x14 },
+ { 13, NONE, NONE, NONE, NONE, NONE, 0xD, 0x15 },
+ { 11, NONE, NONE, NONE, NONE, NONE, 0xF, 0x17 },
+ { 9, NONE, NONE, NONE, NONE, NONE, 0xE, 0x16 },
+ { 7, NONE, NONE, NONE, NONE, 0x6, 0xA, 0x12 },
+ { 5, NONE, NONE, NONE, NONE, 0x7, 0xB, 0x13 },
+ { 3, NONE, NONE, 0x3, 0x3, 0x5, 0x9, 0x11 },
+ { 1, 0x1, 0x1, 0x2, 0x2, 0x4, 0x8, 0x10 },
+ { -1, 0X0, 0X0, 0x0, 0x0, 0x0, 0x0, 0X00 },
+ { -3, NONE, NONE, 0x1, 0x1, 0x1, 0x1, 0x01 },
+ { -5, NONE, NONE, NONE, NONE, 0x3, 0x3, 0x03 },
+ { -7, NONE, NONE, NONE, NONE, 0x2, 0x2, 0x02 },
+ { -9, NONE, NONE, NONE, NONE, NONE, 0x6, 0x06 },
+ { -11, NONE, NONE, NONE, NONE, NONE, 0x7, 0x07 },
+ { -13, NONE, NONE, NONE, NONE, NONE, 0x5, 0x05 },
+ { -15, NONE, NONE, NONE, NONE, NONE, 0x4, 0x04 },
+ { -17, NONE, NONE, NONE, NONE, NONE, NONE, 0x0C },
+ { -19, NONE, NONE, NONE, NONE, NONE, NONE, 0x0D },
+ { -21, NONE, NONE, NONE, NONE, NONE, NONE, 0x0F },
+ { -23, NONE, NONE, NONE, NONE, NONE, NONE, 0x0E },
+ { -25, NONE, NONE, NONE, NONE, NONE, NONE, 0x0A },
+ { -27, NONE, NONE, NONE, NONE, NONE, NONE, 0x0B },
+ { -29, NONE, NONE, NONE, NONE, NONE, NONE, 0x09 },
+ { -31, NONE, NONE, NONE, NONE, NONE, NONE, 0x08 } };
+
+
+// Constructors/Destructors
+//
+
+
+ChannelMapping::ChannelMapping ( ):
+mCode(0)
+{
+ //logFunction();
+}
+
+
+ChannelMapping::ChannelMapping ( const unsigned short int code ):
+mCode(0)
+{
+ //logFunction();
+
+ setCode(code);
+}
+
+
+ChannelMapping::ChannelMapping ( const ChannelPoint & point ):
+mCode(0)
+{
+ //logFunction();
+
+ setPoint(point);
+}
+
+
+ChannelMapping::~ChannelMapping ( )
+{
+ //logFunction();
+}
+
+
+//
+// Methods
+//
+
+
+// Other methods
+//
+
+
+// public methods
+//
+
+
+const unsigned short int ChannelMapping::computeCode ( const Channel_Mod modulation )
+{
+ //logFunction();
+ unsigned short int codeI = 0, codeQ = 0;
+
+ if (MAXIMUS_CHANNEL_MOD_NB <= modulation)
+ {
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "Modulation is out-of-range", errno);
+ }
+ else if (getPoint().checkValidity())
+ {
+ /* Retrieve the code from the I and Q coordinates and the used modulation. */
+ for (int i=0; i<MAXIMUS_CHANNEL_VALUE_MAX_NB; i++)
+ {
+ // Retrieve the code corresponding to I value
+ if (getI() == mMappingArray[i][MAXIMUS_CHANNEL_I_Q_VALUE])
+ {
+ codeI = mMappingArray[i][modulation];
+ }
+ // Retrieve the code corresponding to Q value
+ if (getQ() == mMappingArray[i][MAXIMUS_CHANNEL_I_Q_VALUE])
+ {
+ codeQ = mMappingArray[i][modulation];
+ }
+ }
+
+ /* Compute the code depending on the used modulation. */
+ /* (Table 3-21: Bit Mapping, Chapter 3.5) */
+
+ if (MAXIMUS_CHANNEL_MOD_BPSK == modulation)
+ {
+ // For BPSK, the code equals to the code corresponding to I value
+ setCode(codeI);
+ }
+ else if (MAXIMUS_CHANNEL_MOD_QAM8 == modulation)
+ {
+ // For QAM8, the code equals to the code corresponding to I value
+ // + 0b100 if Q = 1.29
+ if (MAXIMUS_CHANNEL_Q_QAM8_ABSOLUTE_VALUE == getQ())
+ {
+ setCode(0x4 | codeI);
+ }
+ else if (-MAXIMUS_CHANNEL_Q_QAM8_ABSOLUTE_VALUE == getQ())
+ {
+ setCode(codeI);
+ }
+ else
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "Q value is out-of-range", errno);
+ }
+ }
+ else
+ {
+ // For other modulations, the code is composed of:
+ // - the code corresponding to I value (LSB)
+ // - and the code corresponding to Q value (MSB)
+ unsigned short int halfNbOfBits = mNbOfBitsArray[modulation] >> 1; // mNbOfBitsArray[modulation] / 2
+ setCode((codeQ << halfNbOfBits) | codeI);
+ }
+ }
+
+ return getCode();
+}
+
+
+const ChannelPoint & ChannelMapping::computePoint ( const Channel_Mod modulation )
+{
+ //logFunction();
+
+ /* Retrieve the I and Q coordinates from the code and the used modulation. */
+ if (MAXIMUS_CHANNEL_MOD_BPSK == modulation)
+ {
+ // For BPSK, the Q value is not used
+ for (int i=0; i<MAXIMUS_CHANNEL_VALUE_MAX_NB; i++)
+ {
+ if (getCode() == mMappingArray[i][modulation])
+ {
+ setI(mMappingArray[i][MAXIMUS_CHANNEL_I_Q_VALUE]);
+ setQ(0);
+ break;
+ }
+ }
+ }
+ else if (MAXIMUS_CHANNEL_MOD_QAM8 == modulation)
+ {
+ // For QAM8, the I value equals to the 2 LSB of the code,
+ // and the Q value sign depends on the 3rd bit value
+ // (Q is positive 0 if the 3rd bit is set to 0b1, else Q is negative)
+ for (int i=0; i<MAXIMUS_CHANNEL_VALUE_MAX_NB; i++)
+ {
+ if ((getCode() & 0x3) == mMappingArray[i][modulation])
+ {
+ setI(mMappingArray[i][MAXIMUS_CHANNEL_I_Q_VALUE]);
+ setQ((getCode() > 0x3) ? MAXIMUS_CHANNEL_Q_QAM8_ABSOLUTE_VALUE : -MAXIMUS_CHANNEL_Q_QAM8_ABSOLUTE_VALUE);
+ break;
+ }
+ }
+ }
+ else
+ {
+ // For other modulations:
+ // - the I value equals to the LSB of the code
+ // - the Q value equals to the MSB of the code
+ unsigned short int halfNbOfBits = mNbOfBitsArray[modulation] >> 1; // mNbOfBitsArray[modulation] / 2
+ unsigned short int mask = (1 << halfNbOfBits) - 1; // halfNbOfBits * '1'
+ for (int i=0; i<MAXIMUS_CHANNEL_VALUE_MAX_NB; i++)
+ {
+ if ((getCode() & mask) == mMappingArray[i][modulation])
+ {
+ setI(mMappingArray[i][MAXIMUS_CHANNEL_I_Q_VALUE]);
+ }
+ if (((getCode() >> halfNbOfBits) & mask) == mMappingArray[i][modulation])
+ {
+ setQ(mMappingArray[i][MAXIMUS_CHANNEL_I_Q_VALUE]);
+ }
+ }
+ }
+
+ getPoint().checkValidity();
+ return getPoint();
+}
+
+
+const ChannelPoint ChannelMapping::retrievePoint ( const Channel_Mod modulation )
+{
+ //logFunction();
+
+ float x = getI();
+ float y = getQ();
+ short int max = 0;
+
+ /* Depending on the modulation, find the maximum value of the I and Q coordinates. */
+
+ int i;
+ for (i=0; i<MAXIMUS_CHANNEL_VALUE_MAX_NB; i++)
+ {
+ if (NONE != (unsigned short int)mMappingArray[i][modulation])
+ {
+ max = mMappingArray[i][MAXIMUS_CHANNEL_I_Q_VALUE];
+ break;
+ }
+ }
+
+ /* If abscissa or ordinate exceeds this maximum value,
+ * set it to the maximum value. */
+
+ if (x > max)
+ {
+ x = max;
+ }
+ else if (x < -max)
+ {
+ x = -max;
+ }
+ if (y > max)
+ {
+ y = max;
+ }
+ else if (y < -max)
+ {
+ y = -max;
+ }
+
+ /* Retrieve the I and Q coordinates from abscissa and ordinate. */
+
+ for (int j=i; j<MAXIMUS_CHANNEL_VALUE_MAX_NB-i; j++)
+ {
+ if ( (x <= mMappingArray[j][MAXIMUS_CHANNEL_I_Q_VALUE] + 1)
+ && (x >= mMappingArray[j][MAXIMUS_CHANNEL_I_Q_VALUE] - 1) )
+ {
+ x = mMappingArray[j][MAXIMUS_CHANNEL_I_Q_VALUE];
+ break;
+ }
+ }
+
+ for (int j=i; j<MAXIMUS_CHANNEL_VALUE_MAX_NB-i; j++)
+ {
+ if ( (y <= mMappingArray[j][MAXIMUS_CHANNEL_I_Q_VALUE] + 1)
+ && (y >= mMappingArray[j][MAXIMUS_CHANNEL_I_Q_VALUE] - 1) )
+ {
+ y = mMappingArray[j][MAXIMUS_CHANNEL_I_Q_VALUE];
+ break;
+ }
+ }
+
+ // For BPSK, the Q value is not used
+ if (MAXIMUS_CHANNEL_MOD_BPSK == modulation)
+ {
+ y = 0;
+ }
+
+ // For QAM8, the Q value equals to 1.29 or -1.29
+ else if (MAXIMUS_CHANNEL_MOD_QAM8 == modulation)
+ {
+ (y >= 0) ? y = MAXIMUS_CHANNEL_Q_QAM8_ABSOLUTE_VALUE : y = -MAXIMUS_CHANNEL_Q_QAM8_ABSOLUTE_VALUE;
+ }
+
+ ChannelPoint(x, y).checkValidity();
+ return ChannelPoint(x, y);
+}
+
+
+// private methods
+//
+
+
+// protected methods
+//
+
+
+// Accessor methods
+//
+
+
+// public attribute accessor methods
+//
+
+
+// private attribute accessor methods
+//
+
+
+bool ChannelMapping::setCode ( const Channel_Mod modulation,
+ const unsigned long mpdu_payload_length,
+ const unsigned char * p_mpdu_payload,
+ unsigned int & mpdu_index )
+{
+ //logFunction();
+ bool bSetCode = false;
+
+ if (NULL == p_mpdu_payload)
+ {
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "MPDU payload pointer is NULL", errno);
+ }
+ else
+ {
+ unsigned short int nbOfBits = mNbOfBitsArray[modulation];
+ unsigned short int offset = 24 - (8 * (nbOfBits / 8)) + (mpdu_index /* index in bits */ % 8);
+ unsigned int mask = ((1 << nbOfBits) - 1) /* nbOfBits * '1' */ << offset;
+ unsigned int mpduPayload = 0;
+
+ // Zero padding if needed
+ if (mpdu_index + nbOfBits > 8 * mpdu_payload_length)
+ {
+ if (8 * mpdu_payload_length - 2 == mpdu_index)
+ {
+ mpduPayload = ((*(p_mpdu_payload + mpdu_index/8)) << 24)
+ | ((*(p_mpdu_payload + mpdu_index/8 + 1)) << 16);
+ }
+ else // mpdu_index = 8 * mpdu_payload_length - 1
+ {
+ mpduPayload = ((*(p_mpdu_payload + mpdu_index/8)) << 24);
+ }
+ }
+
+ else
+ {
+ mpduPayload = ((*(p_mpdu_payload + mpdu_index/8)) << 24)
+ | ((*(p_mpdu_payload + mpdu_index/8 + 1)) << 16)
+ | ((*(p_mpdu_payload + mpdu_index/8 + 2)) << 8)
+ | (*(p_mpdu_payload + mpdu_index/8 + 3));
+ }
+
+ mCode = (mpduPayload & mask) >> offset;
+
+ mpdu_index += nbOfBits;
+ bSetCode = true;
+ }
+
+ return bSetCode;
+}
+
+
+bool ChannelMapping::setCode ( const unsigned short int code )
+{
+ //logFunction();
+ bool bSetCode = false;
+
+ if (MAXIMUS_CHANNEL_CODE_MAX_VALUE < code)
+ {
+ errno = EINVAL;
+ throw Error(__PRETTY_FUNCTION__, "code value is out-of-range", errno);
+ }
+ else
+ {
+ mCode = code;
+ bSetCode = true;
+ }
+
+ return bSetCode;
+}
+
+
+unsigned short int ChannelMapping::getCode ( ) const
+{
+ if (MAXIMUS_CHANNEL_CODE_MAX_VALUE < mCode)
+ {
+ errno = EPROTO;
+ throw Error(__PRETTY_FUNCTION__, "code value is out-of-range", errno);
+ }
+
+ return mCode;
+}
+
+
+bool ChannelMapping::setPoint ( const ChannelPoint & point )
+{
+ //logFunction();
+
+ mPoint = point;
+
+ return true;
+}
+
+
+ChannelPoint & ChannelMapping::getPoint ( )
+{
+ return mPoint;
+}
+
+
+bool ChannelMapping::setI ( const float i )
+{
+ getPoint().I = i;
+
+ return true;
+}
+
+
+const float ChannelMapping::getI ( )
+{
+ return getPoint().I;
+}
+
+
+bool ChannelMapping::setQ ( const float q )
+{
+ getPoint().Q = q;
+
+ return true;
+}
+
+
+const float ChannelMapping::getQ ( )
+{
+ return getPoint().Q;
+}
+
+
+// protected attribute accessor methods
+//
+