eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

classic Classic list List threaded Threaded
16 messages Options
jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

On Wed, Apr 6, 2011 at 12:57 PM, Bogdan Marinescu
<[hidden email]> wrote:
> Yes, something has to be implemented for situations like this. Two main ways
> I can think of:
> 1. document all of these platform-specific gotchas on the wiki
> 2. add warnings directly in eLua (configurable, like levels and on/off).
> I'd go with 2 personally.

This is an interesting discussion/point.  Lua certainly provides some
mechanisms for complaining about this sort of thing, and being able to
toggle this, or maybe even make it default to be on during interactive
use and default off otherwise would be quite desirable.

However, I think there's also some question as to _how_ and _when_ one
would and should warn the user about such things.  Clearly one wants
to warn the user about potentially unexpected or undesirable behavior,
but where does one draw the line for this sort of thing. This is a
problem with most of the platform modules, and is particularly the
case with ADC where setting the "clock" for one channel, generally
means setting it for all the channels since they're all multiplexed,
but do I warn the user of that every time?

Perhaps there could be some pattern for functions like this that have
side effects to not only return frequency that was set on the stack,
but also a list of the peripheral ids that were affected or something
similar?

We could also go in the direction of having a general facility, which
might actually be necessary in order to implement the warning system
in the first place, whereby the user would be able to check in advance
what groups would be affected by certain settings or changes on a
given platform.

When we come upon details like this, I think we hit some difficult
questions (much more so than just implementing a new peripheral module
or general feature) of how to keep something like this simple and
usable without ballooning into something the size of the USB or ACPI
spec :-)

I, and I suspect Bogdan as well, really like the idea of describing
the platform, pin configurations and whatnot in a machine digestible
form both for the build system and for online documentation as well as
situations like this where the system would be able to provide useful
warnings if the user desired.  I'm also unsure how to prevent
something like this from becoming too resource intensive on an MCU
(aside from maybe optionally storing such information with
documentation on an SD card where the user could enable a flag to turn
on checking that would have an overhead cost).

Another thought could be this:  if the overhead is too high on the MCU
and we do have the MCU described in some sort of data structure, we
could provide some sort of eLua-lint that could be run on the desktop
that would spit out some platform-relevant warnings for the user?





--
James Snyder
Biomedical Engineering
Northwestern University
[hidden email]
PGP: http://fanplastic.org/key.txt
Phone: (847) 448-0386
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

Hi,

On Wed, Apr 6, 2011 at 11:54 PM, James Snyder <[hidden email]> wrote:
On Wed, Apr 6, 2011 at 12:57 PM, Bogdan Marinescu
<[hidden email]> wrote:
> Yes, something has to be implemented for situations like this. Two main ways
> I can think of:
> 1. document all of these platform-specific gotchas on the wiki
> 2. add warnings directly in eLua (configurable, like levels and on/off).
> I'd go with 2 personally.

This is an interesting discussion/point.  Lua certainly provides some
mechanisms for complaining about this sort of thing, and being able to
toggle this, or maybe even make it default to be on during interactive
use and default off otherwise would be quite desirable.

I agree. We ignored this for too long. Doing eLua development with the CPU datasheet opened at all times is possible, but certainly not pleasant. And we can do better. And we have other similar problems. Things that we don't signal explicitly:

1. pin assignments (for example activating an UART might steal a pin that is currently assigned to a PWM output. it would be very nice to let the user know about this)
2. timer delays that are too long/too short for the hardware timer to handle
3. PWMs frequencies that are too high/too low
4. invalid PIO operations (for example platforms that can't do pullup and/or pulldown)

...and so on. One could say that this is a false problem; for example tmr.delay can return an error if the delay is too short (or too long, I can't remember; in any case for some reason I forgot to implement both cases :) ) and pwm.setclock returns the actual clock that was set on the PWM peripheral. True, but not enough. The program still needs to check these errors explicitly. I find that at least in the prototyping phase I'd rather have the system give me some warning/error messages automatically and let me focus on the actual functionality instead of checking for error conditions after each mod.function() call. Something like (following the examples above):

1. Warning: PWM0 needs pin P0_3 which is aleady assigned to UART0.
2. Warning: delay 100000 is too long for TMR0
3. Warning: frequency 5000000 is too high for PWM0. Or Warning: can't set frequency 50000000 on PWM0, the best aproximation is 48000000
4. Warning: P0_5 doesn't have an internal pullup.

Some of these (for example 2-4 above) can be implemented relatively easy with minimum changes. Others (1) need special support and code that wasn't written it. I really believe it's worth doing it though.
 
However, I think there's also some question as to _how_ and _when_ one
would and should warn the user about such things.  Clearly one wants
to warn the user about potentially unexpected or undesirable behavior,
but where does one draw the line for this sort of thing. This is a
problem with most of the platform modules, and is particularly the
case with ADC where setting the "clock" for one channel, generally
means setting it for all the channels since they're all multiplexed,
but do I warn the user of that every time?

Yes, until he explictly tells you not to. In my mind this has two phases:

1. prototyping phase. You experiment a lot in this phase and most likely you want all the warnings you can get.
2. deployment and regular execution phase. In this case you're most likely out of warnings anyway; if not, you still don't want them popping out unexpectedly, so you'd either shut them off completely or redirect them to somewhere else (for example in a file).

We can add some function to the elua module for this. Out of the top of my head:

- elua.enable_warnings( true|false )
- elua.set_warning_device( this can be a file (stdout is of course possible), an UART, a TCP/IP socket ... )

If you want to get fancy:

- elua.set_warn_level( level ) : we can define a set of warnings (like verbose, debug, error...)
- elua.enable_warnings (true|false, [module1, module2, ..., modulen]) - the more advanced version of the above which specifies warnings per module instead of globally.

This requires a bit of work but it's definitely doable.

Perhaps there could be some pattern for functions like this that have
side effects to not only return frequency that was set on the stack,
but also a list of the peripheral ids that were affected or something
similar?

Hmmm, interesting. I was initially thinking about letting each backend return its own error message, however your approach is more generic which makes it easier to implement (and more logical). The danger here, of course, is that the error messages might become a bit too generic to give enough information on the actual case of the error. For example:

Warning: PWM0 affects TMR0 and TMR1

What exactly does this mean? A frequency change? A pin that was "stolen" from another peripheral? This might be clear from the context, or it might not. In the end it might be better for each backend in turn to return its own warning message (although this might lead to duplicated functionality in different backends).
 
We could also go in the direction of having a general facility, which
might actually be necessary in order to implement the warning system
in the first place, whereby the user would be able to check in advance
what groups would be affected by certain settings or changes on a
given platform.

Yes, we need a general facility in any case.
 
When we come upon details like this, I think we hit some difficult
questions (much more so than just implementing a new peripheral module
or general feature) of how to keep something like this simple and
usable without ballooning into something the size of the USB or ACPI
spec :-)

I, and I suspect Bogdan as well, really like the idea of describing
the platform, pin configurations and whatnot in a machine digestible
form both for the build system and for online documentation as well as
situations like this where the system would be able to provide useful
warnings if the user desired.  

Yes, Bogdan likes this a lot too :)
 
I'm also unsure how to prevent
something like this from becoming too resource intensive on an MCU
(aside from maybe optionally storing such information with
documentation on an SD card where the user could enable a flag to turn
on checking that would have an overhead cost).

You don't really have much choice here I'm afraid. The best we can do is a remote database (which is exactly your SD card suggestion) with a structure that makes it easily indexable on its storage so that one doesn't need to read all of it into memory. Personally I'd be happy to have it even only in Flash though :)
 
Another thought could be this:  if the overhead is too high on the MCU
and we do have the MCU described in some sort of data structure, we
could provide some sort of eLua-lint that could be run on the desktop
that would spit out some platform-relevant warnings for the user?

I'm not sure that a compile-time solution is good enough (plus it would be damn hard to implement). I think that a configurable runtime component (like just about everything we have in eLua until now) is the way to go here.

Best,
Bogdan


_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

-1 for warning messages, partly because eLua is for embedded systems
so should be essential, and partly because "the users" are embedded
systems engineers who do need to be familiar with the characteristics
of device they are using, and need to know how to use eLua to achieve
the exact effects they require. in short, they need good
documentation.


We can help them (and ourselves!) in this by documenting what the
modules/platforms actually do with much more precision and detail
(think of the precision of a datasheet: waveform characteristics,
timing behaviour, mandatory initialization/use sequences of the
primitives, bugs/defects in some scenarios) and we can make this task
easier and more comprehensible by making the different ports behave in
more similar ways.

Let me give an example: I couldn't find out what the behaviour of a
PWM should be and don't have the other hardware platforms to be able
to compare them so have just had to guess while implementing it for
AVR32 and the result is the following:
- each channel's pin is not driven until pwm.start() is called for it,
at which point it becomes a driven output
- after pwm.setup(), the output remains low (GND) until pwm.start() is called
- it always outputs a complete number of cycles even if you call
pwm.stop() immediately
- you can call pwm.start() before pwm.setup() if you like and it still works
- the actual frequency differs from the required frequency and is
always >= the requested frequency. The reported frequency differs from
the actual frequency (because the real frequency is a floating point
value while the primitives return an integer) and is <= the actual
frequency  (so most often what is reported is the same as what was
requested). (Yes, giving the nearest frequency would be better in both
cases).
- the output is high for approximately "duty" percent of the cycle
(again, rounding and imprecision), and the high part is at the end of
the cycle, not the beginning.
- you can call pio.whatever() on the same pins to turn the PWM outputs
into generic GPIOs like the others, even after having called calling
pwm.*() functions or while they are running. You can than call
pwm.setup to turn that GPIO pin back into a PWM output.
- if you change the frequency or duty cycle, it currently just
modifies them in the registers, so you probably get one cycle of junk
when you do this.
- platform-specific: there is a (currently disabled) mechanism to
delay freq or duty updates until the end of a cycle, but this makes
the "set" primitive delay up to one cycle if the frequency is changed.
Worse, with this mechanism, if you change both the frequency and the
length of the duty cycle in clocks, it can only update one of them at
a time, so there is both a potential two-cycle delay and a compulsory
intermediate cycle of junk, either at the old frequency and new duty
period or vice versa, depending on the change.

... and probably a lot more that is only documented as comments in the code.

Another example I noticed in passing: if you ask for an SPI clock rate
that is not supported, the code selects the arithmetically closest
available clock rate, which may be higher, so if you try to initialise
a device at its maximum rated transfer speed, the code can select a
higher one that is out of spec.

I think that without this level of detail in the documentation (which
becomes a specification) it is unlikely that an example program such
as tvbgone.lua will work on any platform other than the one it was
developed on due to the different timing characteristics and
behaviour.  This level of detail also helps us to ensure that the
different implementations behave the same way.

    M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

On Thu, Apr 7, 2011 at 6:13 PM, Martin Guy <[hidden email]> wrote:
-1 for warning messages, partly because eLua is for embedded systems
so should be essential, and partly because "the users" are embedded
systems engineers

Not really. A large part of the eLua audience are those people that are NOT embedded engineers but want to use the hardware anyway (see http://www.eluaproject.net/en_overview.html for details). If I were one of them I'd really appreciate a feature like this. Hell, I'd appreciate something like this anyway because while I am quite familiar with embedded systems in general I am also extremely lazy :) so I'd like to have my tools outline my possible mistakes for me. Lazy or not this is likely to translate into better efficiency in the end.
 
who do need to be familiar with the characteristics
of device they are using, and need to know how to use eLua to achieve
the exact effects they require. in short, they need good
documentation.


We can help them (and ourselves!) in this by documenting what the
modules/platforms actually do with much more precision and detail
(think of the precision of a datasheet: waveform characteristics,
timing behaviour, mandatory initialization/use sequences of the
primitives, bugs/defects in some scenarios) and we can make this task
easier and more comprehensible by making the different ports behave in
more similar ways.

Let me give an example: I couldn't find out what the behaviour of a
PWM should be and don't have the other hardware platforms to be able
to compare them so have just had to guess while implementing it for
AVR32 and the result is the following:
- each channel's pin is not driven until pwm.start() is called for it,
at which point it becomes a driven output
- after pwm.setup(), the output remains low (GND) until pwm.start() is called
- it always outputs a complete number of cycles even if you call
pwm.stop() immediately
- you can call pwm.start() before pwm.setup() if you like and it still works
- the actual frequency differs from the required frequency and is
always >= the requested frequency. The reported frequency differs from
the actual frequency (because the real frequency is a floating point
value while the primitives return an integer) and is <= the actual
frequency  (so most often what is reported is the same as what was
requested). (Yes, giving the nearest frequency would be better in both
cases).
- the output is high for approximately "duty" percent of the cycle
(again, rounding and imprecision), and the high part is at the end of
the cycle, not the beginning.
- you can call pio.whatever() on the same pins to turn the PWM outputs
into generic GPIOs like the others, even after having called calling
pwm.*() functions or while they are running. You can than call
pwm.setup to turn that GPIO pin back into a PWM output.
- if you change the frequency or duty cycle, it currently just
modifies them in the registers, so you probably get one cycle of junk
when you do this.
- platform-specific: there is a (currently disabled) mechanism to
delay freq or duty updates until the end of a cycle, but this makes
the "set" primitive delay up to one cycle if the frequency is changed.
Worse, with this mechanism, if you change both the frequency and the
length of the duty cycle in clocks, it can only update one of them at
a time, so there is both a potential two-cycle delay and a compulsory
intermediate cycle of junk, either at the old frequency and new duty
period or vice versa, depending on the change.

... and probably a lot more that is only documented as comments in the code.

Impressive. Wow, I didn't know about most of the stuff you are talking about here :) While some of them are implementation errors (for example the PWM frequency being always higher than what you request) others are platform or implementation quirks that are best documented in text (which is a job for the wiki). I never intended to use the warnings system for very detailed things like this but rather for easy to make mistakes (like the ones outlined in my previous e-mail).
 
Another example I noticed in passing: if you ask for an SPI clock rate
that is not supported, the code selects the arithmetically closest
available clock rate, which may be higher, so if you try to initialise
a device at its maximum rated transfer speed, the code can select a
higher one that is out of spec.

IMO this is exactly the kind of situation where a warning could make things much better. You set your clock in the program, eLua says "hey, i can't give you that, i'm going to setup something a bit higher" and you think "oh wait, that's not good" and try another clock. I simply can't think of a more convenient way to do it. Don't forget that one of the strongest point of eLua is that it makes (or is supposed to make :) ) prototyping very easy. I believe these kind of warnings are a very good tool for making this goal a reality.
 
I think that without this level of detail in the documentation (which
becomes a specification) it is unlikely that an example program such
as tvbgone.lua will work on any platform other than the one it was
developed on due to the different timing characteristics and
behaviour.  This level of detail also helps us to ensure that the
different implementations behave the same way.

Certainly. The more docs we have for a specific platform, the better.

Best,
Bogdan


_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

On Thu, Apr 7, 2011 at 10:46 AM, Bogdan Marinescu
<[hidden email]> wrote:

> On Thu, Apr 7, 2011 at 6:13 PM, Martin Guy <[hidden email]> wrote:
>>
>> -1 for warning messages, partly because eLua is for embedded systems
>> so should be essential, and partly because "the users" are embedded
>> systems engineers
>
> Not really. A large part of the eLua audience are those people that are NOT
> embedded engineers but want to use the hardware anyway
> (see http://www.eluaproject.net/en_overview.html for details). If I were one
> of them I'd really appreciate a feature like this. Hell, I'd appreciate
> something like this anyway because while I am quite familiar with embedded
> systems in general I am also extremely lazy :) so I'd like to have my tools
> outline my possible mistakes for me. Lazy or not this is likely to translate
> into better efficiency in the end.
>
>>
>> who do need to be familiar with the characteristics
>> of device they are using, and need to know how to use eLua to achieve
>> the exact effects they require. in short, they need good
>> documentation.
>>
>>
>> We can help them (and ourselves!) in this by documenting what the
>> modules/platforms actually do with much more precision and detail
>> (think of the precision of a datasheet: waveform characteristics,
>> timing behaviour, mandatory initialization/use sequences of the
>> primitives, bugs/defects in some scenarios) and we can make this task
>> easier and more comprehensible by making the different ports behave in
>> more similar ways.
>>
>> Let me give an example: I couldn't find out what the behaviour of a
>> PWM should be and don't have the other hardware platforms to be able
>> to compare them so have just had to guess while implementing it for
>> AVR32 and the result is the following:
>> - each channel's pin is not driven until pwm.start() is called for it,
>> at which point it becomes a driven output
>> - after pwm.setup(), the output remains low (GND) until pwm.start() is
>> called
>> - it always outputs a complete number of cycles even if you call
>> pwm.stop() immediately
>> - you can call pwm.start() before pwm.setup() if you like and it still
>> works
>> - the actual frequency differs from the required frequency and is
>> always >= the requested frequency. The reported frequency differs from
>> the actual frequency (because the real frequency is a floating point
>> value while the primitives return an integer) and is <= the actual
>> frequency  (so most often what is reported is the same as what was
>> requested). (Yes, giving the nearest frequency would be better in both
>> cases).
>> - the output is high for approximately "duty" percent of the cycle
>> (again, rounding and imprecision), and the high part is at the end of
>> the cycle, not the beginning.
>> - you can call pio.whatever() on the same pins to turn the PWM outputs
>> into generic GPIOs like the others, even after having called calling
>> pwm.*() functions or while they are running. You can than call
>> pwm.setup to turn that GPIO pin back into a PWM output.
>> - if you change the frequency or duty cycle, it currently just
>> modifies them in the registers, so you probably get one cycle of junk
>> when you do this.
>> - platform-specific: there is a (currently disabled) mechanism to
>> delay freq or duty updates until the end of a cycle, but this makes
>> the "set" primitive delay up to one cycle if the frequency is changed.
>> Worse, with this mechanism, if you change both the frequency and the
>> length of the duty cycle in clocks, it can only update one of them at
>> a time, so there is both a potential two-cycle delay and a compulsory
>> intermediate cycle of junk, either at the old frequency and new duty
>> period or vice versa, depending on the change.
>>
>> ... and probably a lot more that is only documented as comments in the
>> code.
>
> Impressive. Wow, I didn't know about most of the stuff you are talking about
> here :) While some of them are implementation errors (for example the PWM
> frequency being always higher than what you request) others are platform or
> implementation quirks that are best documented in text (which is a job for
> the wiki). I never intended to use the warnings system for very detailed
> things like this but rather for easy to make mistakes (like the ones
> outlined in my previous e-mail).

I would agree that where there's an example of an error, we should
clearly fix that, and in no way am I suggesting that we don't lay down
a bit more in the way of detailing expected behavior and deviations
from it within documentation or on the wiki.

I can't speak for Bogdan, but I get the sense that we're thinking
somewhat similarly here in that if there were a system like this it
would be more for "obvious" side effects like settings applying to
groups of ids when the user only asked to apply it to 1. I think that
returning a different clock than requested is also a decent example.
I'm really more thinking of this as a "we or the hardware are going to
make a non-obvious decision for you because we can't do exactly what
you asked for, we're going to let you know about that" (that said,
documenting these quirks is also important).  Pin reassignments I
think are different.  I think we can almost upfront state that if you
use a pin on one peripheral mode then try to use it in another
peripheral mode it A) might not work without reconfiguration B) if it
does get reconfigured it's not going to work in the original
peripheral mode until you switch it back.

On a related note, since the duty cycles are fractional, I would
support some mechanism for letting the program or the user know about
what the actual selected fraction ended up being, just like we return
the actual frequency that was acquired even when we don't give the
user exactly what they requested.  I think we could maybe set some
minimum standards we use on implementations in order to make platforms
more consistent, but they're always going to differ to some extent
since they don't use the same clock dividers, register sizes,
configuration models, etc..

>
>>
>> Another example I noticed in passing: if you ask for an SPI clock rate
>> that is not supported, the code selects the arithmetically closest
>> available clock rate, which may be higher, so if you try to initialise
>> a device at its maximum rated transfer speed, the code can select a
>> higher one that is out of spec.
>
> IMO this is exactly the kind of situation where a warning could make things
> much better. You set your clock in the program, eLua says "hey, i can't give
> you that, i'm going to setup something a bit higher" and you think "oh wait,
> that's not good" and try another clock. I simply can't think of a more
> convenient way to do it. Don't forget that one of the strongest point of
> eLua is that it makes (or is supposed to make :) ) prototyping very easy. I
> believe these kind of warnings are a very good tool for making this goal a
> reality.

Yep, although we do "notify" the user in the sense that we're supposed
to return the frequency that actually got selected so at least they
can look at their return parameter and decide if what they got was
acceptable.  I could see this sort of model extending further to
provide more details in return values on these types of decisions that
are made for the user (i.e.: let the user know what pwm fraction in
addition to clock was actually used when pwm.setup is called).  On the
other hand some sort of error/warning channel of logging output is
fairly simple and would be useful as well.

I could imagine this also working something like STDOUT and STDERR,
which might work nicely with our mux implementation to prevent these
types of messages from polluting the main interface stream.  In fact
this might be a generally useful facility for us when
testing/debugging to spit out messages on a separate stream.  We can
already do this in an adhoc manner, but I suppose this could establish
a standardized mechanism.

>
>>
>> I think that without this level of detail in the documentation (which
>> becomes a specification) it is unlikely that an example program such
>> as tvbgone.lua will work on any platform other than the one it was
>> developed on due to the different timing characteristics and
>> behaviour.  This level of detail also helps us to ensure that the
>> different implementations behave the same way.
>
> Certainly. The more docs we have for a specific platform, the better.
> Best,
> Bogdan
>
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev
>
>



--
James Snyder
Biomedical Engineering
Northwestern University
[hidden email]
PGP: http://fanplastic.org/key.txt
Phone: (847) 448-0386
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

In reply to this post by BogdanM
On 7 April 2011 17:46, Bogdan Marinescu <[hidden email]> wrote:
> Not really. A large part of the eLua audience are those people that are NOT
> embedded engineers but want to use the hardware anyway

Ah, OK. We have different objectives then.
In a toy system for beginners, I suppose holding their hands and
popping up with info boxs on simple errors may be useful to people who
don't have a good grasp of what they are doing..
I aim for a production-quality system that permits you to drive the
hardware with precision to achieve quality results.
Of course, these two objectives are not mutually exclusive.

However, the objectives *do* conflict when it comes to something like
the difference between being able to set the duty cycle roughly in
percent or getting the maximum available precision, in which case you
need to be able to find out the period in cycles and set it to a
number of cycles.  If you just want to dim LEDs and don't mind the
dimming being visibly stepped at low values, percent is OK. If you
want to use PWM as a crude DAC, percent reduces it to being slightly
worse than a 7-bit DAC whereas the hardware (in this case) is capable
of 1 in 1000 precision at 11kHz - a little better than telephone
quality.

Yes, I know there's an issue proposing a higher precision of PWM duty
cycle specification, though I expect it will be to set it as a
fraction of a million, like the delays.  The most precise primitive
would be to be able to find out the period in clock cycles and to set
the duty period in clock cycles, but from what you say that seems
inappropriate to the eLua way of thinking.

>> Another example I noticed in passing: if you ask for an SPI clock rate
>> that is not supported, the code selects the arithmetically closest
>> available clock rate, which may be higher, so if you try to initialise
>> a device at its maximum rated transfer speed, the code can select a
>> higher one that is out of spec.
>
> IMO this is exactly the kind of situation where a warning could make things
> much better. You set your clock in the program, eLua says "hey, i can't give
> you that, i'm going to setup something a bit higher"

Or you (as the implementer) can know that SPI clocks tend to be chosen
to drive devices at their maximum rated speed, and select an available
speed that is as high as possible without exceeding the specified
speed, while UART baud rates need to be as close to the requested rate
as possible so that the communication is more likely to work, and PWM
frequencies are more likely to be used to generate an audio tone or ti
signal devices that respond to PWM signals, so are probably best
chosen as close to the requested value as possible.  That also seems
best for beginners, since their SPI device is more likely to work and
their piano is more likely to be well tuned. (Currently the strategies
are exactly the opposite to this!)
However, it's well documented that the primitives return the actual
speed selected (or, rather a number close to the actual value!), so
power programmers can check that to see what really happened and
correct if necessary.

My feeling is that issuing a warning is a solution to the programmer
anxiety that arises when you can't do exactly what was asked and can't
decide what would be right. Dumping the problem on the user is one
solution, to make them decide. Another is to make a policy decision
(for example, if a requested value is higher or lower than the
possible values, set the highest or lowest possible, and if it cannot
be precisely obtained, set the arithmetically closest value, or the
nearest available lower value or whatever).
Issuing a warning when the value is not precise creates the question
"How much imprecision is not precise?" More than an integer different?
That will throw errors all the time. More than 10% different?  Or 5%?
Why 5? Why 10? Do we need another primitive to set the imprecision
that triggers warnings?
OK, I'm exaggerating to make a point, but there is a risk that it just
replaces a technical problem with a philosophical one and unless
someone wants to go through all the existing code looking for places
where a warning might be useful to a beginner, I can predict that the
warning support will be not be consistent, but just limited to a few
cases where the programmer thought it might be useful.

Still, when working on mainline eLua, I'll try to implement stuff as
close to the eLua way as possible.

     M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

Hi,

On Fri, Apr 8, 2011 at 2:29 PM, Martin Guy <[hidden email]> wrote:
On 7 April 2011 17:46, Bogdan Marinescu <[hidden email]> wrote:
> Not really. A large part of the eLua audience are those people that are NOT
> embedded engineers but want to use the hardware anyway

Ah, OK. We have different objectives then.
In a toy system for beginners, I suppose holding their hands and
popping up with info boxs on simple errors may be useful to people who
don't have a good grasp of what they are doing..

Definitely. l maintain that this is also useful in the prototyping phase of a project even if you know very well what you're doing. We're all prone to mistakes.
 
I aim for a production-quality system that permits you to drive the
hardware with precision to achieve quality results.
Of course, these two objectives are not mutually exclusive.

However, the objectives *do* conflict when it comes to something like
the difference between being able to set the duty cycle roughly in
percent or getting the maximum available precision, in which case you
need to be able to find out the period in cycles and set it to a
number of cycles.  If you just want to dim LEDs and don't mind the
dimming being visibly stepped at low values, percent is OK. If you
want to use PWM as a crude DAC, percent reduces it to being slightly
worse than a 7-bit DAC whereas the hardware (in this case) is capable
of 1 in 1000 precision at 11kHz - a little better than telephone
quality.

Why would the objectives conflict? You're talking about an API change which has nothing to do with the proposed warnings system. 
As a side note, as James already suggested a number of times, the PWM API should really be changed. I'm talking about a major change (directly in the platform interface). We can discuss how to accomplish this in another thread. Martin, you seem to know a lot of things about how a PWM should actually be used. Would you mind starting this thread?
 
Yes, I know there's an issue proposing a higher precision of PWM duty
cycle specification, though I expect it will be to set it as a
fraction of a million, like the delays.  The most precise primitive
would be to be able to find out the period in clock cycles and to set
the duty period in clock cycles, but from what you say that seems
inappropriate to the eLua way of thinking.

I didn't mean to imply that, I apologize if I did. What I aim for is platform independence, as much as possible. If you have an API that respects that but allows for a better usage of a peripheral (PWM or anything else) then I really don't have anything against implementing it. 
 
Or you (as the implementer) can know that SPI clocks tend to be chosen
to drive devices at their maximum rated speed, and select an available
speed that is as high as possible without exceeding the specified
speed, while UART baud rates need to be as close to the requested rate
as possible so that the communication is more likely to work,

Agreed.  This was always the intended functionality anyway (except for the SPI part where AFARK none of the implementations try to return a clock which is always lower than or equal with the expected one).

and PWM
frequencies are more likely to be used to generate an audio tone or ti
signal devices that respond to PWM signals, so are probably best
chosen as close to the requested value as possible.  

This, on the other hand, is something that I generally don't agree with: enforcing a policy. I always believed this is a bad thing to do in general. In this case the policy enforcement happens because of some assumptions like "PWM frequencies are more likely to be used to generate an audio tone". Maybe or maybe not. You might feed this PWM into a boost converter and you might not want to round to the nearest higher value in this case. Then you'd like to return the lower value. Then again, your boost converter might be working in inverted logic for some reason, thus in this case you'd want to round to the nearest higher value. No good response here, the safest thing to do is to round to the nearest value in either direction and let the user know about this.
 
However, it's well documented that the primitives return the actual
speed selected (or, rather a number close to the actual value!), so
power programmers can check that to see what really happened and
correct if necessary.

Yes, or they could completely forget about that :) I did this so many times before that I can't even count them. So I'd be grateful if the sytem lets them know about their mistake. I'm ready to bet that I'm not the only one.
 
My feeling is that issuing a warning is a solution to the programmer
anxiety that arises when you can't do exactly what was asked and can't
decide what would be right. Dumping the problem on the user is one
solution, to make them decide. Another is to make a policy decision
(for example, if a requested value is higher or lower than the
possible values, set the highest or lowest possible, and if it cannot
be precisely obtained, set the arithmetically closest value, or the
nearest available lower value or whatever).

As specified above I'm not a big fan on imposing policies in general. I recently read "Linux Device Drivers" which seems to agree on the "don't inforce policy" idea for drivers. Sometimes it makes sense (like the UART situation you presented above). Sometimes it might only look that it makes sense.
 
Issuing a warning when the value is not precise creates the question
"How much imprecision is not precise?" More than an integer different?

You can always say "Warning: clock set to y instead of requested x". That's pretty precise :) and it lets the user decide on the actual implications of this.
 
That will throw errors all the time. More than 10% different?  Or 5%?
Why 5? Why 10? Do we need another primitive to set the imprecision
that triggers warnings?
OK, I'm exaggerating to make a point, but there is a risk that it just
replaces a technical problem with a philosophical one and unless
someone wants to go through all the existing code looking for places
where a warning might be useful to a beginner, I can predict that the
warning support will be not be consistent, but just limited to a few
cases where the programmer thought it might be useful.

I can almost guarantee that it will be exactly this at first. However, if we make it into an easy to use framework, implementers will hopefully feel encouraged to add more warnings as they are found.
 
Best,
Bogdan


_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

On 8 April 2011 14:13, Bogdan Marinescu <[hidden email]> wrote:

> Why would the objectives conflict?

In general, a system that is "easy to use" cannot be powerful and vice versa.

> Martin, you seem to know a lot of things about how a PWM should
> actually be used. Would you mind starting this thread?

I never used PWM in my life before, which is probably why I find it so
difficult to understand how it should behave.

> "PWM frequencies are more likely to be used to generate an audio tone".
> Maybe or maybe not. You might feed this PWM into a boost converter and you
> might not want to round to the nearest higher value in this case.

Thanks! Another application of PWM that I was unaware of...

> The safest thing to do is to round to the nearest value in either direction and let the user
> know about this.

OK. That sounds like a good general guideline.
Unfortunately, in the SPI case, the difference between the chosen
frequency and the actual frequency can be quite large. In a few tests
I ran, if you set the maximum SPI data rate for an SD card (400kHz)
the result was something like 35% higher because of the coarse
precision of the dividers when they are at small values. But to the
code, this seemed like the arithmetically closest value.
On the second point, since the API returns the integer value closest
to the actual frequency selected, we have already achieved the "let
the user know° part in this case.

> As specified above I'm not a big fan on imposing policies in general.

If you don't make a policy, you get chaos with every individual case
behaving in a different, random way. That is the current case in eLua.
But maybe we mean different things by the word "policy".  I'm meaning
"a guideline on how to make decisions when you're not sure what to
do", which then gets interpreted according to each case when you have
to make a decision.  In this case, the policy decision seems to be
changing from "do whatever you like" to "if you can't do exactly what
the user asked for, print a warning".
Linux device drivers are a very different world from a programming
system for beginners, so the policy there (of not enforcing one way of
driving a peripheral, but of having a complex programmer interface
that allows the caller to set the device up with as much precision and
flexibility as possible) is made according to the world of Linux
device drivers.

>> Issuing a warning when the value is not precise creates the question
>> "How much imprecision is not precise?" More than an integer different?
>
> You can always say "Warning: clock set to y instead of requested x". That's
> pretty precise :) and it lets the user decide on the actual implications of
> this.

Example: at 1MHz PWM clock rate, the same frequency as you asked for
is returned for every frequency <= 1kHz.
Above 1kHz, most frequencies set (and return) something different,
with the granularity increasing as the frequency increases.
So if the system works by varying the frequency, most settings will
provoke a warning.

   M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

In reply to this post by BogdanM
On Fri, Apr 8, 2011 at 3:52 PM, Martin Guy <[hidden email]> wrote:
On 8 April 2011 14:13, Bogdan Marinescu <[hidden email]> wrote:

> Why would the objectives conflict?

In general, a system that is "easy to use" cannot be powerful and vice versa.

I make it my mission to prove this wrong :) Which of course I'll never be able to do, as "easy to use" is a fairly subjective matter. But at least I can try :) In this particular case, for example, a warning system which is parallel to the actual peripheral API shouldn't make the system less powerful. As long as you design your warnings system to follow your API and not the other way around you shouldn't have to worry about performance. 

I never used PWM in my life before, which is probably why I find it so
difficult to understand how it should behave.

Ah, OK. My bad.
 
> The safest thing to do is to round to the nearest value in either direction and let the user
> know about this.

OK. That sounds like a good general guideline.
Unfortunately, in the SPI case, the difference between the chosen
frequency and the actual frequency can be quite large. In a few tests
I ran, if you set the maximum SPI data rate for an SD card (400kHz)
the result was something like 35% higher because of the coarse
precision of the dividers when they are at small values. But to the
code, this seemed like the arithmetically closest value.

This is unavoidable unfortunately. Even with a very good API you're still stuck with the platform-specific hardware limitations.
 
On the second point, since the API returns the integer value closest
to the actual frequency selected, we have already achieved the "let
the user know° part in this case.

> As specified above I'm not a big fan on imposing policies in general.

If you don't make a policy, you get chaos with every individual case
behaving in a different, random way. That is the current case in eLua.
But maybe we mean different things by the word "policy".  I'm meaning
"a guideline on how to make decisions when you're not sure what to
do", which then gets interpreted according to each case when you have
to make a decision.  In this case, the policy decision seems to be
changing from "do whatever you like" to "if you can't do exactly what
the user asked for, print a warning".

Ideally we would have a combination of the two: choose a reasonable aproximation of the input (what "reasonable" means needs to be decided) and also issue a warning if the aproximation and the input have different values. Once again, the warnings themselves shouldn't have any influence on the actual functionality. In OOP terms, they should be simple observers. An observer never modifies the state or functionality of the system it observes, it just reads its internal state and executes some actions based on this. 
Agreed on the "random way" issue. For example, the return value of platform_spi_setup  has this description:

Returns: the actual clock set for the SPI interface. Depending on the hardware, this may have a different value than the clock argument.

A simple change like this:

Returns: the actual clock set for the SPI interface. Depending on the hardware, this may have a different value than the clock argument. In this case, the highest value which is lower than clock will be returned.

would be enough to make the policy clear. I always had this on my mind but I found it so obvious that I forgot to specify it :) (except for the "lower than clock" part which I completely missed until now). And you're right, this isn't really policy. Or maybe it's that lowest level of policy that ensures things aren't completely random. I don't know how to call it, but I agree this minimal set of rules should be enforced.
 
Linux device drivers are a very different world from a programming
system for beginners, so the policy there (of not enforcing one way of
driving a peripheral, but of having a complex programmer interface
that allows the caller to set the device up with as much precision and
flexibility as possible) is made according to the world of Linux
device drivers.

Sure. It's a good generic principle though and I'm trying to follow it as much as I can.
 

>> Issuing a warning when the value is not precise creates the question
>> "How much imprecision is not precise?" More than an integer different?
>
> You can always say "Warning: clock set to y instead of requested x". That's
> pretty precise :) and it lets the user decide on the actual implications of
> this.

Example: at 1MHz PWM clock rate, the same frequency as you asked for
is returned for every frequency <= 1kHz.
Above 1kHz, most frequencies set (and return) something different,
with the granularity increasing as the frequency increases.
So if the system works by varying the frequency, most settings will
provoke a warning.

Which is perfectly fine. Once you're aware that something is wrong you can turn off that warning (my original proposal included something like this) and move on.  I can understand that a lot of warnings could quickly become annoying but having a simple way to turn them on/off should help with this. 

Best,
Bogdan


_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

On 8 April 2011 15:16, Bogdan Marinescu <[hidden email]> wrote:
>> In general, a system that is "easy to use" cannot be powerful and vice
>> versa.
>
> I make it my mission to prove this wrong :) Which of course I'll never be
> able to do, as "easy to use" is a fairly subjective matter.

No, it's a decision you have to make when designing a system, and it
applies to all fields of technology.

If people want to be able to express themselves with precision, they
need a larger vocabulary, so need to understand more.
If you understand less, the range of concepts that you can express is smaller.

The thing to avoid is making a  system that is difficult to use and
still gives you no power. Think MS-DOS command.com

Computers are the most complex machines ever built, and creating the
illusion of simplicity is what programming is all about.
You do this by hiding the immense underlying complexity, which you do
by making decisions for the users and doing "the right thing" without
bothering them.
How successful you are in doing this determines how easy your product
is to use, and the goal is the same whether you are aiming at
high-level or low-level users.
The Linux device drivers are high-complexity because they give wide
expressive power to their callers, but they still hide everything else
that is not relevant.

A flood of warning messages exposes complexity instead of hiding it.
Think of a Windows machine where there is a constant flow of
distracting boxes popping up with incomprehensible messages in them.
No user likes that, whether naive or advanced. It confuses the naive
ones and annoys the advanced ones.

> the warnings themselves shouldn't have any influence on
> the actual functionality.

Printing an error message IS a change in functionality.
If an application changes the duty cycle once per cycle (like the
crude DAC example), the flood of error messages to print on the serisl
port will slow the system to a crawl.
If they are controlling some device on the serial port, a warning
message will come out in the middle of their protocol.
At present, a running eLua program never writes anything to the UART
unless you ask it to.

> An observer never modifies the state or functionality of the system it
> observes

An observer ALWAYS modifies the system it observes.
Unobtrusive observation, even though it is one of the dogmas of naive
scientists, is impossible. Even serious physicists have now woken up
to this.
It's one of the fallacies of scientific method (the other one is that
you can recreate the same initial state to repeat the same
experiment).

>> Linux device drivers are a very different world from a programming
>> system for beginners, so the policy there (of not enforcing one way of
>> driving a peripheral, but of having a complex programmer interface
>> that allows the caller to set the device up with as much precision and
>> flexibility as possible) is made according to the world of Linux
>> device drivers.
>
> Sure. It's a good generic principle though and I'm trying to follow it as
> much as I can.

Don't do that if you want your system to be easy to use.
An expressive interface is complex, and a complex interface is more
difficult to use.
A simple interface is easy to use, but a simple interface doesn't let
you do much.
Choosing the right level of complexity/expressiveness in an interface
is an important choice, but it is still a choice. If you don't make
that choice consciously, the simple interface will grow lots of extra
methods to perform advanced tasks... which is what is happening to
eLua.

If you try to make it both complex and simple, both powerful and easy
to use, you are trying to resolve a paradox and are certain not to
succeed.
Of course, in the attempt to do the impossible, you may achieve enlightenment :)

    M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)



On Fri, Apr 8, 2011 at 5:25 PM, Martin Guy <[hidden email]> wrote:
On 8 April 2011 15:16, Bogdan Marinescu <[hidden email]> wrote:
>> In general, a system that is "easy to use" cannot be powerful and vice
>> versa.
>
> I make it my mission to prove this wrong :) Which of course I'll never be
> able to do, as "easy to use" is a fairly subjective matter.

No, it's a decision you have to make when designing a system, and it
applies to all fields of technology.

Sorry, I simply don't agree that "ease of use" precludes "power". The first example that immediately comes to mind is Xcode under OS/X. I believe that simplicity and power can co-exist, at least up to a point which is very much ahead of what we have in eLua right now.
 
If people want to be able to express themselves with precision, they
need a larger vocabulary, so need to understand more.
If you understand less, the range of concepts that you can express is smaller.

Absolutely correct. I fail to see the connection though. I feel like you're still talking about APIs and I'm still talking about warning messages. I'm with you on the API front.
 
The thing to avoid is making a  system that is difficult to use and
still gives you no power. Think MS-DOS command.com

Computers are the most complex machines ever built, and creating the
illusion of simplicity is what programming is all about.
You do this by hiding the immense underlying complexity, which you do
by making decisions for the users and doing "the right thing" without
bothering them.
How successful you are in doing this determines how easy your product
is to use, and the goal is the same whether you are aiming at
high-level or low-level users.
The Linux device drivers are high-complexity because they give wide
expressive power to their callers, but they still hide everything else
that is not relevant.

A flood of warning messages exposes complexity instead of hiding it.
Think of a Windows machine where there is a constant flow of
distracting boxes popping up with incomprehensible messages in them.
No user likes that, whether naive or advanced. It confuses the naive
ones and annoys the advanced ones.

Ah, this is a problem of perspective then. I agree with you in most cases, but not always. While _developing_ a program I personally find the message boxes extremely useful. Moreover, I found myself reading the Windows debug logs more than once in an attempt to find bugs. It was helpful on many ocasions. And when I didn't want it anymore, I just closed it. Linux has a generic logging facility which you can control however you like and it doesn't have to stay in front of your eyes at all times. What I'm trying to achieve is exactly something between these lines.
 
> the warnings themselves shouldn't have any influence on
> the actual functionality.

Printing an error message IS a change in functionality.
If an application changes the duty cycle once per cycle (like the
crude DAC example), the flood of error messages to print on the serisl
port will slow the system to a crawl.

Absolutely correct. This is why you'll most likely decide not to use them after the prototyping phase. As I see it, the flow is like this:

1. you write your program
2. you get one or more warnings
3. you fix them and mask them if needed so they don't interfere with your work anymore
4. repeat from step 1 until your program works. At this point you can disable warnings completely.

When the warnings are disabled, what you're left with is the overhead of calling the warning system functions. I believe that's mostly negligeable in a system built around an interpreted language.
 
If they are controlling some device on the serial port, a warning
message will come out in the middle of their protocol.
At present, a running eLua program never writes anything to the UART
unless you ask it to.

And it won't issue a warning if you tell it not to :)
 
An observer ALWAYS modifies the system it observes.

Which is extremely important if you want to talk about quantum physics, Heisenberg's principle and related topics. Not that much in this particular and very practical situation :)
 
Unobtrusive observation, even though it is one of the dogmas of naive
scientists, is impossible. Even serious physicists have now woken up
to this.
 
I suspected tha the discussion might be headed in this direction :) Again: you're perfectly right in theory. In practice though, in the particular case of eLua, I believe this is a non-issue.

It's one of the fallacies of scientific method (the other one is that
you can recreate the same initial state to repeat the same
experiment).

>> Linux device drivers are a very different world from a programming
>> system for beginners, so the policy there (of not enforcing one way of
>> driving a peripheral, but of having a complex programmer interface
>> that allows the caller to set the device up with as much precision and
>> flexibility as possible) is made according to the world of Linux
>> device drivers.
>
> Sure. It's a good generic principle though and I'm trying to follow it as
> much as I can.

Don't do that if you want your system to be easy to use.

I do want it to be easy to use, but remember the "power' aspect. Equilibrium, this is what it's all about (no, not the movie). One can't have everything. I won't pretend for a second that I know how to find this equilibrium, but at least I'm trying :)
 
An expressive interface is complex, and a complex interface is more
difficult to use.
A simple interface is easy to use, but a simple interface doesn't let
you do much.
Choosing the right level of complexity/expressiveness in an interface
is an important choice, but it is still a choice. If you don't make
that choice consciously, the simple interface will grow lots of extra
methods to perform advanced tasks... which is what is happening to
eLua.

It's a bit more complex than that in  eLua as we have the additional platform independce requirement. It's fairly easy to write an interface that use all the capabilities of a certain peripheral on a certain platform, it's much harder to generalize. And even after you're done generalizing you're still left with pieces of platform-specific funtionality that can only be implemented by a certain platform. 
 
If you try to make it both complex and simple, both powerful and easy
to use, you are trying to resolve a paradox and are certain not to
succeed. 
Of course, in the attempt to do the impossible, you may achieve enlightenment :)

:) 
 
Best,
Bogdan


_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

In reply to this post by Martin Guy
On Fri, Apr 8, 2011 at 9:25 AM, Martin Guy <[hidden email]> wrote:

> On 8 April 2011 15:16, Bogdan Marinescu <[hidden email]> wrote:
>>> In general, a system that is "easy to use" cannot be powerful and vice
>>> versa.
>>
>> I make it my mission to prove this wrong :) Which of course I'll never be
>> able to do, as "easy to use" is a fairly subjective matter.
>
> No, it's a decision you have to make when designing a system, and it
> applies to all fields of technology.
>
> If people want to be able to express themselves with precision, they
> need a larger vocabulary, so need to understand more.
> If you understand less, the range of concepts that you can express is smaller.

However, even with limited vocabulary you can get useful things done
like ask what time is it? or where is the bathroom?  A user should be
able to do that with a short guide rather than a guide + a 500 page
data sheet.

I don't think anyone here is saying this is easy to do, but the goal,
I believe is to have a system that one can easily dive into without
being an expert in the platform and be able to put together
interesting and neat projects where simple tasks are simple, not
overcomplicated.  At the same time, we're not trying to "dumb down"
the system to make it undesirable for power users.  I don't think at
any level we're suggesting taking away functionality.  This is not
Gnome 3 (what are they thinking?!) :-)

>
> The thing to avoid is making a  system that is difficult to use and
> still gives you no power. Think MS-DOS command.com
>
> Computers are the most complex machines ever built, and creating the
> illusion of simplicity is what programming is all about.

I suppose there are different ways of looking at this, but I see this
a bit differently.  At least for end users it's about hiding most of
the complexity of what makes the machine work so that they can work at
the level of the task they're interested in so that at that level:
simple tasks are simple

Context is very important though. With the appropriate understanding
of current GUI interface metafors and interaction models, the user
doesn't have to know anything about operating system internals to boot
up their machine and play Solitaire or type up a document.  On the
other hand, if they look in the appropriate places and install the
appropriate tools the layers of abstraction are accessible to work at
lower levels if that's desirable.

The same should be the case with eLua, simple tasks, like setting up
PWM should be simple, but one should tell the user when their
intentions have not been met when a command is executed.  I think
return parameters plus performing at or above certain minimums in
terms of performance cover most of this at least for heavy users that
care.  Warning messages might be a nice optional feature for users to
have especially if they're switching between platforms.  If I run code
on LM3S and things run fine, then I switch to AVR32 or STM32 and
suddenly something doesn't work, something like this could be helpful
in debugging.

On another note:  Silent failure is generally a bad idea in
programming.  On the other hand, in embedded systems one generally
doesn't want to throw unhandlable errors unless they're absolutely
necessary since often times there either is no direct user of the
device or the user doesn't have an ability to fix things.  This also
applies to spewing out lots of messages.  However at development time,
this sort of thing can be useful.

> You do this by hiding the immense underlying complexity, which you do
> by making decisions for the users and doing "the right thing" without
> bothering them.
> How successful you are in doing this determines how easy your product
> is to use, and the goal is the same whether you are aiming at
> high-level or low-level users.
> The Linux device drivers are high-complexity because they give wide
> expressive power to their callers, but they still hide everything else
> that is not relevant.
>
> A flood of warning messages exposes complexity instead of hiding it.
> Think of a Windows machine where there is a constant flow of
> distracting boxes popping up with incomprehensible messages in them.
> No user likes that, whether naive or advanced. It confuses the naive
> ones and annoys the advanced ones.

Except, what we're talking about here is a user issuing a command
like... change the clock for PWM on one channel, and that affects
multiple channels, or the fractional period isn't the percent they
requested, or the clock isn't what they requested.  These aren't
incomprehensible or irrelevant messages about the printer driver
finding that its cache is corrupted and it needs to clear it, it's
directly relevant to the context of what the user just asked asked us
for, and whether this is done through a warning message or return
parameters (I definitely favor AT LEAST doing the latter.. since
otherwise the user has no idea what we've done differently.. since
they're return parameters on the stack if they don't accept them, then
we just wasted a few compute cycles putting them on the stack, but
that's all).

I don't think anyone is suggesting that this would be used in a manner
where it should always be dumping these out. It should maybe be off by
default or something similar?  Or as suggested it could be handled
similarly to stdout & stderr where it really is a secondary stream
that can either be merged in or split out.

Actually, as I think about this, I think that warnings like this
should probably be off by default, or maybe should only appear if the
user explicitly asks to listen to stderr output in some way.

>
>> the warnings themselves shouldn't have any influence on
>> the actual functionality.
>
> Printing an error message IS a change in functionality.
> If an application changes the duty cycle once per cycle (like the
> crude DAC example), the flood of error messages to print on the serisl
> port will slow the system to a crawl.
> If they are controlling some device on the serial port, a warning
> message will come out in the middle of their protocol.
> At present, a running eLua program never writes anything to the UART
> unless you ask it to.

So, what's the problem if it isn't enabled by default?  This could be
akin to enabling a debug mode.

Also, these aren't errors.  Actual failures or errors should be
handled differently, these are warnings.



>
>> An observer never modifies the state or functionality of the system it
>> observes
>
> An observer ALWAYS modifies the system it observes.
> Unobtrusive observation, even though it is one of the dogmas of naive
> scientists, is impossible. Even serious physicists have now woken up
> to this.
> It's one of the fallacies of scientific method (the other one is that
> you can recreate the same initial state to repeat the same
> experiment).

Yep, Bogdan, I think you might have just made Heisenberg turn in his grave :-)

That said.. there actually is one place where one can repeatably run
experiments: in mathematics or computation (provided if you're using
pseudorandom number sources and if you are you seed them consistently)
:-)  We'd really be in trouble if we didn't have repeatable execution
of code on computers (barring cosmic rays, power fluctuations, EMI or
other infrequent interactions with the physical world that manage flip
one or more bits).

>
>>> Linux device drivers are a very different world from a programming
>>> system for beginners, so the policy there (of not enforcing one way of
>>> driving a peripheral, but of having a complex programmer interface
>>> that allows the caller to set the device up with as much precision and
>>> flexibility as possible) is made according to the world of Linux
>>> device drivers.
>>
>> Sure. It's a good generic principle though and I'm trying to follow it as
>> much as I can.
>
> Don't do that if you want your system to be easy to use.
> An expressive interface is complex, and a complex interface is more
> difficult to use.
> A simple interface is easy to use, but a simple interface doesn't let
> you do much.
> Choosing the right level of complexity/expressiveness in an interface
> is an important choice, but it is still a choice. If you don't make
> that choice consciously, the simple interface will grow lots of extra
> methods to perform advanced tasks... which is what is happening to
> eLua.

I agree with the last part about choosing complexity/expressiveness.
However, to go back to the language example here: growing some extra
methods, if needed, can be just like learning more of a language to
become more expressive.  The original model matters in terms of making
a choice for initial simplicity or complexity, but in the end if with
something that enables both simple and complex behavior I don't see a
huge problem with growing some extra functions to perform more
advanced tasks.  We haven't really grown the basic individual
peripheral APIs within themselves much after initial implementation so
I don't think we're growing that much in that direction.  Are we
adding additional modules for other advanced tasks that are for other
types of functionality? Yes, as well, but many of these have been
planned features:
http://www.eluaproject.net/en_status.html#roadmap

Additionally, much of this is intended to be modular so that it's not
essential to have or use all of it.

I think where one runs into trouble is when either there are needless
tools that just add weight to the system and maintenance thereof.
Addition of features carries quite a bit of weight not only because of
bloat, but because it can be difficult to take them back later :-)

This is not to say that I don't understand your point... even if you
end up with complex systems in both cases, the one designed to be
complex from the outset could be argued to be "cleaner" in some
fashion than the one that started more simply and grew organically.
That said.. I'm having a tough time thinking of great examples of this
working out, most things that started out intending to be complex just
ended up being a mess anyways (ACPI, I'm looking at you...).  Things
that grow organically can turn into messes (bloatware), but they don't
have to.

>
> If you try to make it both complex and simple, both powerful and easy
> to use, you are trying to resolve a paradox and are certain not to
> succeed.
> Of course, in the attempt to do the impossible, you may achieve enlightenment :)

All designs are a tradeoff to some extent.  I think Apple actually
does a pretty good job with this with their target audiences in Mac OS
X (iOS is a different story with different tradeoffs... I somewhat buy
into them, but not entirely).  I've got pretty much all the power and
flexibility of a BSD Unix underneath a nice clean interface.  While
Linux desktop environments still fight with this to some extent, I
really don't have to give a damn about those underpinnings if I don't
want, but I can dig into them if I want.  Also, while the sources for
the GUI layer might not be available, heck, I can even build my own
kernels if I want to:
http://www.opensource.apple.com/source/xnu/xnu-1504.9.37/

Whether one agrees or not with this example (there are definitely
problems and flaws with Apple as well), the point is that there are
examples of good tradeoffs in design.  While I'm damned sure we're not
near an ideal point, I'd like to make us better if we can do it :-)

>
>    M
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev
>



--
James Snyder
Biomedical Engineering
Northwestern University
[hidden email]
PGP: http://fanplastic.org/key.txt
Phone: (847) 448-0386
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

On 8 April 2011 23:39, James Snyder <[hidden email]> wrote:
> On Fri, Apr 8, 2011 at 9:25 AM, Martin Guy <[hidden email]> wrote:
>> If people want to be able to express themselves with precision, they
>> need a larger vocabulary, so need to understand more.
>> If you understand less, the range of concepts that you can express is smaller.
>
> However, even with limited vocabulary you can get useful things done

Yes, like a tourist in a foreign country where they don't speak the
language and can only point at things you can see, say "This, this and
this" and hold yuor money out for them to take (GUIs, I'm looking at
you! :)

> On another note:  Silent failure is generally a bad idea in
> programming.

As usual, there is the opposite proverb as well: "Never check for
error conditions that you don't know how to handle" :)

> Except, what we're talking about here is a user issuing a command
> like... change the clock for PWM on one channel, and that affects
> multiple channels, or the fractional period isn't the percent they
> requested, or the clock isn't what they requested.

Right. So every time anyone sets a clock speed, it will always tell
them that it has also changed the clock speed of the other channels.
And every time they set an output frequency >1000Hz it will print a
warning that the output frequency is imprecise.  That means spewing
always!

> Actually, as I think about this, I think that warnings like this
> should probably be off by default

Here we agree. I guess that mean different compiles of the firmware:
firmware with debug/warning/educational messages and without.
I don't see a way to turn it on/off au runtime from the same firmware
if you want the device to start on power on
How about a new Lua module with warning.enable() and
warning.disable()?  Or better, put it inside the module "elua".
elua.warnings = true (or non-nil?) to enable them.

While developing code you can easily add a line to do this at the
start of the first file.
Of course, I still need it under a compile-time flag for my precious 120KB.

> Heisenberg turn in his grave :-)
Yes,  "Theory" means "something that is not relevant to practice" ;-)

> some extra
> methods, if needed, can be just like learning more of a language to
> become more expressive.

That's a good analogy.

> Addition of features carries quite a bit of weight not only because of
> bloat, but because it can be difficult to take them back later :-)

I love those days when I can delete hundreds of lines of code.
It feels good.  I vote we kill pio.decode() today
http://tracker.eluaproject.net/issues/187

    M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

On Sat, Apr 9, 2011 at 1:51 AM, Martin Guy <[hidden email]> wrote:
As usual, there is the opposite proverb as well: "Never check for
error conditions that you don't know how to handle" :)

Then simply don't check for them. Just look at the warnings issued from the system and wonder "what the f**k is this supposed to mean anyway?" :)

Right. So every time anyone sets a clock speed, it will always tell
them that it has also changed the clock speed of the other channels.
And every time they set an output frequency >1000Hz it will print a
warning that the output frequency is imprecise.  That means spewing
always!

Sure, but presumtively setting a clock speed is not something one does very often. Plus, I remind you that this is a feature which is supposed to be helpful mainly in the _prototyping_ phase. I for one would welcome a bit of help from my system while prototyping. In any case, there are ways to fix this:

1. turn off warnings completely
2. turn off warnings for the PWM module only
3. turn off only that specific warning (probably wasteful to implement in terms of memory).
4. associate levels to warnings and inhibit specific module/warning level combinations (not as powerful as 4 but less resource demanding)
5. set a warning filter (a set of Lua regexps) 

And probably many others :)
By the way, I don't have anything against turning all the warnings off by default.


> Actually, as I think about this, I think that warnings like this
> should probably be off by default

Here we agree. I guess that mean different compiles of the firmware:
firmware with debug/warning/educational messages and without.
I don't see a way to turn it on/off au runtime from the same firmware
if you want the device to start on power on
How about a new Lua module with warning.enable() and
warning.disable()?  Or better, put it inside the module "elua".
elua.warnings = true (or non-nil?) to enable them.

My original proposal included exactly something like this inside the elua module.
 
While developing code you can easily add a line to do this at the
start of the first file.
Of course, I still need it under a compile-time flag for my precious 120KB.

You'll be able to load it as a module eventually :) Not sure how much it would help in this particular case though.
 
> Heisenberg turn in his grave :-)
Yes,  "Theory" means "something that is not relevant to practice" ;-)

You have spoken like a true engineer :)
 
I love those days when I can delete hundreds of lines of code.
It feels good.  I vote we kill pio.decode() today
http://tracker.eluaproject.net/issues/187


INT_GPIO_POSEDGE and INT_GPIO_NEGEDGE are called with an argument which is a (pio,port) combination (code). There is a single interrupt handler for each of these interrupts, so if you remove pio.decode() and you want to know which port generated the interrupt you'll have no way of doing that (at least not without issuing a lot of comparisons).
I vaguely remember using it in a non-interrupt related context but I can't remember the details.

Best,
Bogdan


_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
RHS Linux User RHS Linux User
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

In reply to this post by jbsnyder

Hi All,

   It seems to me that a model line TinyCore Linux is the right
approach. VERY small kernel (RAM and ROM). Additions simple to
write, simple to link in.

   BIG advantages: Kernel can be easily understood. No obtuse
side effects.

   Parts and pieces independent. Easy to write, debug, modify, etc.

   EASY to configure of VERY small chips and very powerful for
large chips!

   I have been working on moving lua to MIPS. What a pain!! Much
to complex and HUGE.

   So I have started writing my own MICRO-LUA like piece of code. Now its
up and running :). Works pretty well. Just gotta write some drivers, etc.

   Most lua programs seem to port pretty well :).

   Only problem left is SMOP (Small Matter of Programming) ((Consultant's
Joke)) :).

   warm regards to all,
   Wiz (pen name)


On Thu, 7 Apr 2011, James Snyder wrote:

> On Thu, Apr 7, 2011 at 10:46 AM, Bogdan Marinescu
> <[hidden email]> wrote:
> > On Thu, Apr 7, 2011 at 6:13 PM, Martin Guy <[hidden email]> wrote:
> >>
> >> -1 for warning messages, partly because eLua is for embedded systems
> >> so should be essential, and partly because "the users" are embedded
> >> systems engineers
> >
> > Not really. A large part of the eLua audience are those people that are NOT
> > embedded engineers but want to use the hardware anyway
> > (see http://www.eluaproject.net/en_overview.html for details). If I were one
> > of them I'd really appreciate a feature like this. Hell, I'd appreciate
> > something like this anyway because while I am quite familiar with embedded
> > systems in general I am also extremely lazy :) so I'd like to have my tools
> > outline my possible mistakes for me. Lazy or not this is likely to translate
> > into better efficiency in the end.
> >
> >>
> >> who do need to be familiar with the characteristics
> >> of device they are using, and need to know how to use eLua to achieve
> >> the exact effects they require. in short, they need good
> >> documentation.
> >>
> >>
> >> We can help them (and ourselves!) in this by documenting what the
> >> modules/platforms actually do with much more precision and detail
> >> (think of the precision of a datasheet: waveform characteristics,
> >> timing behaviour, mandatory initialization/use sequences of the
> >> primitives, bugs/defects in some scenarios) and we can make this task
> >> easier and more comprehensible by making the different ports behave in
> >> more similar ways.
> >>
> >> Let me give an example: I couldn't find out what the behaviour of a
> >> PWM should be and don't have the other hardware platforms to be able
> >> to compare them so have just had to guess while implementing it for
> >> AVR32 and the result is the following:
> >> - each channel's pin is not driven until pwm.start() is called for it,
> >> at which point it becomes a driven output
> >> - after pwm.setup(), the output remains low (GND) until pwm.start() is
> >> called
> >> - it always outputs a complete number of cycles even if you call
> >> pwm.stop() immediately
> >> - you can call pwm.start() before pwm.setup() if you like and it still
> >> works
> >> - the actual frequency differs from the required frequency and is
> >> always >= the requested frequency. The reported frequency differs from
> >> the actual frequency (because the real frequency is a floating point
> >> value while the primitives return an integer) and is <= the actual
> >> frequency  (so most often what is reported is the same as what was
> >> requested). (Yes, giving the nearest frequency would be better in both
> >> cases).
> >> - the output is high for approximately "duty" percent of the cycle
> >> (again, rounding and imprecision), and the high part is at the end of
> >> the cycle, not the beginning.
> >> - you can call pio.whatever() on the same pins to turn the PWM outputs
> >> into generic GPIOs like the others, even after having called calling
> >> pwm.*() functions or while they are running. You can than call
> >> pwm.setup to turn that GPIO pin back into a PWM output.
> >> - if you change the frequency or duty cycle, it currently just
> >> modifies them in the registers, so you probably get one cycle of junk
> >> when you do this.
> >> - platform-specific: there is a (currently disabled) mechanism to
> >> delay freq or duty updates until the end of a cycle, but this makes
> >> the "set" primitive delay up to one cycle if the frequency is changed.
> >> Worse, with this mechanism, if you change both the frequency and the
> >> length of the duty cycle in clocks, it can only update one of them at
> >> a time, so there is both a potential two-cycle delay and a compulsory
> >> intermediate cycle of junk, either at the old frequency and new duty
> >> period or vice versa, depending on the change.
> >>
> >> ... and probably a lot more that is only documented as comments in the
> >> code.
> >
> > Impressive. Wow, I didn't know about most of the stuff you are talking about
> > here :) While some of them are implementation errors (for example the PWM
> > frequency being always higher than what you request) others are platform or
> > implementation quirks that are best documented in text (which is a job for
> > the wiki). I never intended to use the warnings system for very detailed
> > things like this but rather for easy to make mistakes (like the ones
> > outlined in my previous e-mail).
>
> I would agree that where there's an example of an error, we should
> clearly fix that, and in no way am I suggesting that we don't lay down
> a bit more in the way of detailing expected behavior and deviations
> from it within documentation or on the wiki.
>
> I can't speak for Bogdan, but I get the sense that we're thinking
> somewhat similarly here in that if there were a system like this it
> would be more for "obvious" side effects like settings applying to
> groups of ids when the user only asked to apply it to 1. I think that
> returning a different clock than requested is also a decent example.
> I'm really more thinking of this as a "we or the hardware are going to
> make a non-obvious decision for you because we can't do exactly what
> you asked for, we're going to let you know about that" (that said,
> documenting these quirks is also important).  Pin reassignments I
> think are different.  I think we can almost upfront state that if you
> use a pin on one peripheral mode then try to use it in another
> peripheral mode it A) might not work without reconfiguration B) if it
> does get reconfigured it's not going to work in the original
> peripheral mode until you switch it back.
>
> On a related note, since the duty cycles are fractional, I would
> support some mechanism for letting the program or the user know about
> what the actual selected fraction ended up being, just like we return
> the actual frequency that was acquired even when we don't give the
> user exactly what they requested.  I think we could maybe set some
> minimum standards we use on implementations in order to make platforms
> more consistent, but they're always going to differ to some extent
> since they don't use the same clock dividers, register sizes,
> configuration models, etc..
>
> >
> >>
> >> Another example I noticed in passing: if you ask for an SPI clock rate
> >> that is not supported, the code selects the arithmetically closest
> >> available clock rate, which may be higher, so if you try to initialise
> >> a device at its maximum rated transfer speed, the code can select a
> >> higher one that is out of spec.
> >
> > IMO this is exactly the kind of situation where a warning could make things
> > much better. You set your clock in the program, eLua says "hey, i can't give
> > you that, i'm going to setup something a bit higher" and you think "oh wait,
> > that's not good" and try another clock. I simply can't think of a more
> > convenient way to do it. Don't forget that one of the strongest point of
> > eLua is that it makes (or is supposed to make :) ) prototyping very easy. I
> > believe these kind of warnings are a very good tool for making this goal a
> > reality.
>
> Yep, although we do "notify" the user in the sense that we're supposed
> to return the frequency that actually got selected so at least they
> can look at their return parameter and decide if what they got was
> acceptable.  I could see this sort of model extending further to
> provide more details in return values on these types of decisions that
> are made for the user (i.e.: let the user know what pwm fraction in
> addition to clock was actually used when pwm.setup is called).  On the
> other hand some sort of error/warning channel of logging output is
> fairly simple and would be useful as well.
>
> I could imagine this also working something like STDOUT and STDERR,
> which might work nicely with our mux implementation to prevent these
> types of messages from polluting the main interface stream.  In fact
> this might be a generally useful facility for us when
> testing/debugging to spit out messages on a separate stream.  We can
> already do this in an adhoc manner, but I suppose this could establish
> a standardized mechanism.
>
> >
> >>
> >> I think that without this level of detail in the documentation (which
> >> becomes a specification) it is unlikely that an example program such
> >> as tvbgone.lua will work on any platform other than the one it was
> >> developed on due to the different timing characteristics and
> >> behaviour.  This level of detail also helps us to ensure that the
> >> different implementations behave the same way.
> >
> > Certainly. The more docs we have for a specific platform, the better.
> > Best,
> > Bogdan
> >
> > _______________________________________________
> > eLua-dev mailing list
> > [hidden email]
> > https://lists.berlios.de/mailman/listinfo/elua-dev
> >
> >
>
>
>
> --
> James Snyder
> Biomedical Engineering
> Northwestern University
> jbsnyder@fanplastic..org
> PGP: http://fanplastic.org/key.txt
> Phone: (847) 448-0386
> _______________________________________________
> eLua-dev mailing list
> [hidden email]
> https://lists.berlios.de/mailman/listinfo/elua-dev
>

_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev
Martin Guy Martin Guy
Reply | Threaded
Open this post in threaded view
|

Re: eLua Peripheral Function Side Effects (was: eLua design change to allow synchronized PWM channel start?)

In reply to this post by BogdanM
>>  I vote we kill pio.decode() today
>> http://tracker.eluaproject.net/issues/187
>
> http://www.eluaproject.net/en_arch_ints.html#intlist
> INT_GPIO_POSEDGE and INT_GPIO_NEGEDGE are called with an argument which is a
> (pio,port) combination (code). There is a single interrupt handler for each
> of these interrupts, so if you remove pio.decode() and you want to know
> which port generated the interrupt you'll have no way of doing that

Right. That makes sense. Thanks.

    M
_______________________________________________
eLua-dev mailing list
[hidden email]
https://lists.berlios.de/mailman/listinfo/elua-dev