Replace TCP with UDP. (#1)

* replace tcp with udp
* remove python grc
pull/3/head v1.1
Luigi Cruz 2021-05-02 21:36:21 -06:00 zatwierdzone przez GitHub
rodzic bf54ea7286
commit 21d4f22c8b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
6 zmienionych plików z 90 dodań i 397 usunięć

Wyświetl plik

@ -9,6 +9,7 @@ target_link_libraries(piccolosdr LINK_PUBLIC
hardware_adc hardware_adc
hardware_dma hardware_dma
hardware_irq hardware_irq
pico_sync
) )
pico_add_extra_outputs(piccolosdr) pico_add_extra_outputs(piccolosdr)

Wyświetl plik

@ -7,40 +7,36 @@
#include "hardware/irq.h" #include "hardware/irq.h"
#include "usb_network.h" #include "usb_network.h"
bool streaming = false; uint data_ovf;
struct tcp_pcb* client; uint data_dma;
bool data_val;
bool streaming;
struct repeating_timer timer; struct repeating_timer timer;
//#define DEBUG
#define CAPTURE_CHANNEL 0 #define CAPTURE_CHANNEL 0
#define CAPTURE_DEPTH 500 #define CAPTURE_DEPTH 1472
uint dma_chan_a, dma_chan_b; uint dma_chan_a, dma_chan_b;
uint8_t capture_buf_a[CAPTURE_DEPTH]; struct pbuf *pbuf_a, *pbuf_b;
uint8_t capture_buf_b[CAPTURE_DEPTH];
void dma_handler(uint8_t* buffer, int id) { static void dma_handler(uint id) {
#ifdef DEBUG if (data_val) {
char str[64]; data_ovf += 1;
int len = sprintf(str, "DMA IRQ %d [%d %d ... %d]\n", id, buffer[0], buffer[1], buffer[CAPTURE_DEPTH-1]); }
tcp_write(client, str, len, 0); data_dma = id;
tcp_output(client); data_val = true;
#else
tcp_write(client, buffer, CAPTURE_DEPTH, 0x01);
tcp_output(client);
#endif
} }
void dma_handler_a() { static void dma_handler_a() {
dma_handler((uint8_t*)&capture_buf_a, 0); dma_handler(0);
dma_channel_set_write_addr(dma_chan_a, pbuf_a->payload, false);
dma_hw->ints0 = 1u << dma_chan_a; dma_hw->ints0 = 1u << dma_chan_a;
dma_channel_set_write_addr(dma_chan_a, &capture_buf_a, false);
} }
void dma_handler_b() { static void dma_handler_b() {
dma_handler((uint8_t*)&capture_buf_b, 1); dma_handler(1);
dma_channel_set_write_addr(dma_chan_b, pbuf_b->payload, false);
dma_hw->ints1 = 1u << dma_chan_b; dma_hw->ints1 = 1u << dma_chan_b;
dma_channel_set_write_addr(dma_chan_b, &capture_buf_b, false);
} }
static void init_adc_dma_chain() { static void init_adc_dma_chain() {
@ -80,14 +76,14 @@ static void init_adc_dma_chain() {
channel_config_set_chain_to(&dma_cfg_b, dma_chan_a); channel_config_set_chain_to(&dma_cfg_b, dma_chan_a);
dma_channel_configure(dma_chan_a, &dma_cfg_a, dma_channel_configure(dma_chan_a, &dma_cfg_a,
capture_buf_a, // dst pbuf_a->payload,// dst
&adc_hw->fifo, // src &adc_hw->fifo, // src
CAPTURE_DEPTH, // transfer count CAPTURE_DEPTH, // transfer count
true // start now true // start now
); );
dma_channel_configure(dma_chan_b, &dma_cfg_b, dma_channel_configure(dma_chan_b, &dma_cfg_b,
capture_buf_b, // dst pbuf_b->payload, // dst
&adc_hw->fifo, // src &adc_hw->fifo, // src
CAPTURE_DEPTH, // transfer count CAPTURE_DEPTH, // transfer count
false // start now false // start now
@ -106,70 +102,38 @@ static void init_adc_dma_chain() {
adc_run(false); adc_run(false);
} }
static void start_stream() { static void start_stream(struct tcp_pcb *pcb) {
dma_channel_set_write_addr(dma_chan_a, &capture_buf_a, true); if (streaming) {
dma_channel_set_write_addr(dma_chan_b, &capture_buf_b, false); return;
adc_run(true); }
streaming = true;
data_ovf = 0;
data_dma = 0;
data_val = false;
streaming = true;
dma_channel_set_write_addr(dma_chan_a, pbuf_a->payload, true);
dma_channel_set_write_addr(dma_chan_b, pbuf_b->payload, false);
adc_run(true);
}
static void stop_stream(struct tcp_pcb *pcb) {
if (!streaming) {
return;
} }
static void stop_stream() {
adc_run(false); adc_run(false);
adc_fifo_drain(); adc_fifo_drain();
dma_channel_set_write_addr(dma_chan_a, &capture_buf_a, false); dma_channel_set_write_addr(dma_chan_a, pbuf_a->payload, false);
dma_channel_set_write_addr(dma_chan_b, &capture_buf_b, false); dma_channel_set_write_addr(dma_chan_b, pbuf_b->payload, false);
data_ovf = 0;
data_dma = 0;
data_val = false;
streaming = false; streaming = false;
} }
static void srv_close(struct tcp_pcb *pcb){ static bool led_timer(struct repeating_timer *t) {
stop_stream();
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_close(pcb);
}
static void srv_err(void *arg, err_t err) {
// Probably an indication that the client connection went kaput! Stopping stream...
srv_close(client);
}
static err_t srv_receive(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {
if (err != ERR_OK && p != NULL) {
goto exception;
}
tcp_recved(pcb, p->tot_len);
tcp_sent(pcb, NULL);
// The connection is closed if the client sends "X".
if (((char*)p->payload)[0] == 'X') {
srv_close(pcb);
}
exception:
pbuf_free(p);
return err;
}
static err_t srv_accept(void * arg, struct tcp_pcb * pcb, err_t err) {
if (err != ERR_OK) {
return err;
}
tcp_setprio(pcb, TCP_PRIO_MIN);
tcp_recv(pcb, srv_receive);
tcp_err(pcb, srv_err);
tcp_poll(pcb, NULL, 4);
client = pcb;
start_stream();
return err;
}
bool led_timer(struct repeating_timer *t) {
int status = 1; int status = 1;
if (streaming) { if (streaming) {
status = !gpio_get(PICO_DEFAULT_LED_PIN); status = !gpio_get(PICO_DEFAULT_LED_PIN);
@ -183,27 +147,45 @@ int main(void) {
gpio_init(PICO_DEFAULT_LED_PIN); gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
// Init ADC DMA chain.
init_adc_dma_chain();
// Init network stack. // Init network stack.
network_init(); network_init();
// Start TCP server. // Allocate zero-copy memory for DMA and UDP.
struct tcp_pcb* pcb = tcp_new(); pbuf_a = pbuf_alloc(PBUF_RAW, CAPTURE_DEPTH, PBUF_RAM);
pcb->so_options |= SOF_KEEPALIVE; pbuf_b = pbuf_alloc(PBUF_RAW, CAPTURE_DEPTH, PBUF_RAM);
pcb->keep_intvl = 75000000;
tcp_bind(pcb, IP_ADDR_ANY, 7777);
// Start listening for connections. if (pbuf_a == NULL && pbuf_b == NULL) {
struct tcp_pcb* listen = tcp_listen(pcb); return 1;
tcp_accept(listen, srv_accept); }
// Init ADC DMA chain.
init_adc_dma_chain();
// Start data UDP port.
ip_addr_t client;
struct udp_pcb* dpcb = udp_new();
IP4_ADDR(&client, 192, 168, 7, 2);
udp_connect(dpcb, &client, 7778);
// Start LED indicator. // Start LED indicator.
add_repeating_timer_ms(250, led_timer, NULL, &timer); add_repeating_timer_ms(250, led_timer, NULL, &timer);
// Start stream right away.
start_stream(NULL);
// Listen to events. // Listen to events.
while (1) { while (1) {
if (data_val && streaming) {
if (data_dma == 0) {
udp_send(dpcb, pbuf_a);
}
if (data_dma == 1) {
udp_send(dpcb, pbuf_b);
}
data_val = false;
}
network_step(); network_step();
} }

Wyświetl plik

@ -77,42 +77,27 @@ blocks:
coordinate: [403, 167] coordinate: [403, 167]
rotation: 0 rotation: 0
state: true state: true
- name: blocks_vector_to_stream_0 - name: grnet_udp_source_0
id: blocks_vector_to_stream id: grnet_udp_source
parameters: parameters:
affinity: '' affinity: ''
alias: '' alias: ''
comment: '' comment: ''
header: '0'
ipv6: 'False'
maxoutbuf: '0' maxoutbuf: '0'
minoutbuf: '0' minoutbuf: '0'
num_items: '500' notifyMissed: 'False'
payloadsize: '1472'
port: '7778'
srcZeros: 'False'
type: byte type: byte
vlen: '1' vlen: '1'
states: states:
bus_sink: false bus_sink: false
bus_source: false bus_source: false
bus_structure: null bus_structure: null
coordinate: [211, 167] coordinate: [37, 173]
rotation: 0
state: true
- name: grnet_tcp_source_0
id: grnet_tcp_source
parameters:
addr: 192.168.7.1
affinity: ''
alias: ''
comment: ''
maxoutbuf: '0'
minoutbuf: '0'
port: '7777'
server: 'False'
type: byte
vlen: '500'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [22, 140]
rotation: 0 rotation: 0
state: true state: true
- name: qtgui_freq_sink_x_0 - name: qtgui_freq_sink_x_0
@ -359,8 +344,7 @@ connections:
- [blocks_multiply_const_vxx_0, '0', qtgui_time_sink_x_0, '0'] - [blocks_multiply_const_vxx_0, '0', qtgui_time_sink_x_0, '0']
- [blocks_multiply_const_vxx_0, '0', qtgui_waterfall_sink_x_0, '0'] - [blocks_multiply_const_vxx_0, '0', qtgui_waterfall_sink_x_0, '0']
- [blocks_uchar_to_float_0, '0', blocks_multiply_const_vxx_0, '0'] - [blocks_uchar_to_float_0, '0', blocks_multiply_const_vxx_0, '0']
- [blocks_vector_to_stream_0, '0', blocks_uchar_to_float_0, '0'] - [grnet_udp_source_0, '0', blocks_uchar_to_float_0, '0']
- [grnet_tcp_source_0, '0', blocks_vector_to_stream_0, '0']
metadata: metadata:
file_format: 1 file_format: 1

Wyświetl plik

@ -1,275 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# SPDX-License-Identifier: GPL-3.0
#
# GNU Radio Python Flow Graph
# Title: PiccoloSDR
# Author: Luigi Cruz
# Copyright: MIT
# GNU Radio version: 3.8.2.0
from distutils.version import StrictVersion
if __name__ == '__main__':
import ctypes
import sys
if sys.platform.startswith('linux'):
try:
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
except:
print("Warning: failed to XInitThreads()")
from PyQt5 import Qt
from gnuradio import qtgui
from gnuradio.filter import firdes
import sip
from gnuradio import blocks
from gnuradio import gr
import sys
import signal
from argparse import ArgumentParser
from gnuradio.eng_arg import eng_float, intx
from gnuradio import eng_notation
import grnet
from gnuradio import qtgui
class piccolosdr(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "PiccoloSDR")
Qt.QWidget.__init__(self)
self.setWindowTitle("PiccoloSDR")
qtgui.util.check_set_qss()
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except:
pass
self.top_scroll_layout = Qt.QVBoxLayout()
self.setLayout(self.top_scroll_layout)
self.top_scroll = Qt.QScrollArea()
self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
self.top_scroll_layout.addWidget(self.top_scroll)
self.top_scroll.setWidgetResizable(True)
self.top_widget = Qt.QWidget()
self.top_scroll.setWidget(self.top_widget)
self.top_layout = Qt.QVBoxLayout(self.top_widget)
self.top_grid_layout = Qt.QGridLayout()
self.top_layout.addLayout(self.top_grid_layout)
self.settings = Qt.QSettings("GNU Radio", "piccolosdr")
try:
if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
self.restoreGeometry(self.settings.value("geometry").toByteArray())
else:
self.restoreGeometry(self.settings.value("geometry"))
except:
pass
##################################################
# Variables
##################################################
self.samp_rate = samp_rate = 500000
##################################################
# Blocks
##################################################
self.qtgui_waterfall_sink_x_0 = qtgui.waterfall_sink_f(
1024, #size
firdes.WIN_BLACKMAN_hARRIS, #wintype
0, #fc
samp_rate, #bw
"", #name
1 #number of inputs
)
self.qtgui_waterfall_sink_x_0.set_update_time(0.10)
self.qtgui_waterfall_sink_x_0.enable_grid(False)
self.qtgui_waterfall_sink_x_0.enable_axis_labels(True)
self.qtgui_waterfall_sink_x_0.set_plot_pos_half(not True)
labels = ['', '', '', '', '',
'', '', '', '', '']
colors = [0, 0, 0, 0, 0,
0, 0, 0, 0, 0]
alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0]
for i in range(1):
if len(labels[i]) == 0:
self.qtgui_waterfall_sink_x_0.set_line_label(i, "Data {0}".format(i))
else:
self.qtgui_waterfall_sink_x_0.set_line_label(i, labels[i])
self.qtgui_waterfall_sink_x_0.set_color_map(i, colors[i])
self.qtgui_waterfall_sink_x_0.set_line_alpha(i, alphas[i])
self.qtgui_waterfall_sink_x_0.set_intensity_range(-140, 10)
self._qtgui_waterfall_sink_x_0_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_0.pyqwidget(), Qt.QWidget)
self.top_grid_layout.addWidget(self._qtgui_waterfall_sink_x_0_win)
self.qtgui_time_sink_x_0 = qtgui.time_sink_f(
1024, #size
samp_rate, #samp_rate
"", #name
1 #number of inputs
)
self.qtgui_time_sink_x_0.set_update_time(0.10)
self.qtgui_time_sink_x_0.set_y_axis(-1, 1)
self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")
self.qtgui_time_sink_x_0.enable_tags(True)
self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
self.qtgui_time_sink_x_0.enable_autoscale(True)
self.qtgui_time_sink_x_0.enable_grid(False)
self.qtgui_time_sink_x_0.enable_axis_labels(True)
self.qtgui_time_sink_x_0.enable_control_panel(False)
self.qtgui_time_sink_x_0.enable_stem_plot(False)
labels = ['Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5',
'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10']
widths = [1, 1, 1, 1, 1,
1, 1, 1, 1, 1]
colors = ['blue', 'red', 'green', 'black', 'cyan',
'magenta', 'yellow', 'dark red', 'dark green', 'dark blue']
alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0]
styles = [1, 1, 1, 1, 1,
1, 1, 1, 1, 1]
markers = [-1, -1, -1, -1, -1,
-1, -1, -1, -1, -1]
for i in range(1):
if len(labels[i]) == 0:
self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i))
else:
self.qtgui_time_sink_x_0.set_line_label(i, labels[i])
self.qtgui_time_sink_x_0.set_line_width(i, widths[i])
self.qtgui_time_sink_x_0.set_line_color(i, colors[i])
self.qtgui_time_sink_x_0.set_line_style(i, styles[i])
self.qtgui_time_sink_x_0.set_line_marker(i, markers[i])
self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i])
self._qtgui_time_sink_x_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget)
self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win)
self.qtgui_freq_sink_x_0 = qtgui.freq_sink_f(
1024, #size
firdes.WIN_BLACKMAN_hARRIS, #wintype
0, #fc
samp_rate, #bw
"", #name
1
)
self.qtgui_freq_sink_x_0.set_update_time(0.10)
self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
self.qtgui_freq_sink_x_0.enable_autoscale(False)
self.qtgui_freq_sink_x_0.enable_grid(False)
self.qtgui_freq_sink_x_0.set_fft_average(1.0)
self.qtgui_freq_sink_x_0.enable_axis_labels(True)
self.qtgui_freq_sink_x_0.enable_control_panel(False)
self.qtgui_freq_sink_x_0.set_plot_pos_half(not True)
labels = ['', '', '', '', '',
'', '', '', '', '']
widths = [1, 1, 1, 1, 1,
1, 1, 1, 1, 1]
colors = ["blue", "red", "green", "black", "cyan",
"magenta", "yellow", "dark red", "dark green", "dark blue"]
alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0]
for i in range(1):
if len(labels[i]) == 0:
self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
else:
self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])
self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win)
self.grnet_tcp_source_0 = grnet.tcp_source.tcp_source(
itemsize=gr.sizeof_char*500,
addr='192.168.7.1',
port=7777,
server=False,
)
self.blocks_vector_to_stream_0 = blocks.vector_to_stream(gr.sizeof_char*1, 500)
self.blocks_uchar_to_float_0 = blocks.uchar_to_float()
self.blocks_multiply_const_vxx_0 = blocks.multiply_const_ff(3.3 / 255.0)
##################################################
# Connections
##################################################
self.connect((self.blocks_multiply_const_vxx_0, 0), (self.qtgui_freq_sink_x_0, 0))
self.connect((self.blocks_multiply_const_vxx_0, 0), (self.qtgui_time_sink_x_0, 0))
self.connect((self.blocks_multiply_const_vxx_0, 0), (self.qtgui_waterfall_sink_x_0, 0))
self.connect((self.blocks_uchar_to_float_0, 0), (self.blocks_multiply_const_vxx_0, 0))
self.connect((self.blocks_vector_to_stream_0, 0), (self.blocks_uchar_to_float_0, 0))
self.connect((self.grnet_tcp_source_0, 0), (self.blocks_vector_to_stream_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "piccolosdr")
self.settings.setValue("geometry", self.saveGeometry())
event.accept()
def get_samp_rate(self):
return self.samp_rate
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
self.qtgui_freq_sink_x_0.set_frequency_range(0, self.samp_rate)
self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate)
self.qtgui_waterfall_sink_x_0.set_frequency_range(0, self.samp_rate)
def main(top_block_cls=piccolosdr, options=None):
if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
style = gr.prefs().get_string('qtgui', 'style', 'raster')
Qt.QApplication.setGraphicsSystem(style)
qapp = Qt.QApplication(sys.argv)
tb = top_block_cls()
tb.start()
tb.show()
def sig_handler(sig=None, frame=None):
Qt.QApplication.quit()
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
timer = Qt.QTimer()
timer.start(500)
timer.timeout.connect(lambda: None)
def quitting():
tb.stop()
tb.wait()
qapp.aboutToQuit.connect(quitting)
qapp.exec_()
if __name__ == '__main__':
main()

Wyświetl plik

@ -35,7 +35,8 @@
/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */ /* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
#define NO_SYS 1 #define NO_SYS 1
#define MEM_ALIGNMENT 4 #define MEM_ALIGNMENT 4
#define LWIP_RAW 0 #define MEM_SIZE 8192 * 8
#define LWIP_RAW 1
#define LWIP_NETCONN 0 #define LWIP_NETCONN 0
#define LWIP_SOCKET 0 #define LWIP_SOCKET 0
#define LWIP_DHCP 0 #define LWIP_DHCP 0