aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArturs Artamonovs <dos21h@gmail.com>2023-03-22 22:55:37 +0000
committerArturs Artamonovs <dos21h@gmail.com>2023-03-22 22:55:37 +0000
commite74679711bb9051080e7f11e16fe474fb6b56e60 (patch)
treebc64b1027e1c38e01334a5523d4a71ef291b8ea1
parent9c7aa6dc844b92c93734fd62bb0cde561998012a (diff)
downloadpyairspyhf-e74679711bb9051080e7f11e16fe474fb6b56e60.tar.gz
pyairspyhf-e74679711bb9051080e7f11e16fe474fb6b56e60.zip
airspyhf_waterfall shows first signs of working
-rw-r--r--airspyhf/airspyhf.py31
-rwxr-xr-xairspyhf_power.py0
-rwxr-xr-xairspyhf_rx.py2
-rwxr-xr-xairspyhf_shedule.py54
-rw-r--r--airspyhf_waterfall.py226
5 files changed, 307 insertions, 6 deletions
diff --git a/airspyhf/airspyhf.py b/airspyhf/airspyhf.py
index 562d8e5..5a26fa3 100644
--- a/airspyhf/airspyhf.py
+++ b/airspyhf/airspyhf.py
@@ -5,6 +5,7 @@ class AirSpyHF:
dev_p = airspyhf_device_t_p(None)
sample_rates = []
initalized = False
+ cur_freq = 0
def __init__(self,):
#self.dev_p = airspyhf_device_t_p(None)
pass
@@ -54,6 +55,7 @@ class AirSpyHF:
def set_samplerate(self, samplerate:int):
if not self.initalized:
+ print("airspy not initalized")
return -1
if self.sample_rates == []:
self.get_samplerates()
@@ -70,42 +72,66 @@ class AirSpyHF:
def set_hf_agc(self,flag):
if not self.initalized:
+ print("airspy not initalized")
return -1
ret = libairspyhf.airspyhf_set_hf_agc(self.dev_p, flag)
return ret
def set_hf_agc_threshold(self,flag):
if not self.initalized:
+ print("airspy not initalized")
return -1
ret = libairspyhf.airspyhf_set_hf_agc_threshold(self.dev_p, flag)
return ret
def set_hf_att(self, value):
if not self.initalized:
+ print("airspy not initalized")
return -1
ret = libairspyhf.airspyhf_set_hf_att(self.dev_p, value)
return ret
def set_hf_lna(self,flag):
if not self.initalized:
+ print("airspy not initalized")
return -1
ret = libairspyhf.airspyhf_set_hf_lna(self.dev_p, flag)
return ret
- def start(self, read_samples):
+ def set_frequency(self,freq:int):
if not self.initalized:
+ print("airspy not initalized")
return -1
- ret = libairspyhf.airspyhf_start(self.dev_p, airspyhf_sample_block_cb_fn(read_samples), None)
+ ret = libairspyhf.airspyhf_set_freq(self.dev_p, int(freq))
+ if ret != 0:
+ return -1
+ self.cur_freq = int(freq)
+ return 0
+
+ #def get_frequency(self,freq:int):
+ # return self.cur_freq
+
+ def start(self, read_samples_cb):
+ if not self.initalized:
+ print("airspy not initalized")
+ return -1
+ #read_samples()
+ #ret = libairspyhf.airspyhf_start(self.dev_p, airspyhf_sample_block_cb_fn(read_samples), None)
+ ret = libairspyhf.airspyhf_start(self.dev_p, read_samples_cb, None)
if ret != 0:
print(f"airspyhf_start ret={ret}")
+ return -1
+ return 0
def is_streaming(self):
if not self.initalized:
+ print("airspy not initalized")
return -1
return libairspyhf.airspyhf_is_streaming(self.dev_p)
def stop(self):
if not self.initalized:
+ print("airspy not initalized")
return -1
ret = libairspyhf.airspyhf_stop(self.dev_p)
if ret != 0:
@@ -115,6 +141,7 @@ class AirSpyHF:
def close(self):
if not self.initalized:
+ print("airspy not initalized")
return -1
ret = libairspyhf.close(self.dev_p)
if ret != 0:
diff --git a/airspyhf_power.py b/airspyhf_power.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/airspyhf_power.py
diff --git a/airspyhf_rx.py b/airspyhf_rx.py
index 2ae35f7..7d55c35 100755
--- a/airspyhf_rx.py
+++ b/airspyhf_rx.py
@@ -108,7 +108,7 @@ def read_samples(transfer):
return 0
-read_samples_cb = airspyhf_sample_block_cb_fn(read_samples)
+#read_samples_cb = airspyhf_sample_block_cb_fn(read_samples)
ret = libairspyhf.airspyhf_start(dev_p, airspyhf_sample_block_cb_fn(read_samples), None)
diff --git a/airspyhf_shedule.py b/airspyhf_shedule.py
index 03139bc..a82b1b4 100755
--- a/airspyhf_shedule.py
+++ b/airspyhf_shedule.py
@@ -53,11 +53,59 @@ class Station:
self.duration = time_in_sec
if "day" in config:
- self.day = config["day"]
+ self.day = []
+ if config["day"] == "every":
+ self.day = [1,2,3,4,5,6,7]
+ else:
+ #Supported
+ # lowercase mon,tue,wen,thu,fri,sat,sun
+ days = config["day"].lower().split(",")
+ if "mon" in days:
+ self.day.append(1)
+ if "tur" in days:
+ self.day.append(2)
+ if "wen" in days:
+ self.day.append(3)
+ if "thu" in days:
+ self.day.append(4)
+ if "fri" in days:
+ self.day.append(5)
+ if "sat" in days:
+ self.day.append(6)
+ if "sun" in days:
+ self.day.append(7)
if "month" in config:
- self.month = config["month"]
-
+ self.month = []
+ #Supported
+ #jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec
+ month = config["month"].lower().split(",")
+ if "jan" in month:
+ self.month.append(1)
+ if "feb" in month:
+ self.month.append(2)
+ if "mar" in month:
+ self.month.append(3)
+ if "apr" in month:
+ self.month.append(4)
+ if "may" in month:
+ self.month.append(5)
+ if "jun" in month:
+ self.month.append(6)
+ if "jul" in month:
+ self.month.append(7)
+ if "aug" in month:
+ self.month.append(8)
+ if "sep" in month:
+ self.month.append(9)
+ if "oct" in month:
+ self.month.append(10)
+ if "nov" in month:
+ self.month.append(11)
+ if "dec" in month:
+ self.month.append(12)
+ def __str__(self):
+ return f"{self.name} freq:{self.frequency} time:{self.time} day:{self.day} month:{self.month}"
class StationCollection:
stations = []
diff --git a/airspyhf_waterfall.py b/airspyhf_waterfall.py
new file mode 100644
index 0000000..fc1de56
--- /dev/null
+++ b/airspyhf_waterfall.py
@@ -0,0 +1,226 @@
+import os
+import sys
+import math
+
+import airspyhf
+
+import matplotlib
+import numpy
+import pylab
+import time
+import threading
+
+import pygame
+from pygame import gfxdraw
+
+CENTER_FREQ = 101000000
+SAMPLE_RATE = 196e3
+SAMPLE_NUM = 2048
+
+SCREEN_X = 1025
+SCREEN_Y = 320
+
+MOVE_STEP = int(SAMPLE_RATE/2)
+
+sample_buf_lock = threading.Lock()
+
+# init AIRSPY and if no then go out
+airspy = airspyhf.AirSpyHF()
+if airspy.open(device_index=0) == -1:
+ print("Cant open airspyhf device")
+ sys.exit(1)
+
+# config rtlsdr device
+airspy.set_samplerate(SAMPLE_RATE)
+airspy.set_frequency(CENTER_FREQ)
+airspy.set_hf_agc(1)
+airspy.set_hf_agc_threshold(0)
+airspy.set_hf_lna(1)
+
+
+def iq_abs(c):
+ return (math.sqrt((c.real ** 2 + c.imag ** 2)))
+
+
+# point should be normalised to 0.0 ... 1.0
+def color_normalise(point):
+ ret = (255, 0, 0)
+ # blue
+ if (point < 0.3):
+ ret = (0, 0, int(point * 255 * 3.3))
+ # yello
+ elif (point < 0.7):
+ ret = (0, int((point - 0.3) * 255 * 2.5), 0)
+ # red
+ elif (point <= 1.0):
+ ret = (int((point - 0.7) * 255 * 3.3), 0, 0)
+ else:
+ # print "Color Error ", point
+ pass
+ return ret
+
+
+def color_mapping(x):
+ "assumes -50 to 0 range, returns color"
+ r = int((x + 70) * 255 // 70)
+ r = max(0, r)
+ r = min(255, r)
+ return (r, r, 100)
+
+
+# def draw_Hz( surface, x, y, hz ):
+
+
+arr = [[0 for i in range(0, SCREEN_X)] for j in range(0, SCREEN_Y)]
+
+# init all pygame modules audio,video and more
+pygame.init()
+
+# [NEW] creates screen surface using constants
+screen = pygame.display.set_mode((SCREEN_X, SCREEN_Y))
+
+#samples = rtl.read_samples(SAMPLE_NUM)
+sample_buffer = []
+def read_samples(transfer):
+ global sample_buffer
+ #print("callback")
+ #if sample_buf_lock.locked():
+ # print("Buffer locked")
+ # return 0
+ #sample_buf_lock.acquire()
+ #print("Python call back")
+ t = transfer.contents
+ bytes_to_write = t.sample_count * 4 * 2
+ #print("Received %d samples"%(t.sample_count))
+ rx_buffer = t.samples
+ #print(f"{bytes_to_write} bytes receieved")
+ #sample_buffer.append(rx_buffer)
+ for i in range(0,t.sample_count):
+ d_re = t.samples[i].re
+ d_im = t.samples[i].im
+ sample_buffer.append(math.sqrt(d_re*d_re+d_im*d_im))
+ #data = struct.pack("<f",d_re) # FIX ?!
+ #wave_file.writeframesraw(data)
+ #data = struct.pack("<f", d_im) # FIX ?!
+ #wave_file.writeframesraw(data)
+ #print("End call back")
+ #sample_buf_lock.release()
+ return 0
+
+def get_samples(num=1024):
+ global sample_buffer
+ buf_size = len(sample_buffer)
+
+ if buf_size < num:
+ print("sample buffer small")
+ return [1]*num
+ print("getting stuff ", buf_size)
+ #while sample_buf_lock.locked():
+ # time.sleep(0.1)
+ samples = sample_buffer[:int(buf_size/2)]
+ del sample_buffer[:int(buf_size/2)]
+ return samples
+ #if len(samples) == num:
+ # sample_buffer = []
+ # return samples
+ #if len(samples) > num:
+ # arr = []
+ # times = len(samples)/num
+ # for i in range(0, num):
+ # avg = numpy.average(samples[times*num:times*num+times-1])
+ # arr.append(avg)
+ # return arr
+ #else:
+ # print("Error in get_samples")
+ # return []
+ return []
+
+read_samples_cb = airspyhf.airspyhf_sample_block_cb_fn(read_samples)
+airspy.start(read_samples_cb)
+
+run = True
+line = 0
+while run and airspy.is_streaming():
+
+ print("Loop tick")
+
+ # check for all events that where ocure
+ for event in pygame.event.get():
+ # if some one clicked on close button
+ if event.type == pygame.QUIT:
+ # terminate programm
+ run = False
+ # don't waste your time by waiting while event loop will end
+ break
+ elif event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_LEFT:
+ print("Left")
+ #rtl.center_freq -= MOVE_STEP
+ airspy.set_frequency(airspy.cur_freq - MOVE_STEP)
+ #print("Center freq: ", rtl.center_freq, " Hz")
+ elif event.key == pygame.K_RIGHT:
+ print("Right")
+ #rtl.center_freq += MOVE_STEP
+ #print("Center freq: ", rtl.center_freq, " Hz")
+ airspy.set_frequency(airspy.cur_freq + MOVE_STEP)
+
+ width = SCREEN_X
+ height = SCREEN_Y
+
+ samples = get_samples(SAMPLE_NUM)
+ if samples == []:
+ print("sample buffer is empty")
+ time.sleep(1)
+ continue
+ #print(samples)
+ spect = numpy.fft.fft(samples,n=SAMPLE_NUM)
+
+ spect = spect[0:int((len(spect) / 2))]
+
+ # (1/(Fs*N)) * abs(xdft).^2;
+ spect_n = [(1.0 / (SAMPLE_NUM * len(spect))) * iq_abs(x) ** 2 for x in spect]
+ spect_n = (10 * numpy.log10(spect_n)).tolist()
+
+ #print(spect_n)
+
+ # total data size
+ spect_len = len(spect_n)
+ #print(spect_len)
+ # calculate amount spect points per pixel without rounding
+ pixel_width = int(spect_len / SCREEN_X + 1)
+ #print(pixel_width)
+ pixel_steps = int(spect_len / pixel_width)
+ #print(pixel_steps)
+ #print(spect_n)
+ for step in range(0, pixel_steps):
+ avg = 0.0
+ for i in range(0, pixel_width):
+ avg += spect_n[step * pixel_width + i]
+ avg /= pixel_width
+ if math.isinf(avg):
+ avg = -1000
+
+ # print avg
+ # gfxdraw.pixel( screen, step, line, color_normalise((100-abs(avg))/10))
+ gfxdraw.pixel(screen, step, line, color_mapping(int(avg)))
+
+ # draw central freq
+ #font = pygame.font.Font(None, 20)
+ #text = font.render(str(rtl.center_freq / 1e6), 1, (200, 30, 30), (0, 0, 0))
+ #screen.blit(text, (SCREEN_X / 2, SCREEN_Y - 20))
+ #text = font.render(str((rtl.center_freq + SAMPLE_RATE / 2) / 1e6), 1, (200, 30, 30), (0, 0, 0))
+ #screen.blit(text, (SCREEN_X - 40, SCREEN_Y - 20))
+ #text = font.render(str((rtl.center_freq - SAMPLE_RATE / 2) / 1e6), 1, (200, 30, 30), (0, 0, 0))
+ #screen.blit(text, (20, SCREEN_Y - 20))
+
+ pygame.display.flip()
+ line += 1
+ if (line > SCREEN_Y):
+ line = 0
+ time.sleep(0.1)
+
+pygame.quit()
+
+airspy.stop()
+airspy.close()
+