This question is somewhat related to the one asked here: [How is multiplexing achieved in spread-spectrum modulations like CSS?](https://dsp.stackexchange.com/questions/36604/how-is-multiplexing-achieved-in-spread-spectrum-modulations-like-css)

I am looking at the bit error rate (BER) performance of communication systems based on chirp spread spectrum (CSS) like the one implemented by Semtech's LoRa CSS. 

Authors of the research paper [Range and coexistence analysis of long range unlicensed communication](http://ieeexplore.ieee.org/document/7500415/) give an analytical expression for computing the $BER$ given the spreading factor ($sf$) and the energy per bit to noise ratio ($E\_b/E\_0$). The expression is as follows: 
\begin{equation}
BER = Q(\frac{log\_{12}(sf)}{\sqrt{2}} \frac{E\_b}{N\_0} )
\end{equation}
where $Q(x)$ is the Q-function. Authors also show some results comparing the BER for a LoRa CSS system with a BPSK system. If useful, I have reproduced the results:
[![BER versus $E_{b}/N_{0}$](https://i.stack.imgur.com/Vg3z8.png)](https://i.stack.imgur.com/Vg3z8.png)
My question is related to the conversion from $E\_b/N\_0$ to $SNR$. This is something I have done many times (a very useful resource to relate these two metrics can be found [here](https://www.dsprelated.com/showarticle/168.php)), but results from such conversion are a bit confusing to me. 

The general expression (in dB) that relates $SNR$ and $E\_b/N\_0$ is:

\begin{equation}
SNR(dB) = {E\_b}/{N\_0} + 10\cdot log\_{10}(R\_s) + 10\cdot log\_{10}(k) + 10\cdot log\_{10}(R) - 10\cdot log\_{10}(BW\_n)
\end{equation}

where $R\_s$ is the symbol rate; $k$ is the number of information bits per symbol, $R$ is the code rate and $BW\_n$ is the noise bandwidth.

Say for an uncoded 2PSK system (R=1), k is 1, and if considering matched transmit and receive filters, $Rs = BW\_n$, then $SNR = E\_b/N\_0$.

Now, I am confused with LoRa CSS. Let's consider there is no FEC either (R again is 1). To my knowledge, the number of information bits per symbol, $k$, is $k = log\_2(2^{sf}) = sf$; and the symbol rate, $R\_s$, is $R\_s=BW/2^{sf}$, where $BW$ is one of LoRa's bandwidths (e.g., 125kHz, 250kHz or 500kHz). 

Could I take the same consideration regarding matched transmit and receive filters? If so, $Rs = BW\_n$, and this would yield the following expression (in dB): $SNR = E\_{b}/N\_{0} + 10\cdot log\_{10}(sf)$. The figure below shows the BER versus SNR using such expression, and I am not sure if they make sense:

[![enter image description here](https://i.stack.imgur.com/WukUU.png)](https://i.stack.imgur.com/WukUU.png)

Okay, say now that I do not consider matched transmit and receive filters. The equation for calculating SNR would be (R = 1): 

\begin{equation}
SNR(dB) = {E\_b}/{N\_0} + 10\cdot log\_{10}(BW/2^{sf}) + 10\cdot log\_{10}(sf) - 10\cdot log\_{10}(BW\_n)
\end{equation}

What would be the value of $BW\_n$? Can I consider the same as BW (e.g., 125kHz)? If so, I got the following results: 

[![enter image description here](https://i.stack.imgur.com/aZhpI.png)](https://i.stack.imgur.com/aZhpI.png)

Is this okay? What am I doing or considering wrong? I would appreciate if anyone could shed some light in what I am doing. 

Thanks

If useful, I generated the previous figures on python, and the code is:

```
from __future__ import division
from numpy.random import rand, randn
import numpy as np
import matplotlib.pyplot as plt
import scipy.special
import math

qfunc = lambda x: 0.5 * scipy.special.erfc(x/np.sqrt(2))

sf_range = [7,8,9,10,11,12]
EbN0dB_range = range(-10,15)

itr = len(EbN0dB_range)
itr_sf = len(sf_range)

## BPSK
bpsk_ber = [None for _ in range(itr)] # BER
bpsk_SNR_dB = [None for _ in range(itr)]  # Signal to noise ratio in dB
bpsk_M = 2               # Modulation Order
bpsk_k = np.log2(bpsk_M) # No of bits per symbol (BPSK is 1 bit per symbol)
bpsk_Rfec = 1
bpsk_Rs = 1
bpsk_BWn = 1  # Noise bandwidth

## LoRa
lora_ber = [[None for _ in range(itr)] for _ in range(itr_sf)]
lora_SNR_dB = [[None for _ in range(itr)] for _ in range(itr_sf)]  # Signal to noise ratio in dB
lora_Rs = [None for _ in range(itr_sf)]
lora_Rb = [None for _ in range(itr_sf)]
lora_Rfec = 1
lora_bw = 125e3
lora_BWn = 125e3

for s in range (0, itr_sf):
  sf = sf_range[s]
  lora_Rs[s] = ( lora_bw / ( 2 ** sf ) )
  lora_Rb[s] = lora_Rs[s] * sf

for n in range (0, itr):
  EbNOdB = EbN0dB_range[n]

  # For a matched-filter BPSK system, BWn = Rs
  bpsk_SNR_dB[n] = EbNOdB  + 10 * np.log10(bpsk_Rs) + 10 * np.log10(bpsk_k) + 10 * np.log10(bpsk_Rfec) - 10 * np.log10(bpsk_BWn)

  EbN0 = 10.0 ** (EbNOdB / 10.0)
  bpsk_ber[n] = qfunc(np.sqrt(2 * EbN0)) # or ber[n] = Pb(np.sqrt(EbN0))

  # LoRa
  for s in range (0, itr_sf):
    sf = sf_range[s]

    # Convert EbN0 to SNR
    # We consider matched transmit and receive filters (lora_Rs == BWn)
    lora_SNR_dB[s][n] = EbNOdB + 10 * np.log10(sf)
    # lora_SNR_dB[s][n] = EbNOdB + 10 * np.log10(lora_Rs[s]) + 10 * np.log10(sf) + 10 * np.log10(lora_Rfec) - 10 * np.log10(lora_BWn)
    # Calculate BER for LoRa CSS
    lora_ber[s][n] = qfunc(( log12(sf) / np.sqrt(2) ) * EbN0)

plt.figure()
plt.plot(EbN0dB_range, bpsk_ber, '-o', label='BPSK')
for i,b in enumerate(css_ber):
  plt.plot(EbN0dB_range, b,'-o', label='LoRa CSS, SF {}'.format(sf_range[i]))
axes = plt.gca()
axes.set_xlim([EbN0dB_range[0], EbN0dB_range[-1]])
axes.set_ylim([1e-4, 1e-0])
plt.xscale('linear')
plt.yscale('log')
plt.xlabel('$E_{b}/N_{0}$ (dB)')
plt.ylabel('Bit error rate, BER')
plt.grid(True)
plt.legend(loc = 'best')

plt.figure()
plt.plot(bpsk_SNR_dB, bpsk_ber, '-o', label='BPSK')
for i,b in enumerate(lora_ber):
    plt.plot(lora_SNR_dB[i], lora_ber[i], '-o', label='LoRa (sf {})'.format(sf_range[i]))
axes = plt.gca()
axes.set_ylim([1e-4, 1e-0])
plt.xscale('linear')
plt.yscale('log')
plt.ylabel('Bit error rate')
plt.xlabel('Signal to noise ratio, SNR (dB)')
plt.grid(True)
plt.legend(loc = 'best')
plt.show()

```