diff --git a/CHANGELOG b/CHANGELOG
index 341def69841d913e30c180411e6e5fab8bfa4960..258f559995b511ba6870f8853ab92e5cd342b303 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,6 +8,8 @@ TODO::
 LAST DONE:
 
 CHANGES:
+- ver. 0.20.021 - <b>2022.04.04</b> Added: 
+  - DSP::u::SymbolMapper - experimental support for QAM for even bits_per_symbol (Gray ordering) 
 - ver. 0.20.020 - <b>2022.04.04</b> Fixed: 
   - DSP::u::SymbolMapper - fixed support for phase rotation of DSP::e::ModulationType::ASK constelation 
 - ver. 0.20.019 - <b>2022.03.30</b> Fixed: 
diff --git a/src/cpp/DSP_modules2.cpp b/src/cpp/DSP_modules2.cpp
index 2b5d42404cb3849a411a6545f56f0a01899382ae..41702b7895b053042b030f8588e132d565817404 100644
--- a/src/cpp/DSP_modules2.cpp
+++ b/src/cpp/DSP_modules2.cpp
@@ -1817,7 +1817,7 @@ unsigned int getConstellation(
       break;
 
     case DSP::e::ModulationType::ASK: {
-      constellation.resize(M);
+        constellation.resize(M);
         for (unsigned int n=0; n < M; n++) {
           constellation[n].re = static_cast<DSP::Float>(n)/static_cast<DSP::Float>(M-1);
           constellation[n].im = 0;
@@ -1834,6 +1834,38 @@ unsigned int getConstellation(
       }
       break;
 
+    case DSP::e::ModulationType::QAM: {
+        //  to convert number into gray, take the number and perform XOR after shifting the number 1 bit to the right.
+        // x_gray = x ^ (x >> 1);
+        DSP::Float component_offset = (sqrt(DSP::Float(M))-1);
+        if ((bits_per_symbol % 2) == 0) {
+          unsigned int mask = 0x00;
+          for (unsigned int ind = 0; ind < bits_per_symbol/2; ind++) {
+            mask <<= 1;
+            mask += 1; 
+          }
+          constellation.resize(M);
+          for (unsigned int n=0; n < M; n++) {
+            unsigned int x_gray = n ^ (n >> 1);
+            unsigned int i = x_gray & mask;
+            unsigned int q = (x_gray >> (bits_per_symbol/2));
+            q = q & mask;
+            constellation[n] = DSP::Complex(DSP::Float(i) - component_offset, DSP::Float(q) - component_offset);
+          }
+          if (constellation_phase_offset != 0.0) {
+            for (unsigned int ind=0; ind < M; ind++) {
+              constellation[ind] = constellation[ind] * DSP::Complex(cos(constellation_phase_offset), sin(constellation_phase_offset));
+            }
+          }
+          is_real = false;
+        }
+        else {
+          //! \TODO for odd bits_per_symbol generate QAM constellation for bits_per_symbol+1 and next remove half of the symbols with larger magnitude ???
+          DSP::log << DSP::e::LogMode::Error << "getConstellation" << DSP::e::LogMode::second << "Unsupported modulation QAM bits_per_symbol value " << endl;
+        }
+      }
+      break;
+
     default:
       DSP::log << DSP::e::LogMode::Error << "getConstellation" << DSP::e::LogMode::second << "Unsupported modulation type" << endl;
       break;
diff --git a/src/include/DSP_lib.h b/src/include/DSP_lib.h
index 9ff7484fb69c61c3d6778d64c431184ad74197f5..34d78944aa39bf4b309a79f59e7a569118cf84c0 100644
--- a/src/include/DSP_lib.h
+++ b/src/include/DSP_lib.h
@@ -11,7 +11,7 @@
 
 #define DSP_VER_MAJOR 0
 #define DSP_VER_MINOR 20
-#define DSP_VER_BUILD 20 // !!! without zeroes before, else this will be treated as octal number
+#define DSP_VER_BUILD 21 // !!! without zeroes before, else this will be treated as octal number
 #define DSP_VER_YEAR  2023
 #define DSP_VER       DSP_VER_MAJOR.DSP_VER_MINOR.DSP_VER_BUILD