ivanseidel / DueTimer

⏳ Timer Library fully implemented for Arduino DUE
MIT License
212 stars 89 forks source link

DueTimer Library v2.0 #20

Open ivanseidel opened 11 years ago

ivanseidel commented 11 years ago

Here is the place to discuss the enchancements of the library for the v2.0

Key things that will be created/changed:

ivanseidel commented 11 years ago

Here is my proposed UML diagram for the new Library version:

duetimer

@pklaus @colombod

colombod commented 11 years ago

Sounds great

the only thing I'd do is not to have the class name as DueTime but actually have a namespace Due and keep the Class Name As Timer

so the include would look like

#include <timer.h> // whatever , this is where the base class is define
namespace Due{
class Time : public virtual BaseTimer{
public:
    .
};
}

When I use that timer i make use i sue the correct namepsace.

#include <due/Timer.h>

Due::Timer* ptr_myTiler;

or using namespace Due;

What do you think?

On 9 Jun 2013, at 21:55, Ivan Seidel notifications@github.com wrote:

Here is my proposed UML diagram for the new Library version:

@pklaus @colombod

— Reply to this email directly or view it on GitHub.


Diego Colombo PhD

ivanseidel commented 11 years ago

Sounds great the only thing I'd do is not to have the class name as DueTime but actually have a namespace Due and keep the Class Name As Timer so the include would look like #include // whatever , this is where the base class is define namespace Due{ class Time : public virtual BaseTimer{ public: . . . }; } When I use that timer i make use i sue the correct namepsace. #include <due/Timer.h> Due::Timer* ptr_myTiler; or using namespace Due; What do you think?

The only problem is that the Library should be "easy" to use. Implementing C++ namespaces stuff will require more knowledge from the users.

Because Arduino is made to be simple, it wouldn't be the simplest way of doing. I like to use namespaces as you said, but not for this kind of library...

colombod commented 11 years ago

Not sure about arduino being simple to use. The IDE is quite naive and anything else is quite complicated because involves being familiar with make files and the underlying tool chain. The current state of tools and education of the arduino user base encourage to one of the practices that scares me the most : copy paste of code between projects.

I do not see any harm or too high complexity into using namespace to minimise the risk of name collision, which is pretty serious problem in languages as c and cpp due to no real type system at runtime. Python is also a great example of how having namespace is useful to keep all thing tidy. And python user base goes from hobbyist to research passing for financial institution.

But I will be happy with the guidelines you want to take since this is your project and I am happy to be a contributor here.

Just if we could avoid that name for the concrete arduino due class:)

I am really looking forward for the new start to I can also integrate your new designed library in the project I am doing for mUBreeze.

Ready to start when you are !

On 9 Jun 2013, at 22:34, Ivan Seidel notifications@github.com wrote:

Sounds great the only thing I'd do is not to have the class name as DueTime but actually have a namespace Due and keep the Class Name As Timer so the include would look like #include // whatever , this is where the base class is define namespace Due{ class Time : public virtual BaseTimer{ public: . . . }; } When I use that timer i make use i sue the correct namepsace. #include Due::Timer* ptr_myTiler; or using namespace Due; What do you think?

The only problem is that the Library should be "easy" to use. Implementing C++ namespaces stuff will require more knowledge from the users.

Because Arduino is made to be simple, it wouldn't be the simple as it can be. In my opinion, I like to use namespaces as you said, but not for this kind of library...

— Reply to this email directly or view it on GitHub.

pklaus commented 11 years ago

@ivanseidel OK, here's what I think about the UML draft:

Your CounterTimer class inherits from DueTimer which in turn inherits from BaseTimer. Thus, the CounterTimer class will also have the methods attachInterrupt(), detachInterrupt(), setFrequency(), setPeriod(), getFrequency(), getPeriod() which are all function that you don't need when using the CounterTimer class (OK, I can think of some usage scenarios where you might like to use the attached interrupt.) Would you make all those functions private then? Sounds kind of strange to inherit first and then make all methods private (not to use them internally but to hide them).

The thing is: From the hardware point of view, the Timer Counter blocks as described in the datasheet are built around a 32-bit counter. This is the central piece of hardware that you have to use in order to create a timer or to measure frequency, or to create a hardware PWM, etc. The requirements of your use case define how to configure this counter and the multiplexers around it. For example, to create a timer, you have to configure the clock input of the counter to be one of the predefined system clocks. Or to create an event counter you would connect it the counter's clock input to an external pin signal.

I'm convinced that having classes that really represent the underlying hardware will enable developers to easily derive classes with new application specific behaviour. What's important for the users, is the API of our high-level classes DueTimer, DuePWM, etc. Thus the API of those classes should be defined in an interface and that interface could be made as similar to existing libraries as possible.

I propose the following:

duetimercounter_uml_v1 1

@colombod As far as namespaces are concerned, I'm not sure it will help much in this case. On the Arduino we don't live in a wold of easily separable software cubicles. We all share the same hardware. So when you implement the Timers in your code and implement the callbacks for their IRQ routines, you're the only one who can use them... OK, still namespaces are a good concept but when you look at the Arduino-provided functions and classes I think that what our user base is most familiar with are no namespaces.

colombod commented 11 years ago

The diagram looks great. Don't worry about my point of view. But you put Due in front of every class :) sounds like a call for namespaces to me but I am fine whatever naming convention you want to go for. Can you imagine all classes in stl being stdstring etc :)

Let's get this started and it is going to be great !

Apple teaches it : educate your user base :)

Looking forward to the next version of this great library.

On 11 Jun 2013, at 11:33, Philipp Klaus notifications@github.com wrote:

@ivanseidel OK, here's what I think about the UML draft:

Your CounterTimer class inherits from DueTimer which in turn inherits from BaseTimer. Thus, the CounterTimer class will also have the methods attachInterrupt(), detachInterrupt(), setFrequency(), setPeriod(), getFrequency(), getPeriod() which are all function that you don't need when using the CounterTimer class (OK, I can think of some usage scenarios where you might like to use the attached interrupt.) Would you make all those functions private then? Sounds kind of strange to inherit first and then make all methods private (not to use them internally but to hide them).

The thing is: From the hardware point of view, the Timer Counter blocks as described in the datasheet are built around a 32-bit counter. This is the central piece of hardware that you have to use in order to create a timer or to measure frequency, or to create a hardware PWM, etc. The requirements of your use case define how to configure this counter and the multiplexers around it. For example, to create a timer, you have to configure the clock input of the counter to be one of the predefined system clocks. Or to create an event counter you would connect it the counter's clock input to an external pin signal.

I'm convinced that having classes that really represent the underlying hardware will enable developers to easily derive classes with new application specific behaviour. What's important for the users, is the API of our high-level classes DueTimer, DuePWM, etc. Thus the API of those classes should be defined in an interface and that interface could be made as similar to existing libraries as possible.

I propose the following:

@colombod As far as namespaces are concerned, I'm not sure it will help much in this case. On the Arduino we don't live in a wold of easily separable software cubicles. We all share the same hardware. So when you implement the Timers in your code and implement the callbacks for their IRQ routines, you're the only one who can use them... OK, still namespaces are a good concept but when you look at the Arduino-provided functions and classes I think that what our user base is most familiar with are no namespaces.

— Reply to this email directly or view it on GitHub.

ivanseidel commented 11 years ago

In OO, sometimes we just leave a method not being used, however, changing a public method to private or protected (a more restrict type than the father) is not possible.

But, what I tought about, when inheriting methods attachInterrupt and detachInterrupt is to be able to set a custom callback on the PWM class, IF there is no routed output for the selected pin.

So the logic is:

  1. The selected pin to output PWM is an Hardware pin?
  2. Yes: then route it correcly
  3. No: create a custom callback to turn ON and OFF the pin.

It will not be That fast, since we are using a Software timer. However, Servo library from atmega328 use exacly this: creating a simple timer and changing the output via software.

In that way, we would require a attachInterrupt and an detachInterrupt on the father, to register those callbacks.

I'm even thinking about implementing setDutyCycle on BaseTimer, since it can be helpfull on others classes.

My core idea is: Make a FULL interface, with all posible methods of configuring the PWM form of the Timer, Interrupts. Even we NOT using all of those methods our childs, we will be able to do it.

Implementing interfaces for each of the main "things" (Servo, PWM, TimerInterrupt, Counter...) is essential for extensions and others developers/coders to make use of our library.

Usualy, I name interfaces with the Base name before. For eg.: BaseTimer, BaseCounter...

Also, we should keep in mind that: This Library MUST work with others plataforms. To do so, interfaces are perfect for us. If we are using the word "Due" in front of the class, is JUST to show that we are mplementing the Due part of the library. But, i belive that would be fine to drop that name, and use only Servo, TimerInterrupt...

In that way, on compilation time we check the plataform, and include the correct code, and NOTHING will change.

colombod commented 11 years ago

Makes sense

On 11 Jun 2013, at 12:26, Ivan Seidel notifications@github.com wrote:

In OO, sometimes we just leave a method not being used, however, changing a public method to private or protected (a more restrict type than the father) is not possible.

But, what I tought about, when inheriting methods attachInterrupt and detachInterrupt is to be able to set a custom callback on the PWM class, IF there is no routed output for the selected pin.

So the logic is:

The selected pin to output PWM is an Hardware pin? Yes: then route it correcly No: create a custom callback to turn ON and OFF the pin. It will not be That fast, since we are using a Software timer. However, Servo library from atmega328 use exacly this: creating a simple timer and changing the output via software.

In that way, we would require a attachInterrupt and an detachInterrupt on the father, to register those callbacks.

I'm even thinking about implementing setDutyCycle on BaseTimer, since it can be helpfull on others classes.

My core idea is: Make a FULL interface, with all posible methods of configuring the PWM form of the Timer, Interrupts. Even we NOT using all of those methods our childs, we will be able to do it.

Implementing interfaces for each of the main "things" (Servo, PWM, TimerInterrupt, Counter...) is essential for extensions and others developers/coders to make use of our library.

Usualy, I name interfaces with the Base name before. For eg.: BaseTimer,

— Reply to this email directly or view it on GitHub.

pklaus commented 11 years ago

In OO, sometimes we just leave a method not being used, however, changing a public method to private or protected (a more restrict type than the father) is not possible.

Off course you can: See this C++ OOP tutorial and scroll through to Hiding functionality.

But, what I tought about, when inheriting methods attachInterrupt and detachInterrupt is to be able to set a custom callback on the PWM class, IF there is no routed output for the selected pin.

OK, so we need to attach callbacks in the PWM class. that's fine. But we still don't need them in the Counter class.

So the logic is:

The selected pin to output PWM is an Hardware pin?
Yes: then route it correcly
No: create a custom callback to turn ON and OFF the pin.

It will not be That fast, since we are using a Software timer. However, Servo library from atmega328 use exacly this: creating a simple timer and changing the output via software.

Yes, this is also how it's done by cmaglie's Servo2 lib. It only uses callback functions for the PWM (to support any pin).

In that way, we would require a attachInterrupt and an detachInterrupt on the father, to register those callbacks.

True.

I'm even thinking about implementing setDutyCycle on BaseTimer, since it can be helpfull on others classes.

I think that any interface should have a clean and well defined API. See it as a contract between you and your users.

My core idea is: Make a FULL interface, with all posible methods of configuring the PWM form of the Timer, Interrupts. Even we NOT using all of those methods our childs, we will be able to do it.

Does this not contradict your previous statement about avoiding "a class with thousands of methods"?

Implementing interfaces for each of the main "things" (Servo, PWM, TimerInterrupt, Counter...) is essential for extensions and others developers/coders to make use of our library.

True. And in order to let them quickly understand what's going on in our code, its structure should be logical. In digital electronics, controlling a servo is based on pulse width modulation. A pulse width modulation can be implemented by programming a timer. That timer can be built by using a counter together with a clock source. This order should be reflected in our inheritance model. Otherwise you will get clutter all over the place like methods where they don't belong...

Usualy, I name interfaces with the Base name before. For eg.: BaseTimer, BaseCounter...

Also, we should keep in mind that: This Library MUST work with others plataforms. To do so, interfaces are perfect for us. If we are using the word "Due" in front of the class, is JUST to show that we are mplementing the Due part of the library. But, i belive that would be fine to drop that name, and use only Servo, TimerInterrupt...

In that way, on compilation time we check the plataform, and include the correct code, and NOTHING will change.

As I read it this library was initially called ARMtimer. I see the chance that this library could be adopted to newer boards that may follow the Arduino Due (also based on the ARM SAM platform). If we want to go on and use the library format 1.5, we should move the implementation files to the subfolder ./arch/sam/. But I don't see it coming that this library will every work on the older AVR boards. Therefore the old name was probably not too bad, it could also have been SAMtimer. But as we add PWM, Servo and more functionality, the Timer part of the name may become confusing.

So from my point of view I think it's fine to drop the Due from the class names. We should make it clear in the README and the description though that this project is for the Due and possibly future boards to come.

ivanseidel commented 11 years ago

Off course you can: See this C++ OOP tutorial and scroll through to Hiding functionality.

But is not cool to do that (it's a workaround). Imagine: you pass an object of class A, or B that extends A. You require at least A to be passed, meaning that: You require at least ALL functionality of A, extras doesen't matter.

Hiding/removing/encapsulating a method or atribute on another class would result on a crash in runtime (witch is not cool, and that's why Java doesen't allows it, only permiting you to make the method/atribute less restrict, but not more restrict than the father...)

Attaching a callback to a counter might be needed, to create a software counter (in case of exceeding all the counters, or for example: you have to counters with the same Timer, with the same frequency.

Perhaps, what we really should do, is to make all methods private, and make it public acordingly to what the class does.

Eg.: PWM class will inherit from Timer class, and BasePWM interface. However, attachInterrupts, setDutyCycle... are protected on the father class, then, it will become public and do properly implementation.

One other thing, why shouldn't we attach an interrupt on a TimerCounter? Perhaps, you want to count AND to call a function. Or, on PWM, why not setting up a PWM with low frequency, and call a function on the Edges...

I understand your point, about keeping it clean. I belive that the fewer the methods, the better. But key things such as: Set frequency and duty cycle and callbacks is the base of the Timer.

What do you think?

colombod commented 11 years ago

How about multiple inheritance done safe ? It is like the categories in objective c. That way we can partition the functionalities on block of interface and the time we inherit more than one class we implement them. If course on this scenario base classes needs to put all pure virtual.

Dr Diego Colombo PhD

On 11 Jun 2013, at 20:19, Ivan Seidel notifications@github.com wrote:

Off course you can: See this C++ OOP tutorial and scroll through to Hiding functionality.

But is not cool to do that (it's a workaround). Imagine: you pass an object of class A, or B that extends A. You require at least A to be passed, meaning that: You require at least ALL functionality of A, extras doesen't matter.

Hiding/removing/encapsulating a method or atribute on another class would result on a crash in runtime (witch is not cool, and that's why Java doesen't allows it, only permiting you to make the method/atribute less restrict, but not more restrict than the father...)

Attaching a callback to a counter might be needed, to create a software counter (in case of exceeding all the counters, or for example: you have to counters with the same Timer, with the same frequency.

Perhaps, what we really should do, is to make all methods private, and make it public acordingly to what the class does.

Eg.: PWM class will inherit from Timer class, and BasePWM interface. However, attachInterrupts, setDutyCycle... are protected on the father class, then, it will become public and do properly implementation.

One other thing, why shouldn't we attach an interrupt on a TimerCounter? Perhaps, you want to count AND to call a function. Or, on PWM, why not setting up a PWM with low frequency, and call a function on the Edges...

I understand your point, about keeping it clean. I belive that the fewer the methods, the better. But key things such as: Set frequency and duty cycle and callbacks is the base of the Timer.

What do you think?

— Reply to this email directly or view it on GitHub.

ivanseidel commented 11 years ago

A little old, but still up the idea of a new Generic Version... I'm finishing up some new Libraries and would be great if this was implemented.

@colombod and @pklaus

colombod commented 11 years ago

Yes still interested !

Dr Diego Colombo PhD

On 5 Sep 2013, at 01:01, Ivan Seidel notifications@github.com wrote:

A little old, but still up the idea of a new Generic Version... I'm finishing up some new Libraries and would be great if this was implemented.

@colombod and @pklaus

— Reply to this email directly or view it on GitHub.

LowFly2 commented 11 years ago

I'm interested too , in TimerCounter

ammoniak commented 10 years ago

Is it possible to integrate ADC functionality? I.e. trigger ADC readings using the TC (this is supported by the ADC/timer hardware)

ivanseidel commented 10 years ago

Hi ammoniak,

It is possible, but in the moment I'm not thinking about implementing those features...

But fell free to do it, and send to us the updated version =)

Ivan

Ivan Seidel Gomes http://TendaDigital.net

2014-08-26 8:18 GMT-03:00 ammoniak notifications@github.com:

Is it possible to integrate ADC functionality? I.e. trigger ADC readings using the TC (this is supported by the ADC/timer hardware)

— Reply to this email directly or view it on GitHub https://github.com/ivanseidel/DueTimer/issues/20#issuecomment-53405670.

Oegtsgeest commented 9 years ago

Hi Ivan Nice library. But I ran into problem with my Due. I need a timer of about 2000Hz (e.g.yours) and various external button controlled interrupts. If I attach the external interrupts the timer does not work any more but only gives one shot of one of the external interrupts. Is there a way for example to use " attachInterrupt(Button_51, btn51Interrupt, RISING); " and " Timer.getAvailable().attachInterrupt(myHandler).setFrequency(2000).start(); " together?

ivanseidel commented 9 years ago

hello @Oegtsgeest, This seems like an interruption priority problem. When you say "only gives one shot", means that the your interruption is not being called again, or, that your cold hangs up?

Oegtsgeest commented 9 years ago

Thx for yr quick reply. Yes indeed it had to to with priorities. Thanks to your lead i solved the issue.

edwardanoliefo commented 8 years ago

Hi , can you help me with a simple sketch for the library. I intoduced it in my code and it has display poblem. Thanks

edwardanoliefo commented 8 years ago

Hi. I have fixed the problem. Thanks

vigneshr92 commented 7 years ago

Hi Ivan. I am using your Timer library for the Due. But when I have a complex code running within the Timer Interrupt Service Routine and I try print data serially I do not get it printed when I use the Serial.print within the ISR. But when I print the data in the loop function I get data but still all the processes are running within the Timer's ISR. Do you understand why I am facing this ?? Please suggest