-
Notifications
You must be signed in to change notification settings - Fork 2k
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
TM1637 7-segment display driver #21112
base: master
Are you sure you want to change the base?
Conversation
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.
thx, this looks quite good to me.
The CI has a few comments (check in the code view here):
- One line is longer than 100 chars, please add a line break
- A few files have no terminating newline. (Btw: What editor are you using? Maybe we can add a config to our repo that your editor will pick up. IMO it is better to automate such tedious style things and concentrate.)
Btw: I think negative numbers and leading zeros will result in the minus sign to be overwritten by a zero, or did I read the code incorrectly?
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.
Thanks, great code quality! I have mostly nits below.
You've rightfully already mentioned #20981. IIRC, the idea was there to provide a unified driver for different kinds of 7-segment displays. How does yours differ and could it be integrated somehow? Otherwise, we should rename the driver in the other PR back to something more specific.
drivers/include/tm1637.h
Outdated
* @brief Brightness level enum for the display | ||
* | ||
* @note The brightness is defined as a fraction of | ||
* the pulse width and must be on of the given values. |
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.
* the pulse width and must be on of the given values. | |
* the pulse width and must be one of the given values. |
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.
also, I don't fully understand the sentence here. The brightness being a fraction of the pulse width is an implementation detail not really interesting to the user, right?
drivers/include/tm1637.h
Outdated
* | ||
* @note The integer can't be bigger than 9999 or smaller than | ||
* -999 as only 4 digits can be displayed at a time. | ||
* With the leading zeros enabled, the display is padded with zeros. |
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.
* With the leading zeros enabled, the display is padded with zeros. | |
* When leading zeros are enabled, the display is padded with zeros. |
drivers/include/tm1637.h
Outdated
* @param[out] dev device descriptor of the display | ||
* @param[in] params configuration parameters | ||
* @return 0 on success, error otherwise |
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.
would be slightly easier to read if the params are aligned, as in
* @param[out] dev device descriptor of the display | |
* @param[in] params configuration parameters | |
* @return 0 on success, error otherwise | |
* @param[out] dev device descriptor of the display | |
* @param[in] params configuration parameters | |
* @return 0 on success, error otherwise |
It is apparently not explicitly mandated by the coding convention, but that's how I've seen it everywhere across RIOT until now.
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.
same for the rest of this file, obviously :)
drivers/include/tm1637.h
Outdated
* and the number. | ||
* | ||
* @param[in] dev device descriptor of the display | ||
* @param[in] number number to write, in the range of 9999 to -999 |
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.
* @param[in] number number to write, in the range of 9999 to -999 | |
* @param[in] number number to write, in the range of -999 to 9999 |
feels a bit more natural to me
drivers/tm1637/Makefile
Outdated
USEMODULE += ztimer | ||
USEMODULE += ztimer_msec | ||
USEMODULE += periph_gpio | ||
|
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.
USEMODULE += ztimer | |
USEMODULE += ztimer_msec | |
USEMODULE += periph_gpio |
those should go (and mostly are already) in Makefile.dep. Specifying periph_gpio
in FEATURES_REQUIRED
should also be enough, I think.
drivers/tm1637/tm1637.c
Outdated
* | ||
* @param[in,out] segments segments to enable the colon on | ||
*/ | ||
static void enable_colon(uint8_t *segments) |
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.
static void enable_colon(uint8_t *segments) | |
inline static void enable_colon(uint8_t *segments) |
void tm1637_clear(const tm1637_t *dev) | ||
{ | ||
uint8_t segments[DIGIT_COUNT] = { 0, 0, 0, 0 }; | ||
transmit_segments(dev, segments, TM1637_PW_1_16); |
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.
why this specific brightness?
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.
A brightness needs to be set for the transmit segments function. The actual brightness does not matter as the display is empty anyway.
drivers/tm1637/tm1637.c
Outdated
assert(number <= 9999); | ||
assert(number >= -999); | ||
|
||
uint8_t segments[DIGIT_COUNT] = { 0, 0, 0, 0 }; |
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.
uint8_t segments[DIGIT_COUNT] = { 0, 0, 0, 0 }; | |
uint8_t segments[DIGIT_COUNT] = { 0 }; |
does the same, and doesn't hard-code DIGIT_COUNT ;-)
if (leading_zeros) { | ||
for (int i = 0; i < DIGIT_COUNT; ++i) { | ||
if (segments[i] == 0) { | ||
segments[i] = segments_array[0]; | ||
} | ||
} | ||
} |
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.
wouldn't this overwrite the minus sign set above in line 251?
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.
No, it only overwrites if the segment is equal to 0, therefore empty/clear. This means that only digits that aren't turned on become zeros.
if (number != 0) { | ||
segments[DIGIT_COUNT - 1 - i] = segments_array[number % 10]; | ||
number /= 10; | ||
} |
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.
Since this is an exact copy of lines 242-245, you could consolidate and reduce the levels of indentation :)
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.
The lines 242-245 are part of an if-condition that can't easily be separated into a different function unless I move the entire branch into functions, i. e. one for negative and one for positive numbers.
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.
I mostly reviewed the API only so far. I had a few suggestions that I noted. Thank you for the great contribution!
* @brief Configuration parameters | ||
* | ||
*/ | ||
tm1637_params_t params; |
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.
The driver should hold a pointer to tm1637_params_t
. Not a copy.
TM1637_PW_12_16 = 0x05, | ||
TM1637_PW_13_16 = 0x06, | ||
TM1637_PW_14_16 = 0x07 | ||
} tm1637_brightness_t; |
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.
The meaning of these values is unclear to me. I assume they are fractions of full brightness, but the doc does not say this. If they are fractions, why are some values skipped?
* | ||
* @param[out] dev device descriptor of the display | ||
* @param[in] params configuration parameters | ||
* @return 0 on success, error otherwise |
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.
* @return 0 on success, error otherwise | |
* @retval 0 on success | |
* @retval -1 on error |
Even better than -1
would be an errno
value if it makes sense to do so.
/** | ||
* @brief see @ref tm1637_params_t | ||
*/ | ||
#define TM1637_PARAM_CLK GPIO_PIN(0, 0) |
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.
I would suggest setting the default to GPIO_UNDEF
. Then add an assert to the init function to check that the pins are defined. There is no sane default you could ever define. Better to fail loudly then quietly do the wrong thing.
Contribution description
This is a 4 digit display driver for the TM1637 7-segment display. It can display base 10 integers on a range from 9999 to -999, with or without leading zeros and variable brightness. The display can be cleared, too.
The driver was implemented according to a subset of all functionality and adheres to the specification .
Testing procedure
A test can be found in tests/drivers/tm1637/. The test covers all possible configurations for the driver and contains default pin configuration in tm1637_params.h.
Issues/PRs references
A similar display driver is still in review at PR #20981, but isn't compatible with this 4 pin display.
Images