|
| 1 | +## This is a comparison of SCAN and SCANRAW to work out some errors in the decode process |
| 2 | +# given that the tinySA is still running during the read, we don't expect SCAN and SCANRAW |
| 3 | +# to be exactly the same, but they should be relatively similar values when SCANRAW is decoded |
| 4 | + |
| 5 | + |
| 6 | +# import tinySA library |
| 7 | +# (NOTE: check library path relative to script path) |
| 8 | +from src.tinySA_python import tinySA |
| 9 | + |
| 10 | + |
| 11 | +# imports FOR THE EXAMPLE |
| 12 | +import numpy as np |
| 13 | +import matplotlib.pyplot as plt |
| 14 | +import struct |
| 15 | + |
| 16 | +def convert_data_to_arrays(start, stop, pts, data): |
| 17 | + # FOR PLOTTING |
| 18 | + # using the start and stop frequencies, and the number of points, |
| 19 | + |
| 20 | + freq_arr = np.linspace(start, stop, pts) # note that the decimals might go out to many places. |
| 21 | + # you can truncate this because its only used |
| 22 | + # for plotting in this example |
| 23 | + |
| 24 | + # As of the Jan. 2024 build in some data returned with SWEEP or SCAN calls there is error data. |
| 25 | + # https://groups.io/g/tinysa/topic/tinasa_ultra_sweep_command/104194367 |
| 26 | + # this shows up as "-:.000000e+01". |
| 27 | + # TEMP fix - replace the colon character with a -10. This puts the 'filled in' points around the noise floor. |
| 28 | + # more advanced filtering should be applied for actual analysis. |
| 29 | + data1 =bytearray(data.replace(b"-:.0", b"-10.0")) |
| 30 | + |
| 31 | + # get both values in each row returned (for reference) |
| 32 | + #data_arr = [list(map(float, line.split())) for line in data.decode('utf-8').split('\n') if line.strip()] |
| 33 | + |
| 34 | + # get first value in each returned row |
| 35 | + data_arr = [float(line.split()[0]) for line in data1.decode('utf-8').split('\n') if line.strip()] |
| 36 | + |
| 37 | + return freq_arr, data_arr |
| 38 | + |
| 39 | + |
| 40 | +# create a new tinySA object |
| 41 | +tsa = tinySA() |
| 42 | +# attempt to autoconnect |
| 43 | +found_bool, connected_bool = tsa.autoconnect() |
| 44 | + |
| 45 | +# if port closed, then return error message |
| 46 | +if connected_bool == False: |
| 47 | + print("ERROR: could not connect to port") |
| 48 | +else: # if port found and connected, then complete task(s) and disconnect |
| 49 | + # detailed messages turned on |
| 50 | + tsa.set_verbose(True) |
| 51 | + |
| 52 | + # set scan values |
| 53 | + start = int(150e6) # 150 MHz |
| 54 | + stop = int(500e6) # 500 MHz |
| 55 | + pts = 450 # for tinySA Ultra |
| 56 | + outmask = 2 # get measured data (y axis) |
| 57 | + # scan raw call - reads until end of stream |
| 58 | + # this CAN be run in a loop. the limiting factor is time to plot. |
| 59 | + |
| 60 | + # SCAN |
| 61 | + scan_data_bytes = tsa.scan(start, stop, pts, outmask) |
| 62 | + |
| 63 | + # SCAN RAW |
| 64 | + scanraw_data_bytes = tsa.scan_raw(start, stop, pts, outmask) |
| 65 | + |
| 66 | + # disconnect because we don't need the tinySA to process data |
| 67 | + tsa.disconnect() |
| 68 | + |
| 69 | + # process the SCAN data (this is already in dBm) |
| 70 | + # convert data to 2 arrays for X and Y |
| 71 | + freq_arr, data_arr = convert_data_to_arrays(start, stop, pts, scan_data_bytes) |
| 72 | + |
| 73 | + # PROCESS SCANRAW into an array & reuse the FREQ_ARR value |
| 74 | + # remove the intro curly brace ({) |
| 75 | + bin_scanraw = scanraw_data_bytes[1:] #skip the first char because it's the raminaing curly brace |
| 76 | + # use struct.unpack() because of the repeating pattern |
| 77 | + # <: indicates little-endian byte order, meaning the least significant byte is stored first |
| 78 | + # 'xH'*pts: a repetition of the format 'xH' once per point. |
| 79 | + # 'x': represents a pad byte, which is ignored |
| 80 | + # 'H': represents an unsigned short integer (2 bytes) |
| 81 | + processed_scanraw = struct.unpack( '<' + 'xH'*pts, bin_scanraw ) # ignore trailing '}ch> ' |
| 82 | + processed_scanraw = np.array(processed_scanraw, dtype=np.uint16 ).reshape(-1, 1) #unit8 has overflow error |
| 83 | + |
| 84 | + # CONVERT to dBm Power |
| 85 | + # take the processed binary data and convert it to dBm. |
| 86 | + # The equation is from tinySA.org & official documentation |
| 87 | + SCALE_FACTOR = 174 # tinySA Basic: 128, tinySA Ultra and newer is 174 |
| 88 | + dBm_data = processed_scanraw / 32 - SCALE_FACTOR |
| 89 | + print(dBm_data) |
| 90 | + |
| 91 | + # plot |
| 92 | + plt.plot(freq_arr, data_arr, label= 'SCAN data') |
| 93 | + plt.plot(freq_arr, dBm_data, label= 'SCANRAW data') |
| 94 | + plt.xlabel("frequency (hz)") |
| 95 | + plt.ylabel("measured data (dBm)") |
| 96 | + plt.title("tinySA SCAN and SCANRAW data") |
| 97 | + plt.legend() |
| 98 | + plt.show() |
| 99 | + |
0 commit comments