def __init__(self, sample_rate, carrier_freq, symbol_length): self.sampleRate = sample_rate self.carrierFreq = carrier_freq self.symbolLength = symbol_length self.modulator = Modulator(carrier_freq, self.symbolLength, self.sampleRate) self.modulatedStartHeader = self.modulator.modulate(headerStart) self.modulatedEndHeader = self.modulator.modulate(headerEnd) self.pluto = adi.Pluto() # self.pluto.tx_rf_bandwidth self.pluto.tx_lo = self.carrierFreq self.pluto.tx_enabled_channels = [0, 1] self.pluto.sample_rate = self.sampleRate self.recordedDataQueue = Queue() self.modulatedDataQueue = Queue() self.dataToTransmit = Queue() self.threads = [] self.threads.append( threading.Thread(target=self.record(), name="micRecorder")) self.threads.append( threading.Thread(target=self.modulateData(), name="modulateData")) self.threads.append( threading.Thread(target=self.prepareDataToTransmit(), name="prepareDataToTransmit")) self.threads.append( threading.Thread(target=self.transmit(), name="transmitter")) for th in self.threads: th.start()
def setup(center_freq,sample_rate,final): #PSD_Format def power(val): p=abs(val**2) pdb=math.log10(p) return(pdb) ##SDR Setup Commands power=np.vectorize(power) fname = center_freq/1e9 name=str('{:.3f}Ghz'.format(fname)) sdr = adi.Pluto("ip:192.168.2.1") sdr.sample_rate = int(sample_rate) sdr.rx_rf_bandwidth = int(sample_rate) # filter cutoff, just set it to the same as sample rate sdr.rx_lo = int(center_freq) sdr.rx_buffer_size = 1024 # this is the buffer the Pluto uses to buffer samples ##Sampling Signal at Carrier Freq samples = sdr.rx() freqx=np.linspace(int(-sample_rate//2+center_freq),int(sample_rate//2+center_freq),int(1024)) frq=np.fft.fft(samples) freq=np.fft.fftshift(frq) sig_avg = signal.find_peaks(filter(b,a,freq),height=10000) #Detecting Required Amplitude Peaks print('Size:',sig_avg[0].size) #if(tuple!=empty)->then Adjust OffsetCorrection->then append in final[] temp=np.array(sig_avg[0]) if(sig_avg[0].size>0): print("Active Band:{}".format(name)) #temp=np.array(sig_avg[0]) for i in range(0,temp.size): temp[i]=temp[i]*(sample_rate/1000)+center_freq print("Signal Peaks:",temp) final=np.concatenate((final, temp)) return final
def setup(center_freq,sample_rate,final): #PSD_Format def power(val): p=abs(val**2) pdb=math.log10(p) return(pdb) ##SDR Setup Commands power=np.vectorize(power) fname = center_freq/1e9 name=str('{:.3f}Ghz'.format(fname)) sdr = adi.Pluto("ip:192.168.2.1") sdr.sample_rate = int(sample_rate) sdr.rx_rf_bandwidth = int(sample_rate) # filter cutoff, just set it to the same as sample rate sdr.rx_lo = int(center_freq) sdr.rx_buffer_size = 1024 # this is the buffer the Pluto uses to buffer samples ##Sampling Signal at Carrier Freq samples = sdr.rx() freqx=np.linspace(int(-sample_rate//2+center_freq),int(sample_rate//2+center_freq),int(1024)) frq=np.fft.fft(samples) freq=np.fft.fftshift(frq) sig_avg = signal.find_peaks(filter(b,a,freq),height=10000) #Detecting Required Amplitude Peaks print('Size:',sig_avg[0].size) #if(tuple!=empty)->then Adjust OffsetCorrection->then append in final[] temp=np.array(sig_avg[0]) if(sig_avg[0].size>0): print("Active Band:{}".format(name)) #temp=np.array(sig_avg[0]) for i in range(0,temp.size): temp[i]=temp[i]*(sample_rate/1000)+center_freq print("Signal Peaks:",temp) final=np.concatenate((final, temp)) ##Plotting Frequency Response #freq1=power(freq) plt.plot(freq) #plt.plot(freqxfreq) plt.xlim((-10,1030)) plt.ylim((-10000,55000)) plt.xlabel('Frequency(Base Freq+Offset)Hz') plt.ylabel('Amplitude of Signal') plt.title("Frequency Amplitude:"+name) #for Single TimeFrame plt.savefig(name+"-FA.png") #///// plt.show() plt.close() ##Storing Dataframe in .csv format store=pd.DataFrame(freq) # Storing Dataframe using PANDAS -> IMPORT TO TX IN PANDAS store.to_csv(name+"-Dataframe.csv") #issue:Relative plot need abs plot spectogram samplegroup=[] #Ploting Waterfall Diagram for _ in range(1000): samples=sdr.rx() frq=np.fft.fft(samples) freq=np.fft.fftshift(frq) #freq=power(freq) samplegroup.append(abs(freq)) plt.imshow(samplegroup) plt.set_cmap('hot') plt.xlabel('Frequency(Base Freq+offset)Hz') plt.title("Waterfall Diagram:"+name) #for 1000ms TimeFrame plt.savefig(name+"-WD.png") #/// plt.show() plt.close() return final
def __init__(self, msg_queue: Queue): # set up SDR self.sdr = adi.Pluto() self.sdr.rx_lo = int(1090e6) # 1090MHz self.sdr.sample_rate = int( 2e6) # protocol rate of 2 bits per microsecond self.sdr.rx_rf_bandwidth = self.sdr.sample_rate self.sdr.gain_control_mode = 'slow_attack' self.raw_buf = [] self.noise_floor = 1e6 super().__init__(msg_queue)
def setup(center_freq, sample_rate): def power(val): p = abs(val**2) pdb = math.log10(p) return (pdb) power = np.vectorize(power) name = center_freq / 1e9 sdr = adi.Pluto("ip:192.168.2.1") sdr.sample_rate = int(sample_rate) sdr.rx_rf_bandwidth = int( sample_rate) # filter cutoff, just set it to the same as sample rate sdr.rx_lo = int(center_freq) sdr.rx_buffer_size = 1024 # this is the buffer the Pluto uses to buffer samples #print("center_frq:{:.3f}".format(name)) samples = sdr.rx() freqx = np.linspace(int(-sample_rate // 2 + center_freq), int(sample_rate // 2 + center_freq), int(1024)) frq = np.fft.fft(samples) freq = np.fft.fftshift(frq) #freq=power(freq) sig_avg = abs(sum(filter(b, a, freq))) print("Signal Avg:", sig_avg) if sig_avg > threshold: print("Active Band:{}Ghz".format(name)) #freq1=power(freq) plot = filter(b, a, freq) plt.plot(freqx, plot) plt.title("Frequency Amplitude") #for Single TimeFrame plt.show() #plt.savefig("{:.3f}Ghz-FA.png".format(name)) #plt.close() samplegroup = [] for _ in range(1000): samples = sdr.rx() frq = np.fft.fft(samples) freq = np.fft.fftshift(frq) #freq=power(freq) samplegroup.append(abs(freq)) plt.imshow(samplegroup) plt.set_cmap('hot') plt.title("Waterfall Diagram") #for 1000ms TimeFrame plt.savefig("{:.3f}Ghz-WD.png".format(name)) plt.close()
def pluto_setup(tx=True, fc_tx=1e9, cyclic=True, rx=True, fc_rx=1e9): # Create device interface sdr = adi.Pluto('ip:192.168.2.1') # Configure properties # Check to see if tx or rx are asserted sdr.gain_contol_mode_chan0 = "manual" if (tx): # Configure Tx property sdr.tx_lo = int(fc_tx) sdr.tx_cyclic_buffer = cyclic sdr.tx_hardwaregain_chan0 = -40 sdr.tx_rf_bandwidth = int(sdr.sample_rate) if (rx): # Configure Rx properties sdr.rx_lo = int(fc_rx) sdr.rx_rf_bandwidth = int(sdr.sample_rate) sdr.rx_hardwaregain_chan0 = 40 return sdr
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY # RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import time import adi import matplotlib.pyplot as plt import numpy as np from scipy import signal # Create radio rx = adi.ad9434(uri="ip:localhost") tx = adi.Pluto() # Configure tx properties tx.tx_lo = 2000000000 tx.tx_cyclic_buffer = True tx.tx_hardwaregain_chan0 = -30 tx.gain_control_mode_chan0 = "slow_attack" # Create a sinewave waveform fs = int(tx.sample_rate) N = 1024 fc = int(3000000 / (fs / N)) * (fs / N) ts = 1 / float(fs) t = np.arange(0, N * ts, ts) i = np.cos(2 * np.pi * t * fc) * 2**14 q = np.sin(2 * np.pi * t * fc) * 2**14
def __init__(self, SDR_ip='ip:192.168.2.1', LO_freq=2400000000, TX_freq=5810000000, SampleRate=3000000, Rx_gain=30, Averages=1, Taper=1, SymTaper=0, PhaseCal=0, SignalFreq=10525000000, RxGain1=127, RxGain2=127, RxGain3=127, RxGain4=127, Rx1_cal=0, Rx2_cal=0, Rx3_cal=0, Rx4_cal=0): """arguments to this function show up as parameters in GRC""" gr.sync_block.__init__( self, name='ADAR1000 Sweeper', # will show up in GRC in_sig=[], out_sig=[np.complex64, np.float32]) #sdr_address = 'ip:192.168.2.1' # This is the default address for Pluto sdr_address = str(SDR_ip) self.LO_freq = LO_freq # RX LO freq self.TX_freq = TX_freq # TX LO freq self.SampleRate = SampleRate self.Rx_gain = Rx_gain self.Averages = Averages self.Taper = Taper self.SymTaper = SymTaper self.PhaseCal = PhaseCal self.RxGain1 = RxGain1 self.RxGain2 = RxGain2 self.RxGain3 = RxGain3 self.RxGain4 = RxGain4 self.Rx1_cal = Rx1_cal self.Rx2_cal = Rx2_cal self.Rx3_cal = Rx3_cal self.Rx4_cal = Rx4_cal self.spi = spidev.SpiDev() self.spi.open(0, 0) #set bus=0 and device=0 self.spi.max_speed_hz = 500000 self.spi.mode = 0 # The ADDR is set by the address pins on the ADAR1000. This is set by P10 on the eval board. self.ADDR1 = 0x20 # ADDR 0x20 is set by jumpering pins 4 and 6 on P10 #self.ADDR1=0x00 # ADDR 0x00 is set by leaving all jumpers off of P10 #self.ADDR2 = 0x40 ADAR_init(self.spi, self.ADDR1) #ADAR_init(self.spi, self.ADDR1) self.c = 299792458 # speed of light in m/s self.d = 0.015 # element to element spacing of the antenna self.SignalFreq = SignalFreq '''Setup SDR Context and Configure Settings''' import adi #self.sdr=adi.Pluto() #This finds pluto over usb. But communicating with its ip address gives us more flexibility self.sdr = adi.Pluto( uri=sdr_address) #This finds the device at that ip address self.sdr._rxadc.set_kernel_buffers_count( 1 ) #Default is 4 Rx buffers are stored, but we want to change and immediately measure the result, so buffers=1 rx = self.sdr._ctrl.find_channel('voltage0') rx.attrs[ 'quadrature_tracking_en'].value = '0' # set to '1' to enable quadrature tracking self.sdr.sample_rate = int(self.SampleRate) #self.sdr.filter = "/home/pi/Documents/PlutoFilters/samprate_40p0.ftr" #pyadi-iio auto applies filters based on sample rate #self.sdr.rx_rf_bandwidth = int(1000000) #self.sdr.tx_rf_bandwidth = int(500000) self.sdr.rx_buffer_size = int( 1 * 256 ) # We only need a few samples to get the gain. And a small buffer will greatly speed up the sweep. It also reduces the size of our fft freq bins, giving an averaging effect self.sdr.tx_lo = int(self.TX_freq) self.sdr.tx_cyclic_buffer = True self.sdr.tx_buffer_size = int(2**18) self.sdr.tx_hardwaregain_chan0 = -10 #self.sdr.dds_enabled = [1, 1, 1, 1] #DDS generator enable state #self.sdr.dds_frequencies = [0.1e6, 0.1e6, 0.1e6, 0.1e6] #Frequencies of DDSs in Hz #self.sdr.dds_scales = [1, 1, 0, 0] #Scale of DDS signal generators Ranges [0,1] self.sdr.dds_single_tone( int(0.0e6), 0.9, 0 ) # sdr.dds_single_tone(tone_freq_hz, tone_scale_0to1, tx_channel) self.sdr.gain_control_mode_chan0 = "manual" #We must be in manual gain control mode (otherwise we won't see the peaks and nulls!) self.sdr.rx_lo = int(self.LO_freq) self.sdr.rx_hardwaregain_chan0 = int(self.Rx_gain) print(self.sdr)
import time import adi import matplotlib.pyplot as plt import numpy as np from scipy import signal # Create radio sdr = adi.Pluto() sample_rate = 8e6 symbol_rate = 1e6 center_freq = 2.45e9 exponent = 10 N = 2**exponent sdr = adi.Pluto("ip:192.168.2.1") sdr.sample_rate = int(sample_rate) sdr.rx_rf_bandwidth = int(sample_rate) sdr.rx_lo = int(center_freq) sdr.rx_buffer_size = N data = sdr.rx() foffset = 1.0e6 # integral added here #Phase_Offset = 0.0 #t = np.linspace(0.0, (N-1)/(float(sample_rate)),N) t = N * (1 / sample_rate) #t = np.linspace(0.0,(N-1)/(float(sample_rate)),N)
import adi import matplotlib.pyplot as plt import numpy as np from scipy import signal import time # Create radio sdr = adi.Pluto() # Configure properties sdr.rx_rf_bandwidth = 4000000 sdr.rx_lo = 2000000000 sdr.tx_lo = 2000000000 sdr.tx_cyclic_buffer = True sdr.tx_hardwaregain = -30 sdr.gain_control_mode = 'slow_attack' # Read properties print("RX LO %s" % (sdr.rx_lo)) # Create a sinewave waveform fs = int(sdr.sample_rate) fc = 3000000 N = 1024 ts = 1 / float(fs) t = np.arange(0, N * ts, ts) i = np.cos(2 * np.pi * t * fc) * 2**14 q = np.sin(2 * np.pi * t * fc) * 2**14 iq = i + 1j * q # Send data
def connect(self): # This function connects to the SDR using the given IP address. self.sdr = adi.Pluto(self.ip)
#!/usr/bin/python3 import numpy as np import adi import matplotlib.pyplot as plt import matplotlib.animation as animation import time sample_rate = 1.0e6 # 1,500,000 Hz sample rate center_freq = 96.5e6 # 94.5e6 MHz frequency fft_size = 1024 # samples per FFT rx_buf_size = fft_size # samples per PLUTO rx buffer sdr = adi.Pluto('ip:192.168.2.1') sdr.sample_rate = sample_rate #sdr.gain_control_mode = 'manual' #sdr.rx_hardwaregain = 70.0 # dB sdr.gain_control_mode_chan0 = 'slow_attack' sdr.rx_rf_bandwidth = int(sample_rate) sdr.rx_lo = int(center_freq) sdr.rx_buffer_size = rx_buf_size # buffer size to store rcvd samples init_vals = np.empty(fft_size) init_vals.fill(0) # the range of the FFT frequency bins start_freq = center_freq - sample_rate / 2.0 stop_freq = center_freq + sample_rate / 2.0 step = (stop_freq - start_freq) / len(init_vals) # square image
def open(self) -> bool: global import_error_msg if import_error_msg != "": msgs = f"no {module_type} device available, {import_error_msg}" self._error = msgs logger.error(msgs) raise ValueError(msgs) if self._source == "?": self._error = f"Can't scan for {module_type} devices" return False # Create device from specific uri address try: self._sdr = adi.Pluto(uri="ip:" + self._source) # use adi.Pluto() for USB except Exception: msgs = f"failed to connect to {self._source}" self._error = str(msgs) logger.error(msgs) raise ValueError(msgs) logger.debug(f"Connected to {module_type} on {self._source}") self._hw_ppm_compensation = False self.get_ppm() # will set _hw_ppm_compensation logger.info(f"Pluto XO-correction {self.get_ppm()}") # pluto is not consistent in its errors so check ranges here if self._centre_frequency_hz < 70e6 or self._centre_frequency_hz > 6e9: msgs = "centre frequency must be between 70MHz and 6GHz, " msgs += f"attempted {self._centre_frequency_hz / 1e6:0.6}MHz, " self._centre_frequency_hz = 100.0e6 msgs += f"set {self._centre_frequency_hz / 1e6:0.6}MHz. \n" self._error = msgs logger.error(msgs) # pluto does raise errors for sample rate though, but we check so we don't raise errors if self._sample_rate_sps < 521e3 or self._sample_rate_sps > 61e6: msgs = "sample rate must be between 521kH and 61MHz, " msgs += f"attempted {self._sample_rate_sps / 1e6:0.6}MHz, " self._sample_rate_sps = 1.0e6 msgs += f"set {self._sample_rate_sps / 1e6:0.6}MHz. " self._error += msgs try: self._sdr.rx_buffer_size = self._read_block_size # sets how many complex samples we get each rx() # don't correct sample rates for ppm error, very small error and XO correction may be doing it for us # NOTE I have seen set_sample_rate_sps() fail for some reason, exception raised - invalid parameter # self._set_iio_attr("out", "voltage_filter_fir_en", False, 1) in ad936x.py # which calls the following which raises the exception, all looked good under debugger # channel.attrs[attr_name].value = str(value) in attribute.py # # reboot of windows, unplug/replug pluto and general magic incantations and it worked again! # This was on Windows10 self.set_sample_rate_sps(self._sample_rate_sps) self.set_centre_frequency_hz(self._centre_frequency_hz) self.set_bandwidth_hz(self._bandwidth_hz) # AGC mode will depend on environment, lots of bursting signals or lots of continuous signals self.set_gain_mode( self._gain_mode ) # self._sdr.gain_control_mode_chan0 = self._gain_mode self.set_gain(40) except Exception as err: msgs = f"problem with initialisation of {module_type}: {err}" self._error += f"str(msgs),\n" logger.error(msgs) raise ValueError(msgs) logger.debug( f"{module_type}: {self._centre_frequency_hz / 1e6:.6}MHz @ {self._sample_rate_sps / 1e6:.3f}Msps" ) self._connected = True return self._connected
def test_pluto(iio_uri): dev = adi.Pluto(iio_uri) assert dev del dev
def __init__(self, var): self.sdr = adi.Pluto(pluto_connection)
def main_qam_tx(debug: bool = False, mic_used: bool = False, hw_used: bool = False, dry_run: bool = True): from Record_Play.Recorder import Recorder from QAM.ModulatorQAM import ModulatorQAM from time import sleep if debug == True: from scipy import signal import numpy as np import matplotlib.pyplot as plt if dry_run == True: hw_used = False mic_used if hw_used == True: try: import adi if debug == True: print("ADI PLUTO lib successfully imported.") sdr = adi.Pluto() # TODO: Change to int as conversion introduces rounding errors sdr.tx_lo = int(2e9) # 2000000000 # TODONE: remove cyclic buffer as it continously sends single packet/framebuffer sdr.tx_cyclic_buffer = False sdr.tx_hardwaregain = -10 sdr.gain_control_mode = "slow_attack" fs = int(sdr.sample_rate) if debug == True: print("PLUTO sample rate: " + str(fs)) except: print('Error while importing Analog Device\'s PLUTO library\n') if mic_used == True: try: # Recorder class is used to open input device (microphone) # TODO: automatically find correct `input_device_index` rec = Recorder(input_device_index=1, frames_per_buffer=1024, channels=1, bit_rate=44100) if debug == True: rec.get_mic_info() rec.start() # TODO: caught exception when bad index is chosen # INFO: for demonstration, mic is turned off except: print('Ex: error while opening input stream\n') # Modulator class transforms microphone data into QAM modulated packets # TODO: calculate correct sample rate which is # sum of data rate(bit_rate) + overhead created by header and footer mod = ModulatorQAM(carrierFreq=__CARRIER_FREQ, upsamplingFactor=8, sampleRate=__SAMPLING_RATE) if mic_used == True and hw_used == True: # Starting gathering voice samples. Data is returned by method get_data() try: print('Transmission Started!') while True: if rec.isEmpty(): # sleep time related to acq of single voice frame sleep(44100 / 1024) else: # obtaining samples from microphone soundFrame = rec.get_data() # modulating data # TODO: add proper header and trailer to data modulatedFrame = mod.modulateQAM16( soundFrame, isSignalUpconverted=True, debug=debug) # send data to pluto sdr.tx(modulatedFrame) except KeyboardInterrupt: print('Transmission Ended!') rec.exit() elif debug == True: try: from QAM_UT.ModulatorQAM_UT import __RANDOM_1024_INT16 as soundFrame # from Synchronization_ST.FrameSynchronization_ST import __START_HEADER # from Synchronization_ST.FrameSynchronization_ST import __END_HEADER print("Dry run. Showing plots...") while True: modulatedFrame = mod.modulateQAM16( np.concatenate(( np.frombuffer(np.asarray(__START_HEADER) * 2**15, dtype=np.int16), soundFrame[:], # TODO: change number of samples by cmd option np.frombuffer(np.asarray(__END_HEADER) * 2**15, dtype=np.int16))), isSignalUpconverted=True, debug=True) break except KeyboardInterrupt: print('Dry Run Ended!') # TODO: show just plots print(modulatedFrame[:100]) # plt.plot(np.real(modulatedFrame)) # plt.show() pass else: NameError("asdasasd")