Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #21399 > unrolled thread

Design pattern: refresh-based or event-based?

Started bypozz <pozzugno@gmail.com>
First post2015-07-21 10:02 +0200
Last post2015-07-22 07:32 +0200
Articles 20 on this page of 33 — 10 participants

Back to article view | Back to comp.arch.embedded


Contents

  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 →


#21399 — Design pattern: refresh-based or event-based?

Frompozz <pozzugno@gmail.com>
Date2015-07-21 10:02 +0200
SubjectDesign 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]


#21400

Fromupsidedown@downunder.com
Date2015-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]


#21401

Frompozz <pozzugno@gmail.com>
Date2015-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]


#21413

FromDimiter_Popoff <dp@tgi-sci.com>
Date2015-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]


#21423

Frompozz <pozzugno@gmail.com>
Date2015-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]


#21429

FromPaul Rubin <no.email@nospam.invalid>
Date2015-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]


#21432

Frompozz <pozzugno@gmail.com>
Date2015-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]


#21433

FromPaul Rubin <no.email@nospam.invalid>
Date2015-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]


#21431

Fromupsidedown@downunder.com
Date2015-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]


#21438

FromDimiter_Popoff <dp@tgi-sci.com>
Date2015-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]


#21453

Frompozz <pozzugno@gmail.com>
Date2015-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]


#21454

FromDimiter_Popoff <dp@tgi-sci.com>
Date2015-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]


#21607

Fromraimond.dragomir@gmail.com
Date2015-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]


#21402

FromDon Y <this@is.not.me.com>
Date2015-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]


#21403

FromHans-Bernhard Bröker <HBBroeker@t-online.de>
Date2015-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]


#21425

Frompozz <pozzugno@gmail.com>
Date2015-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]


#21439

FromStefan Reuther <stefan.news@arcor.de>
Date2015-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]


#21440

FromPaul Rubin <no.email@nospam.invalid>
Date2015-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]


#21405

FromPaul Rubin <no.email@nospam.invalid>
Date2015-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]


#21426

Frompozz <pozzugno@gmail.com>
Date2015-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