How to get precisely times samples?

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

Re: How to get precisely times samples?

On Wed, Jul 20, 2011 at 3:45 AM, Martin Guy <[hidden email]> wrote:
> We seem to be talking about four separate questions here:
> - turning the _op primitives into separate functions
> - allowing more precise low sampling frequencies, like Etna's
> seismographs at 27.27Hz, for ADC (and I guess PWM).
> - getting higher precision for duty cycles
> - use of floating point

Yep, sorry for complicating things a bit.  As far as the PWM stuff
goes, I was just using that as a reference point.  Discussion of
modifying that should go under another thread (resurrecting an earlier
discussion or tracker issue).

>
> in order:
>
> - turning the _op primitives into separate functions
>
> The _op primitives seem to be imitating the ioctl() system call.
> However, the ioctl system call, with hundreds of "operations" and a
> single pointer parameter, was designed to collect hundreds of
> different device-specific functions without having to have hundreds of
> new system calls, and to allow the addition of new operations for new
> hardware devices without having to change the system call interface
> each time. In some Unix platforms the number of system calls is
> limited by the hardware/instruction set, so they were forced to put
> hundreds of different functions through a single hole.
> eLua doesn't have that limitation, since functions are cheap and not
> limited in number. Having one C function per operation also makes the
> documentation clearer, since each operation has its own paragraph
> instead of trying to document 6 different things mixed together.
>
> I assume there's no objection to turning these into separate functions
> where possible.

Bogdan may or may not object to doing that in other places. I think
the reasons you have laid out, especially for ADC are pretty
compelling.

>
> - allowing more precise low sampling frequencies like Etna's
> seismographs at 27.27Hz, for ADC (and I guess PWM).
>
> I agree with not making floating point mandatory because one of eLua's
> design objectives is to run on embedded platforms where code size can
> be critical, and the floating point emulator adds 50K to the code
> size.

At the end of the day, I think this is mainly what needs to remain consistent.

>
> On 19 July 2011 01:35, James Snyder <[hidden email]> wrote:
>> Indeed.  My only point here is that so far we've intentionally kept
>> types that are defined by Lua out of the platform layer so that they
>> don't depend on Lua itself.
>
> Is that so that the C platform layer can be more easily re-used, say
> as the platform-driver layer for a different language, or in custom
> applications?

I'm not sure what Dado and Bogdan might have to say on the matter, but
given the way it is designed, it is structurally not horribly
complicated to simply jump into a different main function on start and
instead of starting Lua start something else and use the platform API.
 At certain points I've wanted to investigate the work that might be
involved in separating out the lower level API and maybe build system
as a multiplatform hardware abstraction layer that would make it easy
to build C applications or use other VMs on top of the platform
interface (like PyMite/Python-on-a-Chip) for example.  Even if one
isn't interested in Lua per-se the project does provide working
examples of how to build with open toolchains across a variety of
platforms.  I'd like it if we can keep this flexibility.

>
>> There are two ways I can think of that could remain exclusively integer:
>> 1) Passing optional divisors.  For PWM, at one point, I suggested that
>> we could allow finer resolution duty cyles by allowing other fractions
>> than per cent such as /1000 (per mil) or 10000 (per basis point).
>> Clock frequencies could have this as well, either fixed or arbitrary
>> divisors passed as a parameter.
>
> I sort of like this idea - using an optional extra parameter in Lua
> which by default would be 100 (for percent) for duty cycles.
> The PWM setup function is currently:
> frequency = pwm.setup(id, frequency, duty_cycle)
> and, as far as duty cycle goes, this is OK, since it is the last
> parameter, but it does nothing for frequencies unless we add two
> optional parameters as divisors with default values of 100 and 1. Or 1
> and 100.

It would need some adaptation for frequencies, since the values one is
using are generally greater than 1 Hz, so the divisors would likely be
smaller (or arbitrary).  I haven't thought through an implementation
to decide which would be easier.

When you say two optional parameters are you meaning two different
values that could be placed in a divisor parameter, or multiple
additional parameters?  I would be thinking of essentially having two
parameters, the first being the numerator, the latter being the
divisor with a default value of 1 if not passed.  If the user passes a
divisor then the platform will attempt to match the fractional
frequency as closely as hardware allows.

>
>> 2) Something similar to POSIX's timer API
>
> POSIX is not a manual of good interface design. It was born as an
> attempt to unite the different ways that manufacturers had extended
> the original Unix kernel interfaces. All the new stuff since then
> comes from design-by-committee, which usually produces awful
> interfaces. Google POSIX timer API.

Well, I don't mean to actually _implement_ the posix timer API, merely
borrow the concept of second sized ticks, and mircosecond sized ticks
as a compound value/structure or multiple parameters that could be
passed.

There's some horrible stuff in the POSIX API due to munging of various
implementations together that you mention plus some things were
clearly meant for different purposes in a different time, like POSIX
RS-323 support, but I've come to appreciate it over dealing with some
Win32 API stuff that just feels baroque by comparison.

>
>> which allows specification
>> of a low and higher resolution component.  i.e.: integer Hz + integer
>> µHz or nHz.  This came up a while ago, and wasn't for setting clock
>> frequencies, more for timer intervals, but one could use it for clock
>> frequencies as well.  So that you would define that you wanted 27 Hz +
>> 270000 µHz or something similar
>
>> Just a few thoughts.  In some ways the gymnastics necessary for the
>> user, interface implementer, and backend implementer start making the
>> floating point version sound appealing :-)
>
> Not if floating point becomes necessary, since that goes against the
> "embedded" objective of eLua.

I'm definitely not suggesting tossing integer eLua :-)  While most of
the builds I use may be floating point ones, none of the platforms I'm
using even have hardware FP, and there's a steep cost in code size.

>
> I only suggested that for when FP is already enabled in Lua.
> If it isn't, the user has no way to express a floating point value
> from Lua anyway, or to receive an FP value back.

Right.  Essentially the function for setting frequency would take a
lua_Number (or something like it) and the code on the backend would be
carefully written to work with both floating point and integer builds.


> What's the lesser of these evils:
> - no way to express low frequencies with precision, limited PWM duty
> cycle resolution (current situation)
> - higher precision in the FP version of Lua, lower precision in the
> integer one, for duty cycles and low frequencies
> - interfaces in Lua and C that express floating point values as some
> combination of integers

This is the tough question. Generally I would be trying to minimize
pain for implementation and ugliness in the interface I think.  The
divisor/fraction stuff doesn't actually sound too bad to me,
especially if it's done as an optional parameter with a default that's
the same as current behavior.  This way users can blithely ignore the
functionality, and current code continues to work, but even the
integer port can define non-integer frequencies.

It does have one other complication, which is what do we return as the
actual frequency acquired, especially on the integer port.  I suppose
it should be in the form passed, with two returned values, the first
being the numerator and the second being the denominator.  This
wouldn't break existing code, and those who just receive one value
would get just the numerator, plus we can still tell them, with
reasonable accuracy, what frequency they got.

Anyone else have opinions here?

>
>   M
> _______________________________________________
> 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
Dado Sutter Dado Sutter
Reply | Threaded
Open this post in threaded view
|

Re: How to get precisely times samples?

Hi,

On Wed, Jul 20, 2011 at 15:14, James Snyder <[hidden email]> wrote:
On Wed, Jul 20, 2011 at 3:45 AM, Martin Guy <[hidden email]> wrote:
> We seem to be talking about four separate questions here:
> - turning the _op primitives into separate functions
> - allowing more precise low sampling frequencies, like Etna's
> seismographs at 27.27Hz, for ADC (and I guess PWM).
> - getting higher precision for duty cycles
> - use of floating point

Yep, sorry for complicating things a bit.  As far as the PWM stuff
goes, I was just using that as a reference point.  Discussion of
modifying that should go under another thread (resurrecting an earlier
discussion or tracker issue).

>
> in order:
>
> - turning the _op primitives into separate functions
>
> The _op primitives seem to be imitating the ioctl() system call.
> However, the ioctl system call, with hundreds of "operations" and a
> single pointer parameter, was designed to collect hundreds of
> different device-specific functions without having to have hundreds of
> new system calls, and to allow the addition of new operations for new
> hardware devices without having to change the system call interface
> each time. In some Unix platforms the number of system calls is
> limited by the hardware/instruction set, so they were forced to put
> hundreds of different functions through a single hole.
> eLua doesn't have that limitation, since functions are cheap and not
> limited in number. Having one C function per operation also makes the
> documentation clearer, since each operation has its own paragraph
> instead of trying to document 6 different things mixed together.
>
> I assume there's no objection to turning these into separate functions
> where possible.

Bogdan may or may not object to doing that in other places. I think
the reasons you have laid out, especially for ADC are pretty
compelling.

>
> - allowing more precise low sampling frequencies like Etna's
> seismographs at 27.27Hz, for ADC (and I guess PWM).
>
> I agree with not making floating point mandatory because one of eLua's
> design objectives is to run on embedded platforms where code size can
> be critical, and the floating point emulator adds 50K to the code
> size.

At the end of the day, I think this is mainly what needs to remain consistent.

>
> On 19 July 2011 01:35, James Snyder <[hidden email]> wrote:
>> Indeed.  My only point here is that so far we've intentionally kept
>> types that are defined by Lua out of the platform layer so that they
>> don't depend on Lua itself.
>
> Is that so that the C platform layer can be more easily re-used, say
> as the platform-driver layer for a different language, or in custom
> applications?

I'm not sure what Dado and Bogdan might have to say on the matter, but
given the way it is designed, it is structurally not horribly
complicated to simply jump into a different main function on start and
instead of starting Lua start something else and use the platform API.
 At certain points I've wanted to investigate the work that might be
involved in separating out the lower level API and maybe build system
as a multiplatform hardware abstraction layer that would make it easy
to build C applications or use other VMs on top of the platform
interface (like PyMite/Python-on-a-Chip) for example.  Even if one
isn't interested in Lua per-se the project does provide working
examples of how to build with open toolchains across a variety of
platforms.  I'd like it if we can keep this flexibility.

Yes. Personally I would prefer to have an independent, generic and as portable as possible platform layer. Marcelo Politzer and Thiago Naves (@LedLab) have been experimenting with this concept and extending implementations to other targets but some implementation details have been making it harder.
It would be nice to hear them here for some more details, in a different thread.
I would love to be able to use the platform layer for C-only applications. It is certainly possible to do it today but not in an easy way IMHO.


>
>> There are two ways I can think of that could remain exclusively integer:
>> 1) Passing optional divisors.  For PWM, at one point, I suggested that
>> we could allow finer resolution duty cyles by allowing other fractions
>> than per cent such as /1000 (per mil) or 10000 (per basis point).
>> Clock frequencies could have this as well, either fixed or arbitrary
>> divisors passed as a parameter.
>
> I sort of like this idea - using an optional extra parameter in Lua
> which by default would be 100 (for percent) for duty cycles.
> The PWM setup function is currently:
> frequency = pwm.setup(id, frequency, duty_cycle)
> and, as far as duty cycle goes, this is OK, since it is the last
> parameter, but it does nothing for frequencies unless we add two
> optional parameters as divisors with default values of 100 and 1. Or 1
> and 100.

It would need some adaptation for frequencies, since the values one is
using are generally greater than 1 Hz, so the divisors would likely be
smaller (or arbitrary).  I haven't thought through an implementation
to decide which would be easier.

When you say two optional parameters are you meaning two different
values that could be placed in a divisor parameter, or multiple
additional parameters?  I would be thinking of essentially having two
parameters, the first being the numerator, the latter being the
divisor with a default value of 1 if not passed.  If the user passes a
divisor then the platform will attempt to match the fractional
frequency as closely as hardware allows.

>
>> 2) Something similar to POSIX's timer API
>
> POSIX is not a manual of good interface design. It was born as an
> attempt to unite the different ways that manufacturers had extended
> the original Unix kernel interfaces. All the new stuff since then
> comes from design-by-committee, which usually produces awful
> interfaces. Google POSIX timer API.

Well, I don't mean to actually _implement_ the posix timer API, merely
borrow the concept of second sized ticks, and mircosecond sized ticks
as a compound value/structure or multiple parameters that could be
passed.

There's some horrible stuff in the POSIX API due to munging of various
implementations together that you mention plus some things were
clearly meant for different purposes in a different time, like POSIX
RS-323 support, but I've come to appreciate it over dealing with some
Win32 API stuff that just feels baroque by comparison.

>
>> which allows specification
>> of a low and higher resolution component.  i.e.: integer Hz + integer
>> µHz or nHz.  This came up a while ago, and wasn't for setting clock
>> frequencies, more for timer intervals, but one could use it for clock
>> frequencies as well.  So that you would define that you wanted 27 Hz +
>> 270000 µHz or something similar
>
>> Just a few thoughts.  In some ways the gymnastics necessary for the
>> user, interface implementer, and backend implementer start making the
>> floating point version sound appealing :-)
>
> Not if floating point becomes necessary, since that goes against the
> "embedded" objective of eLua.

I'm definitely not suggesting tossing integer eLua :-)  While most of
the builds I use may be floating point ones, none of the platforms I'm
using even have hardware FP, and there's a steep cost in code size.

>
> I only suggested that for when FP is already enabled in Lua.
> If it isn't, the user has no way to express a floating point value
> from Lua anyway, or to receive an FP value back.

Right.  Essentially the function for setting frequency would take a
lua_Number (or something like it) and the code on the backend would be
carefully written to work with both floating point and integer builds.


> What's the lesser of these evils:
> - no way to express low frequencies with precision, limited PWM duty
> cycle resolution (current situation)
> - higher precision in the FP version of Lua, lower precision in the
> integer one, for duty cycles and low frequencies
> - interfaces in Lua and C that express floating point values as some
> combination of integers

This is the tough question. Generally I would be trying to minimize
pain for implementation and ugliness in the interface I think.

+1
 
 The
divisor/fraction stuff doesn't actually sound too bad to me,
especially if it's done as an optional parameter with a default that's
the same as current behavior.  This way users can blithely ignore the
functionality, and current code continues to work, but even the
integer port can define non-integer frequencies.

It does have one other complication, which is what do we return as the
actual frequency acquired, especially on the integer port.  I suppose
it should be in the form passed, with two returned values, the first
being the numerator and the second being the denominator.  This
wouldn't break existing code, and those who just receive one value
would get just the numerator, plus we can still tell them, with
reasonable accuracy, what frequency they got.

Anyone else have opinions here?

I can't say now if this is the best final solution, in the sense that it should be adopted for similar needs in the future too. But it sounds like an elegant and simple solution, although the return-value issue will seem pretty strange on the higher level. But I can't think of anything better now, without forcing some major refactoring on the platform layer.


>
>   M

Best
Dado



 
> _______________________________________________
> 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


_______________________________________________
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: How to get precisely times samples?

On Wed, Jul 20, 2011 at 5:38 PM, Dado Sutter <[hidden email]> wrote:

> Hi,
>
> On Wed, Jul 20, 2011 at 15:14, James Snyder <[hidden email]> wrote:
>>
>> On Wed, Jul 20, 2011 at 3:45 AM, Martin Guy <[hidden email]> wrote:
>> > We seem to be talking about four separate questions here:
>> > - turning the _op primitives into separate functions
>> > - allowing more precise low sampling frequencies, like Etna's
>> > seismographs at 27.27Hz, for ADC (and I guess PWM).
>> > - getting higher precision for duty cycles
>> > - use of floating point
>>
>> Yep, sorry for complicating things a bit.  As far as the PWM stuff
>> goes, I was just using that as a reference point.  Discussion of
>> modifying that should go under another thread (resurrecting an earlier
>> discussion or tracker issue).
>>
>> >
>> > in order:
>> >
>> > - turning the _op primitives into separate functions
>> >
>> > The _op primitives seem to be imitating the ioctl() system call.
>> > However, the ioctl system call, with hundreds of "operations" and a
>> > single pointer parameter, was designed to collect hundreds of
>> > different device-specific functions without having to have hundreds of
>> > new system calls, and to allow the addition of new operations for new
>> > hardware devices without having to change the system call interface
>> > each time. In some Unix platforms the number of system calls is
>> > limited by the hardware/instruction set, so they were forced to put
>> > hundreds of different functions through a single hole.
>> > eLua doesn't have that limitation, since functions are cheap and not
>> > limited in number. Having one C function per operation also makes the
>> > documentation clearer, since each operation has its own paragraph
>> > instead of trying to document 6 different things mixed together.
>> >
>> > I assume there's no objection to turning these into separate functions
>> > where possible.
>>
>> Bogdan may or may not object to doing that in other places. I think
>> the reasons you have laid out, especially for ADC are pretty
>> compelling.
>>
>> >
>> > - allowing more precise low sampling frequencies like Etna's
>> > seismographs at 27.27Hz, for ADC (and I guess PWM).
>> >
>> > I agree with not making floating point mandatory because one of eLua's
>> > design objectives is to run on embedded platforms where code size can
>> > be critical, and the floating point emulator adds 50K to the code
>> > size.
>>
>> At the end of the day, I think this is mainly what needs to remain
>> consistent.
>>
>> >
>> > On 19 July 2011 01:35, James Snyder <[hidden email]> wrote:
>> >> Indeed.  My only point here is that so far we've intentionally kept
>> >> types that are defined by Lua out of the platform layer so that they
>> >> don't depend on Lua itself.
>> >
>> > Is that so that the C platform layer can be more easily re-used, say
>> > as the platform-driver layer for a different language, or in custom
>> > applications?
>>
>> I'm not sure what Dado and Bogdan might have to say on the matter, but
>> given the way it is designed, it is structurally not horribly
>> complicated to simply jump into a different main function on start and
>> instead of starting Lua start something else and use the platform API.
>>  At certain points I've wanted to investigate the work that might be
>> involved in separating out the lower level API and maybe build system
>> as a multiplatform hardware abstraction layer that would make it easy
>> to build C applications or use other VMs on top of the platform
>> interface (like PyMite/Python-on-a-Chip) for example.  Even if one
>> isn't interested in Lua per-se the project does provide working
>> examples of how to build with open toolchains across a variety of
>> platforms.  I'd like it if we can keep this flexibility.
>
> Yes. Personally I would prefer to have an independent, generic and as
> portable as possible platform layer. Marcelo Politzer and Thiago Naves
> (@LedLab) have been experimenting with this concept and extending
> implementations to other targets but some implementation details have been
> making it harder.
> It would be nice to hear them here for some more details, in a different
> thread.
> I would love to be able to use the platform layer for C-only applications.
> It is certainly possible to do it today but not in an easy way IMHO.
>
>>
>> >
>> >> There are two ways I can think of that could remain exclusively
>> >> integer:
>> >> 1) Passing optional divisors.  For PWM, at one point, I suggested that
>> >> we could allow finer resolution duty cyles by allowing other fractions
>> >> than per cent such as /1000 (per mil) or 10000 (per basis point).
>> >> Clock frequencies could have this as well, either fixed or arbitrary
>> >> divisors passed as a parameter.
>> >
>> > I sort of like this idea - using an optional extra parameter in Lua
>> > which by default would be 100 (for percent) for duty cycles.
>> > The PWM setup function is currently:
>> > frequency = pwm.setup(id, frequency, duty_cycle)
>> > and, as far as duty cycle goes, this is OK, since it is the last
>> > parameter, but it does nothing for frequencies unless we add two
>> > optional parameters as divisors with default values of 100 and 1. Or 1
>> > and 100.
>>
>> It would need some adaptation for frequencies, since the values one is
>> using are generally greater than 1 Hz, so the divisors would likely be
>> smaller (or arbitrary).  I haven't thought through an implementation
>> to decide which would be easier.
>>
>> When you say two optional parameters are you meaning two different
>> values that could be placed in a divisor parameter, or multiple
>> additional parameters?  I would be thinking of essentially having two
>> parameters, the first being the numerator, the latter being the
>> divisor with a default value of 1 if not passed.  If the user passes a
>> divisor then the platform will attempt to match the fractional
>> frequency as closely as hardware allows.
>>
>> >
>> >> 2) Something similar to POSIX's timer API
>> >
>> > POSIX is not a manual of good interface design. It was born as an
>> > attempt to unite the different ways that manufacturers had extended
>> > the original Unix kernel interfaces. All the new stuff since then
>> > comes from design-by-committee, which usually produces awful
>> > interfaces. Google POSIX timer API.
>>
>> Well, I don't mean to actually _implement_ the posix timer API, merely
>> borrow the concept of second sized ticks, and mircosecond sized ticks
>> as a compound value/structure or multiple parameters that could be
>> passed.
>>
>> There's some horrible stuff in the POSIX API due to munging of various
>> implementations together that you mention plus some things were
>> clearly meant for different purposes in a different time, like POSIX
>> RS-323 support, but I've come to appreciate it over dealing with some
>> Win32 API stuff that just feels baroque by comparison.
>>
>> >
>> >> which allows specification
>> >> of a low and higher resolution component.  i.e.: integer Hz + integer
>> >> µHz or nHz.  This came up a while ago, and wasn't for setting clock
>> >> frequencies, more for timer intervals, but one could use it for clock
>> >> frequencies as well.  So that you would define that you wanted 27 Hz +
>> >> 270000 µHz or something similar
>> >
>> >> Just a few thoughts.  In some ways the gymnastics necessary for the
>> >> user, interface implementer, and backend implementer start making the
>> >> floating point version sound appealing :-)
>> >
>> > Not if floating point becomes necessary, since that goes against the
>> > "embedded" objective of eLua.
>>
>> I'm definitely not suggesting tossing integer eLua :-)  While most of
>> the builds I use may be floating point ones, none of the platforms I'm
>> using even have hardware FP, and there's a steep cost in code size.
>>
>> >
>> > I only suggested that for when FP is already enabled in Lua.
>> > If it isn't, the user has no way to express a floating point value
>> > from Lua anyway, or to receive an FP value back.
>>
>> Right.  Essentially the function for setting frequency would take a
>> lua_Number (or something like it) and the code on the backend would be
>> carefully written to work with both floating point and integer builds.
>>
>>
>> > What's the lesser of these evils:
>> > - no way to express low frequencies with precision, limited PWM duty
>> > cycle resolution (current situation)
>> > - higher precision in the FP version of Lua, lower precision in the
>> > integer one, for duty cycles and low frequencies
>> > - interfaces in Lua and C that express floating point values as some
>> > combination of integers
>>
>> This is the tough question. Generally I would be trying to minimize
>> pain for implementation and ugliness in the interface I think.
>
> +1
>
>>
>>  The
>> divisor/fraction stuff doesn't actually sound too bad to me,
>> especially if it's done as an optional parameter with a default that's
>> the same as current behavior.  This way users can blithely ignore the
>> functionality, and current code continues to work, but even the
>> integer port can define non-integer frequencies.
>>
>> It does have one other complication, which is what do we return as the
>> actual frequency acquired, especially on the integer port.  I suppose
>> it should be in the form passed, with two returned values, the first
>> being the numerator and the second being the denominator.  This
>> wouldn't break existing code, and those who just receive one value
>> would get just the numerator, plus we can still tell them, with
>> reasonable accuracy, what frequency they got.
>>
>> Anyone else have opinions here?
>
> I can't say now if this is the best final solution, in the sense that it
> should be adopted for similar needs in the future too. But it sounds like an
> elegant and simple solution, although the return-value issue will seem
> pretty strange on the higher level. But I can't think of anything better
> now, without forcing some major refactoring on the platform layer.

The fundamental issue there is returning a potentially non-integer
frequency through integer values, since they've been requested using
integer numerator and denominator.  The are some possible restrictions
that could be placed on the values returned:
1) for cases where the divisor is 1 or not provided, the returned
divisor will always be 1 (to preserve existing behavior, even if the
returned frequency can't precisely be represented as an integer value)

For all other cases there are two options:
2) Always use the same divisor as passed in.  In some ways this sounds
a bit stupid to return the divisor in this case, but I think I prefer
the idea that the units of the return value can be interpreted without
having to refer to the passed values.  The biggest downside to this is
that there's a potential loss of precision if the divisor doesn't
match up well with the actual clock frequency.

3) The divisor returned is determined by the low-level code in order
to provide best accuracy in conveying the frequency selected given the
available variable size for storing the values. Optionally, the low
level implementor can use the same divisor originally passed.  This
would potentially allow providing the highest fidelity in conveying
the frequency selected, and it might also be the easiest way to make
this work given that you could probably just base the values directly
on the main system clock, divisors applied to that, and the timer
reload value and you provide the precise fraction for the clock
frequency.

As a potential additional option, 1) could be revised such that if no
divisor is passed, return divisor is always 1, but if a 1 is passed
than the divisor is allowed to float as in 3) above.  This would
provide consistency with current behavior and maximum potential return
value accuracy.

With either of these, determination of the clock frequency on a
floating point MCU is one division operation away.  On integer units,
some more complex math would need to be employed to ensure the
fraction is within desired tolerances.


As far as rethinking the API is concerned, I think either way we come
back to an issue of fractional frequencies with integer expressions
problem, unless the integer builds are to have different functionality
than the floating point builds.

-jsnyder

>
>>
>> >
>> >   M
>
> Best
> Dado
>
>
>
>
>>
>> > _______________________________________________
>> > 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
>
>
> _______________________________________________
> 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: How to get precisely times samples?

On 25 July 2011 20:17, James Snyder <[hidden email]> wrote:
> On Wed, Jul 20, 2011 at 5:38 PM, Dado Sutter <[hidden email]> wrote:
>>> > - allowing more precise low sampling frequencies, like Etna's
>>> > seismographs at 27.27Hz, for ADC (and I guess PWM).
>>> > - getting higher precision for duty cycles
>>> > - use of floating point

>>> This is the tough question. Generally I would be trying to minimize
>>> pain for implementation and ugliness in the interface I think.
>> +1

> 2) Always use the same divisor as passed in.


There is already an industry convention for passing floating point
values as integers. It's called fixed point arithmetic, and that is
already in use in eLua: time delays are fixed-point with radix 1000000
(microseconds), duty cycles are fixed point with radix 100.  The
easiest-to-understand interface would be to allow people to specify
the radix of the fixed-point values they are passing, and receive
values back in that same radix they asked for.

In eLua we have three separate usage cases of arbitrary numbers being
passed/returned as integers:
1. high frequencies for clocks, used in PWM clock, timer clock (also
used in ADC), maybe also for I2C and SPI clocks and (even more maybe)
UART baud rates.
2. low frequencies for ADC sampling rates and PWM frequencies
3. duty cycles for PWM

Let's look at these:

The high frequencies already seem precise enough to me for our
purposes, since they're in the 100,000s and 1,000,000, already giving
a precision of 1 part in 100.000 except for baud rates, but I've only
ever seen integer baud rates, and with a minimum of 110. Checking the
actual baud rate that was set and caring about whether it is  less
than 0.5% different is Book 3 stuff, not really a design goal for eLua
if it will make things more complicated.

The resolution of the clock that the low frequencies depend on is
already returned by their setclock() (or setup()) functions, which
return the actual frequency set. This may be very different from the
one requested, often a power-of-two divisor of some fixed system clock
rate, still in the 100,000s or 1,000,000s range.

[[[
As a separate issue, I notice that there is a function in the ADC
module, also called setclock, that does something different from the
other setclock() functions.
i2c, spi and tmr.setclock() all set their own underlying hardware
independently of each other, and they all have a setclock() function
that works the same way as the others (nice!).
adc.setclock() is different: it sets a lower frequency sampling rate
based on a number of cycles of a chosen timer. The user can find the
real frequency of the timer in question, since they can called
tmr.setclock() (or tmr.getclock()) on the timer they are associating
with the adc channel.
I suggest adc.setclock() be renamed to something different, since it's
a different function with different parameters from the other
setclock() functions. In fact, it's more similar in what it does to
the other modules' *.setup() functions.
]]]

In the last case, the duty cycles' true precision is the period of one
cycle of the PWM waveform expressed in PWM clock cycles. That
information is available to the user through pwm.setclock() and
getclock() interfaces.
However, the underlying granularity of the available duty cycles as a
fraction of the PWM wave period changes whenever you change the PWM
frequency.
Users who want to get the maximum precision from their PWM duty cycle
will need to do some interesting math coding to achieve this, but it
should be possible. The Lua code to do that would be good as an
advanced example in the eLua manual. Such power users would need to
figure out the period in clock cycles of the PWM at the actual
frequency that was set, then set the duty cycle with a radix that is
equal to that. That is awkward in the current pwm.setup() function,
since it takes duty cycle and frequency at the same time, so they'd
have to call it twice, once with the wrong duty cycle and once with
the right one once you've found out the actual PWM frequency.

Furthermore, on AVR32, being told to set both the frequency and duty
cycle causes a glitch in the output because the stupid hardware
interface can only set either the frequency or the duty cycle once per
output cycle so you get one cycle either at the new frequency and old
duty cycle or at the old frequency with the new duty cycle.

Worse yet, pwm.setup(id, frequency, duty_cycle) takes two parameters
both of which are in the proposed fixed-point format, which is ugly.
Even in the naive case where you get higher precision by giving a duty
cycle radix of 1000 or 1000000, you'd need to supply a bogus extra
parameter for the undesired precision of the PWM output frequency.

These are three arguments in favour of splitting pwm.setup() into two
functions like pwm.setfreq() and pwm.setduty().  A fourth is that all
the other modules' setup() functions are usually called once at start
of program, then the output is varied as the program runs using
module-specific functions, whereas the current pwm.setup() is used
repeatedly while the programming is running to vary the output.

> 3) The divisor returned is determined by the low-level code in order
> to provide best accuracy in conveying the frequency selected given the
> available variable size for storing the values.

Trying to select the most precise pair of integers to represent an
arbitrary value is actually quite a difficult math-theoretical
problem, not to mention the difficullty in the user code that would be
necessary to correctly handle them.

> As a potential additional option, 1) could be revised such that if no
> divisor is passed, return divisor is always 1, but if a 1 is passed
> than the divisor is allowed to float as in 3) above.

We already have the first part, and the defaults are 100 for the duty
cycle, 1,000,000 for delays and 1 for frequencies.  I hink the second
idea is a nightmare for us and for the users.

> provide consistency with current behavior and maximum potential return
> value accuracy.

I don't value euther of these. On the one hand I'm not afraid to
change the platform (or the Lua) interfaces if that gives a worthwhile
improvement in what you can do or how easy it is to understand, and
the current interface did not consider the practical problems that we
are trying to improve now.
  I seem to remember someone saying that, before we release eLua 1.0,
maintaining backward compatability is not a problem, especially given
the small user base.  Of course, we don't want to break things for no
significant gain.
  I don't think total laboratory-standard mathematical accuracy is as
important a degisn goal for eLua as being simple to use and having an
Lua interface that is pleasant to use and easy to understand.  It's a
design tradeoff, since lab accuracy requires a different set of
interfaces than one that is easy-to-use but adequate for most
purposes.
  Already, moving to optional variable radix fixed point for some
values is a step towards higher accuracy and away from easy-to-use,
but seems to bring some advantages.

> As far as rethinking the API is concerned, I think either way we come
> back to an issue of fractional frequencies with integer expressions
> problem, unless the integer builds are to have different functionality
> than the floating point builds.

That was my first idea for low frequencies: optional FP, but I think
your optional divisor (or radix in fixed-point math language) solution
may be a better one.

     M
_______________________________________________
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: How to get precisely times samples?

On Thu, Jul 28, 2011 at 12:01 PM, Martin Guy <[hidden email]> wrote:

> On 25 July 2011 20:17, James Snyder <[hidden email]> wrote:
>> On Wed, Jul 20, 2011 at 5:38 PM, Dado Sutter <[hidden email]> wrote:
>>>> > - allowing more precise low sampling frequencies, like Etna's
>>>> > seismographs at 27.27Hz, for ADC (and I guess PWM).
>>>> > - getting higher precision for duty cycles
>>>> > - use of floating point
>
>>>> This is the tough question. Generally I would be trying to minimize
>>>> pain for implementation and ugliness in the interface I think.
>>> +1
>
>> 2) Always use the same divisor as passed in.
>
>
> There is already an industry convention for passing floating point
> values as integers. It's called fixed point arithmetic, and that is
> already in use in eLua: time delays are fixed-point with radix 1000000
> (microseconds), duty cycles are fixed point with radix 100.  The
> easiest-to-understand interface would be to allow people to specify
> the radix of the fixed-point values they are passing, and receive
> values back in that same radix they asked for.

Right, perhaps with a range of radices that make sense for the
application, since using microseconds would be overkill and would
limit sampling rates to the kilohertz range with 32-bit integers, I
think.

>
> In eLua we have three separate usage cases of arbitrary numbers being
> passed/returned as integers:
> 1. high frequencies for clocks, used in PWM clock, timer clock (also
> used in ADC), maybe also for I2C and SPI clocks and (even more maybe)
> UART baud rates.
> 2. low frequencies for ADC sampling rates and PWM frequencies

These don't have to be low frequencies unless hundreds of kilohertz or
an order of magnitude higher is considered low :-)  Of course, the
distinction is relative and for the most part, especially for ADC, I
would expect sampling rates to be low given the rate of bytecode
execution in Lua and the cost of doing operations on samples.  PWM can
certainly run at a few megahertz on many of the platforms we use,
though this doesn't provide excellent resolution in duty cycle.  That
said, higher frequencies can be convenient when you want to use it as
a cheap DAC with an LPF, or to even generate audio.

> 3. duty cycles for PWM
>
> Let's look at these:
>
> The high frequencies already seem precise enough to me for our
> purposes, since they're in the 100,000s and 1,000,000, already giving
> a precision of 1 part in 100.000 except for baud rates, but I've only
> ever seen integer baud rates, and with a minimum of 110. Checking the
> actual baud rate that was set and caring about whether it is  less
> than 0.5% different is Book 3 stuff, not really a design goal for eLua
> if it will make things more complicated.

I would agree.

>
> The resolution of the clock that the low frequencies depend on is
> already returned by their setclock() (or setup()) functions, which
> return the actual frequency set. This may be very different from the
> one requested, often a power-of-two divisor of some fixed system clock
> rate, still in the 100,000s or 1,000,000s range.

Yep.  Some platforms probably could do frequency matching a little
better, depending on whether there are multiple divisors that can be
mixed to generate the clock, but that's a separate issue that depends
on the platform.  When I've noticed that there are deficiencies of
this sort, I've attempted to improve it.  stm32, for example, was
adjusting only one clock divisor to get its frequencies which both
limited the range (couldn't go below around 1Khz) and limited the
resolution of the selectable frequencies.  There are established
routines, sometimes provided by the vendor, for properly selecting
clocks that should be used when finer integer resolution in clocks is
important.

>
> [[[
> As a separate issue, I notice that there is a function in the ADC
> module, also called setclock, that does something different from the
> other setclock() functions.
> i2c, spi and tmr.setclock() all set their own underlying hardware
> independently of each other, and they all have a setclock() function
> that works the same way as the others (nice!).
> adc.setclock() is different: it sets a lower frequency sampling rate
> based on a number of cycles of a chosen timer. The user can find the
> real frequency of the timer in question, since they can called
> tmr.setclock() (or tmr.getclock()) on the timer they are associating
> with the adc channel.
> I suggest adc.setclock() be renamed to something different, since it's
> a different function with different parameters from the other
> setclock() functions. In fact, it's more similar in what it does to
> the other modules' *.setup() functions.
> ]]]

This is a good point.  It does multiple things... It configures the
ADC to trigger on the timer passed, and then sets up a timer so that
it has a period close to the requested clock.  Setup might be OK, but
I actually have a minor dislike for the convention of the "setup"
function since they take different parameters depending on the
peripheral that's being setup. For consistency sake this would make
sense though.  As far as alternatives, maybe something like settimer
or setuptimer might make more sense?  Alternately if we wanted ADC to
support other trigger sources, it could be named something like
settrigger or setuptrigger?

Ideally, maybe the tmr module could be adapted so that it's functions
could be used to set up the period, and then the ADC function could
just ensure that the ADC would trigger on match (or whatever event it
can use from the timer).  Besides some special configuration for
timers to sometimes generate events or certain things like that, the
current tmr API doesn't lend itself to configuring cycle durations.
One could add another function, similar to set_match_int, or adapt
set_match_int/rename it to allow it to configure hardware peripheral
triggers in addition to interrupts.

>
> In the last case, the duty cycles' true precision is the period of one
> cycle of the PWM waveform expressed in PWM clock cycles. That
> information is available to the user through pwm.setclock() and
> getclock() interfaces.
> However, the underlying granularity of the available duty cycles as a
> fraction of the PWM wave period changes whenever you change the PWM
> frequency.
> Users who want to get the maximum precision from their PWM duty cycle
> will need to do some interesting math coding to achieve this, but it
> should be possible.

As I was mentioning before, there are some established/recommended
routines that vendors provide for doing things like this.  For STM32,
for example, we do the following for PWM and I think ADC frequencies:

period = (base peripheral clock) / desired_clock;
prescaler = ( period / 65536 ) + 1;
period = period/prescaler;

period (automatic reload value) and prescaler are then set to
registers after subtracting 1.

The resulting clock can then be computed as:
(base peripheral clock) / prescaler / period

With a 32 MHz clock this gives error along these lines along with
minimum step sizes (100/period)
http://i.imgur.com/YwqB8.png

This is a little platform specific in terms of register sizes and max
prescaler sizes, but something similar could be adapted for most
platforms.

> The Lua code to do that would be good as an
> advanced example in the eLua manual. Such power users would need to
> figure out the period in clock cycles of the PWM at the actual
> frequency that was set, then set the duty cycle with a radix that is
> equal to that. That is awkward in the current pwm.setup() function,
> since it takes duty cycle and frequency at the same time, so they'd
> have to call it twice, once with the wrong duty cycle and once with
> the right one once you've found out the actual PWM frequency.

I think it would be nice to show how to do the manual approach from
Lua and to maybe make the interface a little less awkward.  I also
like making the default behavior one that doesn't require that the
user write an algorithm to set PWM up as long as we can do a pretty
good job automatically.

>
> Furthermore, on AVR32, being told to set both the frequency and duty
> cycle causes a glitch in the output because the stupid hardware
> interface can only set either the frequency or the duty cycle once per
> output cycle so you get one cycle either at the new frequency and old
> duty cycle or at the old frequency with the new duty cycle.

Interesting.  I assume that you can temporarily stop the peripheral,
set the values and then start it again though?  Sure you might lose
some clock cycles, but I'm not sure we're guaranteeing that PWM is
continuous through successive calls.  Not sure if we would need to do
so either.

>
> Worse yet, pwm.setup(id, frequency, duty_cycle) takes two parameters
> both of which are in the proposed fixed-point format, which is ugly.
> Even in the naive case where you get higher precision by giving a duty
> cycle radix of 1000 or 1000000, you'd need to supply a bogus extra
> parameter for the undesired precision of the PWM output frequency.

This is another reason why I'm not a massive fan of "setup" functions,
I kindof think this should be two separate functions.

Would we really need a radix other than 1 for PWM frequencies though?
I'm not sure if non-integer frequencies are ever needed.

>
> These are three arguments in favour of splitting pwm.setup() into two
> functions like pwm.setfreq() and pwm.setduty().  A fourth is that all
> the other modules' setup() functions are usually called once at start
> of program, then the output is varied as the program runs using
> module-specific functions, whereas the current pwm.setup() is used
> repeatedly while the programming is running to vary the output.

Yeah, I've felt this way for a while now.  Bogdan, any comments on
this front? We're starting to get into a number of API changes and
proposals here :-)

>
>> 3) The divisor returned is determined by the low-level code in order
>> to provide best accuracy in conveying the frequency selected given the
>> available variable size for storing the values.
>
> Trying to select the most precise pair of integers to represent an
> arbitrary value is actually quite a difficult math-theoretical
> problem, not to mention the difficullty in the user code that would be
> necessary to correctly handle them.

This is true.  It's an optimization problem.  There are some simple
single-shot approaches that have what are most likely acceptable error
levels like the one mentioned earlier.  Really choosing things
optimally is harder and is iterative unless one has a lookup table.
I'd be OK with selecting one that's not perfect, but could be adjusted
a little to provide low error in the ranges that the peripherals are
generally used.

>
>> As a potential additional option, 1) could be revised such that if no
>> divisor is passed, return divisor is always 1, but if a 1 is passed
>> than the divisor is allowed to float as in 3) above.
>
> We already have the first part, and the defaults are 100 for the duty
> cycle, 1,000,000 for delays and 1 for frequencies.  I hink the second
> idea is a nightmare for us and for the users.
>
>> provide consistency with current behavior and maximum potential return
>> value accuracy.
>
> I don't value euther of these. On the one hand I'm not afraid to
> change the platform (or the Lua) interfaces if that gives a worthwhile
> improvement in what you can do or how easy it is to understand, and
> the current interface did not consider the practical problems that we
> are trying to improve now.
>  I seem to remember someone saying that, before we release eLua 1.0,
> maintaining backward compatability is not a problem, especially given
> the small user base.  Of course, we don't want to break things for no
> significant gain.

I could have worded that better, and I agree with what you just said
here, I believe I was just saying that it was a plus that it wouldn't
break existing functionality, which does have some value.

>  I don't think total laboratory-standard mathematical accuracy is as
> important a degisn goal for eLua as being simple to use and having an
> Lua interface that is pleasant to use and easy to understand.  It's a
> design tradeoff, since lab accuracy requires a different set of
> interfaces than one that is easy-to-use but adequate for most
> purposes.

I don't mean to say that they really need to be optimal, we would end
up wasting computational time and memory with some iterative
optimization algorithm or lookup tables.  The reason that I said
"maximum _potential_ return value accuracy" was that this would give
the backend implementer the most precise representation of the
frequency the user wanted.  Again, I would be happy with a simple
non-iterative algorithm with a known worst-case that is acceptable.

>  Already, moving to optional variable radix fixed point for some
> values is a step towards higher accuracy and away from easy-to-use,
> but seems to bring some advantages.
>
>> As far as rethinking the API is concerned, I think either way we come
>> back to an issue of fractional frequencies with integer expressions
>> problem, unless the integer builds are to have different functionality
>> than the floating point builds.
>
> That was my first idea for low frequencies: optional FP, but I think
> your optional divisor (or radix in fixed-point math language) solution
> may be a better one.

It's a tradeoff, but since we already have some pre-selected radix
notation, I think making it an option that the user can provide to
select different radices make sense.  I would tend to agree that just
going with fixed-point (powers of 10) might be the least messy to deal
with, and also makes for easy mental digesting of parameters and
return values for the programmer.
_______________________________________________
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: How to get precisely times samples?

On 29 July 2011 02:51, James Snyder <[hidden email]> wrote:

> > In eLua we have three separate usage cases of arbitrary numbers being
> > passed/returned as integers:
> > 1. high frequencies for clocks, used in PWM clock, timer clock (also
> > used in ADC), maybe also for I2C and SPI clocks and (even more maybe)
> > UART baud rates.
> > 2. low frequencies for ADC sampling rates and PWM frequencies
>
> These don't have to be low frequencies unless hundreds of kilohertz or
> an order of magnitude higher is considered low.

Sorry, I obviously wasn't very clear in my explanation.
I'm trying to distinguish what seem to be three different types of
data object in the platform interface that have have different
characteristics and require differ kinds of reasoning about them:
1. clock frequencies derived from a crystal, that are used in
pwm.setclock(), tmr.setclock() and elsewhere;
2. frequencies that are derived from these by dividing these down,
usually with a hardware counter that resets every N clock cycles, as
used in adc sampling rates, pwm output frequencies(), free-running
timer interrupts and so on.

I just used the words "high" and "low" because their typical ranges of
frequencies are higher and lower.
Shall we call then "clocking frequencies" and "output frequencies" or
something, to avoid the subjective associations of the words "high"
and "low"?

By separating the different cases, we can reason more usefully about
each one, rather than talking about a single solution to three
different types of object.

It may be that what I have called "low" frequencies are not worth
making more precise, which would just leave PWM duty cycles.

> PWM can
> certainly run at a few megahertz on many of the platforms we use,
> though this doesn't provide excellent resolution in duty cycle.

As well as 1 or 2 hertz if used to flash christmas lights, where one
would be able to produce a slowly-accelerating flashing rate.
What I mean, again, is that these are lower frequencies derived from
the clocking rate.  Of course, the divisor used to produce the output
frequency could even be 1, giving the same frequency as the clock
rate, but in terms of the program interface, that data object is still
an output frequency derived from the clocking frequency.

> I actually have a minor dislike for the convention of the "setup"
> function since they take different parameters depending on the
> peripheral that's being setup.

I have no problem aith that, since different devices need setting up
with different parameters.
For me, if the function sets the interface up (i.e. initializes it to
make it ready for subsequent use), then "setup" is OK.
I am concerned by a *.setup() function that doesn't set the interface
up, but is used to drive it!

> As far as alternatives, maybe something like settimer
> or setuptimer might make more sense?  Alternately if we wanted ADC to
> support other trigger sources, it could be named something like
> settrigger or setuptrigger?

OK, I'll leave you to think about that. I'm happy as long as
foo.setup() sets foo up ready to be used, foo.setclock() sets foo's
clock frequency and so on, so that when you read the Lua code, it
makes some kind of sense.

> > Furthermore, on AVR32, being told to set both the frequency and duty
> > cycle causes a glitch in the output because the stupid hardware
> > interface can only set either the frequency or the duty cycle once per
> > output cycle so you get one cycle either at the new frequency and old
> > duty cycle or at the old frequency with the new duty cycle.
>
> Interesting.  I assume that you can temporarily stop the peripheral,
> set the values and then start it again though?  Sure you might lose
> some clock cycles, but I'm not sure we're guaranteeing that PWM is
> continuous through successive calls.  Not sure if we would need to do
> so either.

The most demanding application I can think of is when it is being used
to signal data, such as in TV remote controls, where a blip at the
wrong frequency or duty cycle might make it do the wrong thing. Yes,
you can also stop the output, reprogram it and start again, though for
applications like using PWM to implement an audio DAC, that causes an
audible bubble in the output. I like producing good quality output
when that is possible, so that when people push the envelope, the
system doesn't let them down.

> > Worse yet, pwm.setup(id, frequency, duty_cycle) takes two parameters
> > both of which are in the proposed fixed-point format, which is ugly.
> > Even in the naive case where you get higher precision by giving a duty
> > cycle radix of 1000 or 1000000, you'd need to supply a bogus extra
> > parameter for the undesired precision of the PWM output frequency.
>
> This is another reason why I'm not a massive fan of "setup" functions,
> I kindof think this should be two separate functions.

OK

> Would we really need a radix other than 1 for PWM frequencies though?
> I'm not sure if non-integer frequencies are ever needed.

Flashing christmas lights?

> > These are three arguments in favour of splitting pwm.setup() into two
> > functions like pwm.setfreq() and pwm.setduty().  A fourth is that all
> > the other modules' setup() functions are usually called once at start
> > of program, then the output is varied as the program runs using
> > module-specific functions, whereas the current pwm.setup() is used
> > repeatedly while the programming is running to vary the output.
>
> Yeah, I've felt this way for a while now.  Bogdan, any comments on
> this front? We're starting to get into a number of API changes and
> proposals here :-)

> >> 3) The divisor returned is determined by the low-level code in order
> >> to provide best accuracy in conveying the frequency selected given the
> >> available variable size for storing the values.
> >
> > Trying to select the most precise pair of integers to represent an
> > arbitrary value is actually quite a difficult math-theoretical
> > problem, not to mention the difficullty in the user code that would be
> > necessary to correctly handle them.
>
> This is true.  It's an optimization problem.  There are some simple
> single-shot approaches that have what are most likely acceptable error
> levels like the one mentioned earlier.  Really choosing things
> optimally is harder and is iterative unless one has a lookup table.
> I'd be OK with selecting one that's not perfect, but could be adjusted
> a little to provide low error in the ranges that the peripherals are
> generally used.
>
> I don't mean to say that they really need to be optimal, we would end
> up wasting computational time and memory with some iterative
> optimization algorithm or lookup tables.  The reason that I said
> "maximum _potential_ return value accuracy" was that this would give
> the backend implementer the most precise representation of the
> frequency the user wanted.  Again, I would be happy with a simple
> non-iterative algorithm with a known worst-case that is acceptable.

I would drop this idea and keep it simple, returning values in the
same radix as the user passed, where that is appropriate.

Or, if we drop the proposal to make "output" frequencies more precise
(for the 27.27Hz ADCs in seismographs and for the xmas lights), that
only leaves PWM duty cycles, and in that case we don't return the
"actual" duty cycle set at all, so the problem goes away.

> I would tend to agree that just
> going with fixed-point (powers of 10) might be the least messy to deal
> with.

I have no problem if they want to express something in 360ths for some
reason of their own, or, in units of the period of the PWM cycle
counter to get max precision. Our code would be the same in any case,
without needing to impose artificial restrictions.

Can we focus on concrete proposals and decide?

I'm in favour of adding optional extra parameter after duty cycles to
get higher precision (indeed, hardware precision if you pick the right
radix)

I'm ambivalent about adding radix to frequencies for higher-precision
low frequencies. It would be nice.

Lastly, these kinds of changes are hard because they have to be
implemented on every platform simultaneously, which either needs
someone who has all the platforms, or some tight collaboration.
James, have you been able to test on an ARm platform that patch to
split platform_adc_op()

   M
_______________________________________________
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: How to get precisely times samples?

On 31 July 2011 07:32, Martin Guy <[hidden email]> wrote:
> James, have you been able to test on an ARm platform that patch to
> split platform_adc_op()

Sorry, I mean platform_pwm_op()

   m
_______________________________________________
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: How to get precisely times samples?

In reply to this post by Martin Guy
On Sun, Jul 31, 2011 at 12:32 AM, Martin Guy <[hidden email]> wrote:

> On 29 July 2011 02:51, James Snyder <[hidden email]> wrote:
>
>> > In eLua we have three separate usage cases of arbitrary numbers being
>> > passed/returned as integers:
>> > 1. high frequencies for clocks, used in PWM clock, timer clock (also
>> > used in ADC), maybe also for I2C and SPI clocks and (even more maybe)
>> > UART baud rates.
>> > 2. low frequencies for ADC sampling rates and PWM frequencies
>>
>> These don't have to be low frequencies unless hundreds of kilohertz or
>> an order of magnitude higher is considered low.
>
> Sorry, I obviously wasn't very clear in my explanation.
> I'm trying to distinguish what seem to be three different types of
> data object in the platform interface that have have different
> characteristics and require differ kinds of reasoning about them:
> 1. clock frequencies derived from a crystal, that are used in
> pwm.setclock(), tmr.setclock() and elsewhere;
> 2. frequencies that are derived from these by dividing these down,
> usually with a hardware counter that resets every N clock cycles, as
> used in adc sampling rates, pwm output frequencies(), free-running
> timer interrupts and so on.

Ah, gotcha.  I could be a little bit pedantic here that in both 1 & 2
there is clock division going on that is configurable, but I see what
you mean by the second class being ones that are based on something
like a timer counter with match values or overflow or something like
that that is being incremented by the first class.

>
> I just used the words "high" and "low" because their typical ranges of
> frequencies are higher and lower.
> Shall we call then "clocking frequencies" and "output frequencies" or
> something, to avoid the subjective associations of the words "high"
> and "low"?

Sure.

>
> By separating the different cases, we can reason more usefully about
> each one, rather than talking about a single solution to three
> different types of object.
>
> It may be that what I have called "low" frequencies are not worth
> making more precise, which would just leave PWM duty cycles.
>
>> PWM can
>> certainly run at a few megahertz on many of the platforms we use,
>> though this doesn't provide excellent resolution in duty cycle.
>
> As well as 1 or 2 hertz if used to flash christmas lights, where one
> would be able to produce a slowly-accelerating flashing rate.
> What I mean, again, is that these are lower frequencies derived from
> the clocking rate.  Of course, the divisor used to produce the output
> frequency could even be 1, giving the same frequency as the clock
> rate, but in terms of the program interface, that data object is still
> an output frequency derived from the clocking frequency.
>
>> I actually have a minor dislike for the convention of the "setup"
>> function since they take different parameters depending on the
>> peripheral that's being setup.
>
> I have no problem aith that, since different devices need setting up
> with different parameters.
> For me, if the function sets the interface up (i.e. initializes it to
> make it ready for subsequent use), then "setup" is OK.
> I am concerned by a *.setup() function that doesn't set the interface
> up, but is used to drive it!

I would agree here that this particular case has a stronger motivator behind it.

>
>> As far as alternatives, maybe something like settimer
>> or setuptimer might make more sense?  Alternately if we wanted ADC to
>> support other trigger sources, it could be named something like
>> settrigger or setuptrigger?
>
> OK, I'll leave you to think about that. I'm happy as long as
> foo.setup() sets foo up ready to be used, foo.setclock() sets foo's
> clock frequency and so on, so that when you read the Lua code, it
> makes some kind of sense.

Gotcha.

>
>> > Furthermore, on AVR32, being told to set both the frequency and duty
>> > cycle causes a glitch in the output because the stupid hardware
>> > interface can only set either the frequency or the duty cycle once per
>> > output cycle so you get one cycle either at the new frequency and old
>> > duty cycle or at the old frequency with the new duty cycle.
>>
>> Interesting.  I assume that you can temporarily stop the peripheral,
>> set the values and then start it again though?  Sure you might lose
>> some clock cycles, but I'm not sure we're guaranteeing that PWM is
>> continuous through successive calls.  Not sure if we would need to do
>> so either.
>
> The most demanding application I can think of is when it is being used
> to signal data, such as in TV remote controls, where a blip at the
> wrong frequency or duty cycle might make it do the wrong thing. Yes,
> you can also stop the output, reprogram it and start again, though for
> applications like using PWM to implement an audio DAC, that causes an
> audible bubble in the output. I like producing good quality output
> when that is possible, so that when people push the envelope, the
> system doesn't let them down.

I agree there as well. Audio is probably a good example where this
sort of thing might become noticeable.

>
>> > Worse yet, pwm.setup(id, frequency, duty_cycle) takes two parameters
>> > both of which are in the proposed fixed-point format, which is ugly.
>> > Even in the naive case where you get higher precision by giving a duty
>> > cycle radix of 1000 or 1000000, you'd need to supply a bogus extra
>> > parameter for the undesired precision of the PWM output frequency.
>>
>> This is another reason why I'm not a massive fan of "setup" functions,
>> I kindof think this should be two separate functions.
>
> OK
>
>> Would we really need a radix other than 1 for PWM frequencies though?
>> I'm not sure if non-integer frequencies are ever needed.
>
> Flashing christmas lights?

That's a valid example. I might have considered using other methods to
support something in that frequency range, but that's a convenient way
to handle that type of system without having software in the loop at
each cycle.

>
>> > These are three arguments in favour of splitting pwm.setup() into two
>> > functions like pwm.setfreq() and pwm.setduty().  A fourth is that all
>> > the other modules' setup() functions are usually called once at start
>> > of program, then the output is varied as the program runs using
>> > module-specific functions, whereas the current pwm.setup() is used
>> > repeatedly while the programming is running to vary the output.
>>
>> Yeah, I've felt this way for a while now.  Bogdan, any comments on
>> this front? We're starting to get into a number of API changes and
>> proposals here :-)
>
>> >> 3) The divisor returned is determined by the low-level code in order
>> >> to provide best accuracy in conveying the frequency selected given the
>> >> available variable size for storing the values.
>> >
>> > Trying to select the most precise pair of integers to represent an
>> > arbitrary value is actually quite a difficult math-theoretical
>> > problem, not to mention the difficullty in the user code that would be
>> > necessary to correctly handle them.
>>
>> This is true.  It's an optimization problem.  There are some simple
>> single-shot approaches that have what are most likely acceptable error
>> levels like the one mentioned earlier.  Really choosing things
>> optimally is harder and is iterative unless one has a lookup table.
>> I'd be OK with selecting one that's not perfect, but could be adjusted
>> a little to provide low error in the ranges that the peripherals are
>> generally used.
>>
>> I don't mean to say that they really need to be optimal, we would end
>> up wasting computational time and memory with some iterative
>> optimization algorithm or lookup tables.  The reason that I said
>> "maximum _potential_ return value accuracy" was that this would give
>> the backend implementer the most precise representation of the
>> frequency the user wanted.  Again, I would be happy with a simple
>> non-iterative algorithm with a known worst-case that is acceptable.
>
> I would drop this idea and keep it simple, returning values in the
> same radix as the user passed, where that is appropriate.

Yep.

>
> Or, if we drop the proposal to make "output" frequencies more precise
> (for the 27.27Hz ADCs in seismographs and for the xmas lights), that
> only leaves PWM duty cycles, and in that case we don't return the
> "actual" duty cycle set at all, so the problem goes away.
>
>> I would tend to agree that just
>> going with fixed-point (powers of 10) might be the least messy to deal
>> with.
>
> I have no problem if they want to express something in 360ths for some
> reason of their own, or, in units of the period of the PWM cycle
> counter to get max precision. Our code would be the same in any case,
> without needing to impose artificial restrictions.
>
> Can we focus on concrete proposals and decide?

Sure.

>
> I'm in favour of adding optional extra parameter after duty cycles to
> get higher precision (indeed, hardware precision if you pick the right
> radix)

OK.  So something like:

duty, radix = pwm.setduty(id, duty, [radix=100])

Radix is free-form, but integer?


>
> I'm ambivalent about adding radix to frequencies for higher-precision
> low frequencies. It would be nice.

Does one need the christmas lights to flash at 0.43 Hz?  I dunno.  PWM
can be used for triggering other things like, for example an external
ADC where that might be useful?

freq, radix = pwm.setfreq(id, freq, [radix=1])

For setting the clocking frequency, I don't think there's a good
reason (pwm.setclock).  Some platforms may not even support low
frequencies on this front and the few multipliers/dividers in line
would make it difficult to get precision on those that would make it
worth it.


Question: do we leave setup for now?  Do we provide radix functionality with it?

>
> Lastly, these kinds of changes are hard because they have to be
> implemented on every platform simultaneously, which either needs
> someone who has all the platforms, or some tight collaboration.

Indeed.  I suppose we can stub out functionality for some platforms at
first and fill in support, but it would be nice to have them all as
much on the same page as possible.

> James, have you been able to test on an ARm platform that patch to
> split platform_adc_op()

Yeah, sorry about not getting back to you on that. I ran out of time
last week and then ended up driving to a wedding (which I brought some
MCUs with me on, but had no time).

I have tested some but not all of the platforms yet.  It works fine
for me on LM3S & STM32, but I'm having trouble finding the LPC 17xx
board I have, however looking at the code that one shouldn't be a
problem since there were already functions for providing the
functionality that pwm_op was using.  I guess I also have an LPC24xx
in the form of the PUC rio board, and an STR9 board that I can test.
I'll send results from those tonight since they're at home.  I can do
at least a build test for other platforms, but I don't have hardware.

I suppose I can take a look at the assembler generated for the at91
platform and try to see if it has optimized out that section you had
concerns about.  I can try and poke Bogdan to see if he can test this?


As far as getting changes like this implemented while I know I took a
bit on checking platform compatibility, but I'm in town for the coming
weeks and I'm willing to try and get this implemented/tested with
tighter, at least closer to daily, evaluation and feedback.  I'm also
happy to implement some of this myself since at least for the duty
cycles, I've wanted this for some time (I have a current project where
to effectively get this I add random numbers on the interval -0.5 ->
0.5 to dither PWM duty cycles to get more precise output, and I'd like
to _not_ have to do that.)

We could also do this in stages on a testing branch if we can't get
all platforms tested and implemented quickly and only merge it once
all platforms perform in a satisfactory manner.

Let me know what portions of this you would like to implement, if any.


Thanks for both the work and the discussion. I'm glad to have some
section of this moving forward now.  I would suggest that we start
maybe with PWM _or_ ADC for this and not try to do both in the same
set of patches at the same time and move on to any other places we
want to implement this after we have done these.  Timers, for example,
could do well to support the radix notation, and all of these should
have common code within given platforms so that once we've done one
the others should be easier on both platform implementation and common
code sides.


>
>   M
> _______________________________________________
> 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
jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

Re: How to get precisely times samples?

On Mon, Aug 1, 2011 at 3:40 PM, James Snyder <[hidden email]> wrote:

> On Sun, Jul 31, 2011 at 12:32 AM, Martin Guy <[hidden email]> wrote:
>> On 29 July 2011 02:51, James Snyder <[hidden email]> wrote:
>> James, have you been able to test on an ARm platform that patch to
>> split platform_adc_op()
>
> Yeah, sorry about not getting back to you on that. I ran out of time
> last week and then ended up driving to a wedding (which I brought some
> MCUs with me on, but had no time).
>
> I have tested some but not all of the platforms yet.  It works fine
> for me on LM3S & STM32, but I'm having trouble finding the LPC 17xx
> board I have, however looking at the code that one shouldn't be a
> problem since there were already functions for providing the
> functionality that pwm_op was using.  I guess I also have an LPC24xx
> in the form of the PUC rio board, and an STR9 board that I can test.
> I'll send results from those tonight since they're at home.  I can do
> at least a build test for other platforms, but I don't have hardware.

LPC1768: works.
STR9: works.
LPC24xx: works.
_______________________________________________
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: How to get precisely times samples?

In reply to this post by jbsnyder
I'll send this, cos it's been sitting in my outbox for 4 days and my
brain is elsewhere at present.

On 1 August 2011 22:40, James Snyder <[hidden email]> wrote:

>> I'm in favour of adding optional extra parameter after duty cycles to
>> get higher precision (indeed, hardware precision if you pick the right
>> radix)
>
> OK.  So something like:
>
> duty, radix = pwm.setduty(id, duty, [radix=100])
>
> Radix is free-form, but integer?

Integer, sure. A floating point radix is an interesting idea... :)

I'm not sure the radix needs to be returned from the functions, since
it will always be either 100 or what the user specified, so its value
is 100% predictable and so contains no information. It also simplifies
the documentation, so a beginner isn't immediately worried about
"what's this extra radix thing that it might return" and only power
users need to deal with funny radices.

>> I'm ambivalent about adding radix to frequencies for higher-precision
>> low frequencies. It would be nice.
>
> Does one need the christmas lights to flash at 0.43 Hz?  I dunno.  PWM
> can be used for triggering other things like, for example an external
> ADC where that might be useful?
>
> freq, radix = pwm.setfreq(id, freq, [radix=1])

OK. apart from returning radix again

> For setting the clocking frequency, I don't think there's a good
> reason (pwm.setclock).
>
> Question: do we leave setup for now?  Do we provide radix functionality with it?

OK, let's think about this. If we split into setfreq() and setduty():
- what does it do when they have set a frequency but not set a duty cycle yet?
- What does it do if they set a duty cycle but haven't set a frequency yet?
The platform code I have seen for the current pwm.setup() always goes:
{
   set pwm period in the hardware, calculated from the requested
frequency and clock rate;
   set duty cycle as a period in clock ticks calculated from the pwm period;
}
Maybe for this reason it is handy always to have the frequency and
duty cycle on hand at the same time. However, from the platform code
I've seen, when setting the duty cycle separately, you can fish the
period (that you need for the calculation) back out of the hardware
register.
That's enough to be able to vary the duty cycle while keeping the
frequency the same.

However, if they decide to vary the frequency without changing the
duty cycle, we would need to remember the duty cycle for each channel
in a tiny array duty[NUM_PWM] and presumably radix[NUM_PWM] to be able
to recalculate the duty cycle as a fraction of the PWM period when the
frequency alone is changed. That doesn't seem too hard or costly if it
gives a better Lua interface to the PWM module, and only needs to
happen in src/modules/pwm.c, not in every platform.  I hate to say it,
but that suggests keeping the C platform interface as it is, with freq
and duty always passed as a pair, otherwise we'll have the same code
to cache the duty cycle and radix in a dozen different places.  In the
case of AVR32, with its inability to set both at once, I already check
to see if the frequency (period) is the same as before and only update
the duty cycle in that case.

Question: do PWM applications change the frequency without changing
the duty cycle? Well, I can think of an organ-like instrument where
the duty cycle gives a tone timbre and the frequency the note. For
that, the highest possible precision of the frequency setting is
critical: a hundredth of a percent of the frequency in use is the
target for musical pitches, so the more frequency precision the better
in that application.

That suggests in the Lua interface:
pwm.setduty( id, duty[, radix=100] )
pwm.setfreq( id, freq[, radix=1] )
and keeping the C platform interface the same as it is now, modulo
adding an extra duty/radix parameter.

It would be good to add in the documentation recommended usage
sequences.  For instance, what happens if I call pwm.start() before
setting the frequency and duty cycle for a channel?
Is a call to pwm.setup() necessary to enable the pin as an output,
even if we move the frequency and duty cycle stuff, that can happen
during the program run, elsewhere?

>> James, have you been able to test on an ARm platform that patch to
>> split platform_adc_op()
>
> I suppose I can take a look at the assembler generated for the at91
> platform and try to see if it has optimized out that section you had
> concerns about.

Ah! I hadn't thought of that. Thanks. Yes, it is dutifully reading it
(and storing it in the dummy variable that is immediately forgotten,
der). Thanks.

> I add random numbers on the interval -0.5 ->
> 0.5 to dither PWM duty cycles to get more precise output, and I'd like
> to _not_ have to do that.)

Urk! It's a sign that something is wrong with the interface if you
have to do such gymnastics.

> We could also do this in stages on a testing branch if we can't get
> all platforms tested and implemented quickly and only merge it once
> all platforms perform in a satisfactory manner.

When it means non-trivial reimplementation of platform code on a dozen
platforms, which may or may not work, that sounds wise.

When evolving the Lua interfaces, should we keep the current Lua
interfaces also, for example under
#ifdef ELUA_0_8_COMPAT
to allow existing Lua code to continue working, or do we just change
things to keep the code simpler and more manageable?

>  I would suggest that we start
> maybe with PWM _or_ ADC for this and not try to do both in the same
> set of patches at the same time

Agreed. Let's hit PWM first

> Let me know what portions of this you would like to implement, if any.

Implementing the optional radix in the current pwm.setup() interface
seems like the smallest self-contained step we can take in this
direction, and the least disruptive.

> Timers, for example,
> could do well to support the radix notation, and all of these should
> have common code within given platforms so that once we've done one
> the others should be easier on both platform implementation and common
> code sides.

They could. But if you mean for time delays, that has as a
prerequisite getting rid of the C platform_timer_op primitives, and
this is the second most difficult example of this to refactor, after
pio. Furthermore, they are already radix 1,000,000 (microseconds)
which may already be precise enough for delays. I'm not in favour of
implementing things just for a sense of symmetry, but only if the
upheaval brings a practical advantage.
 If you mean the frequency of free-running interrupts, tmr already
expresses that in microseconds, not Hz, so you already have high
precision at low frequencies.
But that also bring low precision at high frequencies :( so maybe this
is useful, to be able to express free-running interrupt periods (or
ADC conversion frequencies) at the precision of the underlying timer
clock (tmr.getclock()) to be able to get the best out of the hardware,
which may be clocking the timer at 200MHz.

I'm not sure that having ADC sampling rates explicitly use a timers at
the interface level is ideal.
On the one hand, hardware that is able to sample at a given rate will
needlessly occupy a timer just because you have to say so in the Lua
interface.  On the other, if there is no other way to implement it on
a given platform it is better for it be explicit than hidden.
With the ADCs that I've seen on these platforms, you just kick them,
they convert as fast as they can and you the read the result back -
very different from the audio ADCs I'm used to.  That suggests,
instead of hijackng a timer, making the *user* do the stuff with
timers for periodic conversions, probably by an explicit periodic
timer interrupt that calls a kick-the-ADC routine, and limit the ADC
eLua interface to start-a-conversion, is-it-finished and
read-the-value, eliminating the buffering and the smoothing parts.

Already the DHCP server in UIP, and the serial console quietly hijack
a timer each to do timeouts, and between them they occupy both of the
usable timers on AVR32, leaving the user with only the virtual ones
with 1/10th second granularity. DHCP can easily be changed to use the
system tick while for the serial console it's only used to try and
detect LFCR sequences that can never occur.

Actually, it's a bit odd that free-running timer interrupts are the
only frequency in eLua that is expressed as a period. In fact, on the
subect of free-running timer interrupts, I think the
tmr.set_match_int( id, period, type )
(where type = tmr.INT_ONESHOT or tmr.INT_CYCLIC for a single
interrupts after a delay or to set free-running interrupts or
free-running ADC conversions) could be rethought.
The "type" parameter is surely always a constant in the user code, so
we could turn this into two functions. That would let us express an
interrupt after a delay as the usual time in microseconds, and the
frequency of free-running interrupts as a frequency with optional
radix, the same as all the other output-frequency operations.
  But let's see if that is a practical problem for anyone first.

    M
_______________________________________________
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: How to get precisely times samples?



On Fri, Aug 5, 2011 at 1:25 AM, Martin Guy <[hidden email]> wrote:
I'll send this, cos it's been sitting in my outbox for 4 days and my
brain is elsewhere at present.

On 1 August 2011 22:40, James Snyder <[hidden email]> wrote:

>> I'm in favour of adding optional extra parameter after duty cycles to
>> get higher precision (indeed, hardware precision if you pick the right
>> radix)
>
> OK.  So something like:
>
> duty, radix = pwm.setduty(id, duty, [radix=100])
>
> Radix is free-form, but integer?

Integer, sure. A floating point radix is an interesting idea... :)

I'm not sure the radix needs to be returned from the functions, since
it will always be either 100 or what the user specified, so its value
is 100% predictable and so contains no information. It also simplifies
the documentation, so a beginner isn't immediately worried about
"what's this extra radix thing that it might return" and only power
users need to deal with funny radices.

Yeah, I'm trying to think of use cases where returning the radix would be essential, and the only things I think think of are situations where you wanted to feed the value to something else, but selected the radix in another scope (maybe like a coroutine or a closure, but you could divide by the radix before returning, or return both in an ad-hoc manner, so I guess that's not needed.  I just liked the idea that the result could be interpreted unambiguously without access to the scope in which the parameters were passed.

So, count that as a "I guess we don't need it"
 

>> I'm ambivalent about adding radix to frequencies for higher-precision
>> low frequencies. It would be nice.
>
> Does one need the christmas lights to flash at 0.43 Hz?  I dunno.  PWM
> can be used for triggering other things like, for example an external
> ADC where that might be useful?
>
> freq, radix = pwm.setfreq(id, freq, [radix=1])

OK. apart from returning radix again

> For setting the clocking frequency, I don't think there's a good
> reason (pwm.setclock).
>
> Question: do we leave setup for now?  Do we provide radix functionality with it?

OK, let's think about this. If we split into setfreq() and setduty():
- what does it do when they have set a frequency but not set a duty cycle yet?
- What does it do if they set a duty cycle but haven't set a frequency yet?

Good question. Going based on other peripherals, like if you just "start" a timer and possibly even pwm currently, it will start going, but the parameters you haven't set aren't guaranteed.  You get either the default of the hardware or some default that we selected to initialize the hardware.  This is a little less than ideal, perhaps we could standardize this a little more across platforms.. hmm..
 
The platform code I have seen for the current pwm.setup() always goes:
{
  set pwm period in the hardware, calculated from the requested
frequency and clock rate;
  set duty cycle as a period in clock ticks calculated from the pwm period;
}
Maybe for this reason it is handy always to have the frequency and
duty cycle on hand at the same time. However, from the platform code
I've seen, when setting the duty cycle separately, you can fish the
period (that you need for the calculation) back out of the hardware
register.

Yeah, generally those registers are readable, I think we often use this in order to return what things were actually set to.

In a worst case scenario there could be global state in the platform implementation to keep track of this after it has been set.
 
That's enough to be able to vary the duty cycle while keeping the
frequency the same.


Yep.
 

However, if they decide to vary the frequency without changing the
duty cycle, we would need to remember the duty cycle for each channel
in a tiny array duty[NUM_PWM] and presumably radix[NUM_PWM] to be able
to recalculate the duty cycle as a fraction of the PWM period when the
frequency alone is changed. That doesn't seem too hard or costly if it
gives a better Lua interface to the PWM module, and only needs to
happen in src/modules/pwm.c, not in every platform.

Yeah, and you would want to cache the passed numbers rather than fish them out to fix the duty cycle on the fly so as to remain closer to what the user asked for.  Unfortunately this also has an icky side effect of potentially changing the exact duty cycle.
 
 I hate to say it,
but that suggests keeping the C platform interface as it is, with freq
and duty always passed as a pair, otherwise we'll have the same code
to cache the duty cycle and radix in a dozen different places.  In the
case of AVR32, with its inability to set both at once, I already check
to see if the frequency (period) is the same as before and only update
the duty cycle in that case.

I'd agree. There are a few ways to do it, but it is most convenient in the platform code to have both at the same time, and it would help keep.  On the one hand that means less modification to the platforms and less code, but as you're pointing out it's problematic with AVR32. 

Side note: is there some sort of pending or update flag that you could use to set the two sequentially then grind away in a loop watching a register for when that has been accepted, then you can change the other? Or can you just watch the counter?  It certainly means burning extra time in the function, especially if the frequency is quite slow, but perhaps worth it?

 

Question: do PWM applications change the frequency without changing
the duty cycle? Well, I can think of an organ-like instrument where
the duty cycle gives a tone timbre and the frequency the note. For
that, the highest possible precision of the frequency setting is
critical: a hundredth of a percent of the frequency in use is the
target for musical pitches, so the more frequency precision the better
in that application.

That suggests in the Lua interface:
pwm.setduty( id, duty[, radix=100] )
pwm.setfreq( id, freq[, radix=1] )
and keeping the C platform interface the same as it is now, modulo
adding an extra duty/radix parameter.

Right.  There are a lot of applications where you won't touch frequency, but will update duty cycle frequently, but audio applications would hold duty cycle constant (for the most part), but vary the frequency all over.

With this, we would store duty and radix vales in the module, maybe with some sane defaults set initially for whichever value isn't being set, like 50% for duty, and 1 KHz or something for frequency?
 

It would be good to add in the documentation recommended usage
sequences.  For instance, what happens if I call pwm.start() before
setting the frequency and duty cycle for a channel?
Is a call to pwm.setup() necessary to enable the pin as an output,
even if we move the frequency and duty cycle stuff, that can happen
during the program run, elsewhere?

Yeah, this is a good idea, and something we should do for other peripherals like timers and the like as far as what state they're in without setting any parameters.

I think having some sane, documented defaults for the unset parameter is not a bad place to start (I guess we then might have to guarantee those won't change in future versions?).  I suppose you could also do some things like set the initial values to 0 or -1 and only call the platform function when both have been filled in.   Let me know what you think about this... 

On the pin configuration front, we could probably do it when the user calls start, since this is the first point that the output actually needs to start being reflected on the pin.  I suspect there shouldn't be any platform situations where the pin needs to be configured in advance of other stuff.  Also, ultimately, I think we need more of a common interface for supporting various output pin configuration options, but that's a whole separate thread that should be picked up sometime.


 

>> James, have you been able to test on an ARm platform that patch to
>> split platform_adc_op()
>
> I suppose I can take a look at the assembler generated for the at91
> platform and try to see if it has optimized out that section you had
> concerns about.

Ah! I hadn't thought of that. Thanks. Yes, it is dutifully reading it
(and storing it in the dummy variable that is immediately forgotten,
der). Thanks.

> I add random numbers on the interval -0.5 ->
> 0.5 to dither PWM duty cycles to get more precise output, and I'd like
> to _not_ have to do that.)

Urk! It's a sign that something is wrong with the interface if you
have to do such gymnastics.

Yep.  It's ugly, but it did effectively increase resolution.  That was around the point that I think I wrote the original suggestion for a variable radix.
 

> We could also do this in stages on a testing branch if we can't get
> all platforms tested and implemented quickly and only merge it once
> all platforms perform in a satisfactory manner.

When it means non-trivial reimplementation of platform code on a dozen
platforms, which may or may not work, that sounds wise.

When evolving the Lua interfaces, should we keep the current Lua
interfaces also, for example under
#ifdef ELUA_0_8_COMPAT
to allow existing Lua code to continue working, or do we just change
things to keep the code simpler and more manageable?

We haven't used deprecation in the past. I'd vote for keeping things simple for now.  I'd say that would be something that maybe might be necessary for post-1.0 revisions to the API?

We should go through and update examples we've published to the newer API and certainly make it clear in any release notes that updates are required for code using the older style.
 

>  I would suggest that we start
> maybe with PWM _or_ ADC for this and not try to do both in the same
> set of patches at the same time

Agreed. Let's hit PWM first

> Let me know what portions of this you would like to implement, if any.

Implementing the optional radix in the current pwm.setup() interface
seems like the smallest self-contained step we can take in this
direction, and the least disruptive.

Sounds good.
 

> Timers, for example,
> could do well to support the radix notation, and all of these should
> have common code within given platforms so that once we've done one
> the others should be easier on both platform implementation and common
> code sides.

They could. But if you mean for time delays, that has as a
prerequisite getting rid of the C platform_timer_op primitives, and
this is the second most difficult example of this to refactor, after
pio. Furthermore, they are already radix 1,000,000 (microseconds)
which may already be precise enough for delays. I'm not in favour of
implementing things just for a sense of symmetry, but only if the
upheaval brings a practical advantage.
 If you mean the frequency of free-running interrupts, tmr already
expresses that in microseconds, not Hz, so you already have high
precision at low frequencies.
But that also bring low precision at high frequencies :( so maybe this
is useful, to be able to express free-running interrupt periods (or
ADC conversion frequencies) at the precision of the underlying timer
clock (tmr.getclock()) to be able to get the best out of the hardware,
which may be clocking the timer at 200MHz.

Yeah, I wouldn't just do it for symmetry, we can probably leave this alone for now.  Given that we're using unsigned 32-bit integers the largest time chunk we can express is ~71 minutes if I did that correctly... that's probably fine for now.
 

I'm not sure that having ADC sampling rates explicitly use a timers at
the interface level is ideal.
On the one hand, hardware that is able to sample at a given rate will
needlessly occupy a timer just because you have to say so in the Lua
interface.  On the other, if there is no other way to implement it on
a given platform it is better for it be explicit than hidden.
With the ADCs that I've seen on these platforms, you just kick them,
they convert as fast as they can and you the read the result back -
very different from the audio ADCs I'm used to.  That suggests,
instead of hijackng a timer, making the *user* do the stuff with
timers for periodic conversions, probably by an explicit periodic
timer interrupt that calls a kick-the-ADC routine, and limit the ADC
eLua interface to start-a-conversion, is-it-finished and
read-the-value, eliminating the buffering and the smoothing parts.

I agree that there should be a mechanism to use interrupts to drive conversions, but that gets back into the whole issue of jitter and latency.  I think it would be a mistake to not allow use of the built-in timers to trigger conversions since this is always going to be the most consistent, low-jitter way to start a conversion.  It could be that setting up the timer could be moved to a separate module, maybe a platform-specific extension.  Certainly what you're suggesting would simplify the code and support of it, but timing of conversions will be less ideal, and ditching the buffering + smoothing and replicating that in pure Lua is going to be orders of magnitude slower, especially if you're talking about maintaining that data in Lua tables which pre-allocate more elements than you request and have a high memory penalty.
 
Also, I'm not _that_ worried about tying up a timer for ADC conversions.  Depending on the platform there are other things like PWM and encoder interfaces that by definition of hardware implementation must suck up a timer.  At least for ADC, it's still operating as a running timer, ideally you can still request the frequency using the tmr module and use output from it.. it will just be running at a frequency that's selected to enable ADC conversions at the rate the user specified.  Providing the option to not use one and drive it off of some other sort of interrupt is something that I do plan to implement shortly.

Speaking of which: I did get a reply from Atmel regarding the timer channels, and while I didn't get anything definitive, those that were asked thought that it should work, so I might experiment with it.



Already the DHCP server in UIP, and the serial console quietly hijack
a timer each to do timeouts, and between them they occupy both of the
usable timers on AVR32, leaving the user with only the virtual ones
with 1/10th second granularity. DHCP can easily be changed to use the
system tick while for the serial console it's only used to try and
detect LFCR sequences that can never occur.

Yeah, this is stuff that clearly shouldn't be sucking up a timer, especially in the ways that they're implemented (doesn't need interrupts, just polling to get a measure of time).  We should be using system tick or an RTC where available, and only if such a facility isn't available maybe document and suck up a timer and use that in place of the RTC to provide a common system clock that these things can run off of.

Regarding the serial console & uart, it's used for timeouts, which for the console might end up only coming down to that particular code (I can't remember), but configurable timeouts are definitely useful for other consumers of the UART services (LuaRPC, RFS & MUX all use them).  That said and all that behavior should come off of something like a system tick.  Regarding the linefeed and carriage return sequence detection, it does actually happen depending on the terminal being used.  This allows us to automatically support various ways of ending a line without having some sort of compile time option.  If I recall, before this was changed it was something like default behavior from TeraTerm or some other terminal vs using something like screen on Posix used different line endings (probably CRLF on Windows, LF on posix OSes) and supporting one but not the other would make it either irritating or impossible to use with one of the types of line endings, depending on which you supported. So, what it's looking for are CRLF sequences, but it also happens to handle LFCR if that happens to occur (which apparently, according to Wikipedia, was used on Acorn BBC spooled text output ;-) (http://en.wikipedia.org/wiki/Newline)

I think a lot of problems would be solved by having a system tick timer available as a resource for things like uarts, ethernet, mmcfs (which also wants timeouts), and anything that needs consistent but relatively coarse-grained timing intervals (running at a frequency between 10Hz and 1 Khz, maybe?).  Users could also get most of the timing functionality they would normally derive from timers from this common facility as well.  Then the remainder of timers are available for the user to select what they might be consumed by: dedicated timing with the tmr module, periodic interrupts, initiating scans/conversions on ADC, etc...

We could maybe look into this as one of the issues following on to the others we've discussed since I've wanted this for some time as well :-)
 

Actually, it's a bit odd that free-running timer interrupts are the
only frequency in eLua that is expressed as a period. In fact, on the
subect of free-running timer interrupts, I think the
tmr.set_match_int( id, period, type )
(where type = tmr.INT_ONESHOT or tmr.INT_CYCLIC for a single
interrupts after a delay or to set free-running interrupts or
free-running ADC conversions) could be rethought.
The "type" parameter is surely always a constant in the user code, so
we could turn this into two functions. That would let us express an
interrupt after a delay as the usual time in microseconds, and the
frequency of free-running interrupts as a frequency with optional
radix, the same as all the other output-frequency operations.
 But let's see if that is a practical problem for anyone first.

It does feel a little odd given that we have all other cyclic stuff in Hz, supporting the different notations with separate functions would be a fairly clean way to make things more consistent, but it also would also complicate the interfaces a bit to support both notations. Lets table that for now.

Best.

-jsnyder

_______________________________________________
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: How to get precisely times samples?

On 5 August 2011 22:25, James Snyder <[hidden email]> wrote:
> Side note: is there some sort of pending or update flag that you could use
> to set the two sequentially then grind away in a loop watching a register
> for when that has been accepted, then you can change the other? Or can you
> just watch the counter?  It certainly means burning extra time in the
> function, especially if the frequency is quite slow, but perhaps worth it?

There is a bit that tells you when the pending update has been flushed.
For the moment, I'm just interested in getting the thing to work and
not worried about the processing the application could do while the
first update of the two is pending.

> but audio applications would hold duty
> cycle constant (for the most part), but vary the frequency all over.

You mean organ-type audio.  Using PWM as a crude ADC would keep the
frequency at a fixed high and vary the duty cycle to varu the output
value.

> With this, we would store duty and radix vales in the module, maybe with
> some sane defaults set initially for whichever value isn't being set, like
> 50% for duty, and 1 KHz or something for frequency?

I'm not sure there are any sane defaults. I'd prefer that, until they
say what they want, we hold all output.  In my experience, arbitrary
defaults like 1kHz tend to become a ball and chain when it comes to
software maintenance in the future.

>> When evolving the Lua interfaces, should we keep the current Lua
>> interfaces also, for example under
>> #ifdef ELUA_0_8_COMPAT
>> to allow existing Lua code to continue working, or do we just change
>> things to keep the code simpler and more manageable?
>
> We haven't used deprecation in the past. I'd vote for keeping things simple
> for now.  I'd say that would be something that maybe might be necessary for
> post-1.0 revisions to the API?
> We should go through and update examples we've published to the newer API
> and certainly make it clear in any release notes that updates are required
> for code using the older style.

OK. For me, maintaining backward compatibility is no problem - we just
have to make sure we never make the old parameters take on different
meanings, but that's a good defensive principle in any case. The only
difference is in code size for the backward-compatible version.

> I agree that there should be a mechanism to use interrupts to drive
> conversions, but that gets back into the whole issue of jitter and latency.
>  I think it would be a mistake to not allow use of the built-in timers to
> trigger conversions since this is always going to be the most consistent,
> low-jitter way to start a conversion.

Right.  So what do we do for a Lua interface that can cope with
hardware that had a built-in precise conversion rate and hardware
where you have to fake it with timers, interrupts and kicking the ADC
periodically?

My feeling is to make a Lua interface that says "sample at 100Hz" and
then let the platform-dependent code decide whether the underlying
hardware has sample-at-100Hz hardware, or whether we need to fake that
using timers, interrupts and stuff.

I dunno. Being able to say "give me 100 samples per second" is nice,
but optionally hijacking one of the timers on most platforms is nasty.
Opinions?

> ditching the buffering +
> smoothing and replicating that in pure Lua is going to be orders of
> magnitude slower

My main problem with the current "smoothing" is that it is a hack. It
just averages a few of the previous samples.  On the one hand, this
offends me as a DSP nerd, since "smoothing" should be a low-pass
filter, with all the power math that finite-response filters involve,
while averaging the last few samples is more of a distortion effect
than a low-pass filter. It's something like a comb filter with a space
between the peaks equal to the length of your averaging buffer.
  My feeling is that, if you have a noisy input signal that jitters
due to noise above the sampling frequency, you should be low-pass
filtering it in hardware, with capacitors, resistors, inductore and
the like, to get a clean analog signal to sample with no frequency
components above 1/2 of the sampling frequency. Sampling a raw noisy
signal and averaging it to hide the worst of the artifacts seems like
a kludge by comparison.

> (http://en.wikipedia.org/wiki/Newline)

Thanks. That concludes the discussion on this point. LFCR does not
exist, so we can dump this code and save a timer.

> I think a lot of problems would be solved by having a system tick timer
> available as a resource for things like uarts, ethernet, mmcfs (which also
> wants timeouts), and anything that needs consistent but relatively
> coarse-grained timing intervals (running at a frequency between 10Hz and 1
> Khz, maybe?)

We have that as long as virtual timers are enabled.
It would be better if system tick were not virtual timer-dependent,
but existed independently, of which Vtimers would be one of the
clients.
Anyone who wants to refactor that in the code is very welcome.

>  Users could also get most of the timing functionality they
> would normally derive from timers from this common facility as well.  Then
> the remainder of timers are available for the user to select what they might
> be consumed by: dedicated timing with the tmr module, periodic interrupts,
> initiating scans/conversions on ADC, etc...

Are you suggesting that we reserve one timer for internal purposes on
all platforms? I'm not sure that would even be enough, since we want
one for the system tick for coarse timing, another maybe to trigger
arbitrary-frequency ADC conversions... should we allocate timers
dynamically instead of presenting the user with a fixed number of
them?  Hum, this is getting scary...

   M
_______________________________________________
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: How to get precisely times samples?

Sorry about the lack of reply on this one, I've been trying to get
ready for a qualifier recently and just finished it.

On Mon, Aug 29, 2011 at 12:02 PM, Martin Guy <[hidden email]> wrote:

> On 5 August 2011 22:25, James Snyder <[hidden email]> wrote:
>> Side note: is there some sort of pending or update flag that you could use
>> to set the two sequentially then grind away in a loop watching a register
>> for when that has been accepted, then you can change the other? Or can you
>> just watch the counter?  It certainly means burning extra time in the
>> function, especially if the frequency is quite slow, but perhaps worth it?
>
> There is a bit that tells you when the pending update has been flushed.
> For the moment, I'm just interested in getting the thing to work and
> not worried about the processing the application could do while the
> first update of the two is pending.

OK.

>
>> but audio applications would hold duty
>> cycle constant (for the most part), but vary the frequency all over.
>
> You mean organ-type audio.  Using PWM as a crude ADC would keep the
> frequency at a fixed high and vary the duty cycle to varu the output
> value.

Right.  There are different modes for this.  For higher quality audio
reproduction (not just square wave beep of varying frequencies
(+harmonics)), one could use the PWM, vary duty cycle to treat it like
a crude ADC and then low pass it to get desired output.

>
>> With this, we would store duty and radix vales in the module, maybe with
>> some sane defaults set initially for whichever value isn't being set, like
>> 50% for duty, and 1 KHz or something for frequency?
>
> I'm not sure there are any sane defaults. I'd prefer that, until they
> say what they want, we hold all output.  In my experience, arbitrary
> defaults like 1kHz tend to become a ball and chain when it comes to
> software maintenance in the future.

Fair enough, that's fine with me.

>
>>> When evolving the Lua interfaces, should we keep the current Lua
>>> interfaces also, for example under
>>> #ifdef ELUA_0_8_COMPAT
>>> to allow existing Lua code to continue working, or do we just change
>>> things to keep the code simpler and more manageable?
>>
>> We haven't used deprecation in the past. I'd vote for keeping things simple
>> for now.  I'd say that would be something that maybe might be necessary for
>> post-1.0 revisions to the API?
>> We should go through and update examples we've published to the newer API
>> and certainly make it clear in any release notes that updates are required
>> for code using the older style.
>
> OK. For me, maintaining backward compatibility is no problem - we just
> have to make sure we never make the old parameters take on different
> meanings, but that's a good defensive principle in any case. The only
> difference is in code size for the backward-compatible version.
>
>> I agree that there should be a mechanism to use interrupts to drive
>> conversions, but that gets back into the whole issue of jitter and latency.
>>  I think it would be a mistake to not allow use of the built-in timers to
>> trigger conversions since this is always going to be the most consistent,
>> low-jitter way to start a conversion.
>
> Right.  So what do we do for a Lua interface that can cope with
> hardware that had a built-in precise conversion rate and hardware
> where you have to fake it with timers, interrupts and kicking the ADC
> periodically?
>
> My feeling is to make a Lua interface that says "sample at 100Hz" and
> then let the platform-dependent code decide whether the underlying
> hardware has sample-at-100Hz hardware, or whether we need to fake that
> using timers, interrupts and stuff.

Yeah, this complicates the interface a little bit in terms of letting
the user know what resources have been consumed and what side effects
are.  At least if we're talking about systick/timer interrupts vs
triggered ADC.  Using systick ideally would not consume any named/id'd
resource and would just be limited in time resolution by system
systick configuration.  For the timer interrupts, we might have to
swallow a timer, or have one dedicated to providing this type of
functionality, in which case it becomes like systick.  Then for using
triggered interrupts, we have only the option of swallowing a timer.

I'd rather have this done at least somewhat explicitly, i.e.: the user
asks for a given rate, and either dedicates a timer to it or not.  If
no timer is dedicated, then we fall to the resolution of some system
timing facility.  If a timer is dedicated then we use timer interrupts
or ADC triggered by a timer?

I realize that's not 100% explicit, but I don't think we can do this
entirely automatically since we don't know whether the user expects
certain resources to be left as they are already configured (we have
no concept of locking, for example).

>
> I dunno. Being able to say "give me 100 samples per second" is nice,
> but optionally hijacking one of the timers on most platforms is nasty.
> Opinions?

Well, I don't mind the hijacking that much actually, as long as it is
done with the user's knowledge for the reason of getting precise
timing.  This is essentially how things are done with data acquisition
equipment, though they probably just dedicate a timer and never use it
for anything else.

>
>> ditching the buffering +
>> smoothing and replicating that in pure Lua is going to be orders of
>> magnitude slower
>
> My main problem with the current "smoothing" is that it is a hack. It
> just averages a few of the previous samples.  On the one hand, this
> offends me as a DSP nerd, since "smoothing" should be a low-pass
> filter, with all the power math that finite-response filters involve,
> while averaging the last few samples is more of a distortion effect
> than a low-pass filter. It's something like a comb filter with a space
> between the peaks equal to the length of your averaging buffer.

It's an FIR moving average filter, which admittedly is generally only
useful if you're sampling constantly or toss the buffer between
outputting samples if there's delay between sampling sessions.
However, I think a lot of other filtering approaches, without
significant complexity, will suffer from similar issues.

Sure, it could be more complicated, or at least it could be easier to
plug in other operations if the user desires.  It could also be
described differently or operation could be adjusted so that it can
only be used as an oversampling filter.  Enabling an oversampling
mode, actually sounds like not a bad idea...

I don't think hack is entirely the right term and frankly any filter
is distortion of sampled signal.  It's just an FIR moving average
filter or boxcar filter, which has the corresponding advantages and
disadvantages of that type of filter design.

>  My feeling is that, if you have a noisy input signal that jitters
> due to noise above the sampling frequency, you should be low-pass
> filtering it in hardware, with capacitors, resistors, inductore and
> the like, to get a clean analog signal to sample with no frequency
> components above 1/2 of the sampling frequency. Sampling a raw noisy
> signal and averaging it to hide the worst of the artifacts seems like
> a kludge by comparison.

Well, it's a tradeoff.  Ideally, yes, you get your signal perfect
before presenting it to one of the pins for the mux for the ADC, but
the ADC isn't perfect either, especially in lower priced
microcontrollers.  Many of these one can't do much about aside from be
aware of the magnitude of their effect, but moving average filters can
help reduce noise for signals that aren't cleaned up and low impedance
inputs. It's only more of a "hack" than doing proper signal
conditioning in the same way that the rest of post-sampling digital
signal processing is.

Additionally, oversampling (taking N samples at a time and averaging
them), however can also increase the effective number of bits for an
ADC (http://www.atmel.com/dyn/resources/prod_documents/doc8003.pdf).
Some platforms (LM3S for example) even have hardware support for
oversampling.



>
>> (http://en.wikipedia.org/wiki/Newline)
>
> Thanks. That concludes the discussion on this point. LFCR does not
> exist, so we can dump this code and save a timer.

Well, we can use a systick or system timer to deal with CRLF vs LF vs
CR, which is what this code does.  The reason a timer is needed is to
process either the 1 or 2 char version without having the ambiguous
situation where the user provides a 1 char line ending and then the
system has to wait for the next char to decide whether it has gotten a
real line ending or not. The timer provides a window so that if it
doesn't get an LF after a CR during the inter-char limit, it assumes
it has gotten the full line ending and can then finish processing the
line.

>
>> I think a lot of problems would be solved by having a system tick timer
>> available as a resource for things like uarts, ethernet, mmcfs (which also
>> wants timeouts), and anything that needs consistent but relatively
>> coarse-grained timing intervals (running at a frequency between 10Hz and 1
>> Khz, maybe?)
>
> We have that as long as virtual timers are enabled.
> It would be better if system tick were not virtual timer-dependent,
> but existed independently, of which Vtimers would be one of the
> clients.
> Anyone who wants to refactor that in the code is very welcome.

Sounds good.  If someone else doesn't take this up, I may look into it
in the coming weeks since I'm digging around a bit while figuring out
how to support UART over USB CDC.

>
>>  Users could also get most of the timing functionality they
>> would normally derive from timers from this common facility as well.  Then
>> the remainder of timers are available for the user to select what they might
>> be consumed by: dedicated timing with the tmr module, periodic interrupts,
>> initiating scans/conversions on ADC, etc...
>
> Are you suggesting that we reserve one timer for internal purposes on
> all platforms? I'm not sure that would even be enough, since we want
> one for the system tick for coarse timing, another maybe to trigger
> arbitrary-frequency ADC conversions... should we allocate timers
> dynamically instead of presenting the user with a fixed number of
> them?  Hum, this is getting scary...

I'm not going to suggest dynamically allocating timers, aside from
what we already do, where the user is saying "use this timer for
this."  I'm just suggesting that we can take many of the things that
silently suck up one or more timers at startup and move them to a
common coarse resolution timing facility so that 1) fewer or zero
general purpose timers (replaced by systick if available) are consumed
by things like providing UART functionality 2) either way coarse
resolution timer can also be used for other arbitrary things and by
the user.

This would also be a read-only facility, so consumers of it can't
change it's count or frequency on the fly (they're determined at
compile time or boot time).

-jsnyder

>
>   M
> _______________________________________________
> 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
12