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

drivers: Add text display interface #52032

Merged
merged 10 commits into from
May 26, 2023

Conversation

thedjnK
Copy link
Collaborator

@thedjnK thedjnK commented Nov 7, 2022

Adds the base driver include file and noritake itron text display dts file for review.

  • Base noritake itron driver code
  • Base grove LCD driver code
  • Base HD44780 driver code
  • Complete noritake itron driver code
  • Complete grove LCD driver code (unable to test)
  • Complete HD44780 driver code
  • API
  • Documentation
  • Mark API is experimental/unstable
  • Release notes update
  • (Optional) more advanced sample code e.g. display configuration, add test character
  • (Add as feature issue, not for this PR) remove old grove driver and update samples using it to use new driver
  • (Add as feature issue, not for this PR) remove old HD44780 driver sample

Tested:

  • amc2004a (20x4 HD44780-clone): ☑ Works on nucleo_f746zg in both 4 and 8-bit modes
  • Noritake Itron gu280x16g (Noritake itron UART): ☑ Works on nucleo_f401re
  • seed grove lcd rgb (Jinghua Display JHD1313): ☒ Do not have shield to test with
  • Noritake Itron gu24025ecpb (24x2 HD44780-clone): ☑ Works on stm32f4_disco with 800ms boot delay, sometimes displays '6', '66' or '666' at start when board reset button is pressed but this seems to be a quirk of the display/reset or other time value that needs increasing
  • Unbranded 1602a (16x2 HD44780-clone): ☑ Works on stm32f4_disco in 4-bit mode (not checking on 8-bit mode as the debugger deciding if it detects a core or not completely at random is almost making me throw it against a wall)

Fixes #51912

Copy link
Member

@gmarull gmarull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some initial comments

include/zephyr/drivers/text_display.h Outdated Show resolved Hide resolved
include/zephyr/drivers/text_display.h Outdated Show resolved Hide resolved
include/zephyr/drivers/text_display.h Outdated Show resolved Hide resolved
include/zephyr/drivers/text_display.h Outdated Show resolved Hide resolved
include/zephyr/drivers/text_display.h Outdated Show resolved Hide resolved
drivers/text_display/text_display_noritake_itron.c Outdated Show resolved Hide resolved
drivers/text_display/text_display_noritake_itron.c Outdated Show resolved Hide resolved
drivers/text_display/text_display_noritake_itron.c Outdated Show resolved Hide resolved
drivers/text_display/text_display_noritake_itron.c Outdated Show resolved Hide resolved
drivers/text_display/text_display_noritake_itron.c Outdated Show resolved Hide resolved
Copy link
Member

@cfriedt cfriedt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love that you're adding text-based LCDs here!

It's been a while but would be a great addition on my next demo.

Just a couple of questions / comments:

  • Are either of grove or itron displays capable of producing interrupts (e.g. via GPIO)? If so, I would suggest building those capabilities into the drivers.
  • Some of the drivers sleep within the API calls. In general, it would be better to use a semaphore or spinlock and either delayed work or an ISR to unlock

Thanks though - I'm really looking forward to seeing this upstream 😁

@cfriedt
Copy link
Member

cfriedt commented Nov 22, 2022

It might also be useful to wrap API calls in a __syscall wrapper (see <zephyr/drivers/gpio.h>. For kernel-mode only builds, there is very little overhead (other than some argument checking), but for user mode, it protects access to the driver data

@thedjnK
Copy link
Collaborator Author

thedjnK commented Nov 27, 2022

Are either of grove or itron displays capable of producing interrupts (e.g. via GPIO)? If so, I would suggest building those capabilities into the drivers.

@cfriedt Not sure what you mean here by interrupt, unless you mean if they have user input/buttons/touchscreen? The noritake itron has a busy output line which I did expose here but will hide internally in the driver and not expose externally, HD44780 does not have inputs.

@cfriedt
Copy link
Member

cfriedt commented Nov 27, 2022

@cfriedt Not sure what you mean here by interrupt, unless you mean if they have user input/buttons/touchscreen? The noritake itron has a busy output line which I did expose here but will hide internally in the driver and not expose externally, HD44780 does not have inputs.

@thedjnK - a busy line should do for a gpio interrupt.

I could make some additional code comments if you need clarification, but my general suggestion was to avoid sleeping (ans also busy looping). Sleeping is usually bad for drivers.

Using an interrupt (e.g. a busy line) is one way to avoid sleeping, and another way to avoid sleeping is to use a workqueue. It might be smart to use a dedicated workqueue in this case.

@thedjnK
Copy link
Collaborator Author

thedjnK commented Nov 27, 2022

@cfriedt 😆 this was the comment from the architecture meeting:

text_display_is_busy probably debatable

I just removed it so I can add it back quickly...


rc = i2c_write_dt(&config->bus, clear, sizeof(clear));
LOG_DBG("clear, delay 20 ms");
k_sleep(K_MSEC(20));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would avoid sleeping here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is from the original zephyr driver (copy and paste) and would think sleeping is the only course since the command should be blocking until it is complete (someone raised this in the architecture meeting)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commands can still be blocking if you use e.g. a semaphore (semaphore can be unlocked via ISR or workqueue).

This is done in a few places in e.g. sensor drivers.

Just a thought.

rc = i2c_write_dt(&config->bus, buf, sizeof(buf));

LOG_DBG("set display_state options, delay 5 ms");
k_sleep(K_MSEC(5));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would avoid sleeping here

i2c_write_dt(&config->bus, buf, sizeof(buf));

LOG_DBG("set function options, delay 5 ms");
k_sleep(K_MSEC(5));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would avoid sleeping here

* VDD to power on, so pause a little here, 30 ms min, so we go 50
*/
LOG_DBG("delay 50 ms while the VDD powers on");
k_sleep(K_MSEC(50));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably better to move this to something like an enable() function.

@thedjnK thedjnK force-pushed the text_display_test branch 4 times, most recently from 3104e47 to b41753d Compare November 29, 2022 22:10
@thedjnK thedjnK force-pushed the text_display_test branch 3 times, most recently from e085483 to 9f54533 Compare January 4, 2023 22:55
@thedjnK
Copy link
Collaborator Author

thedjnK commented Jan 4, 2023

OK I've made some fixes and updates, PM is implemented in my display, added a simple sample application, still some work to do on it.

@cfriedt I'm a bit stuck with using interrupts and semaphores, I was about to switch to them on my display driver, then I stopped and paused because that would pose a problem, a problem for me at least, I want to be able to use the display from a bootloader (i.e. mcuboot) and imposing semaphores then means I would need to build mcuboot with mutlthreading support, just enabling that option without using the functions in code adds 4KB to a bootloader build which isn't a small number, and thinking about it, the delays should not really be long for a display (for mine at 38400 baud, assuming you output 40 characters and every 3 characters you have to pause for 4ms, the total time needed to display all that is about 63ms, and whilst the display is busy, other tasks can run perhaps, so at least for my driver (note: noritake display, not the groove) I don't think it's worth changing to interrupts. I don't think it's worth doing either for the groove but that's because that driver is basically a straight up copy and paste from existing zephyr code, I don't have that display to test with so don't want to submit a driver that might be broken and I'm unable to test with. For a HD44780 driver (which will have to come at a later date) I will think about it, although I think that would fall under the same bucket of using k_sleep() because I don't think those display drivers have an interrupt line either, it's all "hold these lines for a minimum time period".

@cfriedt
Copy link
Member

cfriedt commented Jan 4, 2023

OK I've made some fixes and updates, PM is implemented in my display, added a simple sample application, still some work to do on it.

@cfriedt I'm a bit stuck with using interrupts and semaphores.

Device Tree can fix that 😄 Make it a DT property and hook up things in your INIT.

@nordicjm
Copy link
Collaborator

nordicjm commented Jan 5, 2023

@cfriedt not for setting up the GPIO, that's already done in this PR, it's for usage of semaphores, the burden of enabling that is too great for a simple bootloader

@cfriedt
Copy link
Member

cfriedt commented Jan 5, 2023

@cfriedt not for setting up the GPIO, that's already done in this PR, it's for usage of semaphores, the burden of enabling that is too great for a simple bootloader

@nordicjm - you can use DT properties to compile-in or compile-out support for semaphores. In the non-semaphore version just use a different function pointer for achieving the same thing. Then you get the best of both worlds :-)

@gmarull
Copy link
Member

gmarull commented Jan 10, 2023

@cfriedt not for setting up the GPIO, that's already done in this PR, it's for usage of semaphores, the burden of enabling that is too great for a simple bootloader

@nordicjm - you can use DT properties to compile-in or compile-out support for semaphores. In the non-semaphore version just use a different function pointer for achieving the same thing. Then you get the best of both worlds :-)

Just saw this comment: DT describes hardware, not software configuration ;-)

@cfriedt
Copy link
Member

cfriedt commented Jan 10, 2023

@cfriedt not for setting up the GPIO, that's already done in this PR, it's for usage of semaphores, the burden of enabling that is too great for a simple bootloader

@nordicjm - you can use DT properties to compile-in or compile-out support for semaphores. In the non-semaphore version just use a different function pointer for achieving the same thing. Then you get the best of both worlds :-)

Just saw this comment: DT describes hardware, not software configuration ;-)

@gmarull - that's right. In this case the DT would be describing whether or not there are interrupts available for the device (so business as usual) and then the driver would be configured to either use an interrupt-driven routine or polling based on that (also pretty normal, right?).

I'm just pointing out that it can be done in a compile-time const way inside of DT_INST_FOREACH_STATUS_OKAY(). It can be done at runtime in init() too of course.

@nordicjm
Copy link
Collaborator

nordicjm commented Jan 10, 2023

@gmarull - that's right. In this case the DT would be describing whether or not there are interrupts available for the device (so business as usual) and then the driver would be configured to either use an interrupt-driven routine or polling based on that (also pretty normal, right?).

That doesn't make sense, if a display needs an interrupt then it needs an interrupt and the driver would have it, if it doesn't need an interrupt then it wouldn't be present in the driver. If there is an optional one then it would down to the driver if it used it or not (and with displays, they are not optional, the display I have here will happily print complete garbage if you do not use and respect the busy line). And from a dts perspective, it's just a phandle-array

None of which has any relation to multithreading.

Ports the Jinghua Display JHD1313 LCD (with RGB backlight) driver
to use the new auxdisplay driver interface. This driver is used on
the seeed grove LCD RGB display, and replaces it.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
@thedjnK thedjnK force-pushed the text_display_test branch 3 times, most recently from 57c1413 to a9a1ea0 Compare May 26, 2023 19:39
.capabilities = { \
.columns = DT_INST_PROP(inst, columns), \
.rows = DT_INST_PROP(inst, rows), \
.mode = DT_ENUM_IDX(DT_DRV_INST(inst), mode), \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DT_INST…

.clear_delay = DT_INST_PROP(inst, clear_command_delay_us), \
.boot_delay = DT_INST_PROP(inst, boot_delay_ms), \
}; \
PM_DEVICE_DT_INST_DEFINE(inst, auxdisplay_hd44780_pm_action); \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftover

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed


This sample shows how to use the auxiliary display drivers by outputting a
sample "Hello World" text to one. If power management is enabled when
building (:kconfig:option:`CONFIG_PM_DEVICE`), it also demonstrates
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outdated?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


k_sleep(K_SECONDS(3));

pm_device_action_run(dev, PM_DEVICE_ACTION_SUSPEND);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs update?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@thedjnK thedjnK force-pushed the text_display_test branch 3 times, most recently from fe815fb to ed9bc44 Compare May 26, 2023 20:14
cfriedt
cfriedt previously approved these changes May 26, 2023
@thedjnK thedjnK requested a review from gmarull May 26, 2023 20:25
Adds an auxiliary display driver for Hitachi HD44780-based (and
compatible) LCD displays.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
Add myself as auxiliary display maintainer.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
Add myself as auxiliary display maintainer.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
Adds a simple auxdisplay sample which outputs hello world and the
name of the board. A sample overlay is provided for the
nucleo_f746zg board with a Hitachi HD44780-compatible display.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
Adds base auxdisplay documentation.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
Adds the new auxiliary display peripheral as an unstable API.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
Adds a note on unstable auxiliary display support being added,
alongside 3 drivers.

Signed-off-by: Jamie McCrae <spam@helper3000.net>
@carlescufi carlescufi merged commit d8d119f into zephyrproject-rtos:main May 26, 2023
24 checks passed
@thedjnK thedjnK deleted the text_display_test branch December 10, 2023 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Devicetree Binding PR modifies or adds a Device Tree binding area: Documentation area: Process Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add textual LCD display driver support