Closed mjadczak closed 4 years ago
@mjadczak that observation is absolutely correct. The reason for that is that this is the only way to operate completely stateless since the display is essentially write-only. It might be possible to keep track of the cursor position and advance accordingly to the next line on a newline "character".
Would you like to give it a try?
I was making the assumption that the terminal mode had to keep track of the position anyway in order to know when to go to the next line, but it seems that this is done in the display chip itself.
In any case, I'll try to get a bit more familiar with the display's commands and give this a go (it would also be nice to support \r
, and I also see some references to "scrolling" in the commands - when put together it would make for a more usable mode that better emulates a "terminal").
@mjadczak The interesting bit about this mode is that it does progressive rendering so it only needs to write the data which is supposed to be displayed next (vs refreshing the whole frame with every update). Unfortunately the SSD1306 is pretty dumb which means this also significantly limits the options what we can do. Newlines should be pretty easy to implement if we know the vertical position (simply update the position with every printed character and if a newline is encountered, fill up with the required amount of blanks to reach the first position in the next line).
Anything beyond that will likely require some voodoo.
Scrolling would be cool, maybe that is indeed possible with some command foo; haven't looked into it. Carriage return would also be nice to have but that would not only require the column position but also the ability to reposition the memory pointer in the display. Might be possible, but maybe not.
Yeah, my mental model (before reading the actual datasheet) was that it functioned as some sort of addressable character display in this mode, but I realise that's incorrect. I'll have a read through the datasheet and see what's possible here (though I agree that newline implemented with writing spaces is a simple solution which should definitely be possible and I'll attempt that first).
I think there is a hierarchy of what we could do to TerminalMode
in order to improve it in this regard, with each step increasing both the usefulness but also the complexity of the mode. My feeling is that at some point it becomes a different mode (CharacterMode
?) but I'm not sure at which point.
\n
by maintaining a simple u8
counter which is incremented every time we write a character. When we encounter a \n
character, we mod the counter with the line width to obtain "the number of characters on the current line", from which we can easily get the number of spaces we need to insert to go to the next line. We can manually wrap this counter to 0 when we wrap around to the top left corner, or just let it wrap around naturally if the line width divides into 256.\r
(though could, in theory, be done). Instead, at this level I would propose moving into page-addressing mode, and keeping track of both the horizontal and vertical position (in terms of characters, not pixels) on the screen. This would mean we would have to handle line-wrapping logic, but would easily be able to handle both \r
and \n
. As a bonus, we could offer an explicit set_cursor(x, y)
, again in character coordinates, to offer a more powerful but still bufferless interface for users (e.g. outputting a few fixed-width pieces of information on the screen in different places).GraphicsMode
, and buffer the contents of the screen as characters rather than as pixels (I imagine this would be a circular buffer of lines). Then, on detecting a line wrap at the bottom of the screen, we can shift the circular buffer and redraw the whole screen, effectively implementing terminal scrolling.Any thoughts on the above? I'm happy to give all of these a go, but as I mentioned I'm just not sure they all belong in TerminalMode
.
I'd start with the 1) and then take it from there. 2) and 3) might be implementable using some clever trickery but introducing a buffer is a big no-no.
I've implemented 1 in #79. 2 would require some changes to the DisplayProperties
to allow an API to use the paging mode for arbitrary addressing, but I also think it's reasonably straightforward to implement.
@mjadczak Arbitrary addressing would also enable partial screen updates which is would be a great thing to have IMHO.
@therealprof I've made another PR #80 (which supersedes the earlier one) which implements 2) and therefore has arbitrary addressing and \r
handling.
TerminalMode
does not treat newline characters in any special way. Instead, they hit this case which just renders an empty bitmap for that character. I think that theTerminalMode
would be much more useful if it recognised\n
and skipped to the beginning of the next line.