| 1 | #include <math.h> |
|---|
| 2 | //need to adjust math to account for data types and not losing precision |
|---|
| 3 | //need to rotate the PSK constellation by pi/M for threshold testing with axis |
|---|
| 4 | enum ConstellationMap { |
|---|
| 5 | bcd = 0, |
|---|
| 6 | gray = 1 |
|---|
| 7 | }; |
|---|
| 8 | |
|---|
| 9 | enum ConstellationType { |
|---|
| 10 | psk = 0, |
|---|
| 11 | qam = 1 |
|---|
| 12 | }; |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | void Constellation(ConstellationType type, ConstellationMapping map, unsigned int M, signed short *I_const, signed short *Q_const, bool *symbolBits){ |
|---|
| 17 | signed short I[M]; |
|---|
| 18 | signed short Q[M]; |
|---|
| 19 | unsigned short bitsPersymbol = log(M)/log(2); |
|---|
| 20 | bool orderedSymbolBits[M][bitsPersymbol] = false; |
|---|
| 21 | unsigned short bitDownshifts[bitsPersymbol]; |
|---|
| 22 | unsigned short bitIntervals[bitsPersymbol]; |
|---|
| 23 | unsigned short bcdMSBpositions[bitsPersymbol]; |
|---|
| 24 | |
|---|
| 25 | //Ordered Counter Clockwise from positive real axis for PSK, top-to-bottom, left-to-right for QAM |
|---|
| 26 | if(map==0){//Binary Coded Decimal Ordered, reguardless of modulation |
|---|
| 27 | for(unsigned short i=0, i<bitsPersymbol, i++){ |
|---|
| 28 | bitIntervals[i] = pow(2,i); |
|---|
| 29 | bitDownshifts[i] = bitIntervals[i]; |
|---|
| 30 | } |
|---|
| 31 | } else if(map==1){//Gray Coded |
|---|
| 32 | if(type==0){ |
|---|
| 33 | //Gray coded PSK |
|---|
| 34 | for(unsigned short i=0, i<bitsPersymbol, i++){ |
|---|
| 35 | bitIntervals[i] = pow(2,(i+1)); |
|---|
| 36 | bitDownshifts[i] = pow(2,i); |
|---|
| 37 | } |
|---|
| 38 | bitIntervals[bitsPersymbol] = bitIntervals[bitsPersymbol-1]; |
|---|
| 39 | |
|---|
| 40 | } else if(type==1){ |
|---|
| 41 | //Gray coded QAM |
|---|
| 42 | //Only going to make this work with Square QAM constellations for now |
|---|
| 43 | unsigned short bitsPersymbolaxis = bitsPersymbol/2; |
|---|
| 44 | //do lower bits |
|---|
| 45 | for(unsigned short i=0, i<bitsPersymbolaxis, i++){ |
|---|
| 46 | bitIntervals[i] = pow(2,(i+1)); |
|---|
| 47 | bitDownshifts[i] = pow(2,i); |
|---|
| 48 | } |
|---|
| 49 | bitIntervals[bitsPersymbolaxis] = bitIntervals[bitsPersymbolaxis-1]; |
|---|
| 50 | //do upper bits |
|---|
| 51 | for(unsigned short i=0, i<bitsPersymbolaxis, i++){ |
|---|
| 52 | bitIntervals[i+bitsPersymbolaxis] = pow(2,(i+bitsPersymbolaxis)); |
|---|
| 53 | bitDownshifts[i+bitsPersymbolaxis] = bitIntervals[i+bitsPersymbolaxis]; |
|---|
| 54 | } |
|---|
| 55 | } |
|---|
| 56 | } |
|---|
| 57 | //Actually assign the one's |
|---|
| 58 | for(unsigned short i=0, i<bitsPersymbol, i++){ |
|---|
| 59 | for(unsigned short j=bitDownshifts[i], j<M, j = j+bitIntervals[i]){ |
|---|
| 60 | for(unsigned short k=0, k<bitIntervals[i], k++){ |
|---|
| 61 | orderedSymbolBits[j+k][i] = true; |
|---|
| 62 | } |
|---|
| 63 | } |
|---|
| 64 | } |
|---|
| 65 | if(type==0){ |
|---|
| 66 | //Assign the constellation points for PSK |
|---|
| 67 | unsigned short mirrorCount = M/2; |
|---|
| 68 | signed short unitInterval = (pi*2)/M; |
|---|
| 69 | for(unsigned short symbolCount = 0, symbolCount<mirrorCount, symbolCount++){ |
|---|
| 70 | I[symbolCount] = cos(symbolCount*unitInterval); |
|---|
| 71 | Q[symbolCount] = sin(symbolCount*unitInterval); |
|---|
| 72 | I[symbolCount + mirrorCount] = -1*I[symbolCount];//Mirror Image |
|---|
| 73 | Q[symbolCount + mirrorCount] = -1*Q[symbolCount];//Mirror Image |
|---|
| 74 | } |
|---|
| 75 | } else if(type==1){ |
|---|
| 76 | //Assign the constellation points for QAM |
|---|
| 77 | unsigned short symbolCount = 0; |
|---|
| 78 | signed short shiftUp = (bitsPersymbol-1)/2; |
|---|
| 79 | signed short shiftLeft = (bitsPersymbol-1)/2; |
|---|
| 80 | for(unsigned short column=0, column<bitsPersymbol/2, column++){ |
|---|
| 81 | for(unsigned short row=0, row<bitsPersymbol/2, row++){ |
|---|
| 82 | I[symbolCount] = column - shiftLeft; |
|---|
| 83 | Q[symbolCount] = shiftUp - row; |
|---|
| 84 | symbolCount = symbolCount + 1; |
|---|
| 85 | } |
|---|
| 86 | } |
|---|
| 87 | } |
|---|
| 88 | } |
|---|
| 89 | void RXconstellation(ConstellationType type, ConstellationMapping map, unsigned int M, signed short *I_const, signed short *Q_const){ |
|---|
| 90 | Constellation(ConstellationType type, ConstellationMapping map, unsigned int M, signed short *I_const, signed short *Q_const) |
|---|
| 91 | //now sort by symbols in constellation to ease searh by received samples |
|---|
| 92 | //only modualtation type will determine what sorting will be done since mapping is done on the binary reresentations of the symbols |
|---|
| 93 | if(type==0){ |
|---|
| 94 | //do nothing since PSK symbols are generated counterclockwise |
|---|
| 95 | } |
|---|
| 96 | else if(type==1){ |
|---|
| 97 | //shift from striped arrangement to recursive quadrants for recursive I and Q threshold comparisons |
|---|
| 98 | unsigned short bitsPersymbol = log(M)/log(2); |
|---|
| 99 | signed short I_temp[M]; |
|---|
| 100 | signed short Q_temp[M]; |
|---|
| 101 | unsigned short symbolReorder[M]; |
|---|
| 102 | bool orderedSymbolBits_temp[M][bitsPersymbol]; |
|---|
| 103 | unsigned short row_increment[pow(bitsPersymbol/2,2)]; |
|---|
| 104 | unsigned short column_increment[pow(bitsPersymbol/2,2)]; |
|---|
| 105 | unsigned int bit_increment; |
|---|
| 106 | |
|---|
| 107 | for(unsigned short bit = 0, bit<bitsPersymbol/2, bit++){ |
|---|
| 108 | bit_increment[bit] = pow(2,bit); |
|---|
| 109 | for(unsigned short inc_count = bit_increment-1, inc_count<pow(bitsPersymbol/2,2)-1, inc_count = inc_count + bit_increment){ |
|---|
| 110 | row_increment[inc_count+1] = row_increment[inc_count] + bit_increment; |
|---|
| 111 | column_increment[inc_count+1] = row_increment[inc_count]*2; |
|---|
| 112 | } |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | for(unsigned short column = 0, column<pow(bitsPersymbol/2,2)-1, column++){ |
|---|
| 116 | for(unsigned short row = 0, row<pow(bitsPersymbol/2,2)-1, row++){ |
|---|
| 117 | symbolReorder[row+column*pow(bitsPersymbol/2,2)] = 1+row_increment[row]+column_increment[column]; |
|---|
| 118 | } |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | |
|---|
| 122 | |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | void TXconstellation(ConstellationType type, ConstellationMapping map, unsigned int M, signed short *I_const, signed short *Q_const){ |
|---|
| 126 | Constellation(ConstellationType type, ConstellationMapping map, unsigned int M, signed short *I_const, signed short *Q_const) |
|---|
| 127 | //now sort by symbol bits to ease symbol mapping |
|---|
| 128 | //only the mapping order will determine the sorting order for the transmitter side |
|---|
| 129 | |
|---|
| 130 | if(map==0){ |
|---|
| 131 | //do nothing since bcd is already sorted for quick recursive binary search |
|---|
| 132 | } |
|---|
| 133 | else if(map==1){ |
|---|
| 134 | //need to reorder gray coded to bcd along with paired symbol points |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | void DemodQAM(unsigned int M, signed short X, signed short Y, DemodScheme scheme, signed char *bitsOut){ |
|---|
| 141 | unsigned int bitsPersymbol = log(M)/log(2); |
|---|
| 142 | |
|---|
| 143 | |
|---|
| 144 | |
|---|
| 145 | } |
|---|
| 146 | |
|---|
| 147 | void DemodPSK(unsigned int M, signed short X, signed short Y, DemodScheme scheme, signed char *bitsOut){ |
|---|
| 148 | unsigned int bitsPersymbol = log(M)/log(2); |
|---|
| 149 | |
|---|
| 150 | |
|---|
| 151 | |
|---|
| 152 | } |
|---|
| 153 | |
|---|