Skip to content
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

Add option to suppress terminal output on display (if present) #2791

Closed
k3wals opened this issue Apr 21, 2020 · 54 comments
Closed

Add option to suppress terminal output on display (if present) #2791

k3wals opened this issue Apr 21, 2020 · 54 comments

Comments

@k3wals
Copy link

k3wals commented Apr 21, 2020

I was able to suppress the terminal output to a display by commenting the following lines:

//supervisor_start_terminal(width, height);

within:

It would be convenient to disable the terminal display output in boot.py perhaps.

Blinka icon is still present though momentarily.

@dhalbert suggested I open an issue after discussing on Discord.

@tannewt
Copy link
Member

tannewt commented Apr 21, 2020

@k3wals What is your reason for this?

@k3wals
Copy link
Author

k3wals commented Apr 21, 2020

The make the device a bit more product like for demo use. Don't need the verbose info to non-technical user.

I think I'm going to replace the bitmap_data with a static image with text such as "Contact XYZ and cycle power". Perhaps show a more intelligent error code if possible.

@hierophect
Copy link
Collaborator

I can see the appeal of this when used in a product. Is it feasible this could be added as a build flag?

@ladyada
Copy link
Member

ladyada commented Apr 29, 2020

perhaps it would make more sense if it was handled in boot.py somehow?

@tannewt
Copy link
Member

tannewt commented Apr 30, 2020

I can see the appeal of this when used in a product. Is it feasible this could be added as a build flag?

Note that CircuitPython is not intended for use in a product and we provide no warranty. It's up to a product creator to understand CircuitPython enough to supply a warranty to their customers.

If they ship with a custom build of CircuitPython they should call it CircuitPython-compatible and not vanilla CircuitPython. CircuitPython has more meaning than just the code base.

@hierophect
Copy link
Collaborator

@tannewt I don't mean a literal commercial product necessarily, and I don't mean to imply anything by that statement regarding warranty or legality. I think the point here is that removing the automatic terminal display just adds a bit of polish when a project is demonstrated to non-technical users. Even just from an aesthetic standpoint I think this request is valid - if an artist was using DisplayIO for something and doesn't want a bunch of technical output on reboot, is that so unreasonable?

@k0d
Copy link
Collaborator

k0d commented Apr 30, 2020

I'm adding a debug_console (VCP on stm32) at the moment, that will be enabled via a build flag, we could add one for the display_console at the same time?

@tannewt
Copy link
Member

tannewt commented May 1, 2020

I don't think it should be a build flag because then building would be required to change.

I think adding something to boot.py is ok.

However, I don't think it's really necessary. One can show an empty group on the display both in boot.py and code.py very early to minimize when the terminal appears. I don't like the idea of a hard disable because it's helpful to have it appear on crashes.

@k0d I think the debug console is fine at build time because I assume folks are already building their own in that case.

@k0d
Copy link
Collaborator

k0d commented May 1, 2020

@tannewt I agree 100%

@dhalbert dhalbert added this to the Long term milestone May 26, 2020
@ricardoquesada
Copy link

Another use case: interactive experience, good for teaching

  • You have a LED matrix display (could be any other display)
  • you want to enable/disable a certain pixel from REPL

right now, whenever I type something on REPL, I see it on the display as well, and the pixels get "erased".

@ricardoquesada
Copy link

nevermind, found a solution that works for me.
Compiling it with make CIRCUITPY_TERMINALIO=0 does what I needed.

@tannewt
Copy link
Member

tannewt commented Dec 23, 2020

@ricardoquesada If you are using displayio, the terminal shouldn't override your displayio Group. How are you setting a pixel?

@ricardoquesada
Copy link

ricardoquesada commented Dec 23, 2020

Thanks, I'm setting the pixels like the following:

# Enter this from REPL
import board
import busio
import displayio
from adafruit_matrixportal.matrix import Matrix

matrix = Matrix(bit_depth=2)
display = matrix.display
bitmap = displayio.Bitmap(64,32,2)
palette = displayio.Palette(2)
palette[0] = (0,0,0)
palette[1] = (255,0,0)

grid = displayio.TileGrid(bitmap, pixel_shader=palette)
group = displayio.Group()
group.append(grid)

display.show(group)
bitmap[1,1] = 1

I'm using a matrix LED + matrixportal_m4.
And I was typing everything from REPL.

  • With CIRCUITPY_TERMINALIO=0, the only thing that I see when the MCU boots it the Blinka logo (and nothing more... what I was looking for).
  • Without CIRCUITPY_TERMINALIO=0 (default option), what I see on the LED matrix is exactly what I see in the REPL... so if I change a pixel from REPL, the pixel might change, but immediately the LED matrix is filled with the REPL output

@tannewt
Copy link
Member

tannewt commented Dec 28, 2020

Hrm. I don't use REPL regularly but it sounds like a bug. Why are you using the REPL for this?

@ricardoquesada
Copy link

mostly for prototyping and doing quick tests.
Also, I'm building a "computer for my kids" using CircuitPython for the API, and I want them to try things using REPL. Things like:

>>> set_pixel([0,1], RED)
>>> play_music("CDEFGAB")
>>> move_sprite(sprite, (x,y))

...and that will give them immediate feedback of what's happening.

@tannewt
Copy link
Member

tannewt commented Dec 29, 2020

@jerryneedell Do you know if the REPL will overwrite the display while it's in use?

@bitboy85
Copy link

I would go further and think this should be disabled by default. This behaviour is unexpected and a small display like the 128x32 shows only two and a half lines. Of course with no useful information.
If someone really needs this output it should be explicitly enabled.
Maybe like this:
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=WIDTH, height=HEIGHT, rotation=180, console=True)

@tannewt
Copy link
Member

tannewt commented Mar 16, 2021

I would go further and think this should be disabled by default. This behaviour is unexpected and a small display like the 128x32 shows only two and a half lines. Of course with no useful information.
If someone really needs this output it should be explicitly enabled.
Maybe like this:
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=WIDTH, height=HEIGHT, rotation=180, console=True)

I strongly disagree. It's useful to know things are running and for most boards the display showing errors is extremely helpful. Getting a serial connection to see errors is a big hurdle for some folks.

@aivarannamaa
Copy link

It looks like the need to update display makes using REPL slower. It may not be relevant for manual usage, but Thonny, for example, uses REPL for management tasks (eg. for querying variables and available modules) and also for running code from the active editor. Because of this, using TrinketM0 in Thonny is much smoother experience compared to CLUE (which contains faster processor, if I'm not mistaken).

What about turning off output mirroring when CircuitPython enters REPL? I assume the REPL can only be entered via working serial connection (or, at least this is the main way for using it). In this case I find it unlikely that anybody prefers to look the output on a tiny (or smallish) screen instead of her terminal program.

@bitboy85
Copy link

I strongly disagree. It's useful to know things are running and for most boards the display showing errors is extremely helpful. Getting a serial connection to see errors is a big hurdle for some folks.

I agree that it might be useful for debugging purpose, but for this reason i also think it should be disabled by default because most software has disabled debug output unless you really want it.
Instead of using an additional function parameter there might be other solutions like a global debug variable in boot.py.

@tannewt
Copy link
Member

tannewt commented Aug 2, 2021

What about turning off output mirroring when CircuitPython enters REPL? I assume the REPL can only be entered via working serial connection (or, at least this is the main way for using it). In this case I find it unlikely that anybody prefers to look the output on a tiny (or smallish) screen instead of her terminal program.

I like that it shows on the REPL. You could have thonny do displayio.release_displays() to turn it off completely. You would need to know how to reinitialize a display then though.

I agree that it might be useful for debugging purpose, but for this reason i also think it should be disabled by default because most software has disabled debug output unless you really want it.

I strongly disagree that it should be off by default. Seeing the serial error output is one of the trickiest parts of the usb workflow and having the display show errors by default greatly simplifies it.

@adrian-the-git
Copy link

I think CircuitPython is and should be a "debug features ON by default" environment, but it would be great to have the ability to disable the REPL without rebuilding (I'll save my comments on why it's undesirable to do so for an appropriate thread).

So anyhow, on a 64x32 matrix panel, the onscreen REPL doesn't really fit, so the output line which I'm interested in reading is not visible, with Blinka looking more like a flamingo than a snake, and it just looks like a graphical glitch—it's not a nice boot screen for a creative project. So I'm agreeing with @hierophect who made this point about artists wanting to control the aesthetics.

Now asking for confirmation @tannewt that we should not expect a hard switch to disable terminalio, but instead should display an empty group in boot.py? So sayeth the developer on this enhancement-labeled issue?

@tannewt
Copy link
Member

tannewt commented Aug 12, 2021

I think CircuitPython is and should be a "debug features ON by default" environment, but it would be great to have the ability to disable the REPL without rebuilding (I'll save my comments on why it's undesirable to do so for an appropriate thread).

Why doesn't displayio.release_displays() work? That would allow you to control when the display is initialized.

@domdfcoding
Copy link

I tried using displayio.release_displays() in boot.py, but I still get a flash of the blinka logo when the device boots up and when reloading the script.

I found that the initialization of a FramebufferDisplay (in my case via a Matrix object from adafruit_matrixportal.matrix) displays the terminal (and blinka) in the brief time until something else is shown on the display. I managed to stop this by setting auto_refresh=False when creating the FramebufferDisplay, and setting it back to True after .show()ing something on the display. Not super elegant, so it would be great for a proper solution.

@zestyping
Copy link

zestyping commented Jan 28, 2022

@tannewt I agree that it's useful to have easily accessible error messages when a program crashes, and that setting up a serial connection to see errors is hard.

The problem is that, when I look at the current implementation:

  • Displaying a flash of the logo and console on startup has nothing to do with showing errors on a program crash; the first is not necessary for the second.
  • Displaying error messages on the LED matrix does not make them accessible; the console output is typically unreadable on a 64x32 matrix. In particular, the most important information about the exception is almost always scrolled off or cut off.

What if we considered an implementation like the following?

  • By default, nothing is displayed on the LED matrix on startup
  • The REPL does not display on the LED matrix (if you're typing into the REPL, you already have a serial connection)
  • If the program exits with an exception, the most essential information about the exception is displayed on the matrix (filename, line number, exception type and message) in the smallest possible readable font

Would that meet the needs you're expressing, in addition to those expressed by @k3wals, @hierophect, and @bitboy85 in this discussion?

@xgpt
Copy link

xgpt commented Jan 29, 2022

Displaying a flash of the logo and console on startup has nothing to do with showing errors on a program crash; the first is not necessary for the second.

Echoing what @zestyping is saying, it's pretty annoying and looks a little...beta-ish? don't understand why we have to see blinka by default.

@bitboy85
Copy link

Is currently someone working on this? There are edits to remove blinka and, i guess, the terminal output.
https://github.com/adafruit/circuitpython/blob/main/supervisor/shared/display.c

@tannewt
Copy link
Member

tannewt commented Mar 15, 2022

I don't think there is work to disable it completely. deshipu only added a flag to remove the Blinka logo: #5298

@justinesmithies
Copy link

I too would love to be able to disable the logo and the terminal output from my ssd1306. At the moment I'm having to use the adafruit_ssd1306 driver instead of the adafruit_displayio_ssd1306 because of the issue when my code that displays a splash in the boot.py and it finishes in the gap between code.py starting I see the logo and the words "code.py running" which is not what I want to see. Using the other driver it just seamlessly changes from one image to the next image that is ran from code.py no interruptions in between. Hope that made sense as it did in my head lol ??

@tannewt
Copy link
Member

tannewt commented Mar 22, 2022

@justinesmithies Would it be ok for you to have the splash setup in code.py? That way you won't have a gap where CircuitPython has control of the display.

@justinesmithies
Copy link

@justinesmithies Would it be ok for you to have the splash setup in code.py? That way you won't have a gap where CircuitPython has control of the display.

Yeah minutes after submitting my comment that exact thought popped into my head. But it would be good and I'm sure that I'm not alone to have some kind of option in displayio to disable the terminal output / logo.

@bitboy85
Copy link

I've seen another flag called CIRCUITPY_TERMINALIO so i guessed its for disabling the terminal output...

@kmatch98
Copy link
Collaborator

Not sure your exact need is, but if you are ok with disabling the terminal in the python-side, you can make use of this recently-added feature and move the root_group outside of the visible display. Keep in mind the terminal will still be present in memory and will reappear whenever you fall back into the REPL.

If you want to prevent an image from flashing on the screen, you can set auto_refresh to false while you make the change you need, and then re-enable it. On second thought, I'm uncertain what happens between boot.py and code.py, maybe that will automatically update the auto_refresh.

@bablokb
Copy link

bablokb commented Jun 16, 2022

I have an additional use-case: I use an OLED to display some info and then go to deep-sleep (exit_and_deep_sleep_until_alarms). As soon as this is executed, the REPL takes over and replaces my content with that very important information that the program is running :-(

Releasing the display before going to deep-sleep is a workaround, but this is clumsy. And I'm not sure if this works with every kind of display. Also, "simulated deep-sleep" does not seem to release the display and bails out after restart.

tannewt added a commit that referenced this issue Aug 5, 2022
* Tweak scroll area position so last line is complete and top is
  under the title bar.
* Pick Blinka size based on the font to minimize unused space in
  title bar. Related to #2791
* Update the title bar after terminal is started. Fixes #6078

Fixes #6668
@jeffThompson
Copy link

100% for this, at least at boot. Flashing some random stuff before the actual content doesn't help anyone debug and makes projects, like the ones outlined above, look crappy. (And we want to use CircuitPython for products! We all understand the open source license provides no warranty... doesn't mean we don't add features when it helps the community.)

If nothing else, adding info in the docs and/or the Learn section of the Adafruit site on how to do this in boot.py would be super helpful. I read this thread a few times and can't figure out how to even start.

@paulmand3l
Copy link

I strongly support the ability to suppress Blinka (why is this shown at all?) and terminal debugging for a few reasons:

  • Being able to create things with a high level of polish (e.g. high-fidelity prototypes, props, home goods, etc) is a very valuable use case. For example, I'm currently using a small OLED display in an interactive prop that's going to be a gift and the flash of Blinka/terminal really detracts from the overall experience.
  • On certain displays (e.g. LED matrixes and smaller OLED displays), terminal output looks broken. For the just-getting-started folks cited as benefiting from the ease-of-use of showing terminal output by default, this appearance of brokenness may end up confusing them more than they would be otherwise.
  • The Blinka + terminal flash on reboot does not aid in debugging at all.

@jeffThompson here's what worked for me to suppress the flash of Blinka and terminal (but not the "Code has been stopped by..." message):

import displayio
from adafruit_displayio_ssd1306 import SSD1306

displayio.release_displays()

i2c = busio.I2C(board.SCL, board.SDA, frequency=1000000)
display_bus = displayio.I2CDisplay(i2c, device_address=0x3c)
display = SSD1306(display_bus, width=128, height=64, rotation=180, auto_refresh=False)

screen = displayio.Group()
display.show(screen)
display.auto_refresh = True

# Draw stuff in the screen group

Here's how I wish it worked:

  • Don't ever show Blinka
  • Add a suppress_terminal argument to the SSD1306 constructor (and other displayio Display constructors) that defaults to False. When set to True, only ever show content the user has explicitly generated in boot.py or code.py (i.e. never show terminal output, errors, or the "Code stopped by" message)

@Rillian-Grant
Copy link

Using a build directly from git including the pull request mentioned above I was able to solve this issue by adding the following to boot.py:

import displayio
displayio.release_displays()

@matwho
Copy link

matwho commented Dec 19, 2022

Hi I too have a project with an LED Matrix that is ruined with the console appearing at startup. displayio.release_displays() in boot.py did not work for me.

@Rillian-Grant
Copy link

Hi I too have a project with an LED Matrix that is ruined with the console appearing at startup. displayio.release_displays() in boot.py did not work for me.

Did you build circuit python from the git repo?
This change is more recent than the latest release.

@Breazile
Copy link

Breazile commented Jan 12, 2023

This issue also seems to block any deep sleep efforts which is my main concern.

I have a design for a small display that Mandalorian cosplayers use in their gauntlets. I am trying to add a feature where you can put the system into deep sleep and wake it up with a button press later.

The problem that I am having is that once I make the alarm call to put the system to sleep (and I turn off the backlight) the system shows the console and more importantly it turns on the backlight to 100% which drains power. To me it does not matter if the console or the snake logo is shown because the backlight is off.

Is there any way to keep the backlight off? Maybe a deep sleep option that does not exit to the console?

This is what it looks like when it goes to sleep
Link to Video

@tannewt
Copy link
Member

tannewt commented Jan 12, 2023

Is there any way to keep the backlight off? Maybe a deep sleep option that does not exit to the console?

The latest beta versions of CircuitPython have a way to preserve pins when going into deep sleep. https://docs.circuitpython.org/en/latest/shared-bindings/alarm/index.html#alarm.exit_and_deep_sleep_until_alarms

@Breazile
Copy link

Thank you for the tip. Will this be available on the Feather? I'm using the Feather M4 Express as well as the ESP32S3. Unfortunately, it looks like preserving the I/O on those boards is not yet available, but I'll put the code in anyway and see what happens.

Limitations: preserve_dios is currently only available on Espressif according to the docs

@Breazile
Copy link

Breazile commented Jan 12, 2023

I went ahead and added the code and hit another issue. I passed in the I/O pin to the display manager and let it control the backlight level:

ST7789(display_bus, rotation=270, width=240, height=135, rowstart=40, colstart=53, auto_refresh=False, backlight_pin=board.D10, brightness=0)

When I try to put the system into deep sleep I get and error that the I/O pin is in use:

alarm.exit_and_deep_sleep_until_alarms(time_alarm, preserve_dios=[digitalio.DigitalInOut(board.D10)])

Traceback (most recent call last):
File "code.py", line 287, in
ValueError: D10 in use

@tannewt
Copy link
Member

tannewt commented Jan 13, 2023

Thank you for the tip. Will this be available on the Feather? I'm using the Feather M4 Express as well as the ESP32S3. Unfortunately, it looks like preserving the I/O on those boards is not yet available, but I'll put the code in anyway and see what happens.

Limitations: preserve_dios is currently only available on Espressif according to the docs

I don't know of anyone adding preserve pin support to the SAMD51 (aka M4). Generally its deep sleep support is less refined.

@tannewt
Copy link
Member

tannewt commented Jan 13, 2023

When I try to put the system into deep sleep I get and error that the I/O pin is in use:

Deinit the display and then try.

@Breazile
Copy link

I set the backlight to 0, and then called displayio.release_displays(), and the result was the backlight was left on.

After the displayio.release_displays() call I setup I/O pin D10 and set it low (driving the backlight), but I received the same error that the GPIO was in use when exit_and_deep_sleep_until_alarms() was called:

backlight = digitalio.DigitalInOut(board.D10)
backlight.direction = digitalio.Direction.OUTPUT
backlight.value = False

Traceback (most recent call last):
File "code.py", line 313, in
ValueError: D10 in use

So it looks like I am not able to sleep with the backlight off unless you have another suggestion to try.

@aricooperdavis
Copy link

... if you are ok with disabling the terminal in the python-side, you can make use of this recently-added feature and move the root_group outside of the visible display. Keep in mind the terminal will still be present in memory and will reappear whenever you fall back into the REPL.

Thank you - this is the easy fix that I was looking for. Just add

display.root_group.hidden = True

after defining your display. e.g.:

import board
display = board.DISPLAY
display.root_group.hidden = True

@kmatch98
Copy link
Collaborator

kmatch98 commented Apr 6, 2023

Closing due to added features with root_group.

@tannewt
Copy link
Member

tannewt commented Apr 6, 2023

So it looks like I am not able to sleep with the backlight off unless you have another suggestion to try.

Please open a separate issue for this.

Closing now that the root_group can be hidden.

@tannewt tannewt closed this as completed Apr 6, 2023
@bradanlane
Copy link

note for posterity ...

Using board.DISPLAY.root_group.hidden = true does not prevent a board level ePaper from refreshing on REPL.

@TonyLHansen
Copy link

  • boards without board.DISPLAY cannot do this. For example, matrixportal s3 does not have board.DISPLAY.

After displayio.release_displays(), there is still a blinka flash when networking seems to be initialized.

@dandindarov
Copy link

  • boards without board.DISPLAY cannot do this. For example, matrixportal s3 does not have board.DISPLAY.

After displayio.release_displays(), there is still a blinka flash when networking seems to be initialized.

Facing this exact issue using a MatrixPortal M4. Any ideas on how to get rid of the blinka flash anyone?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests