-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Terminal mode cursor #80
Terminal mode cursor #80
Conversation
Very nice. For some reason |
Strange—does |
I've pushed two more commits—the first one removes the extra enum, and gets rid of the trait entirely (since it was public, this could technically mean we'd need to version this as 0.3, unlikely as it is that anyone is using it) and the second one is a small change which could be an optimisation or not—basically recursing to the "print a character" case for inserting spaces when printing a newline. Then I realised that actually, a newline probably should not clear the rest of the line, so I made a third commit which makes it behave like an actual terminal in that respect. The only issue there is that because we need the result of the logical cursor change in order to know what to send to the device, there could be a case where the logical cursor is changed but the device cursor is not, resulting in inconsistent state which is what I tried to avoid elsewhere by placing the infallible logical cursor change after the physical data is sent. If you're ok with this, perhaps we could make it a documented property that after any |
Hm, I tried this and either I stumbled right into your described problem or something else is off in the calculations now, i.e. it worked fine in the previous version: If I output a string with a newline character at the end, the linebreak position ends up in some other horizontal position on the screen so when I output some longer runs of text it'll make a diagonal jump somewhere where it's not supposed to do that. |
Sorry, I banged that code out and had not tested it. Should get some time to try to reproduce tomorrow—it's probably some logic bug I introduced. |
So I'm not sure I understand your bug - here are the results I'm getting: disp.write_str("123\n456\nfoo\rbar"); gives me
as expected. disp.write_str("This string is clearly far too long to fit on one line\n456\nfoo\rbar"); gives me
which again seems correct. Can you tell me what the string you tried was, and how it misbehaved? |
I don't have a fixed sequence. I wrote a small application which takes serial input and renders it on the screen. Since my terminal doesn't seem to produce useful character sequences for
|
@mjadczak Okay, I just tried it running it directly with a fixed string and not surprisingly this does the trick as well:
|
fixes it for me; not quite sure why. The whole calculation seems a bit convoluted to me and could use some simplification... |
Ah yes, you're right. What's happening here is that when you go to a new line, the physical cursor is set to the beginning of the new line, but in the logical cursor, only the row is changed, and the current column is not. So, when we have written enough characters such that we would have wrapped (had we not explicitly gone to a new line), we end up just moving down a row—but the assumption there is that we have automatically wrapped around to the first column on the physical screen, and so we don't explicitly tell it to do this, ending up with the other two dots just floating on the line below. The actual fix then is the one I've just pushed, to actually remember in the logical cursor that when we advance to the next line, we go to the first column. I agree that the synchronisation between the logical and physical cursor is a bit convoluted, but I'm not sure how to make it better. Suggestions? |
Not at the moment but I think we can leave improvements to another PR. ;) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks.
@jamwaffles #[deny(warnings)] at its best here. 😅 |
I had to disable |
@jamwaffles I agree that the embedded-hal warnings are a huge annoyance but it's fully independent of what we do here. |
I haven't checked this repo in a while. I noticed this PR was approved, but there are some conflicts and the CI is failing. The fallible v2 traits in #83 should mean that the @mjadczak can I ask you to rebase this PR and fix anything required in the CI? Then this PR can get pushed over the line if people are still happy with it 👌 |
I've rebased this locally but it seems I need to do a bit of work to understand the new way of handling errors, as I have a few functions where I have to materialise an |
You could either map the comms layer error to
Can you push your rebase (even if it fails to compile)? I was investigating your branch and had to rebase it myself. It would be good to save this duplicated effort :) |
3593589
to
26a5aa4
Compare
I've pushed my non-compiling rebase, and I'm taking a look now. I think the biggest issue I had was that /// A method of communicating with SSD1306
pub trait DisplayInterface {
/// Interface error type
type Error;
/// Send a batch of up to 8 commands to display.
fn send_commands(&mut self, cmd: &[u8]) -> Result<(), Self::Error>;
/// Send data to display.
fn send_data(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
} So when I'm writing code which is generic over any particular (also note that I wrote the above before revisiting the code thoroughly, so I may be misremembering / missing something) |
I've just pushed changes which now build on my machine - I have made the lower-level operations inside EDIT: I noticed that the tests are failing because one of the examples |
Sorry it's taken me a while to get back to this. Can you change the error type back to just |
If we're ok with hiding the exact underlying error from the user (by just using |
I'm fine with that approach personally. @therealprof do you have any comments/objections? Otherwise I can merge this PR once the branch is rebased and the build passes. |
Works for me. I'm more concerned with the bloat than with error handling to be honest. And panics, especially with custom messages, do add a lot of that. Since we do have control over the implementations (and I don't think there will be custom implementations of the used traits in this crate) it would make sense to me just remove the associated |
0.3.0 will be breaking due to changes in Embedded Graphics anyway, so we can change this interface for that release. I like the idea of removing the associated type - it will simplify the code quite a bit. Let's explore that in a separate PR so this one can get merged. |
Hey @mjadczak, can you rebase this branch and fix the build when you have a moment? It would be great to get this PR merged! |
Sure! I'll try to take a look this week. Has master now changed to a single error enum? FWIW I have been using a variant of this where I bound |
324cd95
to
ba35a84
Compare
I've rebased on master - for now with the explicit impl of |
Thanks! I'll test this on a physical device as soon as I can. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested on a real device and it works great. I think the doc comments could use a bit of cleanup, but that can happen in another PR for the whole crate. Thanks for your time and hard work!
Released in 0.3.0-alpha.2. Thanks! |
This supersedes #79 by tracking the full vertical and horizontal position ourselves within
TerminalMode
, and implementing line-wrapping manually. This means we can use thePage
addressing mode, so we can write characters to arbitrary points on the screen, while still remaining bufferless. As a bonus, we can handle\r
properly.There may be places that this could be cleaned up—I especially don't like the potential confusion between "pages" and "rows" and the magic
* 8
which needs to be in place (it probably needs a few wrapper types). It does work though—tested manually over I2C on a cheap AliExpress SSD1306 board.Closes #78