From a5899f7a3f954def285ccc73ccb52f318c7ef625 Mon Sep 17 00:00:00 2001
From: Glenn Bradford <glenn.bradford@unimelb.edu.au>
Date: Sat, 13 May 2023 19:52:44 +1000
Subject: [PATCH] add cdc grc block for bladeRF source and sink

---
 examples/cdc_phy_bladeRF.grc     | 162 ++++++++-------------
 grc/CMakeLists.txt               |   5 +-
 grc/cdc_bladeRF_sink.block.yml   | 151 ++++++++++++++++++++
 grc/cdc_bladeRF_source.block.yml | 232 +++++++++++++++++++++++++++++++
 4 files changed, 445 insertions(+), 105 deletions(-)
 create mode 100644 grc/cdc_bladeRF_sink.block.yml
 create mode 100644 grc/cdc_bladeRF_source.block.yml

diff --git a/examples/cdc_phy_bladeRF.grc b/examples/cdc_phy_bladeRF.grc
index 0dd7dd2..58d1f6b 100644
--- a/examples/cdc_phy_bladeRF.grc
+++ b/examples/cdc_phy_bladeRF.grc
@@ -135,154 +135,108 @@ blocks:
     coordinate: [456, 116.0]
     rotation: 0
     state: true
-- name: bladeRF_sink_0
-  id: bladeRF_sink
+- name: blocks_message_debug_0
+  id: blocks_message_debug
   parameters:
     affinity: ''
     alias: ''
-    bias_tee0: 'False'
-    bias_tee1: 'False'
-    bw: samp_rate
     comment: ''
-    dac: '10000'
-    dc_calibration: LPF_TUNING
-    device_id: '0'
-    fpga_image: ''
-    fpga_reload: 'False'
-    freq: rf_freq
-    gain0: tx_gain
-    gain1: '10'
-    if_gain0: '0'
-    if_gain1: '20'
-    in_clk: ONBOARD
-    lpf_mode: disabled
-    maxoutbuf: '0'
-    metadata: 'False'
-    minoutbuf: '0'
-    nchan: '1'
-    out_clk: 'False'
-    ref_clk: '38400000'
-    sample_rate: samp_rate
-    sampling: internal
-    show_pmic: 'False'
-    smb: '0'
-    tamer: internal
-    trigger0: 'False'
-    trigger1: 'False'
-    trigger_role0: master
-    trigger_role1: master
-    trigger_signal0: J51_1
-    trigger_signal1: J51_1
-    use_dac: 'False'
-    use_ref_clk: 'False'
-    verbosity: warning
-    xb200: none
+    en_uvec: 'True'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [456, 244.0]
-    rotation: 0
+    coordinate: [816, 168.0]
+    rotation: 180
     state: enabled
-- name: bladeRF_source_0
-  id: bladeRF_source
+- name: blocks_message_strobe_0
+  id: blocks_message_strobe
   parameters:
     affinity: ''
     alias: ''
-    bias_tee0: 'False'
-    bias_tee1: 'False'
-    bw: samp_rate
     comment: ''
-    dac: '10000'
-    dc_calibration: LPF_TUNING
-    dc_offset_mode0: '2'
-    dc_offset_mode1: '0'
-    device_id: '0'
-    fpga_image: ''
-    fpga_reload: 'False'
-    freq: rf_freq
-    gain0: rx_gain
-    gain1: '10'
-    gain_mode0: 'False'
-    gain_mode1: 'False'
-    if_gain0: '0'
-    if_gain1: '20'
-    in_clk: ONBOARD
-    iq_balance_mode0: '2'
-    iq_balance_mode1: '0'
-    lpf_mode: disabled
     maxoutbuf: '0'
-    metadata: 'False'
     minoutbuf: '0'
-    nchan: '1'
-    out_clk: 'False'
-    ref_clk: '38400000'
-    sample_rate: samp_rate
-    sampling: internal
-    show_pmic: 'False'
-    smb: '0'
-    tamer: internal
-    trigger0: 'False'
-    trigger1: 'False'
-    trigger_role0: master
-    trigger_role1: master
-    trigger_signal0: J51_1
-    trigger_signal1: J51_1
-    use_dac: 'False'
-    use_ref_clk: 'False'
-    verbosity: warning
-    xb200: none
+    msg: pmt.cons(pmt.PMT_NIL, pmt.make_u8vector(nbytes, 0x00))
+    period: '500'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [600, 244.0]
-    rotation: 0
-    state: enabled
-- name: blocks_message_debug_0
-  id: blocks_message_debug
+    coordinate: [72, 252.0]
+    rotation: 180
+    state: true
+- name: blocks_uchar_to_float_0
+  id: blocks_uchar_to_float
   parameters:
     affinity: ''
     alias: ''
     comment: ''
-    en_uvec: 'True'
+    maxoutbuf: '0'
+    minoutbuf: '0'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [816, 168.0]
-    rotation: 180
-    state: enabled
-- name: blocks_message_strobe_0
-  id: blocks_message_strobe
+    coordinate: [1072, 424.0]
+    rotation: 0
+    state: true
+- name: cdc_bladeRF_sink_0
+  id: cdc_bladeRF_sink
   parameters:
     affinity: ''
     alias: ''
+    buffers: '16'
+    buflen: '8192'
+    bw: '0'
     comment: ''
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    msg: pmt.cons(pmt.PMT_NIL, pmt.make_u8vector(nbytes, 0x00))
-    period: '500'
+    device_id: '0'
+    freq: rf_freq
+    gain0: tx_gain
+    gain1: '10'
+    metadata: 'False'
+    nchan: '1'
+    sample_rate: samp_rate
+    transfers: '8'
+    verbosity: warning
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [72, 252.0]
-    rotation: 180
+    coordinate: [456, 276.0]
+    rotation: 0
     state: true
-- name: blocks_uchar_to_float_0
-  id: blocks_uchar_to_float
+- name: cdc_bladeRF_source_0
+  id: cdc_bladeRF_source
   parameters:
     affinity: ''
     alias: ''
+    buffers: '16'
+    buflen: '8192'
+    bw: '0'
     comment: ''
+    dc_offset_mode0: '2'
+    dc_offset_mode1: '0'
+    device_id: '0'
+    freq: rf_freq
+    gain0: rx_gain
+    gain1: '10'
+    gain_mode0: 'False'
+    gain_mode1: 'False'
+    iq_balance_mode0: '2'
+    iq_balance_mode1: '0'
     maxoutbuf: '0'
+    metadata: 'False'
     minoutbuf: '0'
+    nchan: '1'
+    sample_rate: samp_rate
+    transfers: '8'
+    verbosity: warning
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1072, 424.0]
+    coordinate: [600, 276.0]
     rotation: 0
     state: true
 - name: cdc_insert_burst_c_0
@@ -812,10 +766,10 @@ blocks:
     state: true
 
 connections:
-- [bladeRF_source_0, '0', phy_rx_0, '0']
 - [blocks_message_strobe_0, strobe, phy_tx_0, sdu]
 - [blocks_uchar_to_float_0, '0', qtgui_time_sink_x_0_0, '0']
-- [cdc_insert_burst_c_0, '0', bladeRF_sink_0, '0']
+- [cdc_bladeRF_source_0, '0', phy_rx_0, '0']
+- [cdc_insert_burst_c_0, '0', cdc_bladeRF_sink_0, '0']
 - [phy_rx_0, '0', qtgui_const_sink_x_0_0, '0']
 - [phy_rx_0, '1', qtgui_const_sink_x_0_0_0, '0']
 - [phy_rx_0, '2', blocks_uchar_to_float_0, '0']
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index c5e5551..e085ba9 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -12,5 +12,8 @@ install(FILES
     cdc_phy_rx.block.yml
     cdc_insert_burst_c.block.yml
     cdc_dsa_pu_scenario_cc.block.yml
-    cdc_dsa_stats.block.yml DESTINATION share/gnuradio/grc/blocks
+    cdc_dsa_stats.block.yml
+    cdc_bladeRF_sink.block.yml
+    cdc_bladeRF_source.block.yml
+    DESTINATION share/gnuradio/grc/blocks
 )
diff --git a/grc/cdc_bladeRF_sink.block.yml b/grc/cdc_bladeRF_sink.block.yml
new file mode 100644
index 0000000..eab8990
--- /dev/null
+++ b/grc/cdc_bladeRF_sink.block.yml
@@ -0,0 +1,151 @@
+id: cdc_bladeRF_sink
+label: 'CDC bladeRF Sink'
+category: '[CDC]'
+flags: throttle
+
+parameters:
+- id: metadata
+  label: Metadata
+  dtype: enum
+  default: auto
+  options: ['False', 'True']
+  hide: part
+  
+- id: device_id
+  label: 'Device'
+  dtype: string
+  default: '0'
+  hide: ${ 'none' if device_id else 'part'}
+
+- id: nchan
+  label: 'Num Channels'
+  dtype: int
+  default: 1
+  options: [ 1, 2 ]
+  
+- id: verbosity
+  label: 'Verbosity'
+  dtype: enum
+  default: warning
+  options: ['verbose', 'debug', 'info', 'warning', 'error', 'critical', 'silent']
+  option_labels: [verbose, debug, info, warning, error, critical, silent]
+  
+- id: sample_rate
+  label: 'Sample Rate (sps)'
+  dtype: real
+  default: samp_rate
+  
+- id: freq
+  label: 'Frequency (Hz)'
+  dtype: real
+  default: freq
+  
+- id: bw
+  label: 'Bandwidth (Hz)'
+  dtype: real
+  default: 0
+   
+- id: buffers
+  label: 'Num Buffers'
+  dtype: int
+  default: 16
+  hide: part
+
+- id: buflen
+  label: 'Buffer Size'
+  dtype: int
+  default: 8192
+  hide: part
+
+- id: transfers
+  label: 'Num Transfers'
+  dtype: int
+  default: 8
+  hide: part
+
+- id: gain0
+  category: 'Channel 0'
+  label: 'RF Gain (dB)'
+  dtype: real
+  default: 10
+  hide: ${'none' if (nchan > 0) else 'all'}
+  
+- id: gain1
+  category: 'Channel 1'
+  label: 'RF Gain (dB)'
+  dtype: real
+  default: 10
+  hide: ${'none' if (nchan > 1) else 'all'}
+
+inputs:
+- domain: stream
+  dtype: ${type.type}
+  multiplicity: ${nchan}
+
+templates:
+  imports: |-
+     import bladeRF
+  make: |      
+    bladeRF.sink(
+        args = "numchan=" + str(${nchan})
+             + ",metadata=" + '${metadata}'
+             + ",bladerf=" +  str(${device_id})
+             + ",buffers=" + str(${buffers})
+             + ",buflen=" + str(${buflen})
+             + ",transfers=" + str(${transfers})
+             + ",verbosity=" + '${verbosity}'
+    )
+    self.${id}.set_sample_rate(${sample_rate})
+    self.${id}.set_center_freq(${freq},0)
+    self.${id}.set_bandwidth(${bw},0)
+    % if context.get('nchan')() > 0:    
+    self.${id}.set_gain(${gain0}, 0)
+    % endif
+    % if context.get('nchan')() > 1:    
+    self.${id}.set_gain(${gain1}, 1)
+    % endif
+  callbacks:
+    - set_sample_rate(${sample_rate})
+    - set_center_freq(${freq}, 0)
+    - set_bandwidth(${bw}, 0)
+    - set_gain(${gain0}, 0)
+    - set_gain(${gain1}, 1)
+
+documentation: |-
+  CDC GRC wrapper for gr-bladeRF sink block.
+  
+  Device: 
+  Device serial id. If 'device' not specified, the first available device is used.
+  
+  Metadata:
+  Provide metadata with samples
+  
+  Num Channels:
+  Selects the total number of channels in this multi-device configuration. Required when specifying multiple device arguments.
+
+  Verbosity:
+  Sets the filter level for displayed log messages.
+
+  Sample Rate:
+  The sample rate is the number of samples per second output by this block on each channel.
+
+  Frequency:
+  The center frequency is the frequency the RF chain is tuned to.
+
+  Bandwidth:
+  Set the bandpass filter on the radio frontend. To use the default (automatic) bandwidth filter setting, this should be zero.
+
+  Buffers:
+  Number of memory buffers available for exchanging samples between host and device via USB. Smaller value will result in less latency at the risk of sample underruns.
+
+  Buffer Size:
+  Size of memory buffers (in samples), which must be a multiple of 1024. Smaller value will result in less latency but requires faster host processing.
+
+  Transfers:
+  Number of memory buffers in-flight at any one time. Suggested to set less than or equal to half the number of buffers.
+
+  For each channel:
+    RF Gain:
+    Overall RF gain of the device.
+  
+file_format: 1
diff --git a/grc/cdc_bladeRF_source.block.yml b/grc/cdc_bladeRF_source.block.yml
new file mode 100644
index 0000000..067308c
--- /dev/null
+++ b/grc/cdc_bladeRF_source.block.yml
@@ -0,0 +1,232 @@
+id: cdc_bladeRF_source
+label: 'CDC bladeRF Source'
+category: '[CDC]'
+flags: throttle
+
+parameters:
+- id: metadata
+  label: Metadata
+  dtype: enum
+  default: auto
+  options: ['False', 'True']
+  hide: part
+  
+- id: device_id
+  label: 'Device'
+  dtype: string
+  default: '0'
+  hide: ${ 'none' if device_id else 'part'}
+
+- id: nchan
+  label: 'Num Channels'
+  dtype: int
+  default: 1
+  options: [ 1, 2 ]
+  
+- id: verbosity
+  label: 'Verbosity'
+  dtype: enum
+  default: warning
+  options: ['verbose', 'debug', 'info', 'warning', 'error', 'critical', 'silent']
+  option_labels: [verbose, debug, info, warning, error, critical, silent]
+  
+- id: sample_rate
+  label: 'Sample Rate (sps)'
+  dtype: real
+  default: samp_rate
+  
+- id: freq
+  label: 'Frequency (Hz)'
+  dtype: real
+  default: freq
+  
+- id: bw
+  label: 'Bandwidth (Hz)'
+  dtype: real
+  default: 0
+   
+- id: buffers
+  label: 'Num Buffers'
+  dtype: int
+  default: 16
+  hide: part
+
+- id: buflen
+  label: 'Buffer Size'
+  dtype: int
+  default: 8192
+  hide: part
+
+- id: transfers
+  label: 'Num Transfers'
+  dtype: int
+  default: 8
+  hide: part
+
+- id: dc_offset_mode0
+  category: 'Channel 0'
+  label: 'DC Offset Mode'
+  dtype: int
+  default: 0
+  options: [0, 1, 2]  
+  option_labels: [Off, Manual, Automatic]
+  hide: ${'none' if (nchan > 0) else 'all'}
+  
+- id: iq_balance_mode0
+  category: 'Channel 0'
+  label: 'IQ Balance Mode'
+  dtype: int
+  default: 0
+  options: [0, 1, 2]
+  option_labels: [Off, Manual, Automatic]
+  hide: ${'none' if (nchan > 0) else 'all'}
+  
+- id: gain_mode0
+  category: 'Channel 0'
+  label: 'AGC'
+  dtype: enum
+  default: 'False'
+  options: ['False', 'True']
+  hide: ${'none' if (nchan > 0) else 'all'}
+
+- id: gain0
+  category: 'Channel 0'
+  label: 'RF Gain (dB)'
+  dtype: real
+  default: 10
+  hide: ${'none' if (nchan > 0) else 'all'}
+ 
+- id: dc_offset_mode1
+  category: 'Channel 1'
+  label: 'DC Offset Mode'
+  dtype: int
+  default: 0
+  options: [0, 1, 2]  
+  option_labels: [Off, Manual, Automatic]
+  hide: ${'none' if (nchan > 1) else 'all'}
+  
+- id: iq_balance_mode1
+  category: 'Channel 1'
+  label: 'IQ Balance Mode'
+  dtype: int
+  default: 0
+  options: [0, 1, 2]
+  option_labels: [Off, Manual, Automatic]
+  hide: ${'none' if (nchan > 1) else 'all'}
+  
+- id: gain_mode1
+  category: 'Channel 1'
+  label: 'AGC'
+  dtype: enum
+  default: 'False'
+  options: ['False', 'True']
+  hide: ${'none' if (nchan > 1) else 'all'}
+
+- id: gain1
+  category: 'Channel 1'
+  label: 'RF Gain (dB)'
+  dtype: real
+  default: 10
+  hide: ${'none' if (nchan > 1) else 'all'}
+  
+outputs:
+- domain: stream
+  dtype: ${type.type}
+  multiplicity: ${nchan}
+
+templates:
+  imports: |-
+     import bladeRF
+  make: |      
+    bladeRF.source(
+        args = "numchan=" + str(${nchan})
+             + ",metadata=" + '${metadata}'
+             + ",bladerf=" +  str(${device_id})
+             + ",buffers=" + str(${buffers})
+             + ",buflen=" + str(${buflen})
+             + ",transfers=" + str(${transfers})
+             + ",verbosity=" + '${verbosity}'
+    )
+    self.${id}.set_sample_rate(${sample_rate})
+    self.${id}.set_center_freq(${freq},0)
+    self.${id}.set_bandwidth(${bw},0)
+    % if context.get('nchan')() > 0:    
+    self.${id}.set_dc_offset_mode(${dc_offset_mode0}, 0)
+    self.${id}.set_iq_balance_mode(${iq_balance_mode0}, 0)
+    self.${id}.set_gain_mode(${gain_mode0}, 0)    
+    self.${id}.set_gain(${gain0}, 0)
+    % endif
+    % if context.get('nchan')() > 1:    
+    self.${id}.set_dc_offset_mode(${dc_offset_mode1}, 1)
+    self.${id}.set_iq_balance_mode(${iq_balance_mode1}, 1)
+    self.${id}.set_gain_mode(${gain_mode1}, 1)    
+    self.${id}.set_gain(${gain1}, 1)
+    % endif
+  callbacks:
+    - set_sample_rate(${sample_rate})
+    - set_center_freq(${freq}, 0)
+    - set_bandwidth(${bw}, 0)
+    - set_dc_offset_mode(${dc_offset_mode0}, 0)
+    - set_iq_balance_mode(${iq_balance_mode0}, 0)
+    - set_gain_mode(${gain_mode0} == True, 0)
+    - set_gain(${gain0}, 0)
+    - set_dc_offset_mode(${dc_offset_mode1}, 1)
+    - set_iq_balance_mode(${iq_balance_mode1}, 1)
+    - set_gain_mode(${gain_mode1} == True, 1)
+    - set_gain(${gain1}, 1)
+
+documentation: |-
+  CDC GRC wrapper for gr-bladeRF source block.
+  
+  Device: 
+  Device serial id. If 'device' are not specified, the first available device is used.
+  
+  Metadata:
+  Provide metadata with samples
+  
+  Num Channels:
+  Selects the total number of channels in this multi-device configuration. Required when specifying multiple device arguments.
+
+  Verbosity:
+  Sets the filter level for displayed log messages.
+  
+  Sample Rate:
+  The sample rate is the number of samples per second output by this block on each channel.
+  
+  Frequency:
+  The center frequency is the frequency the RF chain is tuned to.
+
+  Bandwidth:
+  Set the bandpass filter on the radio frontend. To use the default (automatic) bandwidth filter setting, this should be zero.
+
+  Num Buffers:
+  Number of memory buffers available for exchanging samples between device and host via USB. Smaller value will result in less latency at the risk of sample overruns.
+
+  Buffer size:
+  Size of memory buffers (in samples), which must be a multiple of 1024. Smaller value will result in less latency but requires faster host processing.
+
+  Num Transfers:
+  Number of buffers in-flight at any one time. Suggested to set less than or equal to half the number of memory buffers.
+
+  For each channel:
+
+    DC Offset Mode:
+    Controls the behavior of hardware DC offset corrrection.
+      Off: Disable correction algorithm (pass through).
+      Manual: Keep last estimated correction when switched from Automatic to Manual.
+      Automatic: Periodicallly find the best solution to compensate for DC offset.
+
+    IQ Balance Mode:
+    Controls the behavior of software IQ imbalance corrrection.
+      Off: Disable correction algorithm (pass through).
+      Manual: Keep last estimated correction when switched from Automatic to Manual.
+      Automatic: Periodicallly find the best solution to compensate for image signals.
+
+    AGC:
+      Chooses between the manual (False) and automatic (True) gain mode where appropriate.
+      To allow manual control of RF/IF gain stages, manual gain mode must be configured.
+
+    RF Gain:
+      Overall RF gain of the device.
+
+file_format: 1
-- 
GitLab