Text only console (VGA) instead of HDMI to free up PRU GPIO pins?

I have a BBB project in mind that would replace an old DOS machine, making use
of one of the PRUs, and it would need about a dozen or so high speed GPIO pins.

To do this project, I can see I’d need to disable HDMI to free up the needed GPIO,
but a text mode console is kinda required; something that can display text reasonably quickly
using direct screen memory access (not slow like a serial port).

Is there such a thing as a text-only cape that the linux kernel can boot with as its default console?

In my case just 80x25 monochrome text is fine.

I could see this being useful for a lot of industrial applications where a graphics screen isn’t needed,
just a high speed text console.

I don’t understand your target.

When you need high speed GPIO and a controller running on a PRU, your controller will operate at a frequency beyond 10 kHz.

Even if you manage to write messages that fast directly to the text screen, nobody can read that fast (the human eye takes ~ 7 picture a second). Even messages at the standard (serial) console are often faster than anybody can read.

What kind of messages should your project provide in a speed that nobody can follow?

I didn’t want to get into the specifics of the project to avoid derailing the focus of the question,
(does a text mode only cape exist?) but if it helps, here are some details:

The text screen will be displaying large frame counters for motion picture film that will run in
realtime while the motors are spinning.

The counters have to be able to update quickly without “wiping” during drawing, so that one can
actually read them easily as they roll by. Even if they can’t read the fast moving digit, they can read
the slow moving ones (depending on the motor speed), to tell where they are in the shot. The operator
needs this information for various reasons (E-stop, knowing when the end of the shot they’d setup approaches…)

The PRU won’t be driving the screen, the PRU will be handling flipping bits on multiple stepper motors.
The main program (running in linux) will be (a) feeding stepper motor velocities to the PRU code through
a ring buffer and will also handle updating the large frame/position counters based on the stepper motor’s
current positions, all while the motors are running. The main program should be able to keep well ahead of
the PRU in generating velocities to the ring buffer, and has plenty of time to update the counter screen.

The counters are “large”; each digit being a 4x3 matrix of ASCII characters (or if available, IBM PC graphics
characters, e.g. codepage 437, if available) to make each digit.

Writing directly to screen memory avoids the main program wasting any time waiting for e.g. a serial controller
buffer or a linux printf()/puts()/write() tty buffer flush to push out a combo of ANSI cursor positioning to redraw
the counters, and avoids the user seeing the text “wipe” as the counters are redrawn, seeing partially drawn
characters, and a text cursor flying all around the updating counters (looks terribly ugly).

But I really don’t want to derail into more details on that subject; suffice it to say the goal is to free up the high speed

GPIOs normally used by HDMI, yet still provide a text screen of some kind that can be updated very quickly
(screen memory would be great, or perhaps some other high speed way to update without using up the high speed
PRU gpio pins). VGA would be best, because then the end user can choose a large screen (instead of a small LCD).

A "VGA" DISPLAY is NOT a "text mode display" -- it is the VGA adapter
card in the computer that contains the logic to accept text (ASCII) and
render it using built-in glyphs, but the display itself is still graphical,
being continuously fed with RGB and sync signals to refresh the display.


  So... I don't see anything feasible... You'd be using something to
render a low-resolution frame buffer, and somehow transferring that frame
buffer to the actual display device (a slow process if being done in
software <G>). In short, duplicating what the HDMI/LCD framer is already

  Probably faster to just hook a VT100 to a serial port and set it to 56
or 115 kbps. Let the terminal handle the rendering of the text.

Your subject is miss-leading. You’re searching for a display.

You can either use a text only display, ie with I2C or SPI interface.

Or you can still use a HDMI monitor, since you need not disable all HDMI pins. Just keep one or three of them for a black & white frame buffer.

BTW: The HDMI pins block PRU-1 GPIO. Only 16 inputs / 15 output are avialable. Instead running on PRU-0 you can have the full set (17 inputs / 16 outputs) and HDMI in parallel. (You’ve to wire some GPIO to the SD card slot.)

So instead of writing maybe 20×5 characters to redraw a counter, you
believe re-rendering and re-painting a 160×40 pixels is going to be faster?

Your subject is miss-leading. You’re searching for a display.

Ah, you must mean, my use of “console”.

I was referring to the “linux console” (/dev/console), which is usually a VGA card in text mode on IBM PCs.

But yes, I guess I mean a display cape, or some kind of text only display hardware/software combo that linux
could boot with as the boot console, and allows fast screen updating.

You bring up some interesting things that sound good:

You can either use a text only display, ie with I2C or SPI interface.

I haven’t experimented with these – guess I should look into such devices with fast update rates.

I did fall across this which maybe looked promising in that it’s a device acting as a linux console:


It’s a bit under my spec; 40x16 instead of 80x25, and a bit small physically. But maybe I can find some
larger I2C oriented displays.

Or you can still use a HDMI monitor, since you need not disable all HDMI pins. Just keep one or three of them for a black & white frame buffer.

Hmm, that sounds cool.

Are there any docs to guide on how to tweak the HDMI virtual cape to black+white mode?
In my application I don’t need color.

BTW: The HDMI pins block PRU-1 GPIO. Only 16 inputs / 15 output are avialable.
Instead running on PRU-0 you can have the full set (17 inputs / 16 outputs) and HDMI in parallel.

Mmm, perhaps you can help clear this up for me; the BBB pin assignments definitely has me confused.

I did find this table which seems to show only 10 outputs available to PRU0 via register __R30,
and only 14 outputs available to PRU1.

Since PRU0 doesn’t compete with HDMI, I could use that, but that means I’d be limited to running 5 motors.
(5 x steps+direction = 10).

If I used PRU1, I take it I could run 7 motors (7 x steps+dir=14), but that means (I think?) stopping HDMI entirely,
so that my code can run in its place.

Is this correct, or am I missing something? Not sure how to get 16 outputs from one PRU, or how to do it
without disabling HDMI completely.

Thanks in advance for any clarity on this…!
I’m definitely drowning a bit in large PDFs and spreadsheets/tables, and trying to see my project fit into all this.

Hmm, no, not at all.

With a VGA device in text mode, screen memory is one byte per character, no pixels,
so writing 20x5 characters is writing 20x5 bytes into screen memory.

The hardware handles turning the character memory into streams of pixels to the VGA connector,
each character’s pixel matrix provided by e.g. the cape’s hardware.

Oh wow, I guess this is close to what I was looking for:

I can’t tell if it’s a dead project (“Discontinued”) or a work in progress (“Manufacturer’s link available soon”)

Also, it sounds like it still uses a lot of pins… probably because it’s supporting full VGA including VGA graphics modes.

You’re searching for an of-the-shelf solution. So the best advice is to use the standard HDMI output and running on PRU-0.

I did find this table which seems to show only 10 outputs available to PRU0 via register __R30,

and only 14 outputs available to PRU1.

This table is incomplete. It neither mentions the JT header pins nor the pins at the SD-card slot. The table is about the capabilities of the standard pinmuxing tools (CapeUniversal/config-pin).

Check out the table in the link I mentioned above.

… and HDMI in parallel. (You’ve to wire some GPIO to the SD card slot.)

Using libpruio pinmuxing, you can additionally use six further pins at the SD-card slot (by the “costs” of less kernel memory consumption and a faster boot process).

The only required hardware is a matching connector. If you need storage for big data, use a USB memory stick instead of the SD-card.

If it acted as a real VGA board (with VGA rendering circuits and
memory) it would probably take a LOT more pins. Real VGA boards were
memory-mapped into the processor space (for that era, that means it likely
had 16 address lines) along with 8 data lines.

  Since the Beagle does not expose the processor address lines (except
possibly for RAM, if the RAM is not inherent to the SoC itself) that means
using GPIO to emulate a parallel address bus, along with GPIO for the 8-bit
data bus... OR one uses a serial transfer to send address and data
information -- in which case one is talking I2C or SPI (or pure UART), and
one is giving up the speed advantage of parallel I/O ports&addressing.

  There is a lack of information for that cape -- but I'm willing to lay
odds at 90% that the cape does NO VGA rendering. I suspect it was simply an
LCD <> VGA converter, using a number of gates to combine digital LCD color
information into VGA analog RGB. It most likely requires the native
LCD/HDMI framer to do actual rendering of the image, with the LCD driver
configured for horizontal/vertical sync at VGA speed.

OK – yeah, that makes sense.

I was trying to envision a text mode only VGA cape that could maybe use
6 bits GPIO; 4 for a data nibble, and one to strobe the nibble, and just have
a write only interface to the 4k of onboard text memory, sending an X, Y position
to write to, and an 8 byte character, and optional attribute char.

Which is maybe fine for making a dumb terminal, but operations like scrolling
become a headache, since partial window “region scrolling” is needed for applications
like VI which allows horizontal split screen, one can’t really use a tty like interface
unless one supports full ANSI/XTERM on the cape. Then we’re basically back to
a VT100. :-/

OK, so I get it – that’s kinda a dead end.

The only way I could see out of that situation is maybe to use PRU0 to offer
4k of shared memory to the processor as ‘screen memory’, and the PRU constantly
snapshots that memory to the cape’s text memory as fast as it can, and the cape
handles converting the text chars to glyphs and a pixel stream to a VGA out connector.

I’m not familiar at all with what the Arm provides, but Stuart sent me a few emails
giving me some idea about that; I take it internally everything’s very pixel oriented,
which probably slows things down a bit when it comes to text; fast enough for most
purposes, maybe even my purposes, I should do some tests.

I did do a quick test writing my counters to /dev/vcs while on the BBB’s text console
(HDMI enabled) and it worked perfectly from a screen layout point of view. Should probably
do a speed test to see how fast I can update the counters.

But I take it writing to “text screen memory” via /dev/vcs might be handled by the linux
drivers as a software operation, converting the text chars into pixels /in software/, is that correct?
And by “in software”, I take that to mean, by the linux host processor itself, which means the pixel
conversion process eats into the processor’s cpu time? Which might be bad for me, since I’ll
also be trying to update motors. AFAIK the Arm is single core, so some of that cpu load couldn’t
be offloaded to another core.

Mmm, I see, I see…

Not at all!