Skip to content

drivers/digit7seg: add 4-digit 7-segment display driver #20981

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

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

plmorange
Copy link
Contributor

Contribution description

Added riot/drivers/sha5461as to control a 4-digit 7-segment display (plus decimal point).

Testing procedure

A test is available in tests/drivers/sha5461as, designed for the Arduino Nano 33 BLE. The test will display "8" segment by segment on each digit, followed by "RIOT," and then it will stop.

Issues/PRs references

@github-actions github-actions bot added Area: doc Area: Documentation Area: tests Area: tests and testing framework Area: drivers Area: Device drivers labels Nov 13, 2024
@plmorange
Copy link
Contributor Author

Hi @Enoch247, I’ve finished my PR! I'm sure it can be improved, especially the sha5461as_display function. Could you please review it when you have a moment?

@mguetschow mguetschow changed the title Driver sha5461as drivers/sha5461as: add 4-digit 7-segment display driver Nov 13, 2024
@plmorange plmorange marked this pull request as draft November 13, 2024 13:51
@Enoch247
Copy link
Contributor

Thanks for the contribution. I'll try to review this tonight.

@Enoch247 Enoch247 self-assigned this Nov 13, 2024
Copy link
Contributor

@Enoch247 Enoch247 left a comment

Choose a reason for hiding this comment

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

I think the level of abstraction provided by the driver is too low. I expected to be able to pass it a number or array of digits to display. Currently the driver requires applications to manually set a bitfield with each bit corresponding to the display's segments. The application must also know the mapping of the bits to segments.

@plmorange plmorange changed the title drivers/sha5461as: add 4-digit 7-segment display driver drivers/digit7seg: add 4-digit 7-segment display driver Nov 14, 2024
@plmorange
Copy link
Contributor Author

I think the level of abstraction provided by the driver is too low. I expected to be able to pass it a number or array of digits to display. Currently the driver requires applications to manually set a bitfield with each bit corresponding to the display's segments. The application must also know the mapping of the bits to segments.

Thank you for reviewing my PR.
Is it a solution to leave the low level abstraction as it is now and create another high-level module?

@plmorange plmorange marked this pull request as ready for review November 14, 2024 14:24
@Enoch247
Copy link
Contributor

I think the level of abstraction provided by the driver is too low. I expected to be able to pass it a number or array of digits to display. Currently the driver requires applications to manually set a bitfield with each bit corresponding to the display's segments. The application must also know the mapping of the bits to segments.

Is it a solution to leave the low level abstraction as it is now and create another high-level module?

It is not my preference, but if you have a reason to do it this way, can you please describe it so that I better understand.

@Enoch247
Copy link
Contributor

BTW, in the future, please hold off to squash/force push until requested once a PR is submitted. It makes the process a bit easier. See here for some helpful tips.

@Enoch247
Copy link
Contributor

Great work adding the documentation for the driver! Its not always the fun part of writing code, but it will really help users of your driver in the future.

@Enoch247
Copy link
Contributor

Thanks. Sorry for the delay. I will set aside some time this weekend to look it over, if not sooner.

@Enoch247
Copy link
Contributor

As state before, I think that there needs to be a way for applications to send numbers to the display. As far as I see, the driver's API allows to manually set the display's segments, but that is the exception rather than the normal way an application would want to interact with a numeric display driver. Something like:

int digit7seg_set(digit7seg_t *dev, int val, int scale);
int digit7seg_set_digit(digit7seg_t *dev, unsigned digit, unsigned val);

val and scale could be similar to that used by phaydat_t

@plmorange
Copy link
Contributor Author

As state before, I think that there needs to be a way for applications to send numbers to the display. As far as I see, the driver's API allows to manually set the display's segments, but that is the exception rather than the normal way an application would want to interact with a numeric display driver. Something like:

int digit7seg_set(digit7seg_t *dev, int val, int scale);
int digit7seg_set_digit(digit7seg_t *dev, unsigned digit, unsigned val);

val and scale could be similar to that used by phaydat_t

OK, I'll do it as soon as I can!

@RIOT-OS RIOT-OS deleted a comment Dec 16, 2024
@RIOT-OS RIOT-OS deleted a comment Dec 16, 2024
Copy link
Contributor

@mguetschow mguetschow left a comment

Choose a reason for hiding this comment

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

Thanks for your work on this! Some first comments from my side below.

/**
* @ingroup drivers_digit7seg
* @file
* @brief Device driver for less than 5 digits of 7 segments without IC
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @brief Device driver for less than 5 digits of 7 segments without IC
* @brief Device driver for up to 4 digits of 7 segments without IC

do we really want such restriction?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, most 7-digit segments are composed of 4 digits, which is easier to manage.

* b the second.... dp the 8th bit.
*
* @return 0 on success
* @return -1 when an incorrect digit is passed
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @return -1 when an incorrect digit is passed
* @return -1 when an invalid index is passed

?


## About

This driver was developed to works with [5461AS](http://www.topliteusa.com/uploadfile/2014/0825/A-5461AS.pdf)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
This driver was developed to works with [5461AS](http://www.topliteusa.com/uploadfile/2014/0825/A-5461AS.pdf)
This driver was developed to work with [5461AS](http://www.topliteusa.com/uploadfile/2014/0825/A-5461AS.pdf)

## About

This driver was developed to works with [5461AS](http://www.topliteusa.com/uploadfile/2014/0825/A-5461AS.pdf)
in a way that all 4 digits (and less) with 7 segments without integrated controller
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
in a way that all 4 digits (and less) with 7 segments without integrated controller
in a way that up to 4 digits with 7 segments without integrated controller

Comment on lines 122 to 125
uint32_t temp_value = value << (index * BYTE_BITS);
uint32_t up_value = dev->value >> ((index + 1) * BYTE_BITS);
up_value <<= ((index + 1) * BYTE_BITS);
uint32_t down_value = ((0b00000001 << (index * BYTE_BITS)) - 1) & dev->value;
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe it's worth adding some explaining comments to what this code does.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right


#define DIGIT7SEG_MAX_DIGITS (4) /**< Max pin number, can be below or equal */
#ifndef DIGIT7SEG_TIMER_HZ
# define DIGIT7SEG_TIMER_HZ MHZ(1) /**< default timer hz */
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
# define DIGIT7SEG_TIMER_HZ MHZ(1) /**< default timer hz */
# define DIGIT7SEG_TIMER_HZ MHZ(1) /**< default timer hz */

as per the Coding Convention. please also check other places

#ifndef DIGIT7SEG_TIMER_HZ
# define DIGIT7SEG_TIMER_HZ MHZ(1) /**< default timer hz */
#endif
#ifndef DIGIT7SEG_DELAY
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be good to prefix all those "over-writeable" parameters with CONFIG_.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You raise a good point, but as all drivers do it this way, is it worth doing it any other way?

Copy link
Contributor

Choose a reason for hiding this comment

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

Older code my do otherwise, but my understanding is that new code should prefix with CONFIG_ if it is a value that is allowed to be changed/overridden and not just a constant.

Copy link
Member

Choose a reason for hiding this comment

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

@Enoch247 is correct. The CONFIG_ prefix allows for easier greping and allows to expose configuration options via KConfig.

Code not following this convention is due to the code base being older than this convention. And also: Reviewers will not always spot any issue or deviation from the coding convention

@plmorange
Copy link
Contributor Author

Hello @mguetschow I hope you're well!
The PR is ready for another review when you have some time.
Thank you for the previous comments.

@plmorange
Copy link
Contributor Author

I think the level of abstraction provided by the driver is too low. I expected to be able to pass it a number or array of digits to display. Currently the driver requires applications to manually set a bitfield with each bit corresponding to the display's segments. The application must also know the mapping of the bits to segments.

@Enoch247, 2 months later, it's done! :)

@plmorange
Copy link
Contributor Author

@mguetschow @Enoch247 I've made all the requested changes, what do you think?

@mguetschow
Copy link
Contributor

I'm sorry I haven't found the time to take another look at it yet (it's on my todo), but one high-level remark: After another 7-segment display is now in with #21112, this driver should be renamed back to refer to the models it works with. In a separate step, a more generic 7-segment-driver could be introduced as a higher-level API to both #21112 and this one.

@Enoch247
Copy link
Contributor

I'm sorry I haven't found the time to take another look at it yet (it's on my todo), but one high-level remark: After another 7-segment display is now in with #21112, this driver should be renamed back to refer to the models it works with. In a separate step, a more generic 7-segment-driver could be introduced as a higher-level API to both #21112 and this one.

The problem with renaming is that this driver can be used with any generic 7 segment display. So it doesn't make since to rename it after any hardware module. If you wanted to reserve the generic name for a top level API, I supose you cold prefix this one with soft_ just like the soft_uart and soft_spi modules?

I will try review the PR this coming week.

@plmorange
Copy link
Contributor Author

I'm sorry I haven't found the time to take another look at it yet (it's on my todo), but one high-level remark: After another 7-segment display is now in with #21112, this driver should be renamed back to refer to the models it works with. In a separate step, a more generic 7-segment-driver could be introduced as a higher-level API to both #21112 and this one.

The problem with renaming is that this driver can be used with any generic 7 segment display. So it doesn't make since to rename it after any hardware module. If you wanted to reserve the generic name for a top level API, I supose you cold prefix this one with soft_ just like the soft_uart and soft_spi modules?

I will try review the PR this coming week.

Thank you, I look forward to hearing your comments on the PR!

@plmorange plmorange requested a review from mguetschow April 22, 2025 12:37
@plmorange
Copy link
Contributor Author

Hi @mguetschow @Enoch247, It seems the PR has been blocked for a long time, are there any problems?

@crasbe crasbe added Type: new feature The issue requests / The PR implemements a new feature for RIOT CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Jun 25, 2025
@riot-ci
Copy link

riot-ci commented Jun 25, 2025

Murdock results

✔️ PASSED

8a00609 Merge branch 'RIOT-OS:master' into driver-sha5461AS

Success Failures Total Runtime
10390 0 10390 15m:28s

Artifacts

Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

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

Looks good to me, thx.

I resolved all comments that have been addressed and added some of my own. Sorry that the review process as been a bit slow here; all maintainers are volunteers and sometimes life get's in the way.

Feel free to ping me again when this is ready. You may squash at will to safe one round-trip-time before getting this merged.

#ifndef DIGIT7SEG_TIMER_HZ
# define DIGIT7SEG_TIMER_HZ MHZ(1) /**< default timer hz */
#endif
#ifndef DIGIT7SEG_DELAY
Copy link
Member

Choose a reason for hiding this comment

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

@Enoch247 is correct. The CONFIG_ prefix allows for easier greping and allows to expose configuration options via KConfig.

Code not following this convention is due to the code base being older than this convention. And also: Reviewers will not always spot any issue or deviation from the coding convention

/**
* @brief Display bitfield for numbers between [0, 9]
*/
static const uint8_t digit7seg_bitfield[] = {
Copy link
Member

Choose a reason for hiding this comment

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

Should this really be in the header?

Every compilation unit that actually makes use of this array will end up adding its own copy. If it would be added to a C file, we don't get duplicates.

* @param[in] value the value between [0, 9]
*
*/
int digit7seg_set_int_value(digit7seg_t *dev, int index, uint8_t value);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int digit7seg_set_int_value(digit7seg_t *dev, int index, uint8_t value);
int digit7seg_set_int_value(digit7seg_t *dev, unsigned index, uint8_t value);

Since negative indices are not allowed per API doc, we could encode this also into thr type.

* will be displayed as 234,1 but with
* precision = 100 it will be 34,15
*/
int digit7seg_set_float_value(digit7seg_t *dev, float value, int precision);
Copy link
Member

Choose a reason for hiding this comment

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

We support a lot of MCUs that do not have an FPU. And soft FPU implementations are surprisingly large (in terms of ROM size) and also slowish.

How about providing the value as integer type and a second integer gives the position of the decimal?

E.g. value=1337 and decimal=2 would be printed as 13.37?

@mguetschow
Copy link
Contributor

I'm sorry I haven't found the time to take another look at it yet (it's on my todo), but one high-level remark: After another 7-segment display is now in with #21112, this driver should be renamed back to refer to the models it works with. In a separate step, a more generic 7-segment-driver could be introduced as a higher-level API to both #21112 and this one.

The problem with renaming is that this driver can be used with any generic 7 segment display. So it doesn't make since to rename it after any hardware module. If you wanted to reserve the generic name for a top level API, I supose you cold prefix this one with soft_ just like the soft_uart and soft_spi modules?

Do you have examples of other such generic 7 segment displays? I'd just like to confirm that the driver would indeed fit them, too. Otherwise I'd favor your suggestion of prefixing with soft_. Maybe we could also link to the TM1637 7-segment-display driver in the documentation of this driver.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: doc Area: Documentation Area: drivers Area: Device drivers Area: tests Area: tests and testing framework CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants