Beispiel #1
0
def main():

    tx_im = Image.open("DC4_150x100.pgm")
    tx_bin = np.unpackbits(np.array(tx_im))

    # make sure every modulation has the same energy per symbol
    bpsk = komm.PSKModulation(2)
    qam_16 = komm.QAModulation(16, base_amplitudes=1/np.sqrt(10))
    qam_256 = komm.QAModulation(256, base_amplitudes=1/np.sqrt(170))

    snr = np.arange(0,40,2)
    ber_bpsk = snr_ber_simulation(tx_bin, snr, bpsk)
    ber_qam_16 = snr_ber_simulation(tx_bin, snr, qam_16)
    ber_qam_256 = snr_ber_simulation(tx_bin, snr, qam_256)

    # plot all snr vs ber curves
    plt.figure()    
    plt.scatter(snr, ber_bpsk)
    plt.plot(snr, ber_bpsk, label = 'BPSK')
    plt.scatter(snr, ber_qam_16)
    plt.plot(snr, ber_qam_16, label = '16QAM')
    plt.scatter(snr, ber_qam_256)
    plt.plot(snr, ber_qam_256, label = '256QAM')

    plt.xlabel('SNR dB')
    plt.ylabel('BER percentage')
    plt.title('SNR vs BER')
    plt.legend()
    plt.yscale('log')

    # image recovery
    # plt.figure()
    # rx_im = np.packbits(rx_bin).reshape(tx_im.size[1],tx_im.size[0])

    plt.show()
Beispiel #2
0
def test_qam_modulation():
    qam4 = komm.QAModulation(4)
    qam8 = komm.QAModulation((4, 2))
    qam16 = komm.QAModulation(16)
    assert np.allclose(qam4.constellation,
                       [-1.0 - 1.0j, 1.0 - 1.0j, -1.0 + 1.0j, 1.0 + 1.0j])
    assert np.allclose(qam8.constellation, [
        -3.0 - 1.0j, -1.0 - 1.0j, 1.0 - 1.0j, 3.0 - 1.0j, -3.0 + 1.0j,
        -1.0 + 1.0j, 1.0 + 1.0j, 3.0 + 1.0j
    ])
    assert np.allclose(qam16.constellation, [
        -3.0 - 3.0j, -1.0 - 3.0j, 1.0 - 3.0j, 3.0 - 3.0j, -3.0 - 1.0j, -1.0 -
        1.0j, 1.0 - 1.0j, 3.0 - 1.0j, -3.0 + 1.0j, -1.0 + 1.0j, 1.0 + 1.0j,
        3.0 + 1.0j, -3.0 + 3.0j, -1.0 + 3.0j, 1.0 + 3.0j, 3.0 + 3.0j
    ])
Beispiel #3
0
    def create_object(self, x):
        """

        Creates an instance of the corresponding modulation scheme
        Parameters
        ----------
        x : string containing the name of the modulation scheme
        
        Returns
        -------
        instance of the corresponding modulation scheme 
        k : bits per symbol
        """
        if x == 'BPSK':
            k = 1
            obj = komm.PSKModulation(2)

        if x == 'QPSK':
            k = 2
            obj = komm.PSKModulation(4, phase_offset=np.pi / 4)

        if x == '4-QAM':
            k = 2
            obj = komm.QAModulation(
                4, base_amplitudes=1 / np.sqrt(2.)
            )  # base_amplitudes is set to a value such that obj.energy_per_symbol becomes unity.

        if x == '16-QAM':
            k = 4
            obj = komm.QAModulation(
                16, base_amplitudes=1 / np.sqrt(10.)
            )  # base_amplitudes is set to a value such that obj.energy_per_symbol becomes unity.

        if x == '256-QAM':
            k = 8
            obj = komm.QAModulation(
                256, base_amplitudes=1 / np.sqrt(170.)
            )  # base_amplitudes is set to a value such that obj.energy_per_symbol becomes unity.
        return obj, k
Beispiel #4
0
    def __init__(self,
                 nFreqSamples=64,
                 pilotIndices=[-21, -7, 7, 21],
                 pilotAmplitude=1,
                 nData=12,
                 fracCyclic=0.25,
                 mQAM=2):
        """
        nFreqSamples sets the number of frequency coefficients of the FFT. Pilot 
        tones are injected at pilotIndices. The real valued pilot amplitude is 
        pilotAmplitude. For transmission nData bytes are expected in an array. 
        The relative length of the Cyclic prefix is fracCyclic. 
        Number of QAM symbols = 2**mQAM, giving mQAM bits per QAM symbol. Average 
        power is normalised to unity. Default example correspond to 802.11a wifi 
        modulation.
        """
        # the total number of frequency samples
        self.nIFFT = nFreqSamples

        # number of data samples in bytes (coded/decoded)
        self.nData = nData

        # fracCyclic is relative cyclic prefix/ guard interval length
        self.nCyclic = int(self.nIFFT * fracCyclic)

        # indices of pilots
        self.pilotIndices = np.array(pilotIndices)

        # amplitudes of the pilot carrier at the beginning
        self.pilotAmplitude = pilotAmplitude

        # mQAM bits per QAM symbol
        self.mQAM = mQAM
        # normalisation to make average bit energy unity for square QAM
        norm = 0
        for i in range(1, 2**(mQAM // 2), 2):
            norm = norm + i**2
        self.norm = np.sqrt(norm * 2**(2 - mQAM // 2))

        # use komm open-source library for QAM mod/demod
        # pypi.org/project/komm
        # by Roberto W. Nobrega <*****@*****.**>
        self.qam = komm.QAModulation(2**self.mQAM,
                                     base_amplitudes=1. / self.norm)

        self.kstart = (8 * self.nData // self.mQAM +
                       self.pilotIndices.size) // 2
Beispiel #5
0
def main():
    parity = Parity('odd')

    tx_im = Image.open("DC4_150x100.pgm")
    tx_bin = np.unpackbits(np.array(tx_im))
    modulator = komm.QAModulation(4, base_amplitudes=1 / np.sqrt(2))
    # modulator = komm.PSKModulation(2)

    snr = 4
    awgn = komm.AWGNChannel(snr=10**(snr / 10.))

    # make the data a multiple of 7
    if (len(tx_bin) % 7 != 0):
        tx_bin = np.int8(np.append(tx_bin, np.zeros(7 - len(tx_bin) % 7)))

    # transmission
    rx_bin = []
    ARQ_counter = 0
    for i in range(0, len(tx_bin), 7):
        temp = tx_bin[i:i + 7]
        temp = np.append(temp, parity.parity_cal(temp))
        tx_data = modulator.modulate(temp)

        rx_data = awgn(tx_data)
        rx_byte = modulator.demodulate(rx_data)

        while (parity.parity_cal(rx_byte[0:7]) != rx_byte[7]):
            # parity check fail, need resend
            rx_data = awgn(tx_data)
            rx_byte = modulator.demodulate(rx_data)
            ARQ_counter += 1

        rx_bin = np.int8(np.append(rx_bin, rx_byte[0:7]))

    print("ARQ counter = " + str(ARQ_counter))
    print("BER = " + str(BER_cal(tx_bin, rx_bin)))
Beispiel #6
0
def qam_constellation_demo(order, base_amplitude, phase_offset, labeling,
                           noise_power_db):
    qam_modulation = komm.QAModulation(order, base_amplitude, phase_offset,
                                       labeling)
    lim = [-2.125 * np.sqrt(order), 2.125 * np.sqrt(order)]
    constellation_demo(qam_modulation, noise_power_db, xlim=lim, ylim=lim)
Beispiel #7
0
def SimulateBER(snrArray, txBin, Npixels, modulatioInfo):
    nSNR = len(snrArray)
    rxDataArray = np.empty(len(txBin))
    BitErrorArray = np.empty(2)
    berArray = np.empty(0)
    mod = 0

    # Create Modulation Scheme Object
    if (modulatioInfo.get("mod") == "PSK"):
        mod = komm.PSKModulation(modulatioInfo.get("order"))

    if (modulatioInfo.get("mod") == 'QAM'):
        mod = komm.QAModulation(modulatioInfo.get("order"))
        # Normalize energy per symbol
        baseAmplitude = 1 / (np.sqrt(mod.energy_per_symbol))
        mod = komm.QAModulation(modulatioInfo.get("order"), baseAmplitude)

    print("Modulation to be used:")
    print(
        str(modulatioInfo.get("order")) + " " + str(modulatioInfo.get("mod")))
    print("Bits Per Symbol: " + str(mod.bits_per_symbol))
    print("Energy Per Symbol: " + str(mod.energy_per_symbol))
    print("\n")

    # Modulate Data
    txData = mod.modulate(txBin)

    # For each transmision
    for i in range(nSNR):
        # Calculate based on db
        awgn = komm.AWGNChannel(snr=10**(snrArray[i] / 10.))
        # Simulate noise in channel
        rxData = awgn(txData)
        # Demodulate Data
        rxBin = mod.demodulate(rxData)
        # Append demodulated data as a new row
        rxDataArray = np.vstack([rxDataArray, rxBin])

    awgn = komm.AWGNChannel(snr=10**(snrArray[10] / 10.))
    rx_data = awgn(txData)
    rx_bin = mod.demodulate(rx_data)

    # Plot few rx bits
    plt.figure()
    plt.axes().set_aspect("equal")
    plt.scatter(rx_data[:10000].real, rx_data[:10000].imag, s=1, marker=".")
    plt.show()
    rx_im = np.packbits(rx_bin).reshape(tx_im.size[1], tx_im.size[0])

    plt.figure()
    plt.imshow(np.array(rx_im), cmap="gray", vmin=0, vmax=255)
    plt.show()

    # Measuring Bit Error Ratio
    # For each transmision
    for j in range(1, nSNR + 1):
        # Reset number of bit errors
        BitErrorCount = 0

        # Compute bit errors
        # i.e For each pixel
        for i in range(Npixels * 8):
            # If pixel value does not match
            if (rxDataArray[j][i] != txBin[i]):
                # Increment error count
                BitErrorCount += 1
        # Calculate bit error rate for transmision
        ber = BitErrorCount / (Npixels * 8)
        berArray = np.append(berArray, ber)
        # Append new dimension containing bit count and bit error rate
        BitErrorArray = np.vstack([BitErrorArray, [BitErrorCount, ber]])

    print("Bit Error Array:")
    print(BitErrorArray)
    print("\n")
    plt.figure()
    plt.scatter(snrArray, berArray)  #plot points
    plt.plot(snrArray, berArray)  #plot lines
    plt.yscale("log")
    plt.ylabel('$BER$')
    plt.xlabel('$SNR$')
    plt.title((str(modulatioInfo.get("order")) + " " +
               str(modulatioInfo.get("mod"))))
    plt.grid(True)
    #plt.show()

    # Calculate theoretical BER
    # Modify k parameter i.e. bits per symbol
    k = mod.bits_per_symbol

    errfcDataSet = np.empty(0)
    # For Each SNR
    for i in range(nSNR):
        # Calculate Theorethical BER
        errfc = 0.5 * scipy.special.erfc(
            math.sqrt((10**(snrArray[i] / 10)) / k))
        errfcDataSet = np.append(errfcDataSet, errfc)
    plt.plot(snrArray, errfcDataSet, color='r')
    plt.show()

    print("Errfc Data Set:")
    print(errfcDataSet)
    print("\n")
    return berArray, errfcDataSet
Beispiel #8
0
def SimulateParityBits(snrArray, txBin, Npixels, modulatioInfo):
    nSNR = len(snrArray)
    rxBinDecoded = np.empty(0)
    rxIncorrect = True

    mod = 0
    if (modulatioInfo.get("mod") == "PSK"):
        mod = komm.PSKModulation(modulatioInfo.get("order"))

    if (modulatioInfo.get("mod") == 'QAM'):
        mod = komm.QAModulation(
            modulatioInfo.get("order"))  # add baseAmplitude
        print("Base Amplitude is: " + str(mod.energy_per_symbol))
        # Normalize Enerhy per symbol
        baseAmplitude = 1 / (np.sqrt(mod.energy_per_symbol))
        print("New Base Amplitude is: " + str(baseAmplitude))
        mod = komm.QAModulation(modulatioInfo.get("order"), baseAmplitude)

    print("Modulation to be used:")
    print(
        str(modulatioInfo.get("order")) + " " + str(modulatioInfo.get("mod")))
    print("Bits Per Symbol: " + str(mod.bits_per_symbol))
    print("Energy Per Symbol: " + str(mod.energy_per_symbol))
    print("\n")
    print("Simulating ARQ based on parity bit check!")

    print("Adding Parity Bits!")
    # Add parity bits
    # For each pixel
    for i in range(Npixels):
        startIndex = i * 8
        # If the sum of on bits is not even
        if (((np.sum(txBin[startIndex:startIndex + 7])) % 2) != 0):
            # Change parity bit to 1
            txBin[(startIndex + 7)] = 1
        # The sum of on bits is even
        else:
            # Change parity bit to 0
            txBin[(startIndex + 7)] = 0

    # Modulate data
    txDataParity = mod.modulate(txBin)
    print("Simulating Transmision!")
    indexFactor = int(8 / mod.bits_per_symbol)
    berArray = np.empty(0)
    arqArray = np.empty(0)

    for c in range(nSNR):
        print("Simulating SNR: " + str(snrArray[c]))
        # Set Average Gausian Noise to reflect new SNR
        awgn = komm.AWGNChannel(snr=10**(snrArray[c] / 10.))
        ARQ = 0
        # For Each Symbol
        for i in range(Npixels):
            # Compute Index of the codeword
            startIndex = i * indexFactor
            # Until the Parity bit check is not passed
            while (rxIncorrect):
                # Simulate noise in the channel during transmision only
                rxData = awgn(txDataParity[startIndex:startIndex +
                                           indexFactor])
                # Demodulate Data
                rxBin = mod.demodulate(rxData)
                # Check if parity = 0
                if ((np.sum(rxBin) % 2) != 0):
                    # Error During Transmision
                    # Increment Request Counter
                    ARQ += 1
                else:
                    # Passed parity check, assume data is correct
                    # Append Data Bits to final binary array
                    rxBinDecoded = np.append(rxBinDecoded, rxBin)
                    # Set while loop flag to false indicating this codeword has been rx without error
                    rxIncorrect = False

            #Set while loop flag to true to process next codeword
            rxIncorrect = True

        # Convert to real int
        rxBinDecoded = np.real(rxBinDecoded)
        rxBinDecoded = rxBinDecoded.astype(int)
        # For SNR 10 Plot graphs
        if (c == 0):
            # Plot few rx bits
            # plt.figure()
            # plt.axes().set_aspect("equal")
            # plt.scatter(rxBinDecoded[:10000].real,rxBinDecoded[:10000].imag,s=1,marker=".")
            # plt.show()
            rx_im = np.packbits(rxBinDecoded).reshape(tx_im.size[1],
                                                      tx_im.size[0])

            plt.figure()
            plt.imshow(np.array(rx_im), cmap="gray", vmin=0, vmax=255)
            plt.show()

        # Count Bit errors
        print("Computing BER: " + str(snrArray[c]))
        BitErrorCount = 0
        # For each bit in the rx data
        for i in range(Npixels * 8):
            # If bit value does not match
            if (rxBinDecoded[i] != txBin[i]):
                # Increment error count
                BitErrorCount += 1
            # Calculate bit error rate for the transmision
        berArray = np.append(berArray, (BitErrorCount / (Npixels * 8)))
        arqArray = np.append(arqArray, (ARQ / (Npixels * 8)))

    print("BER Array:")
    print(berArray)
    print("\n")

    print("ARQ Array:")
    print(arqArray)
    print("\n")

    plt.figure()
    plt.scatter(snrArray, berArray)  #plot points
    plt.plot(snrArray, berArray)  #plot lines
    plt.yscale("log")
    plt.ylabel('$BER$')
    plt.xlabel('$SNR$')
    plt.title((str(modulatioInfo.get("order")) + " " +
               str(modulatioInfo.get("mod")) + " BER"))
    plt.grid(True)

    # Calculate theoretical BER
    # Modify k parameter i.e. bits per symbol
    k = mod.bits_per_symbol

    errfcDataSet = np.empty(0)
    # For Each SNR
    for i in range(nSNR):
        # Calculate Theorethical BER
        errfc = 0.5 * scipy.special.erfc(
            math.sqrt((10**(snrArray[i] / 10)) / k))
        errfcDataSet = np.append(errfcDataSet, errfc)
    plt.plot(snrArray, errfcDataSet, color='r')
    plt.show()

    plt.figure()
    plt.scatter(snrArray, arqArray)  #plot points
    plt.plot(snrArray, arqArray)  #plot lines
    plt.yscale("log")
    plt.ylabel('$ARQ Rate$')
    plt.xlabel('$SNR$')
    plt.title((str(modulatioInfo.get("order")) + " " +
               str(modulatioInfo.get("mod")) + " ARQ/nBits"))
    plt.grid(True)

    return berArray, arqArray, rxBinDecoded
 def modulate(self, bits):
     self.orderCountMethod = "mul"
     qam = komm.QAModulation(self.orders)
     return qam.modulate(bits)
 def demodulate(self, bods):
     self.orderCountMethod = "mul"
     symbols = self.getSymbolsFromSignal(bods)
     qam = komm.QAModulation(self.orders)
     return qam.demodulate(symbols)
Beispiel #11
0
import pprint as pp
import numpy.random as random

# sys.path.append("../")
import custom_tools.fftplot as fftplot
from scipy.fftpack import fft, fftshift, fftfreq, ifft


def db(x):
    # returns dB of number and avoids divide by 0 warnings
    x = np.array(x)
    x_safe = np.where(x == 0, 1e-7, x)
    return 20 * np.log10(np.abs(x_safe))


qam = komm.QAModulation(16)

print(f"Constellation: {qam.constellation}")
print(f"Symbol Mapping (Gray code): {qam.labeling}")

# create dictionary for mapping data words to symbols (matching what we created earlier above
# to demonstrate utility of komm library)
const_map = dict(zip(qam.labeling, qam.constellation))
print("\n")
print("Dictionary for Constellation Mapping for Symbols:")
pp.pprint(const_map)

sym_rate = 1e3

sym_length = 26  # duration of impulse response
oversamp = 4  # samples per symbol