Micro Code

Michael's blog about teaching, hardware, software and the things in between

A Glimpse of Things to Come

November 19, 2019 — Michael Engel

Stay tuned for some big changes ahead... see the teaser picture ;-).

The times they are a changing

Tags: teaser

Further back in time!

November 17, 2019 — Michael Engel

Back in the 1990s, some lecture notes were still handwritten. I just rediscovered these in the last folder hiding in a bottom corner of a bookshelf...

This is an excerpt from Wolfgang Merzenich's Programming Languages and Compilers course at Siegen Uni which I attended ca. 1995. 230 very well legible handwritten pages... great! Sadly, Wolfgang passed away far too early several years ago.

PuC lecture notes

Tags: compilers, course, merzenich, siegen

Blast from the Past part 2!

November 17, 2019 — Michael Engel

This piece is a bit more rare than the iPhone 2G and about two years older than the iPhone.

Before Nokia was destroyed by the hostile Microsoft takeover in 2013, they developed innovative early Linux-based mobile devices. The Maemo OS developed by Nokia is based on Debian, GNOME and a number of additional open source components. The Nokia 770 was the first commercially available system in this tablet series, followup devices included the Nokia 800 and 810. This was also the basis for Nokia's Linux-based mobile phones (N900 and N9, more on these in a later post).

This device runs on a 252 MHZ TI OMAP1710 SoC (ARM926EJ-S+C55x DSP) with 64 MB RAM and 128 MB Flash. The 4.1 inch display has a resolution of 800x480 and is usually used in widescreen format. Note that the system has no mobile wireless connectivity, only 802.11 and Bluetooth.

The Linux-based system previously used by Nokia is still being developed by the Jolla guys as Sailfish. Unfortunately, they seem to have only rather moderate success.

Nokia 770

Tags: Nokia, 770, tablet, Maemo

YABftP! (Yet Another Blast from the Past)

November 17, 2019 — Michael Engel

While cleaning out my apartment in preparation for a move, I rediscovered many pieces of hardware I haven't seen for quite some time :-). This is the first piece, so stay tuned...

This first piece is an original iPhone (called 2G, since it ran on GSM (resp. GPRS/EDGE) instead of the strange US CDMA standard - no LTE, UMTS or 5G...). It was introduced in June 2007 and features an ARM1176JZF-S based single-core SoC (Samsung S5L8900, this is long before Apple starts to design their own ARM cores) running at 412 MHz. The 2G uses 128 MB RAM and 8 GB of flash, the 3.5 inch display has a resolution of 240x320 pixels . This iPhone is still running after 12 years and is amazingly useable with iOS 3.1.3 - Safari, Google Maps and email work, whereas iTunes and the youtube app fail to start.

Maybe the CPU core used in the 2G rings a bell. This is the same core as the one used in the BCM2835 SoC in the original Raspberry Pi and the current Raspberry Pi Zero (W). However, the 5€ Raspi Zero has four times as much RAM and the CPU is clocked 2.5x as fast as the iPhone... if we only had the source code for iOS, a port to the Raspi Zero would be a neat hack.

The brochure the iPhone is resting on is of course also interesting for computer history afficionados... the TI Explorer is one of the few commercial LISP machines, based on a NuBus chassis and the TI S1500 asymmetrical multiprocessor 680x0-based Unix systems.

iPhone 2G

Tags: iPhone, 2G, ARM11, TI, Explorer

Assembler in Latin...

July 16, 2019 — Michael Engel

One of the obscure old computers you have probably never seen is the German Telefunken TR440, a 48 bit machine that came to market in 1970 and was intended to be a competitor for IBM's 360 and 370 series mainframes. Well, that didn't really work out...

While reading through the TR440's assembler manual (TR440 Instruction Set on bitsavers), I noticed that the mnemonics used were mostly abbreviations of German words (though I cannot figure out where "C" for store comes from).

If you look at the mnemonics used for Boolean operations, however, you start to wonder about their origin:

Boolean ops in the TR440

...that is, until you remember your high school Latin... et is probably pretty well-known and means and.

Then you figure out that this choice of mnemonics was pretty ingenious, since Latin -- in contrast to English or German -- has separate words for inclusive or (vel) and exclusive or (aut). Nifty!

Tags: Telefunken, TR440, assembler, latin, mnemonics

New Audio Boards

March 24, 2019 — Michael Engel

Long time no post... lots of things have happened (more on this later) since last July. One of the positive results is that we have designed and built new boards for our Signal Processing course.

Like the previously used Keil MCB4300 boards, we use the LPC4357 (dual core Cortex M4 and M0) SoC as basis, here supported by 32 MB of SDRAM as well as NAND and NOR flash. Since we cannot handle BGA parts in-house, we created an adapter to use Waveshare's Open4357 board with our base board designed for the Cortex M3/LPC1778.

Sound is handled by the relatively ancient NXP UDA1380TT codec, as on the Keil board. This chip is discontinued since around the year 2006, so I had to obtain a number via a specialized IC broker. The advantage of using that codec is that we stay compatible with the Keil board and we can reuse our existing driver code. Strangely, Waveshare still sells add-on boards using the same codec chip (only in an LQFP instead of an SSOP package), so they either have some secret source for the chip or invested in a lifetime supply...

One other addition is the nice graphical OLED display that you can see in the picture.

Signal processing board

Tags: audio, DSP, Cortex-M4, signal processing


July 20, 2018 — Michael Engel

I just dug out an old Sparcstation 20 mainboard from my collection, since someone on Usenet was looking for a spare one to fix his broken machine.

Taking a closer look at the board, I found this little sketch of a bear with a top hat. I have worked with Sparc machines for more than 25 years now, but never noticed that little guy before. Neat!

Bear on board

Tags: sparc, sun, workstation, PCB art

More on Oberon

July 08, 2018 — Michael Engel

Reading the Oberon source code, I got the impression that in a large number of places "magic numbers" are used without much explanation (neither in the code nor in the accompanying book).

One thing that had me wondering was the bitmap graphics generation. The Verilog source code (in VID.v) is quite simple. It uses a combination of simple counters to generate a 1024x768 pixel monochrome display. Based on a pixel clock counter, separate counters for the current horizontal (hcnt) and vertical (vcnt) coordinate are derived.

The video memory is addressed in 32-bit chunks, so each video line uses 1024/32 = 32 32-bit words (=128 bytes). The horizonal pixel counter is not 10 bits wide (counting 0..1023), but 11 bits, since it also counts the horizontal traceback time.

From the (10 bit) pixel position in hcnt, a 5 bit word offset in the current line is derived by cutting away the 5 least significant bits:

reg [10:0] hcnt;
reg [4:0] hword;  // from hcnt, but latched in the clk domain

always @(posedge clk) begin  // CPU (SRAM) clock domain
  hword <= hcnt[9:5];

If one wants to figure out which set of pixels is at what absolute memory address in SRAM, one stumbles across some strange things in the code:

localparam Org = 18'b1101_1111_1111_0000_00;  // DFF00: adr of vcnt=1023
assign vidadr = Org + {3'b0, ~vcnt, hword};

The binary constant in the Verilog code omits the two least significant bits of the address, since the 1 MB memory of the Oberon FPGA system is 32-bit word (4 byte) addressed; the address constant 0xDFF00 in hex gives the byte address of the frame buffer.

The display driver code in Display.Mod, however, gives a different frame buffer start address:

base = 0E7F00H;  (*adr of 1024 x 768 pixel, monocolor display frame*)

There's something fishy... the base address in the Oberon driver and the one in the Verilog source code differ by 0xE7F00-0xDFF00 = 0x8000 = 32768 bytes. So, what is going on here?

Pixels are set using the following function:

PROCEDURE Dot*(col, x, y, mode: INTEGER);
  VAR a: INTEGER; u, s: SET;
BEGIN a := base + (x DIV 32)*4 + y*128;
  s := {x MOD 32}; SYSTEM.GET(a, u);
  IF mode = paint THEN SYSTEM.PUT(a, u + s)
  ELSIF mode = invert THEN SYSTEM.PUT(a, u / s)
  ELSE (*mode = replace*)
    IF col # black THEN SYSTEM.PUT(a, u + s) ELSE SYSTEM.PUT(a, u - s) END
END Dot;

The address for a pixel at position (x,y) is calculated as base + (x div 32) * 4 + y * 128. This sounds reasonable - each line is 128 bytes (128 * 8 = 1024 pixel) wide, x div 32 gives the word address offset in the current line, which is multiplied by 4 to give the word's byte address.

Accordingly, the pixel at address (0,0) is contained in the word at address 0xE7F00. But the Verilog source code starts reading the video buffer at address 0xDFF00... or does it? Let's take a closer look:

assign vidadr = Org + {3'b0, ~vcnt, hword};

When calculating the video memory address, the vcnt counter is inverted. Thus, the pixel at position (0,0) is at memory address (trailing "00" added to give the byte address):

0xDFF00 + { 000 1_1111_1111_1 000_00 00 } = 0xDFF00 + 0x1FF80 = 0xFFE80

Wait, that's still not right - what was the start address in the Oberon source again?

base = 0E7F00H;  (*adr of 1024 x 768 pixel, monocolor display frame*)

That's 0xFFE80-0xE7F00 = 0x17F80 = 98176 (dec.) bytes from the start!

Hmmm, wait... that's vaguely familiar. The whole monochrome 1024x768 bitmap screen uses

1024 / 8 * 768 = 98304 bytes

and 98304-98176 = 128, the memory used by one line of pixels. This works out since we were calculating the address of the leftmost pixel in the line.

Maybe you have already figured out what is going on here... Oberon's graphics coordinate system starts in the lower left corner of the screen, whereas the monitor's coordinate system starts at the upper left corner (see Chapter 4 in Wirth's Oberon book). Thus, the line at Oberon's coordinate y = 0 is the 767th line in monitor coordinates. Accordingly, inverting the y line coordinate in the Verilog address calculation

assign vidadr = Org + {3'b0, ~vcnt, hword};

causes the vertical line counter to count backwards. Note that the x coordinates of Oberon and the monitor count from left to right, so hword is not inverted.

The final remaining question is why the video base address is different. This is now also rather easy to see. vcnt is a 10-bit counter, so it counts from 0...1023. The Oberon y coordinates only are valid up to 767, so the 767th Oberon line = 0th monitor video line is at address

767 = 10_1111_1111 (binary), inverted = 01_0000_0000
0xDFF00 + { 000 0_1000_0000_0 000_00 00 } = 0xDFF00 + 0x08000 = 0xE7F00

Voila, there's the video memory start address that's defined in the Oberon driver source code.

If you take a closer look at the Draw function, you might now wonder what will happen if you pass a y coordinate larger than 767 to the Draw function. More on this in an upcoming blog post...

Tags: FPGA, Oberon, Xilinx, Wirth, graphics