package interference; import math.Complex; import math.UFunctions; public class ZigBeeTransceiver { public static double getNumberOfReceivedErrorBits(String inputMsg, int noNeghboringNodes, int radioRange, double perActiveNodes) { // The number of received error bits to return double errBits = 0; // ------------------------------------------------------ // ZigBee Parameters // ------------------------------------------------------ int signalConstellation = 16; int symbolSize = signalConstellation/4; int maxBitsAllowedToSend = 512; // 64 bytes // ------------------------------------------------------ // Transmitter // ------------------------------------------------------ byte [] binaryData = getStringToBinary(inputMsg); byte [] binarySource = new byte [maxBitsAllowedToSend]; if (binaryData.length>=maxBitsAllowedToSend) System.out.print("Too Long Message"); else { for(int i=0; i<maxBitsAllowedToSend; i++){ if (i<binaryData.length) binarySource[i]=binaryData[i]; else binarySource[i] = 0; } // ------------------------------------------------------ // generating Decimal numbers int lenDecNo = binarySource.length / symbolSize; // gives length for decimal numbers int[] DecNumbers = new int[lenDecNo]; int jj = 0; for (int i = 0; i < binarySource.length; i += 4) { String s = "" + binarySource[i] + binarySource[i + 1] + binarySource[i + 2] + binarySource[i + 3]; DecNumbers[jj] = Integer.parseInt(s, 2); jj++; } // ------------------------------------------------------ // mapping Decimal numbers on PN_tables String s = ""; String S_I = ""; String S_Q = ""; for (int i = 0; i < lenDecNo; i++) { s = s + getPN(DecNumbers[i]); } // ------------------------------------------------------ // taking odd and even bits and repeating them at the same time for (int i = 0; i <= s.length() / 2 - 1; i++) { S_I = S_I + s.charAt(i * 2) + s.charAt(i * 2); S_Q = S_Q + s.charAt((i * 2) + 1) + s.charAt((i * 2) + 1); } // ------------------------------------------------------ // O-QPSK Modulation int map_dec; Complex[] oqpskSource = new Complex[S_I.length() + 1]; for (int i = 0; i < S_I.length() - 1; i++) { // converting from 2-bit binary to decimal numbers map_dec = (S_I.charAt(i + 1) - '0') * 2 + (S_Q.charAt(i) - '0'); // mapping 0,1,2 and 3 on complex numbers oqpskSource[i + 1] = UFunctions.getComplexModulation(map_dec); } // ------------------------------------------------------ // first value of I part and last value of Q part would be single // because of 1-bit delay in Q-part if (S_I.charAt(0) == '0') oqpskSource[0] = new Complex(0.7071, 0.0); else oqpskSource[0] = new Complex(-0.7071, 0.0); if (S_Q.charAt(0) == '0') oqpskSource[S_I.length()] = new Complex(0.0, 0.7071); else oqpskSource[S_I.length()] = new Complex(0.0, -0.7071); // ------------------------------------------------------ // Alpha-Stable Channel // ------------------------------------------------------ // Generating alpha-stable random variables int sizeout = oqpskSource.length; // number of alpha_stable random variables double [] alpharnd1 = AlphaStableRandom.generateNext(noNeghboringNodes, radioRange, perActiveNodes, sizeout); double [] alpharnd2 = AlphaStableRandom.generateNext(noNeghboringNodes, radioRange, perActiveNodes, sizeout); Complex [] alpharnd = new Complex[sizeout]; // generating them twice and then adding them as complex function for (int i = 0; i < sizeout; i++) { alpharnd[i] = new Complex(alpharnd1[i], alpharnd2[i]); } Complex[] rx = new Complex[sizeout]; double [] noise_real = new double[sizeout]; double [] noise_imag = new double[sizeout]; for (int i = 0; i < sizeout; i++) { noise_real[i] = oqpskSource[i].re() + alpharnd[i].re(); noise_imag[i] = oqpskSource[i].im() + alpharnd[i].im(); rx[i] = new Complex(noise_real[i], noise_imag[i]); } // ------------------------------------------------------ // RECEIVER // ------------------------------------------------------ // O-QPSK Demodulation int[] OQPSKdemod = new int[rx.length]; if (rx[0].equals(new Complex(0.7071, 0.0))) OQPSKdemod[0] = 0; if (rx[0].equals(new Complex(-0.7071, 0.0))) OQPSKdemod[0] = 2; if (rx[rx.length - 1].equals(new Complex(0.0, 0.7071))) OQPSKdemod[rx.length - 1] = 0; if (rx[rx.length - 1].equals(new Complex(0.0, -0.7071))) OQPSKdemod[rx.length - 1] = 1; for (int i = 0; i < oqpskSource.length - 1; i++) { OQPSKdemod[i + 1] = getComplexDemodulation(oqpskSource[i + 1]); } // ------------------------------------------------------ // converting into 2-bit binary number String[] rx_rbin = new String[OQPSKdemod.length]; for (int i = 0; i < OQPSKdemod.length; i++) { rx_rbin[i] = twoBitbinConversion(OQPSKdemod[i]); } // ------------------------------------------------------ // converting binary data from parallel to serial byte[] rx_p2s = new byte[rx_rbin.length * 2]; for (int i = 0; i < rx_rbin.length * 2; i += 2) { rx_p2s[i] = (byte) (rx_rbin[i / 2].charAt(0) - '0'); rx_p2s[i + 1] = (byte) (rx_rbin[i / 2].charAt(1) - '0'); } // ------------------------------------------------------ //separating odd and even values byte[] rxOdd = new byte[rx_p2s.length / 4]; byte[] rxEven = new byte[rx_p2s.length / 4]; for (int i = 0; i < rxOdd.length; i++) { rxOdd[i] = rx_p2s[i * 4]; rxEven[i] = rx_p2s[(i + 1) * 4 - 1]; } // ------------------------------------------------------ // combining odd and even values one by one String[] rx_rpn = new String[rx_p2s.length / 64]; for (int i = 0; i < rx_p2s.length / 64; i++) { rx_rpn[i] = ""; for (int k = 0; k < 16; k++) { rx_rpn[i] += rxOdd[i * 16 + k]; rx_rpn[i] += rxEven[i * 16 + k]; } } // ------------------------------------------------------ // De-mapping values over PN-Sequence Table by using Hamming Distance byte[] rx_hamd = new byte[rx_rpn.length]; int min; int imin; int h; for (int i = 0; i < rx_rpn.length; i++) { min = 32; imin = 16; for (int j = 0; j < 16; j++) { h = getHammingDistance(rx_rpn[i], getPN(j)); if (h < min) { min = h; imin = j; } } rx_hamd[i] = (byte) imin; } // ------------------------------------------------------ // converting from decimal to binary byte [] rx_d2b = getDecimalToBinary(rx_hamd); // ------------------------------------------------------ // Finding Errored Bits byte[] cb = new byte[rx_d2b.length]; for (int i = 0; i < rx_d2b.length; i++) { cb[i] = binarySource[i]; errBits += (cb[i] == rx_d2b[i]) ? 0 : 1; } } // errBits = Error Bits in the received data // if errBits == 0 -> Packet Received Correctly // otherwise -> Packet Not Received Correctly return errBits ; } // ------------------------------------------------------ // Other Functions // ------------------------------------------------------ // PN Sequence Table public static String getPN(int i) { String[] PNTable = new String[16]; //PN chip sequence of size 16*32. know at transmitter and receiver PNTable[0] = "11011001110000110101001000101110"; PNTable[1] = "11101101100111000011010100100010"; PNTable[2] = "00101110110110011100001101010010"; PNTable[3] = "00100010111011011001110000110101"; PNTable[4] = "01010010001011101101100111000011"; PNTable[5] = "00110101001000101110110110011100"; PNTable[6] = "11000011010100100010111011011001"; PNTable[7] = "10011100001101010010001011101101"; PNTable[8] = "10001100100101100000011101111011"; PNTable[9] = "10111000110010010110000001110111"; PNTable[10] = "01111011100011001001011000000111"; PNTable[11] = "01110111101110001100100101100000"; PNTable[12] = "00000111011110111000110010010110"; PNTable[13] = "01100000011101111011100011001001"; PNTable[14] = "10010110000001110111101110001100"; PNTable[15] = "11001001011000000111011110111000"; return PNTable[i]; } // ------------------------------------------------------ // 2-bit decimal to complex conversion public static Complex getComplexModulation(int v) { if (v == 0) return new Complex(0.7071, 0.7071); if (v == 1) return new Complex(0.7071, -0.7071); if (v == 2) return new Complex(-0.7071, 0.7071); if (v == 3) return new Complex(-0.7071, -0.7071); return null; } // ------------------------------------------------------ // complex to 0-3 decimal conversion on receiver side public static int getComplexDemodulation(Complex u) { if (u.equals(new Complex(0.7071, 0.7071))) return 0; if (u.equals(new Complex(0.7071, -0.7071))) return 1; if (u.equals(new Complex(-0.7071, 0.7071))) return 2; if (u.equals(new Complex(-0.7071, -0.7071))) return 3; return 0; } // ------------------------------------------------------ // 0-3 decimal to 2-bit binary conversion public static String twoBitbinConversion(int w) { if (w == 0) return "00"; if (w == 1) return "01"; if (w == 2) return "10"; if (w == 3) return "11"; return "00"; } // ------------------------------------------------------ // Hamming Distance Function public static int getHammingDistance(String compOne, String compTwo) { if (compOne.length() != compTwo.length()) { return -1; } int counter = 0; for (int i = 0; i < compOne.length(); i++) { if (compOne.charAt(i) != compTwo.charAt(i)) counter++; } return counter; } // ------------------------------------------------------ // converting Input String to Binary bits Function public static byte [] getStringToBinary(String inputMsg) { String s2 = ""; for(int i=0; i<inputMsg.length(); i++) { char c = inputMsg.charAt(i); s2 += String.format("%8s", Integer.toBinaryString(c)).replaceAll(" ", "0"); } s2 = s2.replaceAll("0", "\0"); s2 = s2.replaceAll("1", "\1"); byte [] binarySource = s2.getBytes(); return binarySource; } // ------------------------------------------------------ // converting [0 - 15] to 4 bit binary public static byte [] getDecimalToBinary(byte [] decimalVector) { byte [] binaryVector = new byte [decimalVector.length*4]; int k = 0; for (int i = 0; i < decimalVector.length; i++) { String s = Integer.toBinaryString(decimalVector[i]); for(int j = 0; j<(4-s.length()); j++ ) { binaryVector[k++] = 0; } for(int j = 0; j<s.length(); j++ ) { binaryVector[k++] = (byte) (s.charAt(j) - '0'); } } return binaryVector; } }