Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.arch.embedded > #21399 > unrolled thread
| Started by | pozz <pozzugno@gmail.com> |
|---|---|
| First post | 2015-07-21 10:02 +0200 |
| Last post | 2015-07-22 07:32 +0200 |
| Articles | 20 on this page of 33 — 10 participants |
Back to article view | Back to comp.arch.embedded
Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-21 10:02 +0200
Re: Design pattern: refresh-based or event-based? upsidedown@downunder.com - 2015-07-21 11:37 +0300
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-21 11:00 +0200
Re: Design pattern: refresh-based or event-based? Dimiter_Popoff <dp@tgi-sci.com> - 2015-07-22 01:34 +0300
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-22 06:57 +0200
Re: Design pattern: refresh-based or event-based? Paul Rubin <no.email@nospam.invalid> - 2015-07-21 23:02 -0700
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-22 09:17 +0200
Re: Design pattern: refresh-based or event-based? Paul Rubin <no.email@nospam.invalid> - 2015-07-22 00:23 -0700
Re: Design pattern: refresh-based or event-based? upsidedown@downunder.com - 2015-07-22 10:02 +0300
Re: Design pattern: refresh-based or event-based? Dimiter_Popoff <dp@tgi-sci.com> - 2015-07-22 19:48 +0300
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-23 09:04 +0200
Re: Design pattern: refresh-based or event-based? Dimiter_Popoff <dp@tgi-sci.com> - 2015-07-23 10:29 +0300
Re: Design pattern: refresh-based or event-based? raimond.dragomir@gmail.com - 2015-07-31 02:34 -0700
Re: Design pattern: refresh-based or event-based? Don Y <this@is.not.me.com> - 2015-07-21 03:16 -0700
Re: Design pattern: refresh-based or event-based? Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2015-07-21 14:40 +0200
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-22 07:01 +0200
Re: Design pattern: refresh-based or event-based? Stefan Reuther <stefan.news@arcor.de> - 2015-07-22 18:30 +0200
Re: Design pattern: refresh-based or event-based? Paul Rubin <no.email@nospam.invalid> - 2015-07-22 10:55 -0700
Re: Design pattern: refresh-based or event-based? Paul Rubin <no.email@nospam.invalid> - 2015-07-21 08:26 -0700
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-22 07:04 +0200
Re: Design pattern: refresh-based or event-based? Paul Rubin <no.email@nospam.invalid> - 2015-07-21 23:13 -0700
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-22 09:24 +0200
Re: Design pattern: refresh-based or event-based? Paul Rubin <no.email@nospam.invalid> - 2015-07-22 08:26 -0700
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-23 09:00 +0200
Re: Design pattern: refresh-based or event-based? hamilton <hamilton@nothere.com> - 2015-07-21 14:07 -0600
Re: Design pattern: refresh-based or event-based? Don Y <this@is.not.me.com> - 2015-07-21 13:12 -0700
Re: Design pattern: refresh-based or event-based? Andrew Smallshaw <andrews@sdf.lonestar.org> - 2015-07-22 00:19 +0000
Re: Design pattern: refresh-based or event-based? Paul Rubin <no.email@nospam.invalid> - 2015-07-21 18:09 -0700
Re: Design pattern: refresh-based or event-based? Andrew Smallshaw <andrews@sdf.lonestar.org> - 2015-07-22 21:18 +0000
Re: Design pattern: refresh-based or event-based? Paul Rubin <no.email@nospam.invalid> - 2015-07-22 23:17 -0700
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-22 07:20 +0200
Re: Design pattern: refresh-based or event-based? upsidedown@downunder.com - 2015-07-22 10:53 +0300
Re: Design pattern: refresh-based or event-based? pozz <pozzugno@gmail.com> - 2015-07-22 07:32 +0200
Page 1 of 2 [1] 2 Next page →
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2015-07-21 10:02 +0200 |
| Subject | Design pattern: refresh-based or event-based? |
| Message-ID | <moku8e$6sf$1@dont-email.me> |
I tried to start a thread
(https://groups.google.com/forum/#!topic/comp.lang.C/A_8BrgLnXdY) on
comp.lang.c, without good success.
I think I haven't described the problem very well and the guys on clc
aren't very interested in those kind of problems.
Maybe this group is better. I try to re-describe my question.
Suppose you have a complex dashboard with tenth of LEDs, gauges, values,
labels and so on. It could be a full-futured high-resolution TFT
display. The values shown on the dashboard come from remote controllers
connected through a bus. I think it's a very common scenario in my systems.
When I design the firmware of the dashboard controller, I always have
many doubts on the design better to choose: refresh-based or event-based?
Refresh-based is very simple: every 20ms, 100ms, 500ms or 1s a refresh
function is called. This function redraws *everything* on the dashboard
based on the current values collected on the bus.
The thing I don't like with this approach is that it could be time
consuming. If the values change slowly, most probably only 1-5 values
really change since the last refresh. Why do I redraw everything?
I could improve this by defining a variable with the old displayed value
for each graphical element:
bool ledX_displayed;
if (ledX_displayed != ledX_currentvalue()) {
ledX_displayed = ledX_currentvalue();
ledX_refresh();
}
However this method uses a double RAM space (current values and
displayed values) and the code isn't so clear.
Another approach is event-based. IMHO, it is very attractive and
elegant, because it remembers state-machines. The drawing operations are
performed only when necessary.
int X, Y, ...;
void bus_rx(const char *msg, size_t msglen) {
int new_value;
...
new_value = <something related to msg> /* X value */
if (X != new_value) {
X = new_value;
event_handler(X_CHANGED);
}
...
}
void event_handler(enum EVENT_TYPE evtype) {
if (X_CHANGED == evtype)
ledX_refresh();
else ...
}
The event X_CHANGED is triggered by the bus task: when a new value for X
is received, it is compared with the current value and, if it is
different, the event is triggered (a callback is called).
Even this design patter have some drawbacks.
IMHO it is dangerous and error-prone, because you could ignore a certain
sequence of events that brings to a wrong state (you will have a wrong
value displayed on the dashboard).
The startup must be designed with great care. Should a "virtual startup
event" be triggered during initialization for each value, so the
current/init value is correctly displayed?
How to distinguish a "virtual startup event" from a "normal event"? It's
important, if I have to make soma actions only if a "normal event" occurs.
What is you preferred method?
[toc] | [next] | [standalone]
| From | upsidedown@downunder.com |
|---|---|
| Date | 2015-07-21 11:37 +0300 |
| Message-ID | <kl0sqa1dtneouv3k3b3dgkfftvt7ns9djc@4ax.com> |
| In reply to | #21399 |
On Tue, 21 Jul 2015 10:02:49 +0200, pozz <pozzugno@gmail.com> wrote: >Even this design patter have some drawbacks. >IMHO it is dangerous and error-prone, because you could ignore a certain >sequence of events that brings to a wrong state (you will have a wrong >value displayed on the dashboard). >The startup must be designed with great care. Should a "virtual startup >event" be triggered during initialization for each value, so the >current/init value is correctly displayed? >How to distinguish a "virtual startup event" from a "normal event"? It's >important, if I have to make soma actions only if a "normal event" occurs. In addition to startup, you should have a method of refreshing the whole screen on request (e.g. refresh button) in case of the actual display and the background information are out of synch, eg. due to EMC issues with some garbage on screen. A clear screen operation followed by the startup time full drawing should do that. Thus the display problems could be handled without restarting the whole system to clear out some garbage on display.
[toc] | [prev] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2015-07-21 11:00 +0200 |
| Message-ID | <mol1jo$har$1@dont-email.me> |
| In reply to | #21400 |
Il 21/07/2015 10:37, upsidedown@downunder.com ha scritto: > On Tue, 21 Jul 2015 10:02:49 +0200, pozz <pozzugno@gmail.com> wrote: > >> Even this design patter have some drawbacks. >> IMHO it is dangerous and error-prone, because you could ignore a certain >> sequence of events that brings to a wrong state (you will have a wrong >> value displayed on the dashboard). >> The startup must be designed with great care. Should a "virtual startup >> event" be triggered during initialization for each value, so the >> current/init value is correctly displayed? >> How to distinguish a "virtual startup event" from a "normal event"? It's >> important, if I have to make soma actions only if a "normal event" occurs. > > In addition to startup, you should have a method of refreshing the > whole screen on request (e.g. refresh button) in case of the actual > display and the background information are out of synch, eg. due to > EMC issues with some garbage on screen. The refresh-based design pattern solves automatically this problem, because it continuously redraws the full screen.
[toc] | [prev] | [next] | [standalone]
| From | Dimiter_Popoff <dp@tgi-sci.com> |
|---|---|
| Date | 2015-07-22 01:34 +0300 |
| Message-ID | <momh9l$f1v$1@dont-email.me> |
| In reply to | #21401 |
On 21.7.2015 г. 12:00, pozz wrote: > Il 21/07/2015 10:37, upsidedown@downunder.com ha scritto: >> On Tue, 21 Jul 2015 10:02:49 +0200, pozz <pozzugno@gmail.com> wrote: >> >>> Even this design patter have some drawbacks. >>> IMHO it is dangerous and error-prone, because you could ignore a certain >>> sequence of events that brings to a wrong state (you will have a wrong >>> value displayed on the dashboard). >>> The startup must be designed with great care. Should a "virtual startup >>> event" be triggered during initialization for each value, so the >>> current/init value is correctly displayed? >>> How to distinguish a "virtual startup event" from a "normal event"? It's >>> important, if I have to make soma actions only if a "normal event" >>> occurs. >> >> In addition to startup, you should have a method of refreshing the >> whole screen on request (e.g. refresh button) in case of the actual >> display and the background information are out of synch, eg. due to >> EMC issues with some garbage on screen. > > The refresh-based design pattern solves automatically this problem, > because it continuously redraws the full screen. > You do not have to pick either this or that. You can do both. The way I do it is refresh based on an event - at a reasonable rate, say no more than 30 times a second - and do a complete refresh after some time - say, 10 seconds - expires even if there are no events. Thus you get the best of both worlds at a negligible "over refresh" cost. Dimiter ------------------------------------------------------ Dimiter Popoff, TGI http://www.tgi-sci.com ------------------------------------------------------ http://www.flickr.com/photos/didi_tgi/
[toc] | [prev] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2015-07-22 06:57 +0200 |
| Message-ID | <mon7op$7md$1@dont-email.me> |
| In reply to | #21413 |
Il 22/07/2015 00:34, Dimiter_Popoff ha scritto: > On 21.7.2015 г. 12:00, pozz wrote: >> Il 21/07/2015 10:37, upsidedown@downunder.com ha scritto: >>> On Tue, 21 Jul 2015 10:02:49 +0200, pozz <pozzugno@gmail.com> wrote: >>> >>>> Even this design patter have some drawbacks. >>>> IMHO it is dangerous and error-prone, because you could ignore a >>>> certain >>>> sequence of events that brings to a wrong state (you will have a wrong >>>> value displayed on the dashboard). >>>> The startup must be designed with great care. Should a "virtual startup >>>> event" be triggered during initialization for each value, so the >>>> current/init value is correctly displayed? >>>> How to distinguish a "virtual startup event" from a "normal event"? >>>> It's >>>> important, if I have to make soma actions only if a "normal event" >>>> occurs. >>> >>> In addition to startup, you should have a method of refreshing the >>> whole screen on request (e.g. refresh button) in case of the actual >>> display and the background information are out of synch, eg. due to >>> EMC issues with some garbage on screen. >> >> The refresh-based design pattern solves automatically this problem, >> because it continuously redraws the full screen. >> > > You do not have to pick either this or that. You can do both. > The way I do it is refresh based on an event - at a reasonable > rate, say no more than 30 times a second - So you use a refresh-based (in my terminology, it's a refresh triggered by a regular timer event) method. > and do a complete > refresh after some time - say, 10 seconds - expires even if there > are no events. > > Thus you get the best of both worlds at a negligible "over refresh" > cost. Ok, this is a good hint. Anyway this solution is for another issue, the possibility to have wrong pixels on the display (EMC?). My original question regards the regular refresh of values on the GUI: triggered by a timer (every 100ms) or by an event (when a value really needs to be updated)?
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2015-07-21 23:02 -0700 |
| Message-ID | <87io9cvif2.fsf@jester.gateway.sonic.net> |
| In reply to | #21423 |
pozz <pozzugno@gmail.com> writes: > My original question regards the regular refresh of values on the GUI: > triggered by a timer (every 100ms) or by an event (when a value really > needs to be updated)? Usually GUI's are drawn from a frame buffer at some fixed frequency like 60 hz. Window systems are usually event-based and write to the frame buffer asynchronously from the refresh. 10 hz updates could look jerky to the user.
[toc] | [prev] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2015-07-22 09:17 +0200 |
| Message-ID | <monfvt$u11$1@dont-email.me> |
| In reply to | #21429 |
Il 22/07/2015 08:02, Paul Rubin ha scritto: > pozz <pozzugno@gmail.com> writes: >> My original question regards the regular refresh of values on the GUI: >> triggered by a timer (every 100ms) or by an event (when a value really >> needs to be updated)? > > Usually GUI's are drawn from a frame buffer at some fixed frequency like > 60 hz. Window systems are usually event-based and write to the frame > buffer asynchronously from the refresh. > > 10 hz updates could look jerky to the user. Don't confuse the low-level refresh of the display pixels and the refresh/updating of the values shown on the display. The first rate should be higher (60Hz or more) to show smoothly animations, blinking and the like. The second rate could be lower.
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2015-07-22 00:23 -0700 |
| Message-ID | <87a8uovep1.fsf@jester.gateway.sonic.net> |
| In reply to | #21432 |
pozz <pozzugno@gmail.com> writes: > The first rate should be higher (60Hz or more) to show smoothly > animations, blinking and the like. The second rate could be lower. I think if several indicators move then the 10 hz updates could be noticable. Also if it's a touch screen then you want it to be more responsive than a 10 hz update could give you.
[toc] | [prev] | [next] | [standalone]
| From | upsidedown@downunder.com |
|---|---|
| Date | 2015-07-22 10:02 +0300 |
| Message-ID | <15fuqalk3j3fiq0pa3ff7elcq4genjg64q@4ax.com> |
| In reply to | #21413 |
On Wed, 22 Jul 2015 01:34:02 +0300, Dimiter_Popoff <dp@tgi-sci.com> wrote: >On 21.7.2015 ?. 12:00, pozz wrote: >> Il 21/07/2015 10:37, upsidedown@downunder.com ha scritto: >>> On Tue, 21 Jul 2015 10:02:49 +0200, pozz <pozzugno@gmail.com> wrote: >>> >>>> Even this design patter have some drawbacks. >>>> IMHO it is dangerous and error-prone, because you could ignore a certain >>>> sequence of events that brings to a wrong state (you will have a wrong >>>> value displayed on the dashboard). >>>> The startup must be designed with great care. Should a "virtual startup >>>> event" be triggered during initialization for each value, so the >>>> current/init value is correctly displayed? >>>> How to distinguish a "virtual startup event" from a "normal event"? It's >>>> important, if I have to make soma actions only if a "normal event" >>>> occurs. >>> >>> In addition to startup, you should have a method of refreshing the >>> whole screen on request (e.g. refresh button) in case of the actual >>> display and the background information are out of synch, eg. due to >>> EMC issues with some garbage on screen. >> >> The refresh-based design pattern solves automatically this problem, >> because it continuously redraws the full screen. >> > >You do not have to pick either this or that. You can do both. >The way I do it is refresh based on an event - at a reasonable >rate, say no more than 30 times a second How exactly should this be implemented ? Assume there are more than one event in 1/30 seconds, you should do the full refresh after the _last_ event, not after the first event. One way would be to scan every 30 ms for any potential signal source, make some internal update for any active events and at the end of the scan, check if there was any active things during the scan and only then, decide if a full refresh is needed. >- and do a complete >refresh after some time - say, 10 seconds - expires even if there >are no events. This is definitively recommend, just check how Windows will have incorrect screens (usually correctable by clicking on a window) and Windows has been out for decades. > >Thus you get the best of both worlds at a negligible "over refresh" >cost. > >Dimiter > >------------------------------------------------------ >Dimiter Popoff, TGI http://www.tgi-sci.com >------------------------------------------------------ >http://www.flickr.com/photos/didi_tgi/
[toc] | [prev] | [next] | [standalone]
| From | Dimiter_Popoff <dp@tgi-sci.com> |
|---|---|
| Date | 2015-07-22 19:48 +0300 |
| Message-ID | <moohem$1du$1@dont-email.me> |
| In reply to | #21431 |
On 22.7.2015 г. 10:02, upsidedown@downunder.com wrote:
> On Wed, 22 Jul 2015 01:34:02 +0300, Dimiter_Popoff <dp@tgi-sci.com>
> wrote:
>
>> On 21.7.2015 ?. 12:00, pozz wrote:
>>> Il 21/07/2015 10:37, upsidedown@downunder.com ha scritto:
>>>> On Tue, 21 Jul 2015 10:02:49 +0200, pozz <pozzugno@gmail.com> wrote:
>>>>
>>>>> Even this design patter have some drawbacks.
>>>>> IMHO it is dangerous and error-prone, because you could ignore a certain
>>>>> sequence of events that brings to a wrong state (you will have a wrong
>>>>> value displayed on the dashboard).
>>>>> The startup must be designed with great care. Should a "virtual startup
>>>>> event" be triggered during initialization for each value, so the
>>>>> current/init value is correctly displayed?
>>>>> How to distinguish a "virtual startup event" from a "normal event"? It's
>>>>> important, if I have to make soma actions only if a "normal event"
>>>>> occurs.
>>>>
>>>> In addition to startup, you should have a method of refreshing the
>>>> whole screen on request (e.g. refresh button) in case of the actual
>>>> display and the background information are out of synch, eg. due to
>>>> EMC issues with some garbage on screen.
>>>
>>> The refresh-based design pattern solves automatically this problem,
>>> because it continuously redraws the full screen.
>>>
>>
>> You do not have to pick either this or that. You can do both.
>> The way I do it is refresh based on an event - at a reasonable
>> rate, say no more than 30 times a second
>
> How exactly should this be implemented ? Assume there are more than
> one event in 1/30 seconds, you should do the full refresh after the
> _last_ event, not after the first event.
For example in the nuvi package (the spectrometry app under DPS running
on our products) each object (spectrum, setup window, oscilloscope
display etc.) keeps track of when it was last modified (in system
timebase ticks IIRC). That is when some object - say, an acquisition
module - modifies the data object it is connected to it sets "last"
moment of change (action being called, well, "setlast" :-) ).
The displaying loop checks all of the objects ("getlast", I may move
this to the more universal getxpar/setxpar, it predates these)
some of them has been modified since its last refresh, it gets
refreshed. One can set the refresh rate on a per "display" (i.e.
window) basis, meaning once a refresh is done no other will be
attempted for that period of time. Whoever missed the train - no
matter by how little - will have to wait for the next one.
Dimiter
------------------------------------------------------
Dimiter Popoff, TGI http://www.tgi-sci.com
------------------------------------------------------
http://www.flickr.com/photos/didi_tgi/
[toc] | [prev] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2015-07-23 09:04 +0200 |
| Message-ID | <moq3ij$pt4$2@dont-email.me> |
| In reply to | #21438 |
Il 22/07/2015 18:48, Dimiter_Popoff ha scritto:
> On 22.7.2015 г. 10:02, upsidedown@downunder.com wrote:
>> On Wed, 22 Jul 2015 01:34:02 +0300, Dimiter_Popoff <dp@tgi-sci.com>
>> wrote:
>>
>>> On 21.7.2015 ?. 12:00, pozz wrote:
>>>> Il 21/07/2015 10:37, upsidedown@downunder.com ha scritto:
>>>>> On Tue, 21 Jul 2015 10:02:49 +0200, pozz <pozzugno@gmail.com> wrote:
>>>>>
>>>>>> Even this design patter have some drawbacks.
>>>>>> IMHO it is dangerous and error-prone, because you could ignore a
>>>>>> certain
>>>>>> sequence of events that brings to a wrong state (you will have a
>>>>>> wrong
>>>>>> value displayed on the dashboard).
>>>>>> The startup must be designed with great care. Should a "virtual
>>>>>> startup
>>>>>> event" be triggered during initialization for each value, so the
>>>>>> current/init value is correctly displayed?
>>>>>> How to distinguish a "virtual startup event" from a "normal
>>>>>> event"? It's
>>>>>> important, if I have to make soma actions only if a "normal event"
>>>>>> occurs.
>>>>>
>>>>> In addition to startup, you should have a method of refreshing the
>>>>> whole screen on request (e.g. refresh button) in case of the actual
>>>>> display and the background information are out of synch, eg. due to
>>>>> EMC issues with some garbage on screen.
>>>>
>>>> The refresh-based design pattern solves automatically this problem,
>>>> because it continuously redraws the full screen.
>>>>
>>>
>>> You do not have to pick either this or that. You can do both.
>>> The way I do it is refresh based on an event - at a reasonable
>>> rate, say no more than 30 times a second
>>
>> How exactly should this be implemented ? Assume there are more than
>> one event in 1/30 seconds, you should do the full refresh after the
>> _last_ event, not after the first event.
>
> For example in the nuvi package (the spectrometry app under DPS running
> on our products) each object (spectrum, setup window, oscilloscope
> display etc.) keeps track of when it was last modified (in system
> timebase ticks IIRC). That is when some object - say, an acquisition
> module - modifies the data object it is connected to it sets "last"
> moment of change (action being called, well, "setlast" :-) ).
> The displaying loop checks all of the objects ("getlast", I may move
> this to the more universal getxpar/setxpar, it predates these)
> some of them has been modified since its last refresh, it gets
> refreshed. One can set the refresh rate on a per "display" (i.e.
> window) basis, meaning once a refresh is done no other will be
> attempted for that period of time. Whoever missed the train - no
> matter by how little - will have to wait for the next one.
It seems to me this is a variant of my "refresh-based" approach. When a
new value is received, no message is asyncronously emitted (or event
triggered). You only save the time when the last value arrived to the
controller.
In the refresh function, you check the last update time only to
understand if the value must be updated on the display too.
[toc] | [prev] | [next] | [standalone]
| From | Dimiter_Popoff <dp@tgi-sci.com> |
|---|---|
| Date | 2015-07-23 10:29 +0300 |
| Message-ID | <moq528$ufg$1@dont-email.me> |
| In reply to | #21453 |
On 23.7.2015 г. 10:04, pozz wrote:
> Il 22/07/2015 18:48, Dimiter_Popoff ha scritto:
>> On 22.7.2015 г. 10:02, upsidedown@downunder.com wrote:
>>> On Wed, 22 Jul 2015 01:34:02 +0300, Dimiter_Popoff <dp@tgi-sci.com>
>>> wrote:
>>>
>>>> On 21.7.2015 ?. 12:00, pozz wrote:
>>>>> Il 21/07/2015 10:37, upsidedown@downunder.com ha scritto:
>>>>>> On Tue, 21 Jul 2015 10:02:49 +0200, pozz <pozzugno@gmail.com> wrote:
>>>>>>
>>>>>>> Even this design patter have some drawbacks.
>>>>>>> IMHO it is dangerous and error-prone, because you could ignore a
>>>>>>> certain
>>>>>>> sequence of events that brings to a wrong state (you will have a
>>>>>>> wrong
>>>>>>> value displayed on the dashboard).
>>>>>>> The startup must be designed with great care. Should a "virtual
>>>>>>> startup
>>>>>>> event" be triggered during initialization for each value, so the
>>>>>>> current/init value is correctly displayed?
>>>>>>> How to distinguish a "virtual startup event" from a "normal
>>>>>>> event"? It's
>>>>>>> important, if I have to make soma actions only if a "normal event"
>>>>>>> occurs.
>>>>>>
>>>>>> In addition to startup, you should have a method of refreshing the
>>>>>> whole screen on request (e.g. refresh button) in case of the actual
>>>>>> display and the background information are out of synch, eg. due to
>>>>>> EMC issues with some garbage on screen.
>>>>>
>>>>> The refresh-based design pattern solves automatically this problem,
>>>>> because it continuously redraws the full screen.
>>>>>
>>>>
>>>> You do not have to pick either this or that. You can do both.
>>>> The way I do it is refresh based on an event - at a reasonable
>>>> rate, say no more than 30 times a second
>>>
>>> How exactly should this be implemented ? Assume there are more than
>>> one event in 1/30 seconds, you should do the full refresh after the
>>> _last_ event, not after the first event.
>>
>> For example in the nuvi package (the spectrometry app under DPS running
>> on our products) each object (spectrum, setup window, oscilloscope
>> display etc.) keeps track of when it was last modified (in system
>> timebase ticks IIRC). That is when some object - say, an acquisition
>> module - modifies the data object it is connected to it sets "last"
>> moment of change (action being called, well, "setlast" :-) ).
>> The displaying loop checks all of the objects ("getlast", I may move
>> this to the more universal getxpar/setxpar, it predates these)
>> some of them has been modified since its last refresh, it gets
>> refreshed. One can set the refresh rate on a per "display" (i.e.
>> window) basis, meaning once a refresh is done no other will be
>> attempted for that period of time. Whoever missed the train - no
>> matter by how little - will have to wait for the next one.
>
> It seems to me this is a variant of my "refresh-based" approach. When a
> new value is received, no message is asyncronously emitted (or event
> triggered). You only save the time when the last value arrived to the
> controller.
>
> In the refresh function, you check the last update time only to
> understand if the value must be updated on the display too.
>
>
No, it is the best of both worlds. You will always have some time
between event and refresh no matter what; wanting it below a few
mS is not practical simply because no human can see that.
So with this approach you get the display refreshed within a certain
time after an event - with DPS you can get that time down even
into microseconds range were it needed - and you do not do any
refresh when it is not needed, as it would be with your
suggested "refresh-based" approach.
Basically it is a simple enough issue, does not take a lot
to get to the optimum choice nor is there much to do to improve
on it.
Dimiter
------------------------------------------------------
Dimiter Popoff, TGI http://www.tgi-sci.com
------------------------------------------------------
http://www.flickr.com/photos/didi_tgi/
[toc] | [prev] | [next] | [standalone]
| From | raimond.dragomir@gmail.com |
|---|---|
| Date | 2015-07-31 02:34 -0700 |
| Message-ID | <bff0dfbf-534a-4b89-9759-9dbd78d1e65d@googlegroups.com> |
| In reply to | #21454 |
For a human eye, 10Hz or 5Hz is enough to feel the system responsive. That's 5 times (or 10 times) per second following rate of the actual events. I would implement such a system this way: 5 or 10 times per second a global "refresh" routine. This will check the "old" values against new ones and make the required update only when a change is detected. Yes, you need memory for keeping the old values. This technique is more important when displaying on large tft displays, it will keep the updates flickering unnoticable. At a lower level I would implement the "event" system. It would be triggered by the real events but all it has to do is to store the new values in memory. Being much more lightweight it may be triggered in any context, even interrupts.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <this@is.not.me.com> |
|---|---|
| Date | 2015-07-21 03:16 -0700 |
| Message-ID | <mol643$vc0$1@speranza.aioe.org> |
| In reply to | #21399 |
On 7/21/2015 1:02 AM, pozz wrote:
> Suppose you have a complex dashboard with tenth of LEDs, gauges, values, labels
> and so on. It could be a full-futured high-resolution TFT display. The values
> shown on the dashboard come from remote controllers connected through a bus. I
> think it's a very common scenario in my systems.
>
> When I design the firmware of the dashboard controller, I always have many
> doubts on the design better to choose: refresh-based or event-based?
>
> Refresh-based is very simple: every 20ms, 100ms, 500ms or 1s a refresh function
> is called. This function redraws *everything* on the dashboard based on the
> current values collected on the bus.
> The thing I don't like with this approach is that it could be time consuming.
> If the values change slowly, most probably only 1-5 values really change since
> the last refresh. Why do I redraw everything?
> I could improve this by defining a variable with the old displayed value for
> each graphical element:
>
> bool ledX_displayed;
> if (ledX_displayed != ledX_currentvalue()) {
> ledX_displayed = ledX_currentvalue();
> ledX_refresh();
> }
>
> However this method uses a double RAM space (current values and displayed
> values) and the code isn't so clear.
>
> Another approach is event-based. IMHO, it is very attractive and elegant,
> because it remembers state-machines. The drawing operations are performed only
> when necessary.
It's not really anything more than remembering the current state of each
*individual* display item. I.e., it is many "simple" state machines with
a common "conditional": if value is no longer what it was previously,
then display new value and remember this value.
> int X, Y, ...;
> void bus_rx(const char *msg, size_t msglen) {
> int new_value;
> ...
> new_value = <something related to msg> /* X value */
> if (X != new_value) {
> X = new_value;
> event_handler(X_CHANGED);
> }
> ...
> }
> void event_handler(enum EVENT_TYPE evtype) {
> if (X_CHANGED == evtype)
> ledX_refresh();
> else ...
> }
>
> The event X_CHANGED is triggered by the bus task: when a new value for X is
> received, it is compared with the current value and, if it is different, the
> event is triggered (a callback is called).
So, you're keeping a copy of the "currently displayed" value in "numeric form"
as well as in "graphical form".
> Even this design patter have some drawbacks.
> IMHO it is dangerous and error-prone, because you could ignore a certain
> sequence of events that brings to a wrong state (you will have a wrong value
> displayed on the dashboard).
> The startup must be designed with great care. Should a "virtual startup event"
> be triggered during initialization for each value, so the current/init value is
> correctly displayed?
> How to distinguish a "virtual startup event" from a "normal event"? It's
> important, if I have to make soma actions only if a "normal event" occurs.
You can force a "change" simply by ensuring the initial state for
every displayed value is "UNDEFINED". So, the first value that
you receive for each displayed value is seen as "different" and
forces that portion of the display to be repainted.
Your initialization routine simply sends an "update display" event
to every registered "display item" (widget, control, etc. -- whatever
you want to call them). Part of that process for each display
item is a means of displaying "UNDEFINED".
> What is you preferred method?
This depends on whether parameters are routinely *reported* (from the
"field") or, only when they change.
If the latter, then how do you know what the initial value to
"display" should be (in your refresh scenario)? In the former,
you are effectively continuously "refreshing" the display -- but
at a rate determined by each "control/widget" and the frequency
of its reporting event(s).
This can work for or against you. E.g., if a parameter is being reported
at a very high frequency, then you are needlessly repainting the display
faster than the user can perceive its changes. (i.e., you'd have to
add an intermediary filter to present values that "make sense" from
the many values coming in).
OTOH, you can choose to update certain portions of the display at
different rates. E.g., engine temperature changes much more slowly
than vehicular velocity; why repaint the temperature gauge if
you know it isn't changing very quickly??
You also have to have a mechanism for ensuring that messages aren't
lost; AND, identifying when they *have* been lost -- perhaps
causing you to manually query each parameter and synthesize
corresponding "events" (i.e., as if the parameters had been
*reported* instead of *queried*).
For example, you may want to demultiplex incoming events to
device specific "handlers". Each of these can then impose
whatever sanity checks they deem necessary on the *data*
AND the *reporting rate*! So, if the "temperature handler"
doesn't get a report/event indicating current engine temperature
in X seconds (where X is greater than the reporting interval
that the *design* was supposed to satisfy), then *it* (the
temperature handler) can schedule a "temperature query".
Eventually, that query will be passed to the appropriate subsystem
and, if all is well, a "temperature event" will be returned.
This will percolate through the demultiplexor to the "temperature
handler" (which is the entity that effectively requested it!)
and be processed as if it had arrived in the course of normal
operation.
If, OTOH, no such message arrives, the temperature handler knowws
that something is broke and can take corrective actions (signal
"check engine", log an error code to black box, place a reduced
limit on the maximum engine speed that can be commanded, etc.)
As well as updating the display, as appropriate!
[toc] | [prev] | [next] | [standalone]
| From | Hans-Bernhard Bröker <HBBroeker@t-online.de> |
|---|---|
| Date | 2015-07-21 14:40 +0200 |
| Message-ID | <d16su5FufvjU1@mid.dfncis.de> |
| In reply to | #21399 |
Am 21.07.2015 um 10:02 schrieb pozz: > Refresh-based is very simple: every 20ms, 100ms, 500ms or 1s a refresh > function is called. This function redraws *everything* on the dashboard > based on the current values collected on the bus. > The thing I don't like with this approach is that it could be time > consuming.If the values change slowly, most probably only 1-5 values > really change since the last refresh. Why do I redraw everything? Well, you did post this to c.a.embedded, where we usually assume that some degree of real-time constraint will be in place. In the case of your display update that means the system almost certainly _must_ be able to handle the case where everything _does_ change, anyway, and without breaking the timing constraints. So if you must be able to do it sometimes, it may well be better to just do it all the time, if only to reduce the variation of CPU load caused by it, and to increase overall predictability of the system's behaviour. The fact that it's a lot easier to do it that way comes an additional bonus.
[toc] | [prev] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2015-07-22 07:01 +0200 |
| Message-ID | <mon7vk$8at$1@dont-email.me> |
| In reply to | #21403 |
Il 21/07/2015 14:40, Hans-Bernhard Bröker ha scritto: > Am 21.07.2015 um 10:02 schrieb pozz: > >> Refresh-based is very simple: every 20ms, 100ms, 500ms or 1s a refresh >> function is called. This function redraws *everything* on the dashboard >> based on the current values collected on the bus. > >> The thing I don't like with this approach is that it could be time >> consuming.If the values change slowly, most probably only 1-5 values > > really change since the last refresh. Why do I redraw everything? > > Well, you did post this to c.a.embedded, where we usually assume that > some degree of real-time constraint will be in place. In the case of > your display update that means the system almost certainly _must_ be > able to handle the case where everything _does_ change, anyway, and > without breaking the timing constraints. So if you must be able to do > it sometimes, it may well be better to just do it all the time, if only > to reduce the variation of CPU load caused by it, and to increase > overall predictability of the system's behaviour. I got your point, but HMIs are't usually hard real-time systems. I could accept a short delay in opening a new screen (completely redraw of the display, think of opening an application on Windows), but I'd prefer to have a responsive interface after this time. If I don't have a powerful graphical CPU, one solution to improve responsiveness could be to update on the display only the values that really change. Mostly if most of them change very slowly. > The fact that it's a lot easier to do it that way comes an additional > bonus. Indeed many times I use a refresh-based mechanism.
[toc] | [prev] | [next] | [standalone]
| From | Stefan Reuther <stefan.news@arcor.de> |
|---|---|
| Date | 2015-07-22 18:30 +0200 |
| Message-ID | <moongf.10c.1@stefan.msgid.phost.de> |
| In reply to | #21425 |
pozz wrote: > Il 21/07/2015 14:40, Hans-Bernhard Bröker ha scritto: >> Well, you did post this to c.a.embedded, where we usually assume that >> some degree of real-time constraint will be in place. In the case of >> your display update that means the system almost certainly _must_ be >> able to handle the case where everything _does_ change, anyway, and >> without breaking the timing constraints. So if you must be able to do >> it sometimes, it may well be better to just do it all the time, if only >> to reduce the variation of CPU load caused by it, and to increase >> overall predictability of the system's behaviour. > > I got your point, but HMIs are't usually hard real-time systems. I could > accept a short delay in opening a new screen (completely redraw of the > display, think of opening an application on Windows), but I'd prefer to > have a responsive interface after this time. > > If I don't have a powerful graphical CPU, one solution to improve > responsiveness could be to update on the display only the values that > really change. Mostly if most of them change very slowly. You were referring to a high-resolution TFT display, so you'll probably have quite a lot of RAM (or are you building your screen like this computer: <https://events.ccc.de/congress/2012/Fahrplan/events/5178.en.html>? Then you're in deep trouble :-). Lots of RAM means a processor with quite a few bits and MHz, so redrawing a full screen of new values should be well possible. It's only a few bitblts and fills; people were doing full-screen 3-D with 66 MHz 486's 20 years ago. Long story short: I would not optimize for minimum redraw, but for simplicity. Probably not redraw the whole wallpaper each time, but every gauge. Stefan
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2015-07-22 10:55 -0700 |
| Message-ID | <87wpxst6u0.fsf@jester.gateway.sonic.net> |
| In reply to | #21439 |
Stefan Reuther <stefan.news@arcor.de> writes: > Long story short: I would not optimize for minimum redraw, but for > simplicity. Probably not redraw the whole wallpaper each time, but > every gauge. I would go for simplicity too, which means let the GUI toolkit or window system deal with the redrawing. I think the question is not about redrawing per se though, but about how to update the individual GUI widgets. And having written a bunch of such things, I've generally found it simplest to just update them asynchronously when external events are observed, rather than trying to synchronize all the updates. That's how gauges and indicators work in the analog world too. It's usually been straightforward to code this way with the toolkits I've used, though that's not a huge number.
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2015-07-21 08:26 -0700 |
| Message-ID | <87zj2pv8et.fsf@jester.gateway.sonic.net> |
| In reply to | #21399 |
pozz <pozzugno@gmail.com> writes: > When I design the firmware of the dashboard controller, I always have > many doubts on the design better to choose: refresh-based or > event-based? Usually interfaces like you describe are implemented with a UI toolkit running under a window system, and those are typically event-based, to use your terminology. Maybe you want to consider using such a toolkit rather than rolling your own. They might seem like code bloat, but there is a huge amount of detail that goes into writing one that can put up good looking UI's. If you're making a consumer-facing product then you should probably also allocate significant development schedule to tweaking the UI after its basics are working. It takes a lot of iterated small improvements to make a UI really attractive, and that in turn has a big effect on product success (look at how much effort Apple puts into this).
[toc] | [prev] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2015-07-22 07:04 +0200 |
| Message-ID | <mon86l$8vt$1@dont-email.me> |
| In reply to | #21405 |
Il 21/07/2015 17:26, Paul Rubin ha scritto: > pozz <pozzugno@gmail.com> writes: >> When I design the firmware of the dashboard controller, I always have >> many doubts on the design better to choose: refresh-based or >> event-based? > > Usually interfaces like you describe are implemented with a UI toolkit > running under a window system, and those are typically event-based, to > use your terminology. Maybe you want to consider using such a toolkit > rather than rolling your own. They might seem like code bloat, but > there is a huge amount of detail that goes into writing one that can put > up good looking UI's. I use emWin graphical libraries, but I think the situation is similar to other similar toolkit. Even with these libraries, you can choose an event-based or a refresh-based approach. Yes, they are usually event-based, but this is limited to the GUI: the user press a button and an event is trigger (a callback is called). Anyway the programmer can choose to update values on the display at a regular rate or when an event (from the field/bus, not from the GUI) is triggered. > If you're making a consumer-facing product then you should probably also > allocate significant development schedule to tweaking the UI after its > basics are working. It takes a lot of iterated small improvements to > make a UI really attractive, and that in turn has a big effect on > product success (look at how much effort Apple puts into this). I know... I know.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.arch.embedded
csiph-web