Platform specific modules proposal

classic Classic list List threaded Threaded
10 messages Options
BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

Hi again,

As most of you know by now, our platform interface is generic enough to be
implemented by any eLua target. The unfortunate side effect of this is that
all the (potentially cool) specific features of each platform/board are left
forgotten, and there's no way to access them directly. As some (probably
most) people would gladly sacrifice portability over the possibility of
taking full advantage of their CPUs, we need to find a way to address this
need.
This is my proposal:

- every platform will have a module which name is the same as the platform
name ("lm3s" for LM3S, "stm32" for STM32, you got the picture :) )
- this module will have two types of "submodules" (for want a better term;
what I mean is that each module will be able to embed other modules inside
it):
  1. submodules with the same name as the "standard" modules. For example:
lm3s.uart, lm3s.tmr, lm3s.pio and so on. These will add to the functionality
of the "standard" modules by providing platform-specific functions.
  2. submodules that implement features found only on that platform/board.
Dado's "disp" module is a very good example of this. By having a module
"lm3s.disp" we know for sure that we're reffering to a display that can be
found on the LM3S board. This is a temporary solution, as a generic display
architecture would be a much better choice, but it's still good enough for
our needs IMO.

What say you?

Best,
Bogdan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090108/2074523c/attachment.html 

Mike Panetta Mike Panetta
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

That sounds pretty good.  I had a slightly different approach in mind, but I
am not sure how you would feel about it.  Basically the idea is we would
turn the platform interface "upside down" from what it is now.  In other
words, we would export only a (minimal compatible) Lua level interface,
instead of the current way of exporting a generic (minimal) C interface.
Each platform would be required to adhere to the minimal Lua interface (IE
define the Lua module at the platform level), but at its discretion add
additional functionality specific to that platform.

In this manner we could possibly give access to the various platform modules
in terms of functionality, like tmr.has_a(16BIT_TIMER), and,
tmr.tmr(TIMER1).capable_of(PULSE_CAPTURE). Since all timers at the top level
basically provide the same kinds of functionality (but may not export it the
same way) this very well could work.

An example usage might be something like:

16bit_timers = tmr.has_a(16BIT_TIMER) -- returns an array of static constant
'timer' objects

The above code would return 8 timer objects on the LM3S CPUs with 4 timer
modules, or 8 timer objects on an STM32F103ZE chip.

Another way to find a timer to use could be done as follows:

pwm_timers = tmr.has_a(PWM_TIMER) -- returns an array of static constant
'timer' objects

The above code on an LM3S with 4 timer modules would return 8 timer objects,
or if it were run on an STM32F103ZE, it would only return 6, since only 6 of
the timers are PWM capable.

One you have access to a timer object, you could do several queries to it
before configuring it. An example:

16bit_timers[7]:capable_of(PWM_TIMER) -- returns true if the timer is
capable of PWM operation.
16bit_timers[7]:capabilities() -- returns a bitmask of all the capabilities
for the timer.
16bit_timers[7]:has_twin() -- returns the timer object of this timers twin,
nil otherwise (for chainable timers)
16bit_timers[1]:name() -- returns the name of the timer for this platform,
if available.
16bit_timers[1]:index() -- returns the platform specific index of this
timer.

16bit_timers[1]:pair(twin) -- pairs a 16bit timer with its twin. The 2
timers (and the associated 32bit pair) must be in the 'unlocked' state.
Returns the static const 32bit timer object associated with the pair, or nil
if an error occured.

16bit_timers[1]:lock() -- Marks a timer as used, so other processes (or
coding errors) do not interrupt a timers config.
16bit_timers[1]:unlock() -- Marks a timer as free to be reconfigured for
other purposes.

16bit_timers[1]:mode(...) -- Initializes a timer for a specific mode of
operation. Timer must be in the unlocked state prior to calling this
function. Available modes dependant on capabilities exported by the timer.
See timer.capabilities(). If a requested mode is not available, an error is
thrown.

16bit_timers[1].counter -- sets or gets the 16bit timer counter register
value.
16bit_timers[1].reload -- sets or gets the 16bit timer reload register
value.


Obviously there are other functions/etc that would need to exist for a full
implementation, but thats for further discussion. :)

What do you guys think?

Mike


On Thu, Jan 8, 2009 at 4:16 PM, Bogdan Marinescu <bogdan.marinescu at gmail.com
> wrote:

> Hi again,
>
> As most of you know by now, our platform interface is generic enough to be
> implemented by any eLua target. The unfortunate side effect of this is that
> all the (potentially cool) specific features of each platform/board are left
> forgotten, and there's no way to access them directly. As some (probably
> most) people would gladly sacrifice portability over the possibility of
> taking full advantage of their CPUs, we need to find a way to address this
> need.
> This is my proposal:
>
> - every platform will have a module which name is the same as the platform
> name ("lm3s" for LM3S, "stm32" for STM32, you got the picture :) )
> - this module will have two types of "submodules" (for want a better term;
> what I mean is that each module will be able to embed other modules inside
> it):
>   1. submodules with the same name as the "standard" modules. For example:
> lm3s.uart, lm3s.tmr, lm3s.pio and so on. These will add to the functionality
> of the "standard" modules by providing platform-specific functions.
>   2. submodules that implement features found only on that platform/board.
> Dado's "disp" module is a very good example of this. By having a module
> "lm3s.disp" we know for sure that we're reffering to a display that can be
> found on the LM3S board. This is a temporary solution, as a generic display
> architecture would be a much better choice, but it's still good enough for
> our needs IMO.
>
> What say you?
>
> Best,
> Bogdan
>
>
> _______________________________________________
> Elua-dev mailing list
> Elua-dev at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/elua-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090109/2d104bf3/attachment.html 

BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

Hi,

Glad to see things are moving in this area.

On Fri, Jan 9, 2009 at 7:48 PM, Mike Panetta <panetta.mike at gmail.com> wrote:

> That sounds pretty good.  I had a slightly different approach in mind, but
> I am not sure how you would feel about it.  Basically the idea is we would
> turn the platform interface "upside down" from what it is now.  In other
> words, we would export only a (minimal compatible) Lua level interface,
> instead of the current way of exporting a generic (minimal) C interface.
> Each platform would be required to adhere to the minimal Lua interface (IE
> define the Lua module at the platform level), but at its discretion add
> additional functionality specific to that platform.


Having a generic C interface has advantages not related to Lua. For example,
writing "generic drivers" for devices like serial ADCs/DACs, or SD/MMC cards
in SPI mode. Each of these can fully benefit from the platform interface.


> In this manner we could possibly give access to the various platform
> modules in terms of functionality, like tmr.has_a(16BIT_TIMER), and,
> tmr.tmr(TIMER1).capable_of(PULSE_CAPTURE). Since all timers at the top level
> basically provide the same kinds of functionality (but may not export it the
> same way) this very well could work.


Your interface seems to be "more OOP", but IMO the code example above
doesn't make it look more useful. For example, I'm actually trying to _hide_
the fact that the platform has 8, 16 or 32 bit timers. As an eLua
programmer, I shouldn't care about that too much, as I just want to use the
timers for delays, or measuring elapsed time. Therefore, all I'd need (in an
ideal world :) ) would be "tmr.delay" and "tmr.gettimediff". Your approach
does have the advantage of hiding some platform details from the user, in
that he can actually ask the system to provide a timer that can do
PULSE_CAPTURE without having to look through the datasheet trying to figure
out which one does. This is something we should consider, but it would
require a very good feature set (by "feature" I mean something like
PULSE_CAPTURE) specified for all peripherals. Not an easy task.


> An example usage might be something like:
>
> 16bit_timers = tmr.has_a(16BIT_TIMER) -- returns an array of static
> constant 'timer' objects

The above code would return 8 timer objects on the LM3S CPUs with 4 timer
> modules, or 8 timer objects on an STM32F103ZE chip.


Please don't take this the wrong way, as it's not in anyway a critique, I'm
just curious: am I right in presumimg that you're more accustomed to desktop
programming than to embedded programming? I'm asking because you just
allocated an array of objects that would steal a bit more of that oh so
precious RAM :) You gave me an idea though: having a method called
"getcount" or something similar for each module that would return the number
of available resources of that kind could be useful.


> 16bit_timers[1]:pair(twin) -- pairs a 16bit timer with its twin. The 2
> timers (and the associated 32bit pair) must be in the 'unlocked' state.
> Returns the static const 32bit timer object associated with the pair, or nil
> if an error occured.


Another interesting problem here. 16bit_timers:pair is a very specific
method (from all the platforms I tried, LM3S is the only one able to
"concatenate" two 16-bit timer channels into a single 32-bit channel). So in
your view, the timer object would get together all the capabilities from all
the platforms inside it, thus letting any platform add any capability (which
was the original ideea, I know :) ). This has some drawbacks in my oppinion:

- potential confusion. If some on (say) AT91SAM tries to do "pair" and gets
a nil, it might not understand why at first.
- documentation issues: having to specify for each function on what platform
it works/doesn't work can be both hard to write and hard to read.
- false sense of portability: if someone sees a code that says
"16bit_timers[1]:pair(twin)" he might think something between the lines of
"cool, eLua can do pair, so I can get any board I want and enjoy this"
(let's face it: given a situation like this most people aren't going to RTFM
until it's too late :) ). But when you say:

lm3s.tmr.pair(0)
tmr.delay(0,delay)

it's a very strong hint that this code might not work on anything else than
LM3S.

16bit_timers[1]:lock() -- Marks a timer as used, so other processes (or
> coding errors) do not interrupt a timers config.
> 16bit_timers[1]:unlock() -- Marks a timer as free to be reconfigured for
> other purposes.


This, on the other hand, is a very interesting idea. Locking/unlocking
resources is gold, since you'll always know what resource you can or cannot
use. Especially important in larger applications, where it's easier to loose
track of resources. Of course, it also introduces a problem: if you call
lock(), you must remember to call unlock(). C++ coders know that this is a
problem, since they frequently forget to deallocate resources in their class
destructors (I should know :) ). Or course, in Lua you could let the garbage
collector help you, and even if you don't it's much easier to track down the
problem, so this is something to keep in minde.

Best,
Bogdan


> On Thu, Jan 8, 2009 at 4:16 PM, Bogdan Marinescu <
> bogdan.marinescu at gmail.com> wrote:
>
>> Hi again,
>>
>> As most of you know by now, our platform interface is generic enough to be
>> implemented by any eLua target. The unfortunate side effect of this is that
>> all the (potentially cool) specific features of each platform/board are left
>> forgotten, and there's no way to access them directly. As some (probably
>> most) people would gladly sacrifice portability over the possibility of
>> taking full advantage of their CPUs, we need to find a way to address this
>> need.
>> This is my proposal:
>>
>> - every platform will have a module which name is the same as the platform
>> name ("lm3s" for LM3S, "stm32" for STM32, you got the picture :) )
>> - this module will have two types of "submodules" (for want a better term;
>> what I mean is that each module will be able to embed other modules inside
>> it):
>>   1. submodules with the same name as the "standard" modules. For example:
>> lm3s.uart, lm3s.tmr, lm3s.pio and so on. These will add to the functionality
>> of the "standard" modules by providing platform-specific functions.
>>   2. submodules that implement features found only on that platform/board.
>> Dado's "disp" module is a very good example of this. By having a module
>> "lm3s.disp" we know for sure that we're reffering to a display that can be
>> found on the LM3S board. This is a temporary solution, as a generic display
>> architecture would be a much better choice, but it's still good enough for
>> our needs IMO.
>>
>> What say you?
>>
>> Best,
>> Bogdan
>>
>>
>> _______________________________________________
>> Elua-dev mailing list
>> Elua-dev at lists.berlios.de
>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>
>>
>
> _______________________________________________
> Elua-dev mailing list
> Elua-dev at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/elua-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090109/297fbeef/attachment-0001.html 

Mike Panetta Mike Panetta
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

On Fri, Jan 9, 2009 at 1:57 PM, Bogdan Marinescu <bogdan.marinescu at gmail.com
> wrote:

> Hi,
>
> Glad to see things are moving in this area.
>
> On Fri, Jan 9, 2009 at 7:48 PM, Mike Panetta <panetta.mike at gmail.com>wrote:
>
>> That sounds pretty good.  I had a slightly different approach in mind, but
>> I am not sure how you would feel about it.  Basically the idea is we would
>> turn the platform interface "upside down" from what it is now.  In other
>> words, we would export only a (minimal compatible) Lua level interface,
>> instead of the current way of exporting a generic (minimal) C interface.
>> Each platform would be required to adhere to the minimal Lua interface (IE
>> define the Lua module at the platform level), but at its discretion add
>> additional functionality specific to that platform.
>
>
> Having a generic C interface has advantages not related to Lua. For
> example, writing "generic drivers" for devices like serial ADCs/DACs, or
> SD/MMC cards in SPI mode. Each of these can fully benefit from the platform
> interface.
>

Very true.  I actually thought of that after I sent the message.  I was
thinking from a pure Lua perspective.


>
>
>
>> In this manner we could possibly give access to the various platform
>> modules in terms of functionality, like tmr.has_a(16BIT_TIMER), and,
>> tmr.tmr(TIMER1).capable_of(PULSE_CAPTURE). Since all timers at the top level
>> basically provide the same kinds of functionality (but may not export it the
>> same way) this very well could work.
>
>
> Your interface seems to be "more OOP", but IMO the code example above
> doesn't make it look more useful. For example, I'm actually trying to _hide_
> the fact that the platform has 8, 16 or 32 bit timers. As an eLua
> programmer, I shouldn't care about that too much, as I just want to use the
> timers for delays, or measuring elapsed time. Therefore, all I'd need (in an
> ideal world :) ) would be "tmr.delay" and "tmr.gettimediff". Your approach
> does have the advantage of hiding some platform details from the user, in
> that he can actually ask the system to provide a timer that can do
> PULSE_CAPTURE without having to look through the datasheet trying to figure
> out which one does. This is something we should consider, but it would
> require a very good feature set (by "feature" I mean something like
> PULSE_CAPTURE) specified for all peripherals. Not an easy task.
>

Oh, but timers can do so much more then just generate delays.  This is why I
proposed such a flexible interface.  As for caring what functionality a
platform has, IMO, since this is an embedded system and users would be
writing software that is closer to the hardware, I would argue that an eLua
user *would* want to know if the timer was 8, 16, or 32 bits.  Even if they
are just doing delays, that knowledge would be invaluable in that it could
tell you minimum timer resolution and maximum timeout values.


>
>
>> An example usage might be something like:
>>
>> 16bit_timers = tmr.has_a(16BIT_TIMER) -- returns an array of static
>> constant 'timer' objects
>
> The above code would return 8 timer objects on the LM3S CPUs with 4 timer
>> modules, or 8 timer objects on an STM32F103ZE chip.
>
>
> Please don't take this the wrong way, as it's not in anyway a critique, I'm
> just curious: am I right in presumimg that you're more accustomed to desktop
> programming than to embedded programming? I'm asking because you just
> allocated an array of objects that would steal a bit more of that oh so
> precious RAM :) You gave me an idea though: having a method called
> "getcount" or something similar for each module that would return the number
> of available resources of that kind could be useful.
>

Yes actually I have done quite a bit, but in C and not Lua, where an array
would take up less space.  Remember I specified that the array members are
static constant objects (could be your rotable, or just light userdata
preallocated in rom), so the only space used would be for the array itself,
which could be forceably destroyed after its done being used by calling the
garbage collector.  The table is basically just a function table so it need
no dynamic storage itself.


>
>
>> 16bit_timers[1]:pair(twin) -- pairs a 16bit timer with its twin. The 2
>> timers (and the associated 32bit pair) must be in the 'unlocked' state.
>> Returns the static const 32bit timer object associated with the pair, or nil
>> if an error occured.
>
>
> Another interesting problem here. 16bit_timers:pair is a very specific
> method (from all the platforms I tried, LM3S is the only one able to
> "concatenate" two 16-bit timer channels into a single 32-bit channel). So in
> your view, the timer object would get together all the capabilities from all
> the platforms inside it, thus letting any platform add any capability (which
> was the original ideea, I know :) ). This has some drawbacks in my oppinion:
>

STM32 will allow this, and I believe some Coldfire processors can as well.


>
>
> - potential confusion. If some on (say) AT91SAM tries to do "pair" and gets
> a nil, it might not understand why at first.
>

Calling pair on a channel that does not support pairing is invalid. ;) I
would assume that users of the interface would use the capabilities
functionality to query channels before performing operations on them.


>
> - documentation issues: having to specify for each function on what
> platform it works/doesn't work can be both hard to write and hard to read.
>

Possibly, but thats why the capabilities functionality exists. I really love
self documenting code. ;)


>
> - false sense of portability: if someone sees a code that says
> "16bit_timers[1]:pair(twin)" he might think something between the lines of
> "cool, eLua can do pair, so I can get any board I want and enjoy this"
> (let's face it: given a situation like this most people aren't going to RTFM
> until it's too late :) ). But when you say:
>
> lm3s.tmr.pair(0)
> tmr.delay(0,delay)
>
> it's a very strong hint that this code might not work on anything else than
> LM3S.
>

Very true, but I assume that the users of eLua know something about the
hardware they are using (after all they have to at least know what pins the
timers connect to!) and are familliar enough with embedded systems
programming to know that all platforms are not created equal. :)


>
>
> 16bit_timers[1]:lock() -- Marks a timer as used, so other processes (or
>> coding errors) do not interrupt a timers config.
>> 16bit_timers[1]:unlock() -- Marks a timer as free to be reconfigured for
>> other purposes.
>
>
> This, on the other hand, is a very interesting idea. Locking/unlocking
> resources is gold, since you'll always know what resource you can or cannot
> use. Especially important in larger applications, where it's easier to loose
> track of resources. Of course, it also introduces a problem: if you call
> lock(), you must remember to call unlock(). C++ coders know that this is a
> problem, since they frequently forget to deallocate resources in their class
> destructors (I should know :) ). Or course, in Lua you could let the garbage
> collector help you, and even if you don't it's much easier to track down the
> problem, so this is something to keep in minde.
>

In my mind the timers object(s) will be eternal and never be collected,
there for the unlock method must be explicitly called.  The reason for this
is the "set it and forget it" mode of operation used for some operations.
If your using a timer to generate a 10KHz square wave you only need to
configure the timer once, and then leave it alone for the duration of the
program. At the same time you don't want some other piece of code
reconfiguring the timer, nor do you want the timer to be reset when it goes
out of program scope.

The other reason to have the timers be eternal objects is you can set them
up in your startup code and then drop the reference, later on in another Lua
thread, ISR (not yet maybe?), or coroutine you can then reget that timer
object from the system and manipulate it without ever having to pass the
object around.

Also, real harware is eternal, how many times have you used a CPU that had a
timer that disappeared when you forgot it was there? ;)

Basically I envision a timer to be lock()ed whenever its being used, even if
its not currently referenced in any code in the current scope, and
unlock()ed if the timer is idle and free to be retasked to do something
else.


>
> Best,
> Bogdan
>

Thanks for the discussion on this, I think if we keep this up we will end up
with quite a robust code base!

Thanks,
Mike


>
>
>
>> On Thu, Jan 8, 2009 at 4:16 PM, Bogdan Marinescu <
>> bogdan.marinescu at gmail.com> wrote:
>>
>>> Hi again,
>>>
>>> As most of you know by now, our platform interface is generic enough to
>>> be implemented by any eLua target. The unfortunate side effect of this is
>>> that all the (potentially cool) specific features of each platform/board are
>>> left forgotten, and there's no way to access them directly. As some
>>> (probably most) people would gladly sacrifice portability over the
>>> possibility of taking full advantage of their CPUs, we need to find a way to
>>> address this need.
>>> This is my proposal:
>>>
>>> - every platform will have a module which name is the same as the
>>> platform name ("lm3s" for LM3S, "stm32" for STM32, you got the picture :) )
>>> - this module will have two types of "submodules" (for want a better
>>> term; what I mean is that each module will be able to embed other modules
>>> inside it):
>>>   1. submodules with the same name as the "standard" modules. For
>>> example: lm3s.uart, lm3s.tmr, lm3s.pio and so on. These will add to the
>>> functionality of the "standard" modules by providing platform-specific
>>> functions.
>>>   2. submodules that implement features found only on that
>>> platform/board. Dado's "disp" module is a very good example of this. By
>>> having a module "lm3s.disp" we know for sure that we're reffering to a
>>> display that can be found on the LM3S board. This is a temporary solution,
>>> as a generic display architecture would be a much better choice, but it's
>>> still good enough for our needs IMO.
>>>
>>> What say you?
>>>
>>> Best,
>>> Bogdan
>>>
>>>
>>> _______________________________________________
>>> Elua-dev mailing list
>>> Elua-dev at lists.berlios.de
>>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>>
>>>
>>
>> _______________________________________________
>> Elua-dev mailing list
>> Elua-dev at lists.berlios.de
>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>
>>
>
> _______________________________________________
> Elua-dev mailing list
> Elua-dev at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/elua-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090109/7ecc5a1e/attachment.html 

BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

> Oh, but timers can do so much more then just generate delays.  This is why
> I proposed such a flexible interface.  As for caring what functionality a
> platform has, IMO, since this is an embedded system and users would be
> writing software that is closer to the hardware, I would argue that an eLua
> user *would* want to know if the timer was 8, 16, or 32 bits.  Even if they
> are just doing delays, that knowledge would be invaluable in that it could
> tell you minimum timer resolution and maximum timeout values.
>

You're right, timers can do much more than just generate delays, I was
simplifying to make a point, the same principle applies to any timer
operation. As for your idea that the users would want to know what kind of
hardware they're using, I could argue that since they're doing that, they
might as well know if their timers can do capture or not :), so querying for
capabilities becomes kinda redundant in this context. And for
minimum/maximum timer resolution, we already have
tmr.getmindelay/tmr.getmaxdelay. Which are much more useful in this
particular situation, since knowing if a timer is 8/16/32 bits tells only
half of the story, you'd also need the timer frequency and a calculator
somewhere :) This is why I still stand by my initial point, which I'd like
to reformulate a bit: yes, the user should know his platform, he just
shouldn't care that much about it. To me it's more natural to call functions
like "getmindelay" that completely hide the hardware (and allow for other
neat stuff, like the virtual timers that I implemented recently) than to try
to figure this out from the hardware. After all, Lua is a high level
language, and although the programmer does indeed use it at a level that's
very close to the hardware, he might not want to feel this. Much like most C
programmer out there don't want to feel that there's some assembly code
lurking in the shadows of their beautifully intended code blocks :)


> Yes actually I have done quite a bit, but in C and not Lua, where an array
> would take up less space.  Remember I specified that the array members are
> static constant objects (could be your rotable, or just light userdata
> preallocated in rom), so the only space used would be for the array itself,
> which could be forceably destroyed after its done being used by calling the
> garbage collector.  The table is basically just a function table so it need
> no dynamic storage itself.
>

Ah, OK, I got it now. You're right, with my patch this doesn't add at all to
the RAM consumption.

STM32 will allow this, and I believe some Coldfire processors can as well.
>

But you probably still agree that most micros don't allow you to do this.

Calling pair on a channel that does not support pairing is invalid. ;) I
> would assume that users of the interface would use the capabilities
> functionality to query channels before performing operations on them.
>

This is the thing that I dislike the most in your approach: the continous
query/execute operation. It kinda reminds me of COM :), but this is not the
main reason I dislike it, it's because I find it very tiring to write code
in this way (asking if you can do something before you actually do it; I
like more the "bad boy" approach: do it directly. Also less safe, it's also
much easier to code IMO). And again, I think this contradicts with the idea
of "the user must know his hardware", in the sense that the query
capabilities step becomes unnecessary.


> Possibly, but thats why the capabilities functionality exists. I really
> love self documenting code. ;)
>

I understand, and I think this is an important difference in our coding
styles. I too like self-documenting code, but to the point where
self-documentation becomes a purpose in itself, thus altering the code too
much.


>
>
>> - false sense of portability: if someone sees a code that says
>> "16bit_timers[1]:pair(twin)" he might think something between the lines of
>> "cool, eLua can do pair, so I can get any board I want and enjoy this"
>> (let's face it: given a situation like this most people aren't going to RTFM
>> until it's too late :) ). But when you say:
>>
>> lm3s.tmr.pair(0)
>> tmr.delay(0,delay)
>>
>> it's a very strong hint that this code might not work on anything else
>> than LM3S.
>>
>
> Very true, but I assume that the users of eLua know something about the
> hardware they are using (after all they have to at least know what pins the
> timers connect to!) and are familliar
>
enough with embedded systems programming to know that all platforms are not
> created equal. :)
>

So, mister self-documenting guy :), don't you think that:

lm3s.tmr.pair(0)
tmr.delay(0, us)

is more self documenting than:

timers[0].pair(0).delay(us) (or something similar)? :P

In my mind the timers object(s) will be eternal and never be collected,
> there for the unlock method must be explicitly called.  The reason for this
> is the "set it and forget it" mode of operation used for some operations.
> If your using a timer to generate a 10KHz square wave you only need to
> configure the timer once, and then leave it alone for the duration of the
> program. At the same time you don't want some other piece of code
> reconfiguring the timer, nor do you want the timer to be reset when it goes
> out of program scope.
>

Very true, and this is why I liked the idea very much. You do have another
approach in this case(which is used by my virtual timers implementation): if
a timer is dedicated to a specific set of operations and you don't want it
disturbed, simply don't expose it to the Lua interface.


> The other reason to have the timers be eternal objects is you can set them
> up in your startup code and then drop the reference, later on in another Lua
> thread, ISR (not yet maybe?), or coroutine you can then reget that timer
> object from the system and manipulate it without ever having to pass the
> object around.
>

You can already do this in the current implementation, as it uses univeral
IDs that are usable from anywhere in the code.
And yes, we'll have ISRs written directly in Lua (not sure this is what you
meant, but I thought I'll mention it anyway :) ).


> Also, real harware is eternal, how many times have you used a CPU that had
> a timer that disappeared when you forgot it was there? ;)
>

I'd rather not answer this :D


> Basically I envision a timer to be lock()ed whenever its being used, even
> if its not currently referenced in any code in the current scope, and
> unlock()ed if the timer is idle and free to be retasked to do something
> else.
>

And this is why your idea seems so good. I'll think of a nice, generic way
to implement it.


> Thanks for the discussion on this, I think if we keep this up we will end
> up with quite a robust code base!
>

So it seems! Thank you too.

Best,
Bogdan


>
>>
>>
>>
>>> On Thu, Jan 8, 2009 at 4:16 PM, Bogdan Marinescu <
>>> bogdan.marinescu at gmail.com> wrote:
>>>
>>>> Hi again,
>>>>
>>>> As most of you know by now, our platform interface is generic enough to
>>>> be implemented by any eLua target. The unfortunate side effect of this is
>>>> that all the (potentially cool) specific features of each platform/board are
>>>> left forgotten, and there's no way to access them directly. As some
>>>> (probably most) people would gladly sacrifice portability over the
>>>> possibility of taking full advantage of their CPUs, we need to find a way to
>>>> address this need.
>>>> This is my proposal:
>>>>
>>>> - every platform will have a module which name is the same as the
>>>> platform name ("lm3s" for LM3S, "stm32" for STM32, you got the picture :) )
>>>> - this module will have two types of "submodules" (for want a better
>>>> term; what I mean is that each module will be able to embed other modules
>>>> inside it):
>>>>   1. submodules with the same name as the "standard" modules. For
>>>> example: lm3s.uart, lm3s.tmr, lm3s.pio and so on. These will add to the
>>>> functionality of the "standard" modules by providing platform-specific
>>>> functions.
>>>>   2. submodules that implement features found only on that
>>>> platform/board. Dado's "disp" module is a very good example of this. By
>>>> having a module "lm3s.disp" we know for sure that we're reffering to a
>>>> display that can be found on the LM3S board. This is a temporary solution,
>>>> as a generic display architecture would be a much better choice, but it's
>>>> still good enough for our needs IMO.
>>>>
>>>> What say you?
>>>>
>>>> Best,
>>>> Bogdan
>>>>
>>>>
>>>> _______________________________________________
>>>> Elua-dev mailing list
>>>> Elua-dev at lists.berlios.de
>>>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>>>
>>>>
>>>
>>> _______________________________________________
>>> Elua-dev mailing list
>>> Elua-dev at lists.berlios.de
>>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>>
>>>
>>
>> _______________________________________________
>> Elua-dev mailing list
>> Elua-dev at lists.berlios.de
>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>
>>
>
> _______________________________________________
> Elua-dev mailing list
> Elua-dev at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/elua-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090109/414323cd/attachment.html 

Mike Panetta Mike Panetta
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

On Fri, Jan 9, 2009 at 3:01 PM, Bogdan Marinescu <bogdan.marinescu at gmail.com
> wrote:

>
>
>> Oh, but timers can do so much more then just generate delays.  This is why
>> I proposed such a flexible interface.  As for caring what functionality a
>> platform has, IMO, since this is an embedded system and users would be
>> writing software that is closer to the hardware, I would argue that an eLua
>> user *would* want to know if the timer was 8, 16, or 32 bits.  Even if they
>> are just doing delays, that knowledge would be invaluable in that it could
>> tell you minimum timer resolution and maximum timeout values.
>>
>
> You're right, timers can do much more than just generate delays, I was
> simplifying to make a point, the same principle applies to any timer
> operation. As for your idea that the users would want to know what kind of
> hardware they're using, I could argue that since they're doing that, they
> might as well know if their timers can do capture or not :), so querying for
> capabilities becomes kinda redundant in this context. And for
> minimum/maximum timer resolution, we already have
> tmr.getmindelay/tmr.getmaxdelay. Which are much more useful in this
> particular situation, since knowing if a timer is 8/16/32 bits tells only
> half of the story, you'd also need the timer frequency and a calculator
> somewhere :) This is why I still stand by my initial point, which I'd like
> to reformulate a bit: yes, the user should know his platform, he just
> shouldn't care that much about it. To me it's more natural to call functions
> like "getmindelay" that completely hide the hardware (and allow for other
> neat stuff, like the virtual timers that I implemented recently) than to try
> to figure this out from the hardware. After all, Lua is a high level
> language, and although the programmer does indeed use it at a level that's
> very close to the hardware, he might not want to feel this. Much like most C
> programmer out there don't want to feel that there's some assembly code
> lurking in the shadows of their beautifully intended code blocks :)
>

Hmm, I think I understand where your coming from now.  I guess I am just the
kind of guy that likes to get down to the nitty gritty some times. :)

Maybe it would be possible to have it both ways? The reason its needed is
because if someone wanted to use the timer as a PWM generator knowing the
counter width is necessary... Unless everything is done in time units, in
which case while it might be odd for the PWM case, I think every other case
it would be more natural for, IE: pulse width measurements,  pulse
generation, frequency generation, etc...

Maybe you are turning me in your direction on this one ;)


>
>
>> Yes actually I have done quite a bit, but in C and not Lua, where an array
>> would take up less space.  Remember I specified that the array members are
>> static constant objects (could be your rotable, or just light userdata
>> preallocated in rom), so the only space used would be for the array itself,
>> which could be forceably destroyed after its done being used by calling the
>> garbage collector.  The table is basically just a function table so it need
>> no dynamic storage itself.
>>
>
> Ah, OK, I got it now. You're right, with my patch this doesn't add at all
> to the RAM consumption.
>
> STM32 will allow this, and I believe some Coldfire processors can as well.
>>
>
> But you probably still agree that most micros don't allow you to do this.
>

Yeah, well definately most of the smaller ones.  Maybe pairing could be
dropped and made 'automatic' then.  Its definately not a required feature
for the interface.


>
>
> Calling pair on a channel that does not support pairing is invalid. ;) I
>> would assume that users of the interface would use the capabilities
>> functionality to query channels before performing operations on them.
>>
>
> This is the thing that I dislike the most in your approach: the continous
> query/execute operation. It kinda reminds me of COM :), but this is not the
> main reason I dislike it, it's because I find it very tiring to write code
> in this way (asking if you can do something before you actually do it; I
> like more the "bad boy" approach: do it directly. Also less safe, it's also
> much easier to code IMO). And again, I think this contradicts with the idea
> of "the user must know his hardware", in the sense that the query
> capabilities step becomes unnecessary.
>

You can still do it the 'dangerous' way with this methodology, there is
nothing keeping you from plugging random things in to the code. ;)  If thats
the case we could remove the query interface completely, but still have the
request channels by type and mode interfaces. Oh, and you only have to ask
once, or not at all if you already know what it can do.

Also, having the query interface makes it possible to write a simple Lua
script that can run on *any* CPU that spewes all the available hardware and
what capabilities it has, for the more novice user. For that alone I think
it would be invaluable. Imagine being able to hand a student an embedded CPU
board and this Lua script, and in 5 minutes they know all the capabilities
of the CPU that Lua has access to.  They could even print the results (hell
we could generate a PDF with them and inclue it in the source) so they would
never have to do a query again.  If they forget for some reason what
capabilities a particular module has, all they have to do is run a simple
script to refresh their memory, never having to look at the documentation
again!  Since I am the kind of person that *hates* having to leave his code
editor, this is an awsome feature.


>
>
>> Possibly, but thats why the capabilities functionality exists. I really
>> love self documenting code. ;)
>>
>
> I understand, and I think this is an important difference in our coding
> styles. I too like self-documenting code, but to the point where
> self-documentation becomes a purpose in itself, thus altering the code too
> much.
>

Nothing is altered, if you already know the capabilities of the hardware,
dont run the query.


>
>
>
>>
>>
>>>
>>>
>> Very true, but I assume that the users of eLua know something about the
>> hardware they are using (after all they have to at least know what pins the
>> timers connect to!) and are familliar
>>
> enough with embedded systems programming to know that all platforms are not
>> created equal. :)
>>
>
> So, mister self-documenting guy :), don't you think that:
>
> lm3s.tmr.pair(0)
> tmr.delay(0, us)
>
> is more self documenting than:
>
> timers[0].pair(0).delay(us) (or something similar)? :P
>

Not really.  The only difference between the two for my eyes is that one is
meant to run on an lm3s CPU and the other can run on anything that supports
timer pairing.  The second is actually cleaner, because if you wanted to
write portable code you would not have to have things like if (cpu.type() ==
"lm3s") do ... everywhere (assuming you knew that every platform you want to
run it on supports timer pairing).


>
>
> Very true, and this is why I liked the idea very much. You do have another
> approach in this case(which is used by my virtual timers implementation): if
> a timer is dedicated to a specific set of operations and you don't want it
> disturbed, simply don't expose it to the Lua interface.
>

But what if you want to use it in Lua, just not have other Lua tasks be able
to use it?


>
> Also, real harware is eternal, how many times have you used a CPU that had
>> a timer that disappeared when you forgot it was there? ;)
>>
>
> I'd rather not answer this :D
>

Of course, it was meant to be silly. :)


>
>
>
>> Basically I envision a timer to be lock()ed whenever its being used, even
>> if its not currently referenced in any code in the current scope, and
>> unlock()ed if the timer is idle and free to be retasked to do something
>> else.
>>
>
> And this is why your idea seems so good. I'll think of a nice, generic way
> to implement it.
>
>
>> Thanks for the discussion on this, I think if we keep this up we will end
>> up with quite a robust code base!
>>
>
> So it seems! Thank you too.
>

Lets keep it up!  I would like others to join too though. :)  Also, this
need not be confined to a timer interface, I was just thinking of the most
complex peripheral I could use as an example. Technically these ideas should
apply to anything.


>
> Best,
> Bogdan
>

Thanks,
Mike


>
>
>
>>
>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090109/b1dbeabe/attachment.html 

jbsnyder jbsnyder
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

In reply to this post by BogdanM

On Jan 9, 2009, at 2:01 PM, Bogdan Marinescu wrote:

>
> Oh, but timers can do so much more then just generate delays.  This  
> is why I proposed such a flexible interface.  As for caring what  
> functionality a platform has, IMO, since this is an embedded system  
> and users would be writing software that is closer to the hardware,  
> I would argue that an eLua user *would* want to know if the timer  
> was 8, 16, or 32 bits.  Even if they are just doing delays, that  
> knowledge would be invaluable in that it could tell you minimum  
> timer resolution and maximum timeout values.
>
> You're right, timers can do much more than just generate delays, I  
> was simplifying to make a point, the same principle applies to any  
> timer operation. As for your idea that the users would want to know  
> what kind of hardware they're using, I could argue that since  
> they're doing that, they might as well know if their timers can do  
> capture or not :), so querying for capabilities becomes kinda  
> redundant in this context. And for minimum/maximum timer resolution,  
> we already have tmr.getmindelay/tmr.getmaxdelay. Which are much more  
> useful in this particular situation, since knowing if a timer is  
> 8/16/32 bits tells only half of the story, you'd also need the timer  
> frequency and a calculator somewhere :) This is why I still stand by  
> my initial point, which I'd like to reformulate a bit: yes, the user  
> should know his platform, he just shouldn't care that much about it.  
> To me it's more natural to call functions like "getmindelay" that  
> completely hide the hardware (and allow for other neat stuff, like  
> the virtual timers that I implemented recently) than to try to  
> figure this out from the hardware. After all, Lua is a high level  
> language, and although the programmer does indeed use it at a level  
> that's very close to the hardware, he might not want to feel this.  
> Much like most C programmer out there don't want to feel that  
> there's some assembly code lurking in the shadows of their  
> beautifully intended code blocks :)

This brings up some basic issues with abstraction.  Recently I've had  
the (not so great, because of the platform) privilege of helping some  
students work with Basic Stamp for projects they were working on that  
involved some servos.  A quick and easy way to control these is using  
the PULSOUT command.  During the project a few of them had their  
boards burn out and they were replaced with ones at higher clock  
rates, and what I found out was that the values being used with  
PULSOUT were directly tied to clock rate, so they had to guess at the  
ranges needed to control the servos.  To me this represents a bad  
tradeoff of "knowing your hardware," especially with something geared  
towards accessibility for beginners.  On the other hand, with Arduino,  
this is handled completely differently, the hardware details are  
completely abstracted away.  One passes angles for the servo instead  
of pulse length related to clock cycles or even millisecond length.  
What's bizarre about this is that Arduino basically uses C, and  
compiles down to AVR assembler, and Basic Stamp is interpreted.

Abstraction, almost much by definition, is limiting in some way. The  
benefits one gets are in making something easier, that otherwise would  
not have been.  In some cases you might want direct access to how the  
timers are implemented and set things yourself.  One major downside to  
this is that it's annoying to port, and may make for rather messy  
implementations.  If you switch to another micro because it's a bit  
faster or has hardware support for something that was previously being  
emulated, you might have to tweak all of your magic numbers over  
again.  In order to get around this you might also end up building  
some sort of abstraction in Lua instead of C.  If the feature is  
useful in many cases, perhaps the module should be extended, while  
keeping the abstraction consistent, to include the feature.  If the  
feature is a one off, you could still write your own custom module in  
C.  I think it would be nicer to keep the Lua side of the interface  
generally the same across platforms where possible, with the exception  
of the platform specific modules.

One other thought though:  If a feature, on some platforms, requires  
emulation, and that emulation is particularly expensive over a full  
hardware implementation, it might be nice to know if eLua is using  
that in emulation rather than in hardware.  Perhaps this could somehow  
be tied in with the pd module, either in the form of a list of  
hardware supported features, like when one looks at /proc/cpuinfo on  
linux, or something else?

Just a few thoughts.

--
James Snyder
Biomedical Engineering
Northwestern University
jbsnyder at fanplastic.org
http://fanplastic.org/key.txt
ph: (847) 644-2322

-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090109/e116674c/attachment-0001.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 194 bytes
Desc: This is a digitally signed message part
Url : https://lists.berlios.de/pipermail/elua-dev/attachments/20090109/e116674c/attachment-0001.pgp 

Alex Babkin Alex Babkin
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

Very interesting discussion!

I think James summarized the debate quite nicely. You just cannot have your
cake and eat it in this situation.
I personally see that there are important values on both sides of the
debate: standardizing things makes it easy and seamless to jump from one
specific HW platform to another, while having Mike's check/execute mechanism
would allow extracting best potential from the specifics of particular HW
platform.
In fact, i am convinced that both of these are needed.

Here are some thoughts about this after reading the debate:
   why not have 2 levels of abstraction the following way:
   - Mike's idea of check/execute mechanism will be the lower level and
implemented directly in C
   - Bogdan's more generic and "worry-less" interface will be the upper
level and *implemented in Lua*, and built *on top* of the Mike's layer
interfacing to it with the check/execute mechanism. This extra level of
abstraction will be HW specific just like Mike's layer, this is necessary as
the items in Bogdan's generic layer will depend on default configuration
details of the specific HW platform (i.e best default timer would be a 32bit
one on a platform that has 32bit timers, and 16bit on a platform that only
has 16bit timers, etc)

Example: Bogdan's layer implements a generic timer abstraction. This layer
queries Mike's layer for types of timers available (of which Mike's layer is
aware of) using a standardized querying mechanism, and also knows how to
determine the best type for the default timer that would be used in Bogdan's
layer as the default timer. Mike's layer knows how to supply hooks to
various types of timers' actions that Bogdan's layer understands how to use.

What this solves: A user who wants to use a generic timer, goes ahead with
the standard (Bogdan's) timer abstraction and doesn't concern oneself with
details like various checks (as Bogdan's layer takes care of all these
details in ways specific to particular HW platform)
A more advanced user, who wants to be "closer to the metal", will use Mike's
layer directly

Potential gotchas and disadvantages:
- two layers instead of one, albeit only one layer is implemented in C, the
other one is all Lua.
- Mike's check/execute mechanism has to be standardized
- two sets of standards to maintain.


Hope this helps somewhat
Alex


On Fri, Jan 9, 2009 at 4:22 PM, James Snyder <jbsnyder at fanplastic.org>wrote:

>
> On Jan 9, 2009, at 2:01 PM, Bogdan Marinescu wrote:
>
>
>
>> Oh, but timers can do so much more then just generate delays.  This is why
>> I proposed such a flexible interface.  As for caring what functionality a
>> platform has, IMO, since this is an embedded system and users would be
>> writing software that is closer to the hardware, I would argue that an eLua
>> user *would* want to know if the timer was 8, 16, or 32 bits.  Even if they
>> are just doing delays, that knowledge would be invaluable in that it could
>> tell you minimum timer resolution and maximum timeout values.
>>
>
> You're right, timers can do much more than just generate delays, I was
> simplifying to make a point, the same principle applies to any timer
> operation. As for your idea that the users would want to know what kind of
> hardware they're using, I could argue that since they're doing that, they
> might as well know if their timers can do capture or not :), so querying for
> capabilities becomes kinda redundant in this context. And for
> minimum/maximum timer resolution, we already have
> tmr.getmindelay/tmr.getmaxdelay. Which are much more useful in this
> particular situation, since knowing if a timer is 8/16/32 bits tells only
> half of the story, you'd also need the timer frequency and a calculator
> somewhere :) This is why I still stand by my initial point, which I'd like
> to reformulate a bit: yes, the user should know his platform, he just
> shouldn't care that much about it. To me it's more natural to call functions
> like "getmindelay" that completely hide the hardware (and allow for other
> neat stuff, like the virtual timers that I implemented recently) than to try
> to figure this out from the hardware. After all, Lua is a high level
> language, and although the programmer does indeed use it at a level that's
> very close to the hardware, he might not want to feel this. Much like most C
> programmer out there don't want to feel that there's some assembly code
> lurking in the shadows of their beautifully intended code blocks :)
>
>
> This brings up some basic issues with abstraction.  Recently I've had the
> (not so great, because of the platform) privilege of helping some students
> work with Basic Stamp for projects they were working on that involved some
> servos.  A quick and easy way to control these is using the PULSOUT command.
>  During the project a few of them had their boards burn out and they were
> replaced with ones at higher clock rates, and what I found out was that the
> values being used with PULSOUT were directly tied to clock rate, so they had
> to guess at the ranges needed to control the servos.  To me this represents
> a bad tradeoff of "knowing your hardware," especially with something geared
> towards accessibility for beginners.  On the other hand, with Arduino, this
> is handled completely differently, the hardware details are completely
> abstracted away.  One passes angles for the servo instead of pulse length
> related to clock cycles or even millisecond length.  What's bizarre about
> this is that Arduino basically uses C, and compiles down to AVR assembler,
> and Basic Stamp is interpreted.
>
> Abstraction, almost much by definition, is limiting in some way. The
> benefits one gets are in making something easier, that otherwise would not
> have been.  In some cases you might want direct access to how the timers are
> implemented and set things yourself.  One major downside to this is that
> it's annoying to port, and may make for rather messy implementations.  If
> you switch to another micro because it's a bit faster or has hardware
> support for something that was previously being emulated, you might have to
> tweak all of your magic numbers over again.  In order to get around this you
> might also end up building some sort of abstraction in Lua instead of C.  If
> the feature is useful in many cases, perhaps the module should be extended,
> while keeping the abstraction consistent, to include the feature.  If the
> feature is a one off, you could still write your own custom module in C.  I
> think it would be nicer to keep the Lua side of the interface generally the
> same across platforms where possible, with the exception of the platform
> specific modules.
>
> One other thought though:  If a feature, on some platforms, requires
> emulation, and that emulation is particularly expensive over a full hardware
> implementation, it might be nice to know if eLua is using that in emulation
> rather than in hardware.  Perhaps this could somehow be tied in with the pd
> module, either in the form of a list of hardware supported features, like
> when one looks at /proc/cpuinfo on linux, or something else?
>
> Just a few thoughts.
>
> --
> James Snyder
> Biomedical Engineering
> Northwestern University
> jbsnyder at fanplastic.org
> http://fanplastic.org/key.txt
> ph: (847) 644-2322
>
>
> _______________________________________________
> Elua-dev mailing list
> Elua-dev at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/elua-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090109/b2f739e6/attachment.html 

BogdanM BogdanM
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

OK, so let's summarize: most people see a benefit in both approaches (Mike's
and main),  and I'm one of them :). So let's try to find the best of both
worlds here.

What Alex proposed is OK and looks very good from an abstraction point of
view, but I don't want to add another layer to eLua. I'm really trying to
keep eLua's design principles in line with Lua's: simple, minimalistic even,
yet completely functional.

What I like most in this thread is Mike's idea about keeping capabilities,
also what I dislike most is his idea about explicitly querying for the
forementioned capabilities :) What if we skip the query step? After all, our
backend already knows the capabilities, so the programmer can simply ask for
what he needs and get an object ID in return. An example:

*local uart_id, errmsg = uart.get{ speed = uart.SPEED_115200, flowctrl =
uart.HW, mode = uart.M8N1, type = uart.RS485}
-- check for errors here
uart.send( uart_id, ... ) -- use the rest of the platform interface as usual
.............................................
uart.unlock( uart_id ) -- we're done with this UART
*
Of course, the query still happens, but this time is not explicit (as it
happens automagically in the backend), and I think this makes life much
easier for the end user. It can also take care of the locking/unlocking
mechanism that Mike proposed.

I'd like to have something like this in eLua, but it requires a very good
understanding of all the attributes of all the peripherals from all the
platforms, which is not something that should be taken lightly (in fact I
think it's something quite difficult).

And James, what happened in BasicStamp will never happen in eLua, unless of
course aliens those pesy aliens FINALLY manage to take control of my mind
and modify the code for their evil purposes :) The platform interface will
ALWAYS use standard units (hertz, microseconds, stuff like this).

Best,
Bogdan

On Sat, Jan 10, 2009 at 12:40 AM, Alex Babkin <ababkin at gmail.com> wrote:

> Very interesting discussion!
>
> I think James summarized the debate quite nicely. You just cannot have your
> cake and eat it in this situation.
> I personally see that there are important values on both sides of the
> debate: standardizing things makes it easy and seamless to jump from one
> specific HW platform to another, while having Mike's check/execute mechanism
> would allow extracting best potential from the specifics of particular HW
> platform.
> In fact, i am convinced that both of these are needed.
>
> Here are some thoughts about this after reading the debate:
>    why not have 2 levels of abstraction the following way:
>    - Mike's idea of check/execute mechanism will be the lower level and
> implemented directly in C
>    - Bogdan's more generic and "worry-less" interface will be the upper
> level and *implemented in Lua*, and built *on top* of the Mike's layer
> interfacing to it with the check/execute mechanism. This extra level of
> abstraction will be HW specific just like Mike's layer, this is necessary as
> the items in Bogdan's generic layer will depend on default configuration
> details of the specific HW platform (i.e best default timer would be a 32bit
> one on a platform that has 32bit timers, and 16bit on a platform that only
> has 16bit timers, etc)
>
> Example: Bogdan's layer implements a generic timer abstraction. This layer
> queries Mike's layer for types of timers available (of which Mike's layer is
> aware of) using a standardized querying mechanism, and also knows how to
> determine the best type for the default timer that would be used in Bogdan's
> layer as the default timer. Mike's layer knows how to supply hooks to
> various types of timers' actions that Bogdan's layer understands how to use.
>
> What this solves: A user who wants to use a generic timer, goes ahead with
> the standard (Bogdan's) timer abstraction and doesn't concern oneself with
> details like various checks (as Bogdan's layer takes care of all these
> details in ways specific to particular HW platform)
> A more advanced user, who wants to be "closer to the metal", will use
> Mike's layer directly
>
> Potential gotchas and disadvantages:
> - two layers instead of one, albeit only one layer is implemented in C, the
> other one is all Lua.
> - Mike's check/execute mechanism has to be standardized
> - two sets of standards to maintain.
>
>
> Hope this helps somewhat
> Alex
>
>
> On Fri, Jan 9, 2009 at 4:22 PM, James Snyder <jbsnyder at fanplastic.org>wrote:
>
>>
>> On Jan 9, 2009, at 2:01 PM, Bogdan Marinescu wrote:
>>
>>
>>
>>> Oh, but timers can do so much more then just generate delays.  This is
>>> why I proposed such a flexible interface.  As for caring what functionality
>>> a platform has, IMO, since this is an embedded system and users would be
>>> writing software that is closer to the hardware, I would argue that an eLua
>>> user *would* want to know if the timer was 8, 16, or 32 bits.  Even if they
>>> are just doing delays, that knowledge would be invaluable in that it could
>>> tell you minimum timer resolution and maximum timeout values.
>>>
>>
>> You're right, timers can do much more than just generate delays, I was
>> simplifying to make a point, the same principle applies to any timer
>> operation. As for your idea that the users would want to know what kind of
>> hardware they're using, I could argue that since they're doing that, they
>> might as well know if their timers can do capture or not :), so querying for
>> capabilities becomes kinda redundant in this context. And for
>> minimum/maximum timer resolution, we already have
>> tmr.getmindelay/tmr.getmaxdelay. Which are much more useful in this
>> particular situation, since knowing if a timer is 8/16/32 bits tells only
>> half of the story, you'd also need the timer frequency and a calculator
>> somewhere :) This is why I still stand by my initial point, which I'd like
>> to reformulate a bit: yes, the user should know his platform, he just
>> shouldn't care that much about it. To me it's more natural to call functions
>> like "getmindelay" that completely hide the hardware (and allow for other
>> neat stuff, like the virtual timers that I implemented recently) than to try
>> to figure this out from the hardware. After all, Lua is a high level
>> language, and although the programmer does indeed use it at a level that's
>> very close to the hardware, he might not want to feel this. Much like most C
>> programmer out there don't want to feel that there's some assembly code
>> lurking in the shadows of their beautifully intended code blocks :)
>>
>>
>> This brings up some basic issues with abstraction.  Recently I've had the
>> (not so great, because of the platform) privilege of helping some students
>> work with Basic Stamp for projects they were working on that involved some
>> servos.  A quick and easy way to control these is using the PULSOUT command.
>>  During the project a few of them had their boards burn out and they were
>> replaced with ones at higher clock rates, and what I found out was that the
>> values being used with PULSOUT were directly tied to clock rate, so they had
>> to guess at the ranges needed to control the servos.  To me this represents
>> a bad tradeoff of "knowing your hardware," especially with something geared
>> towards accessibility for beginners.  On the other hand, with Arduino, this
>> is handled completely differently, the hardware details are completely
>> abstracted away.  One passes angles for the servo instead of pulse length
>> related to clock cycles or even millisecond length.  What's bizarre about
>> this is that Arduino basically uses C, and compiles down to AVR assembler,
>> and Basic Stamp is interpreted.
>>
>> Abstraction, almost much by definition, is limiting in some way. The
>> benefits one gets are in making something easier, that otherwise would not
>> have been.  In some cases you might want direct access to how the timers are
>> implemented and set things yourself.  One major downside to this is that
>> it's annoying to port, and may make for rather messy implementations.  If
>> you switch to another micro because it's a bit faster or has hardware
>> support for something that was previously being emulated, you might have to
>> tweak all of your magic numbers over again.  In order to get around this you
>> might also end up building some sort of abstraction in Lua instead of C.  If
>> the feature is useful in many cases, perhaps the module should be extended,
>> while keeping the abstraction consistent, to include the feature.  If the
>> feature is a one off, you could still write your own custom module in C.  I
>> think it would be nicer to keep the Lua side of the interface generally the
>> same across platforms where possible, with the exception of the platform
>> specific modules.
>>
>> One other thought though:  If a feature, on some platforms, requires
>> emulation, and that emulation is particularly expensive over a full hardware
>> implementation, it might be nice to know if eLua is using that in emulation
>> rather than in hardware.  Perhaps this could somehow be tied in with the pd
>> module, either in the form of a list of hardware supported features, like
>> when one looks at /proc/cpuinfo on linux, or something else?
>>
>> Just a few thoughts.
>>
>>   --
>> James Snyder
>> Biomedical Engineering
>> Northwestern University
>> jbsnyder at fanplastic.org
>> http://fanplastic.org/key.txt
>> ph: (847) 644-2322
>>
>>
>> _______________________________________________
>> Elua-dev mailing list
>> Elua-dev at lists.berlios.de
>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>
>>
>
> _______________________________________________
> Elua-dev mailing list
> Elua-dev at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/elua-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090113/582ff765/attachment.html 

Mike Panetta Mike Panetta
Reply | Threaded
Open this post in threaded view
|

Platform specific modules proposal

This sounds great to me.  A perfect compromise. I agree with the attributes
not being taken lightly, but I think if we can split them in to smaller
sections we would be ok.

Mike

On Tue, Jan 13, 2009 at 1:34 PM, Bogdan Marinescu <
bogdan.marinescu at gmail.com> wrote:

> OK, so let's summarize: most people see a benefit in both approaches
> (Mike's and main),  and I'm one of them :). So let's try to find the best of
> both worlds here.
>
> What Alex proposed is OK and looks very good from an abstraction point of
> view, but I don't want to add another layer to eLua. I'm really trying to
> keep eLua's design principles in line with Lua's: simple, minimalistic even,
> yet completely functional.
>
> What I like most in this thread is Mike's idea about keeping capabilities,
> also what I dislike most is his idea about explicitly querying for the
> forementioned capabilities :) What if we skip the query step? After all, our
> backend already knows the capabilities, so the programmer can simply ask for
> what he needs and get an object ID in return. An example:
>
> *local uart_id, errmsg = uart.get{ speed = uart.SPEED_115200, flowctrl =
> uart.HW, mode = uart.M8N1, type = uart.RS485}
> -- check for errors here
> uart.send( uart_id, ... ) -- use the rest of the platform interface as
> usual
> .............................................
> uart.unlock( uart_id ) -- we're done with this UART
> *
> Of course, the query still happens, but this time is not explicit (as it
> happens automagically in the backend), and I think this makes life much
> easier for the end user. It can also take care of the locking/unlocking
> mechanism that Mike proposed.
>
> I'd like to have something like this in eLua, but it requires a very good
> understanding of all the attributes of all the peripherals from all the
> platforms, which is not something that should be taken lightly (in fact I
> think it's something quite difficult).
>
> And James, what happened in BasicStamp will never happen in eLua, unless of
> course aliens those pesy aliens FINALLY manage to take control of my mind
> and modify the code for their evil purposes :) The platform interface will
> ALWAYS use standard units (hertz, microseconds, stuff like this).
>
> Best,
> Bogdan
>
>
> On Sat, Jan 10, 2009 at 12:40 AM, Alex Babkin <ababkin at gmail.com> wrote:
>
>> Very interesting discussion!
>>
>> I think James summarized the debate quite nicely. You just cannot have
>> your cake and eat it in this situation.
>> I personally see that there are important values on both sides of the
>> debate: standardizing things makes it easy and seamless to jump from one
>> specific HW platform to another, while having Mike's check/execute mechanism
>> would allow extracting best potential from the specifics of particular HW
>> platform.
>> In fact, i am convinced that both of these are needed.
>>
>> Here are some thoughts about this after reading the debate:
>>    why not have 2 levels of abstraction the following way:
>>    - Mike's idea of check/execute mechanism will be the lower level and
>> implemented directly in C
>>    - Bogdan's more generic and "worry-less" interface will be the upper
>> level and *implemented in Lua*, and built *on top* of the Mike's layer
>> interfacing to it with the check/execute mechanism. This extra level of
>> abstraction will be HW specific just like Mike's layer, this is necessary as
>> the items in Bogdan's generic layer will depend on default configuration
>> details of the specific HW platform (i.e best default timer would be a 32bit
>> one on a platform that has 32bit timers, and 16bit on a platform that only
>> has 16bit timers, etc)
>>
>> Example: Bogdan's layer implements a generic timer abstraction. This layer
>> queries Mike's layer for types of timers available (of which Mike's layer is
>> aware of) using a standardized querying mechanism, and also knows how to
>> determine the best type for the default timer that would be used in Bogdan's
>> layer as the default timer. Mike's layer knows how to supply hooks to
>> various types of timers' actions that Bogdan's layer understands how to use.
>>
>> What this solves: A user who wants to use a generic timer, goes ahead with
>> the standard (Bogdan's) timer abstraction and doesn't concern oneself with
>> details like various checks (as Bogdan's layer takes care of all these
>> details in ways specific to particular HW platform)
>> A more advanced user, who wants to be "closer to the metal", will use
>> Mike's layer directly
>>
>> Potential gotchas and disadvantages:
>> - two layers instead of one, albeit only one layer is implemented in C,
>> the other one is all Lua.
>> - Mike's check/execute mechanism has to be standardized
>> - two sets of standards to maintain.
>>
>>
>> Hope this helps somewhat
>> Alex
>>
>>
>> On Fri, Jan 9, 2009 at 4:22 PM, James Snyder <jbsnyder at fanplastic.org>wrote:
>>
>>>
>>> On Jan 9, 2009, at 2:01 PM, Bogdan Marinescu wrote:
>>>
>>>
>>>
>>>> Oh, but timers can do so much more then just generate delays.  This is
>>>> why I proposed such a flexible interface.  As for caring what functionality
>>>> a platform has, IMO, since this is an embedded system and users would be
>>>> writing software that is closer to the hardware, I would argue that an eLua
>>>> user *would* want to know if the timer was 8, 16, or 32 bits.  Even if they
>>>> are just doing delays, that knowledge would be invaluable in that it could
>>>> tell you minimum timer resolution and maximum timeout values.
>>>>
>>>
>>> You're right, timers can do much more than just generate delays, I was
>>> simplifying to make a point, the same principle applies to any timer
>>> operation. As for your idea that the users would want to know what kind of
>>> hardware they're using, I could argue that since they're doing that, they
>>> might as well know if their timers can do capture or not :), so querying for
>>> capabilities becomes kinda redundant in this context. And for
>>> minimum/maximum timer resolution, we already have
>>> tmr.getmindelay/tmr.getmaxdelay. Which are much more useful in this
>>> particular situation, since knowing if a timer is 8/16/32 bits tells only
>>> half of the story, you'd also need the timer frequency and a calculator
>>> somewhere :) This is why I still stand by my initial point, which I'd like
>>> to reformulate a bit: yes, the user should know his platform, he just
>>> shouldn't care that much about it. To me it's more natural to call functions
>>> like "getmindelay" that completely hide the hardware (and allow for other
>>> neat stuff, like the virtual timers that I implemented recently) than to try
>>> to figure this out from the hardware. After all, Lua is a high level
>>> language, and although the programmer does indeed use it at a level that's
>>> very close to the hardware, he might not want to feel this. Much like most C
>>> programmer out there don't want to feel that there's some assembly code
>>> lurking in the shadows of their beautifully intended code blocks :)
>>>
>>>
>>> This brings up some basic issues with abstraction.  Recently I've had the
>>> (not so great, because of the platform) privilege of helping some students
>>> work with Basic Stamp for projects they were working on that involved some
>>> servos.  A quick and easy way to control these is using the PULSOUT command.
>>>  During the project a few of them had their boards burn out and they were
>>> replaced with ones at higher clock rates, and what I found out was that the
>>> values being used with PULSOUT were directly tied to clock rate, so they had
>>> to guess at the ranges needed to control the servos.  To me this represents
>>> a bad tradeoff of "knowing your hardware," especially with something geared
>>> towards accessibility for beginners.  On the other hand, with Arduino, this
>>> is handled completely differently, the hardware details are completely
>>> abstracted away.  One passes angles for the servo instead of pulse length
>>> related to clock cycles or even millisecond length.  What's bizarre about
>>> this is that Arduino basically uses C, and compiles down to AVR assembler,
>>> and Basic Stamp is interpreted.
>>>
>>> Abstraction, almost much by definition, is limiting in some way. The
>>> benefits one gets are in making something easier, that otherwise would not
>>> have been.  In some cases you might want direct access to how the timers are
>>> implemented and set things yourself.  One major downside to this is that
>>> it's annoying to port, and may make for rather messy implementations.  If
>>> you switch to another micro because it's a bit faster or has hardware
>>> support for something that was previously being emulated, you might have to
>>> tweak all of your magic numbers over again.  In order to get around this you
>>> might also end up building some sort of abstraction in Lua instead of C.  If
>>> the feature is useful in many cases, perhaps the module should be extended,
>>> while keeping the abstraction consistent, to include the feature.  If the
>>> feature is a one off, you could still write your own custom module in C.  I
>>> think it would be nicer to keep the Lua side of the interface generally the
>>> same across platforms where possible, with the exception of the platform
>>> specific modules.
>>>
>>> One other thought though:  If a feature, on some platforms, requires
>>> emulation, and that emulation is particularly expensive over a full hardware
>>> implementation, it might be nice to know if eLua is using that in emulation
>>> rather than in hardware.  Perhaps this could somehow be tied in with the pd
>>> module, either in the form of a list of hardware supported features, like
>>> when one looks at /proc/cpuinfo on linux, or something else?
>>>
>>> Just a few thoughts.
>>>
>>>   --
>>> James Snyder
>>> Biomedical Engineering
>>> Northwestern University
>>> jbsnyder at fanplastic.org
>>> http://fanplastic.org/key.txt
>>> ph: (847) 644-2322
>>>
>>>
>>> _______________________________________________
>>> Elua-dev mailing list
>>> Elua-dev at lists.berlios.de
>>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>>
>>>
>>
>> _______________________________________________
>> Elua-dev mailing list
>> Elua-dev at lists.berlios.de
>> https://lists.berlios.de/mailman/listinfo/elua-dev
>>
>>
>
> _______________________________________________
> Elua-dev mailing list
> Elua-dev at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/elua-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.berlios.de/pipermail/elua-dev/attachments/20090113/f71a9fac/attachment-0001.html