Select Git revision
detail.html
gen_bladerf_blocks.py 9.58 KiB
"""
Copyright 2012 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
GNU Radio Companion is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
MAIN_TMPL = """\
id: ${prefix}_${sourk}
label: '${title} ${sourk.title()}'
category: '[bladeRF]'
flags: throttle
parameters:
- id: type
label: '${direction.title()}put Type'
dtype: enum
options: [fc32]
option_labels: [Complex Float32]
option_attributes:
type: [fc32]
hide: part
- id: args
label: 'Device'
dtype: string
default: '""'
hide: ${'$'}{ 'none' if args else 'part'}
- id: nchan
label: 'Number Channels'
dtype: int
default: 1
options: [ ${", ".join([str(n) for n in range(1, max_nchan+1)])} ]
- id: sample_rate
label: 'Sample Rate (sps)'
dtype: real
default: samp_rate
- id: fpga_image
label: 'FPGA image'
dtype: string
- id: power_monitoring
label: 'Enable power monitoring'
dtype: bool
default: False
- id: ref_clk
label: 'Reference clock'
dtype: real
- id: in_clk
label: 'Input clock'
dtype: enum
default: auto
options: ['ONBOARD', 'EXTERNAL']
option_labels: ['ONBOARD', 'EXTERNAL']
- id: out_clk
label: 'Output clock'
dtype: bool
default: False
- id: dac
label: 'VCXTO DAC'
dtype: real
default: 10000
${params}
inputs:
- domain: message
id: command
optional: true
% if sourk == 'source':
outputs:
% endif
- domain: stream
dtype: ${'$'}{type.type}
multiplicity: ${'$'}{nchan}
% if sourk == 'sink':
outputs:
- domain: message
id: async_msgs
optional: true
% endif
templates:
imports: |-
import bladeRF
import time
make: |
bladeRF.${sourk}(
args="numchan=" + str(${'$'}{nchan}) + " " + ${'$'}{args}
)
self.${'$'}{id}.set_sample_rate(${'$'}{sample_rate})
% for n in range(max_nchan):
${'%'} if context.get('nchan')() > ${n}:
self.${'$'}{id}.set_center_freq(${'$'}{${'freq' + str(n)}}, ${n})
self.${'$'}{id}.set_freq_corr(${'$'}{${'corr' + str(n)}}, ${n})
% if sourk == 'source':
self.${'$'}{id}.set_dc_offset_mode(${'$'}{${'dc_offset_mode' + str(n)}}, ${n})
self.${'$'}{id}.set_iq_balance_mode(${'$'}{${'iq_balance_mode' + str(n)}}, ${n})
self.${'$'}{id}.set_gain_mode(${'$'}{${'gain_mode' + str(n)}}, ${n})
% endif
self.${'$'}{id}.set_gain(${'$'}{${'gain' + str(n)}}, ${n})
self.${'$'}{id}.set_if_gain(${'$'}{${'if_gain' + str(n)}}, ${n})
self.${'$'}{id}.set_bb_gain(${'$'}{${'bb_gain' + str(n)}}, ${n})
self.${'$'}{id}.set_bandwidth(${'$'}{${'bw' + str(n)}}, ${n})
${'%'} endif
% endfor
callbacks:
- set_sample_rate(${'$'}{sample_rate})
% for n in range(max_nchan):
- set_center_freq(${'$'}{${'freq' + str(n)}}, ${n})
- set_freq_corr(${'$'}{${'corr' + str(n)}}, ${n})
% if sourk == 'source':
- set_dc_offset_mode(${'$'}{${'dc_offset_mode' + str(n)}}, ${n})
- set_iq_balance_mode(${'$'}{${'iq_balance_mode' + str(n)}}, ${n})
- set_gain_mode(${'$'}{${'gain_mode' + str(n)}}, ${n})
% endif
- set_gain(${'$'}{${'gain' + str(n)}}, ${n})
- set_if_gain(${'$'}{${'if_gain' + str(n)}}, ${n})
- set_bb_gain(${'$'}{${'bb_gain' + str(n)}}, ${n})
- set_bandwidth(${'$'}{${'bw' + str(n)}}, ${n})
% endfor
documentation: |-
The bladeRF ${sourk} block:
Device:
Device serial id. If 'device' are not specified, the first available device is used.
Fpga image:
Load the FPGA bitstream from the specified file. This is required only once after powering the bladeRF on. If the FPGA is already loaded, this argument is ignored, unless 'fpga-reload=1' is specified.
Enable power monitoring:
Read value from Power Monitor IC
Reference clock:
Value of reference clock
Input clock:
Onboard/external clock.
Output clock:
Enable/disable clock output.
VCXTO DAC:
Value to VCTCXO trim DAC
Num Channels:
Selects the total number of channels in this multi-device configuration. Required when specifying multiple device arguments.
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.
Freq. Corr.:
The frequency correction factor in parts per million (ppm). Set to 0 if unknown.
% if sourk == 'source':
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.
This functionality is available for USRP devices only.
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.
Gain Mode:
Chooses between the manual (default) and automatic gain mode where appropriate.
To allow manual control of RF/IF/BB gain stages, manual gain mode must be configured.
Currently, only RTL-SDR devices support automatic gain mode.
% endif
RF Gain:
Overall RF gain of the device.
IF Gain:
Overall intermediate frequency gain of the device.
This setting is available for RTL-SDR and OsmoSDR devices with E4000 tuners and HackRF in receive and transmit mode. Observations lead to a reasonable gain range from 15 to 30dB.
BB Gain:
Overall baseband gain of the device.
This setting is available for HackRF in receive mode. Observations lead to a reasonable gain range from 15 to 30dB.
Bandwidth:
Set the bandpass filter on the radio frontend. To use the default (automatic) bandwidth filter setting, this should be zero.
file_format: 1
"""
# MAIN_TMPL = """\
# <block>
# <check>$max_nchan >= \$nchan</check>
# <check>\$nchan > 0</check>
# </block>
# """
PARAMS_TMPL = """
- id: freq${n}
label: 'Ch${n}: Center frequency (Hz)'
dtype: real
default: 1e8
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
- id: corr${n}
label: 'Ch${n}: Frequency Correction (ppm)'
dtype: real
default: 0
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
- id: bw${n}
label: 'Ch${n}: Bandwidth (Hz)'
dtype: real
default: 200000
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
- id: bias_tee${n}
label: 'Ch${n}: Bias tee'
dtype: bool
default: False
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
- id: xb_200${n}
label: 'Ch${n}: XB-200'
dtype: enum
default: auto
options: ['auto', 'auto3db', '50M', '144M', '222M', 'custom']
option_labels: [auto, auto3db, 50M, 144M, 222M, custom]
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
% if sourk == 'source':
- id: dc_offset_mode${n}
label: 'Ch${n}: DC Offset Mode'
dtype: int
default: 0
options: [0, 1, 2]
option_labels: [Off, Manual, Automatic]
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
- id: iq_balance_mode${n}
label: 'Ch${n}: IQ Balance Mode'
dtype: int
default: 0
options: [0, 1, 2]
option_labels: [Off, Manual, Automatic]
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
- id: gain_mode${n}
label: 'Ch${n}: Gain Mode'
dtype: bool
default: False
options: [False, True]
option_labels: [Manual, Automatic]
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
% endif
- id: gain${n}
label: 'Ch${n}: RF Gain (dB)'
dtype: real
default: 10
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
- id: if_gain${n}
label: 'Ch${n}: IF Gain (dB)'
dtype: real
default: 20
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
- id: bb_gain${n}
label: 'Ch${n}: BB Gain (dB)'
dtype: real
default: 20
hide: ${'$'}{'none' if (nchan > ${n}) else 'all'}
"""
def parse_tmpl(_tmpl, **kwargs):
from mako.template import Template
from mako import exceptions
try:
block_template = Template(_tmpl)
return str(block_template.render(**kwargs))
except:
print(exceptions.text_error_template().render())
MAX_NUM_CHANNELS = 2
import os.path
if __name__ == '__main__':
import sys
for file in sys.argv[1:]:
head, tail = os.path.split(file)
if tail.startswith('bladeRF'):
title = 'bladeRF'
prefix = 'bladeRF'
else:
raise Exception("file {} has wrong syntax!".format(tail))
if tail.endswith('source.block.yml'):
sourk = 'source'
direction = 'out'
elif tail.endswith('sink.block.yml'):
sourk = 'sink'
direction = 'in'
else:
raise Exception("is {} a source or sink?".format(file))
params = ''.join([
parse_tmpl(PARAMS_TMPL, n=n, sourk=sourk)
for n in range(MAX_NUM_CHANNELS)
])
open(file, 'w').write(
parse_tmpl(
MAIN_TMPL,
max_nchan=MAX_NUM_CHANNELS,
params=params,
title=title,
prefix=prefix,
sourk=sourk,
direction=direction,
)
)