Scientific Computing

HD Radio interference to license-free FM

In urban and extended suburban areas typical of southern California and the northeast United States, it can be difficult to find a clear broadcast FM (87.9-107.9 MHz) channel to use for license-free transmissions. As 2020 drove many communities to outdoor activities, many organizations used license-free FM transmitters to share music, lectures and entertainment a large audience locally in their automobiles. An issue we’ve observed is poor audio quality and erratic coverage of the license-free FM system due to sideband spillover of adjacent HD Radio broadcasts. With HD Radio, the first adjacent channel spillover power is hundreds to thousands of times higher on average than with an analog FM signal alone. The usual sound of HD Radio interference is simply a hissing noise that is difficult to distinguish from ordinary noise when a station isn’t present.

The typical community member new to license-free FM would have difficulty distinguishing HD Radio first adjacent channel interference from simply having poor range. Without special equipment beyond an automobile or handheld FM radio, it’s difficult for the inexperienced person to detect the interference. A $20 RTL-SDR USB radio stick would give a spectrum analyzer view showing the HD Radio sidebands spilling within 100 kHz of the license-free carrier frequency. This energy will cover over the license-free FM broadcast. Without such equipment, look in the HD Radio database to see if the FM stations on the channel above and below have HD Radio. If so, pick a different clear license-free FM channel, if the first adjacent stations are clearly audible on your radio when on their channels.

Example

Suppose a first adjacent HD Radio station has a carrier signal strength at the radio of about -70 dBm with a typical car radio antenna. -70 dBm is typically more than adequate for clear-sounding broadcast FM audio when in an outdoor environment where there’s not excessive interference. Take a conservative and simple estimation that the HD Radio first adjacent has a -20 dBc HD Radio injection level, and that 50% of that power (-23 dBc) falls within the license-free receiver passband. This means roughly -90 dBm is on-channel of the license-free FM station. The area to be covered was about 150 meters from a theoretical central location for the FM transmitter. This would be well in excess of that expected for a legal license-free FM transmitter. For us the license-free FM program audio was only detectable over about 80% of the event, when we were probably within about 100 meters of the transmitter. However the audio quality was only usable for about 50% of the park.

We didn’t attempt to quantify this further, but this poor radio coverage would be expected from the use of a first adjacent channel to an HD Radio station, and trying to cover too large an area with a license-free FM transmitter. Once might suppose the FM transmitter used might have more than legal FM transmit power. Even in that case, one should not use a first adjacent channel to HD Radio, as this can drastically reduce coverage. Again, a key metric is if the first adjacent HD Radio channel (say 88.9MHz) is clearly audible when tuned to that channel (88.9), then trying to broadcast license-free on a first adjacent channel (88.7 and 89.1) will be a futile effort.

Illegal broadcasts also seek clear FM frequencies that are naturally not in any official database. Before printing promotional materials for your event, it’s important to verify with a local FM receiver than the planned channel is actually clear. Also consider that another operation may choose the same FM frequency near your event. It may be better to simply instruct attendees to look for big signs near the entrance(s) of your event so that the FM frequency can be quickly changed if interference is experienced. Be sure someone on-site knows how to change the FM transmitter frequency.


Reference: FM Receiver measured performance

CI examples

Continuous Integration services run user-defined self-checks on code on each “git push”. GitHub Actions is often the best place to start with CI. CI is one part of the DevOps lifecycle.

These services have quotas even for public Git repos:

At the time of this writing, these CI didn’t have usage quotas for public repos. They are constrained by the number of concurrent jobs.

We have amassed numerous CI examples across programming languages, including

Microsoft Surface lifecycle

Microsoft Surface computers are generally a good device to consider for education, work and personal computing. Microsoft has published a firmware update lifecycle schedule for all Surface devices. While one would assume after four years or so of firmware updates the bugs would mostly be worked out, there is the possibility of an unpatched firmware vulnerability as has happened across OEMs.

Cygwin on Windows

Since 2016, Windows Subsystem for Linux generally has significantly better performance and more packages available than Cygwin. Nonetheless, for those with a specific need for Cygwin over WSL, Cygwin packages such as SSH, Python, GNU Octave, Git, etc. are kept up to date.

winget install --id Cygwin.Cygwin -e

IPython no confirm on exit

IPython “confirm on exit” is not always desired. To disable confirm on exit, from Terminal (not in Python) type:

ipython profile create

This will print out the locate of the IPython config file, which is like “~/.ipython/profile_default/ipython_config.py”. Open this file in a text editor, and uncomment the line:

c.TerminalInteractiveShell.confirm_exit = False

Upon restarting IPython, the usual Ctrl+D immediately exits without confirmation.

GitHub Actions quick start

GitHub Actions is among the best no-cost CI and is relatively easy to use. Here are a couple example GitHub Actions templates we use across many projects. Each workflow is stored in the project under directory “.github/workflows”. For clarity, usually we use a filename like “.github/workflows/ci.yml”.

This Python template tests on Linux, macOS and Windows. Always enclose version numbers in quotes to avoid YAML interpretation issues.

The optional “Unix FC var” step is an example of setting an environment variable dynamically–here for a Fortran compiler.

name: ci

on:
  push:
    paths:
      - "**.py"
      - .github/workflows/ci.yml


jobs:

  core:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]

    runs-on: ${{ matrix.os}}

    steps:
    - uses: actions/checkout

    - uses: actions/setup-python
      with:
        python-version: '3.x'

    - run: pip install .
    - run: pip install flake8 mypy pytest

    - run: flake8
    - run: mypy

    - name: Unix FC var
      if: runner.os != 'Windows'
      run: echo "FC=gfortran-14" >> $GITHUB_ENV

    - run: pytest

Python vs. Matlab for command line

The Matlab -batch command line option makes running Matlab code from the command line more reliable. However, Matlab is not really designed to be used extensively by end users this way. Matlab does not have a command-line parser like many other languages (scripted and compiled) do.

Python has the argparse module that we generally find sufficient. In Fortran, using the get_command_argument() with select case can make a straightforward command line parser without resorting to external packages.

Perhaps a reason for Matlab not having these features is the startup time of Matlab. While Python can complete a small program in 100 ms from the shell, Matlab takes 10-30 seconds or so depending on the number of toolboxes and the speed of the computer. GNU Octave starts up nearly as quickly as Python when Octave toolboxes are not auto-loaded. It would be nice if Matlab someday will make an actual command-line interface with fast startup time.

CI select OS version

Many CI services use Ubuntu Linux images. The default Linux / Ubuntu version is typically an older version. It can be convenient to switch CI jobs to a newer Linux version to get more recent libraries. Here are examples of switching Linux version for a few popular CI services.

GitHub Actions default Ubuntu version is controlled with .github/workflows/*.yml file(s).

jobs:

  linux:
    runs-on: ubuntu-<version_number>

Profile and speedup Matlab functions

Code profiling and micro-benchmarks can be useful to discover hot spots in code that might be targets for improving efficiency and overall execution time. Matlab has long had an effective profiler built in from the factory.

Commercial and free software often prioritized quality and correctness over speed as part of a good quality software product. There are cases where the Matlab factory functions are simply not optimized due to development time constraints. Yair Altman has expertise with the undocumented scripts inside Matlab that many Matlab users rely on. He has written a three-part series on profiling and optimizing Matlab factory code, which I find to be worthwhile reading even for general Matlab code optimization.

Speeding up builtin Matlab functions:

macOS Homebrew without sudo / admin

Homebrew is a popular framework for quickly installing development tools on macOS, including Gfortran. macOS cloud services such as MacInCloud may say they provide Homebrew, but you may not be able to install packages without a sudo/admin account. To install Homebrew without sudo/admin in the user home directory for cloud or physical hardware, follow these steps:

mkdir ~/homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C ~/homebrew

If one truly doesn’t have sudo / admin access as typical with a managed (less-expensive) cloud macOS plan, and if Xcode is not the appropriate version, GCC may compile from source, which can take tens of minutes. This may occur when doing

brew install gcc

Reference: Homebrew without sudo script