fm2606 wrote: ↑Sun Jun 30, 2019 1:32 pm
For option 2, that would require me to connect a monitor to the GPIO pins correct?
Erhm, not sure I follow you. Those were not options, but required steps. Also you can't connect a monitor to the GPIO pins, there's a HDMI port for that.
In theory you should connect a video terminal to the GPIO, like the
DEC VT100, but those are not manufactured for a long time now. So instead you connect a PC running a terminal emulator application. Just a side note, the original terminal was basically a monitor with a keyboard connected to the machine over the cheap serial line; and it had keys like "Do", "Copy", "Paste" etc. you will not find on any modern keyboards. Modern keyboards have many Fn keys instead.
You should use a serial cable with 3 wires: DATA TRANSFER, DATA RECEIVE, GROUND. Or more likely an
USB serial cable because recent PCs lack RS232 ports. There don't use red, green is transfer, white is receive, black is ground; and they have nice little endings to plug them into the GPIO header.
Code: Select all
RPi GPIO (pins 14 / 15) --------- RS232/USB (aka COM1, PC running minicom, PuTTY or other similar terminal emulator)
fm2606 wrote:3) This sounds more what I am looking for even though it would require writing my own print routines to take care of it, which is fine.
Your print routine does not have to do anything. The CSI sequences are printed just as any other characters. It is the terminal's duty to interpret them (and indeed they do).
I'll try to explain how this works in more detail.
1. Layer - you application
This could run on the GPU in theory, but most tutorials are for the ARM. This is the one you want to write in Assembly. At this level you construct the sequences into strings to print.
2. Layer - print
This is a user space function used to print strings. This level does not care what's in the strings.
On bare metal you have to implement this yourself, no matter what. On Linux, you can link your application with libc and use printf, or you can implement it yourself. For the latter it should call the system call for write(1, string, length), see the SVC instruction and it's arguments for Linux. The system call hides the other layers from you, so that's all you need for Linux.
3. Layer - hardware
Now if you are not using Linux rather bare metal, then you have to implement the glue code that connects the print interface with the actual hardware. This usually done by iterating on the string and sending each character to the UART (or render the glyph on screen), one by one.
With UART, you have two options: PL011 chip and miniAUX, both are integrated (think of them as COM1 and COM2). You have to initialize them apriori to connect one of them to GPIO header pins 14 and 15, set baud rate etc. Sending one character usually consist of a loop, waiting the UART to became ready to send, and a send operation. These are implemented by reading/writing MMIO addresses of the appropriate UART chip. There are many C examples for this, and it's pretty straightforward to convert those into Assembly.
Now terminals and "dialogs" like raspi-config's boxes are sitting on top of all of these. Your application can print special sequences that the other side receiver should understand, and the other side may send sequences in response that your application must parse (such as key presses). Your application can do this on it's own, it's not that hard if you limit yourself to VT100 sequences only and you don't want to use special keys. But to help applications to handle the many different terminal types with many different keys (hence different sequences), the user space library libncurses was written (we could call this 0. Layer). You link your application with this library and you can use high level functions for drawing boxes and things alike. But under the hood, libncurses just calls the kernel's write(1, string, length) routine writing the appropriate escape sequence, that's all.
Hope this helps,
bzt