Other and non-digital radio stuff.

When, around 2012, the cheap SDR devices were "discovered", the first program I wrote for these devices was something to see a whole spectrum. Devices like an SDRplay have a maximum width of say 8 MHz, so half of everything that appears in the FM band can be made visible in a single picture. The spectrumviewer is an ideal program for that, it is able to handle input from a variety of input devices (of course if such device is in the configuration) and it has no less that three "scopes".

The picture shows the spectrum with a width of 5 MHz, using an SDRplay (the control for the device is on a separate widget, now shown), using a simple "whip". The top display shows the spectrum of the signal, with the second one showing the spectrum as a waterfall. The third one, smaller, allows you to look in greater detail to a segment of the spectrum. While it is fun to look at a wide spectrum, sometimes one then wants to zoom in at something. he amount of detail is determined by the decimation setting, a range between 5 and 100. Of course a scan over a selected frequency range is also possible.

Added is a view on the signal - as presented to the detailed viewer - as appearing in the time domain.


Sometimes one wants to get a glimpse of a whole band, no details, just an overview. The picture below shows - as an example - what one gets with a simple whip in the range 550 .. 650 MHz on the so-called panorama viewer. Other tools focus on details, this one on the global view.


The width can be set. Since the picture is built up from frames - in this case frames of 8 MHz width, it takes some time to build pictures with a larger width, such as the one below, covering the range from 200 .. 1000 MHz. Of course, when mapping a spectrum with a width of - say - 500 MHz on a screen with - say - 1000 pixels, details are lost.

The panoramaviewer can also be used with devices like the SDRplay (with support using the 2.13 library as well as the 3.0X library), the airspy, and the RT2832 based DABsticks.


Algol 60

Very long time ago, Algol 60 was an important programming language. While not always popular, it was often used for introductory programming courses and for description of algorithms. I wrote my first programs in Algol 60, using punched cards on an ICL 1905 computer (with turn around times of at least a day per run).

In the 70-ties I wrote a compiler for Algol 60, on the PDP-11 and for the PDP-11 instruction set (using threaded code as virtual machine). The compiler was originally written in BCPL, later, when Unix was there, recoded in C. The sources of these versions were - obviously - lost.

Around 2002/2003, I wrote in spare time, a new version of the compiler (taking into account that the 64 K limitation of the PDP-11 memory was gone). The compiler just builds an annotated parsetree in memory and - in a few passes - generates the resulting C code.

The objective was to write something that produced regular C code rather than some P-code like stack machine. Semantics of typical Algol 60 constructs such as call by name, and unspecified procedure parameters could then be explained as regular C code constructs to students (although I had no direct involvement in education at that time).

Almost as a miracle, a few years ago the sources were discovered on some old floppy discs, and with only a few minor changes the compiler could be compiled and ran. Sources can be found in this repository The repository also contains a number of example programs.

Recently an addition was made, the compiler was used in France, and a command line parameter parameter was added to let the compiler accept French keywords, rather than the default British/US style keywords.

This manual is a user's guide and describes - in about 20 examples - in quite some detail the mappings of Algol 60 constructs in the resulting plain C code. Actually, the compiler works pretty well on my x64 based laptop and my RPI 2 and 3. And, yes, the compiler has no problems with the so-called "man-or-boy" problem.

As an example, the following program is typical Algol 60, demonstrating the so-called Jensen's device

	array a[1:4];
	real t; integer i;
	real procedure jensen1 (i,a); integer i; real a;
	   real s;
	   s := 0;
	   for i:=1 step 1 until 4 do s := s + a;
	   jensen1 := s;

	for i := 1 step 1 until 4 do a[i] := i + 1;
	t := jensen1 (i, a[i]);
	outreal	(1,t);
	outstring (1,"\n");

Running this program gives the number 14 as result. By name parameters were essentially kind of implicit parameterless procedures (implemented as thunks). For each parameter, the compiler creates two thunks, one for the evaluation of the parameter to an address, one for evaluation of the parameter to a value.

As an example, the procedure jensen1 is translated into

 /* jensen1 declared at line 5 */
_jensen1_46 (char *Li_, int (*Ai_) (char *, int), int (*Vi_) (char *, int),
	     char *La_, double (*Aa_) (char *, double), double (*Va_) (char *,
  struct ___jensen1_46_rec local_data_jensen1;
  struct ___jensen1_46_rec *LP = &local_data_jensen1;
  LP->Li_ = Li_;
  LP->Ai_ = Ai_;
  LP->Vi_ = Vi_;
  LP->La_ = La_;
  LP->Aa_ = Aa_;
  LP->Va_ = Va_;

  {				// code for block at line 8
    (LP)->_s_48 = (double) (0);
    for (((LP)->Ai_) ((LP)->Li_, 1);
	 (((LP)->Vi_) (((LP)->Li_), 0) - (4)) * sign ((double) 1) <= 0;
	 ((LP)->Ai_) ((LP)->Li_, ((LP)->Vi_) (((LP)->Li_), 0) + 1))
      (LP)->_s_48 = ((LP)->_s_48) + (((LP)->Va_) (((LP)->La_), 0));
    (LP)->__res_val = (LP)->_s_48;
    ;				// null statement 
  return LP->__res_val;

the actual parameters i and A [i] in the procedure call

	t := jensen (i, a [i]);

are each translated into two parameterless procedures (thunks), one to handle the parameter as left hand side for an assignment, one to evaluate the parameter to a value.

int A_jff_0A (char *LP, int V) {
  return _i_45 = V;

int _jff_0A (char *LP, int d) {
  return _i_45;

double A_jff_1A (char *LP, double V) {
  return _a_45[_i_45 - 1] = V;

double _jff_1A (char *LP, int d) {
  return _a_45[_i_45 - 1];

Of course, these thunks are trivial since they relate to variables in the outermost block, variables that are implemented as global variables in C.

The main program as generated by the compiler, then is

// The main program
int main () {
  char *LP = (char *) NULL;

  {                             // code for block at line 2
    for (_i_45 = 1; (_i_45 - (4)) * sign ((double) 1) <= 0; _i_45 += 1)
      _a_45[_i_45 - 1] = (double) ((_i_45) + (1));
    _t_45 = _jensen1_46 (LP, A_jff_0A, _jff_0A, LP, A_jff_1A, _jff_1A);
    outreal (1, _t_45);
    outstring (1, "\n");
    ;                           // null statement

Of course, thunks referring to expressions containing references to local variables and function calls are slightly more complex.

As said, the documentation contains a number of Algol 60 examples together with their translations, and the source tree contains a number of these and other example programs.