Windows battery time remaining disabled in 20H2

Battery time remaining estimates for computing devices can vary widely in accuracy. The estimates are based on assumptions about future behavior based on prior usage trends, from a mix of current and prior charge usage. Windows updates can disable battery time remaining, and some devices (including Microsoft Surface) may come from the factory with battery time estimates disabled. Even though the battery time remaining estimates on Windows have limited accuracy, I personally prefer to have the estimate shown.

Registry edit

The usual precautions on modifying the Windows Registry apply–do a Windows System Recovery milestone first. These keys are under:


If this value exists, set its value to 0. If it doesn’t exist, that’s fine.

Create this DWORD32 value (if not existing) and set to 1.


Other users suggest alternative combinations of deleting / adding these registry keys. The above is what “worked for me” across multiple models of Microsoft Surface devices.



Logitech on Linux with Solaar

The Solaar program manages connections with Logitech Unifying receiver on Linux, including pairing/unpairing. This means wireless keyboards and mice, including wireless trackballs work well on Linux. Logitech wireless firmware updates are provided seamlessly in Linux. The Unifying receiver “just works” on Linux upon plugging in, with trackballs being recognized as an HID device.

Solaar is strictly a GUI program, so you will need a display or VNC graphical desktop to perform operations like

  • pairing/unpairing
  • configuring buttons
  • monitoring battery level
  • checking firmware version of Unifying receiver and connected devices

Logitech Unifying receivers can be paired with multiple devices. This allows one to carry a laptop from home to office without dragging the wireless keyboard or mouse along.

Python cumtrapz vs. Matlab

The 0-based indexing of Python and Numpy versus the 1-based indexing of Matlab is perhaps the most obvious difference when working between the languages. Other, more subtle defaults come into play and may not be immediately caught within functions except by manual checks.

In atmospheric science among other fields, cumulative integration implemented as cumulative trapezoidal numerical integration is a common function named “cumtrapz”. Distinctive behavior between Matlab cumtrapz and SciPy cumtrapz might not be immediately caught inside a function, although it’s obvious when manually checking. Specifically, SciPy cumtrapz needs the initial=0 argument to match Matlab. Let’s show this by example:


In both languages, suppose

x = [-2.5, 5, 10]

Matlab (or GNU Octave) outputs:

y = cumtrapz(x)

[0, 1.25, 8.75]

Here comes the wrinkle–SciPy cumtrapz output one element less than the input by default:


[1.25, 8.75]

To match Matlab output from SciPy, add the initial=0 argument:

scipy.integrate.cumtrapz(x, initial=0)

[0, 1.25, 8.75]

HDF5 CMake build

We strongly recommend using CMake to build HDF5 rather than autotools. For those building HDF5 on Windows, CMake is required. There is a slight quirk with current (HDF5 1.10.7, 1.12.0) HDF5 CMake scripts in that the “new” cmake -B build flags don’t work properly–the CMake build will fail partway through with weird platform-dependent errors. HDF Group is working to improve CMake and has merged pull requests from us with CMake improvements for HDF5.

These CMake options build HDF5 for Fortran as fast as possible by omitting optional items. If these seems too complicated, try our one-step Python build HDF5 script.

mkdir build
cd build


This creates static and dynamic HDF5 libraries under the user install prefix–we don’t show the library suffixes for simplicity. Note: the *stub files may not be present.


The Fortran .mod files that need to be included are under



Tell CMake to use this HDF5 from your project by:

cmake -B build -DHDF5_ROOT=~/.local/hdf5

cmake --build build

CMake expanduser tilde ~

To have the most reliable path operations in CMake, it’s typically best to resolve paths to the full expanded path. Note: there are a few CMake functions that desire relative paths, but those are clearly spelled out in the docs.

Example showing problem

The get_filename_components(... ABSOLUTE) expands the “~” to the user home directory. Without this, on Windows the else() statement is executed.

set(p "~")

# comment out this line on Windows to see the problem
get_filename_component(p ${p} ABSOLUTE)

  message(STATUS "${p} is a directory")
  message(FATAL_ERROR "${p} is not a directory")

CMake file separator

Windows Explorer from command line

Windows Explorer is widely used, but do you find yourself clicking around too much to navigate? If you already have PowerShell open, why not try opening a new Explorer windows in the desired directory with a simple command, like:

explorer ~/code/myproj

hit Tab then Enter to expand the “~” into the full path, otherwise Explorer will open to a different, default directory. Pressing Tab to expand “~” quickly becomes a convenient muscle memory with PowerShell, much more convenient that %userprofile% or $home.

Matlab + Octave unit tests quick-start

Matlab unit test framework is well-established and xUnit-like. The Matlab unit test framework is incompatible with the GNU Octave BIST unit testing framework. The Matlab unit test syntax is completely different from the Octave unit test syntax. Nonetheless, a common ground between Matlab and GNU Octave can be found in the easy to use Matlab script-based tests. A Matlab script-based test can be run as an ordinary script with GNU Octave.

Script-based test

A key characteristic of Matlab script-based tests is they can’t use the Qualifiable functions (verify*, assert*, assume*). This also means you cannot mark a test as skipped or Incomplete (using assume*) with script-based tests. Basic tests can work without those functions, but more advanced tests suites do strongly benefit from those functions.

Matlab or Octave can run a script-based test as a plain script. The downsides of running a script-based test as a plain script are:

  1. there is no decorated TestResult
  2. the first failure ends the whole test

It’s best to put the script-based test scripts in the same directory as the code they’re testing to avoid Matlab path issues.

Matlab runtests

When using Matlab on this Octave-compatible script-based test, a richer result comes from using Matlab-only runtests(). Matlab runtests() will search all subdirectories under the current working directory and run all scripts with case-insensitive “test” in the filename. For example, a script testing HDF5 function of a program might be named TestHDF5.m or HDF5test.m. This is similar to PyTest filename-filtering.

Denote each test in the script-based test file with a double percent sign like:

% test_example.m
% setup code goes up top, as each test's variables are isolated from each other
% when using Matlab runtests()

A = magic(2);

%% test_dummy
B = A*2;  % only visible to this test, when using Matlab runtests()
assert(isequal(B, A*2), 'dummy example')

%% test_four
C = A*4; % note that "B" is not visible under runtests()
assert(isequal(C, A*4), 'dummy four')

Run Matlab runtests() from CI command like:

matlab -batch "assertSuccess(runtests)"

Just doing matlab -batch runtests will NOT fail in CI, even with failing test.


Octave runtests('.') only runs tests in specially formatted comments that Matlab ignores. For projects that need to have tests supporting Octave and Matlab, we generally recommend writing Matlab script-based tests, and manually running each file from Octave.

Linking HDF5 with CMake for C, C++ and Fortran

CMake links HDF5 into your C, C++, or Fortran program with just two lines in CMakeLists.txt. If experiencing trouble finding HDF5 with CMake, try our FindHDF5.cmake, which is more up to date than the FindHDF5.cmake included with CMake. An example CMake for writing network data to HDF5 in C: CMakeLists.txt.

A simple HDF5 read/write example is given below.

HDF5 prereqs

  • Linux: apt install libhdf5-dev
  • Mac: brew install hdf5
  • Windows MSYS2: pacman -S mingw64/mingw-w64-x86_64-hdf5

Windows Subsystem for Linux

apt install libhdf5-dev

and be sure /etc/wsl.conf includes:


CMakeLists.txt HDF5

Here’s two examples, one for C, one for Fortran. “HL” refers to the high-level HDF5 interface that is more convenient and thus commonly used.

Note: if terminal has the Conda environment loaded and you keep getting the Conda HDF5 library, do first:

conda deactivate

before running the CMake configure commadn.

C HDF5 CMakeLists.txt

project(myproj LANGUAGES C)


add_executable(myprog myprog.c)
target_link_libraries(myprog PRIVATE HDF5::HDF5)

Fortran HDF5 CMakeLists.txt

project(myproj LANGUAGES Fortran)

find_package(HDF5 REQUIRED COMPONENTS Fortran HL)

add_executable(myprog myprog.f90)
target_link_libraries(myprog PRIVATE HDF5::HDF5)

HDF5 C example

The HDF5 syntax is quite similar (and simpler) for Fortran. See the hdf5 directory of Fortran 2018 examples for more.

#include "hdf5.h"
#define FILE "dset.h5"

int main() {

   hid_t       file_id, dataset_id,dataspace_id; /* identifiers */
   herr_t      status;
   int         i, j, dset_data[4][6], read_data[4][6];
  hsize_t     dims[2];

   /* Initialize the dataset. */
   for (i = 0; i < 4; i++)
      for (j = 0; j < 6; j++)
         dset_data[i][j] = i * 6 + j + 1;

   /* Create a new file using default properties. */
   file_id = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

   /* Create the data space for the dataset. */
   dims[0] = 4;
   dims[1] = 6;
   dataspace_id = H5Screate_simple(2, dims, NULL);

   /* Create the dataset. */
   dataset_id = H5Dcreate2(file_id, "/dset", H5T_STD_I32BE, dataspace_id,
                          H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);

   /* Write the dataset. */
   status = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,

   /* End access to the dataset and release resources used by it. */
   status = H5Dclose(dataset_id);


   /* Open an existing dataset. */
   dataset_id = H5Dopen2(file_id, "/dset", H5P_DEFAULT);

   status = H5Dread(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT,

   for (i = 0; i < 4; i++)
      for (j = 0; j < 6; j++)
        printf("%d ",read_data[i][j]); // 1-24

   /* Close the dataset. */
   status = H5Dclose(dataset_id);

   /* Close the file. */
   status = H5Fclose(file_id);

HDF5 compiler macros

As an alternative (or companion to) CMake, one can use compiler macros for HDF5. HDF group provides compiler macro h5cc linking the needed HDF5 librariesĀ upon installing libhdf5-dev:

h5cc myprog.c func.c -lm
  • h5cc: C
  • h5c++: C++
  • h5fc: Fortran

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.

Detecting HD Radio first adjacent interference

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.


The Magic of Lights display in a Gillette Stadium parking lot in Walpole, Massachusetts used 88.7 MHz. A first adjacent HD Radio station WERS 88.9 MHz 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.

Pirate interference

Pirate broadcasters can be running a multi-million dollar illegal broadcast business. As a result, the well-funded pirates tend to invest in being sure their signal is heard. The pirates will 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 legal or illegal 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.