Yup, all code is in flash on AVR, so any callback would need to be a RAM-based pointer which is tested at runtime. Any implementation would eat a bit more CPU time, even if the feature is never used, just for checking the pointer.
My 2 main implementation concerns are how to allow multiple callbacks, since this is likely to be used by libraries without the user being aware, and what to do if the callback uses too much CPU time (eg, about 16200 CPU cycles).
One possible way to deal with the CPU time issue would be to re-enable interrupts before calling. A flag would need to be set, so if the timer0 interrupt happens again before it returns, no additional callbacks are made.
Enabling multiple functions needs to work. A library like Ethernet could really benefit, so it could flush partial packets after a short timeout, rather than the horribly inefficient approach of placing every call to Serial.write() into its own packet. But if a project uses Ethernet, which might use a timer callback without the user's knowledge, the user will still expect to be able to have their own callback, or use some other library which also requires a callback.
Maybe a linked list with malloc makes sense? Or maybe a small fixed size table might work?
I know 1000 Hz (actually 976 Hz) rate would be nice for some applications. But if the API offers one callback for every timer0 ISR, and if multiple callbacks can be registered, even if the functions do very little, such a scheme could quickly consume all available CPU time calling several every tick. A slower callback rate, like 244 Hz or 97.6 Hz could still be very useful.
If an application or library really needs a high rate of timer interrupts, it's best path is to commandeer one of the other timers, rather than getting a CPU-hogging callback from timer0. Several libraries do this today, and having looked at several of them, their needs are pretty specialized. I do not believe a scheme for sharing timer0 will work well for applications which need good performance.
But it would be really useful for slower things, like implementing automatic timeouts, debouncing pushbuttons, etc.
Thanks for this list. While I have pretty much no control over the official Arduino IDE and environment, I'm always looking for ideas to incorporate into Teensyduino.
Teensyduino already has #1 and #5 for, for 0022 and earlier, and also 1.0-rc1.
The F() macro and flash string support appearing in 1.0 was contributed by me, with help and input from Mikal Hard and Brian Cook, both on the Arduino developers list and in private followups. I realize the _P suffix is commonly used by avr-libc and other programs. It was discussed, but there was strong consensus it wasn't Arduino's API style. Had I gone with a _P suffix, this contribution never would have been accepted (it took many months as-is to convince the Arduino Team to merge it).
Something they did not accept, but I tried to contribute, was F() flash-string integration with the String class. So you can use F() with XYZ.print(), but not with anything that takes the newer String objects.
Teensyduino has a heavily optimized delayMicroseconds(), which works for 0 and also small values, with exactly cycle-accurate delays for the common const input case. If anyone wants to see it in Arduino, the code is available. I doubt it ever be accepted, because my coding style and extreme use of inline assembly is not consistent with Arduino's coding style. But if you want this fixed, it is indeed fixed in Teensyduino and the code is open source (after installing, look in hardware/teensy/cores/teensy).
#3 is on my serious wish-list. I worked on some elf/drawf parsing code to extract the call tree and stack framing info from the debug data inside the .elf file. It's quite tricky, and of course if recursion is detected you can't know worst-case stack use. I may never get this written, but I really, really want to have this feature, since running out of RAM really sucks.
I'm also really interested in #2, but if I develop it for Teensyduino and Arduino proper never accepts it, I wonder how much use it would ever get? The huge benefit I see is for libraries. I was considering a table of perhaps 5 or 10 callbacks, which could be triggered at something like 100 Hz (so with 10, the ISR would never need to call more than one). That way, if the user needs 1 or 2, and uses a couple libraries than each need 1 tick callback, everything would still work nicely.
I'm open to ideas on this, and there's a very good chance I'll implement it in Teensyduino at some point, but my hope is the Arduino developers can at least buy into the idea and commit to an outline of the API... so it doesn't end up being a contribution they'll never accept. (while many things I've contributed are now part of Arduino, on average most of the stuff I try to contribute never gets used... eg, look at issue #140).
Anyway, my point of this lengthy rambling post is I am indeed working on some of this stuff for Teensyduino, and a couple have been available for over a year. I generally do try to contribute my improvements back to Arduino when they're general to the hardware, but usually it takes a very long time for any contribution to be accepted into Arduino proper, and often they just sit unused indefinitely.
Joystick and Midi are available in Teensyduino, so it's probably only a matter of time until they're ported or reimplemented in Leonardo. If you have a Teensy 2.0, you can use them in Arduino now!
Audio would be really interesting. LUFA does it, with callback and/or tightly coded loops to keep up the speed..... but how would an audio stream integrate with Arduino? Would you pass blocks of samples with Mic.write(buffer, len); ? It's be really easy to get a buffer underrun.
Due to the underwhelming response, I'm not planning to work further to contribute this feature to the larger Arduino community. The source is there if anyone wants to use it, or continue to improve it and advocate its use.
If you're using Teensy, the data transfer goes pretty fast, since it's full USB speed. I recently discovered that Teensy can go even faster. It turns out much of the time is wasted waiting for operating system scheduling. I'm planning to overhaul the process to use overlapping async I/O to remove the dependency on operating system scheduling. I like things to go fast!
The process for official Arduino boards isn't under my control. In fact, with Teensyduino, I try very hard to make sure I don't accidentally alter anything about how non-Teensy boards work. That's why you need to copy that line into boards.txt to enable this.
Without more info, I can't know why it's recompiling everything.
If you're willing to try more, here's a few suggestions.
1: Can you post the verbose messages. On 1.0-beta4, enable in the preferences. On 0022, hold the shift key. The speedup only applies to "upload", not "verify".
2: Can you post your boards.txt file? There's several boards in the file, so make sure you're added this line for the board you're using.
3: Can you tell me which operating system and which board you're using? I have most combinations here. While it should work on all, I've only tested a small set of all the possible permutations (eg, only Uno and Teensy 2.0 on Windows, etc)
4: Could you reinstall Teensyduino 0.98? If you have 0.97 or earlier, there was a bug parsing the dependency files. It turns out the Windows and Mac versions have extra white space which isn't present on the Linux version.
I wrote code that cuts several seconds off the normal compile/upload time. Here's a little video I made yesterday to demonstrate.
This works much like Make, Ant and other build systems, by reusing the previously compiled files from the last time. I actually wrote this almost a year ago, but it was considered too risky to use in Arduino until more people have tested it and confirmed it really works. So the code sat unused and forgotten for almost a year!
Well, now that Arduino 1.0 is here (or will be in a few days), I'm hoping to revive this and hopefully get enough people to test so it can someday become part of Arduino.
If you're using a non-Teensy board, you'll also have to edit boards.txt. The line that enables it looks like this:
You should notice a substantial speedup compiling the same sketch. Hopefully when you switch sketches, board types, or have multiple windows open at once... stale code from one should not be used again in another.
If you give this a try, working or not, please take a moment to comment on issue 638.
If i understand you right you modify the libs so they work with Teensy that they would no longer work on an Arduino Board?
Oh no, not anything like that!! I always aim to preserve compatibility.
In fact, in the process of porting to Teensy, I often find libraries that were hard-coded to work only with the 168/328 chips. I usually add support for Arduino Mega and Sanguino too. For example, the Firmata library, which is now pre-installed on every Arduino Uno and Arduino Mega, became compatible with the Mega boards only because of my work to add a hardware abstraction layer. To get an idea of the type work I've done, take a look at libraries/Firmata/Boards.h inside your arduino-0022 directory. Several other libraries work on Arduino Mega only because of the Teensy porting effort!
I always attempt to contact the original author(s) and contribute my changes. Usually, when I can find the author's contact info, they publish the changes in a new version. In some cases, I've discovered and fixed bugs too (eg, OneWire was horribly buggy). In a few cases, it's turned out the library was pretty much abandoned code and I've become the de-facto maintainer.
Recently some of the hardware abstractions I've developed for libraries are (finally) being included into the Arduino core. Some libraries (eg, SDfat) have also made use of hardware abstractions I've proposed but haven't (yet) been accepted by the Arduino Team.
I definitely do not patch libraries to work exclusively with Teensy, and in most cases I've gone to quite a lot of extra effort to build robust hardware abstraction layers that support many boards and allow for new boards to be added easily.
Then again, some libraries are already very portable, so all I do it test and document.
But nice to see someone else had the same idea and made a central list for a 3rd party board. If you know of any way to support this application i would be happy.
I'll take a look at Ardulibrary soon. Maybe I could publish a page in the format it expects, so it could query the list I have?
Or if there's more work to create a central list, at least the work I've done so far might help. I only tend to test/port/document the "major" libraries. But a quick look at my list shows several that aren't on the 2 lists I saw mentioned in this thread.
As you can see, I still have quite a number of them to test. Usually when I add one to this list, I buy the necessary hardware - but often it sits for weeks or months due to lack of available time.
A few months ago, I added a feature to the Teensyduino installer (which automatically adds the Teensy-specific files to Arduino) to optionally install any of the tested libraries. Virtually all the libraries are only a few relatively small files. Just copying them all into installer didn't enlarge it very much, less than 1 megabyte.
Several times I considered making a java-based tool right inside the IDE - which does pretty much the same thing your nice-looking application does. The really hard part, though, is the last of a central database of all the libraries. Maybe my efforts can help, at least a bit, or I might be able to contribute in some way?
I believe you should still give the library a try.
The FreqMeasure library measures precise pulse length. If you only want to measure 1 pulse, you can do that. Just call available() and read() to discard everything measured before your pulse begins, and then available() / read() to read only your 1 pulse. After you've got the result you need, just don't bother calling the functions anymore. When you do need to make another measurement, just be sure to call them to discard any measurements it made that you don't want.
FreqMeasure will give you vastly superior results.
There's a similar library for higher frequencies. Martin Nawrath also wrote 2 very similar libraries, long before I did, and they are linked at the bottom of that page. But mine fixes a number of minor issues and offers compatibility with more hardware (including Teensy), so I'd recommend you use mine. :-)
If you really want to do this with attachInterrupt(), the bad news is any change in interrupt response latency directly introduces jitter, as you're seeing.
MarkT pointed out interrupts, and indeed the Timer0 interrupt is always enabled. Approximately every 1ms, it interrupts to run a bit of code that updates the variables used by delay(), millis(), micros(), etc.
Interrupt are also disabled by certain functions you might be using. For example, on Teensy, Serial.print() writes to a USB virtual serial port, rather than a real serial port which talks to your computer via a USB-serial converter chip. That's a lot faster, both due to USB's incredible speed, and hardware buffering. But Teensy's Serial.print() disables interrupts while copying your text into the USB packet buffers.
If the signal edge happens when interrupts are off, either due to another interrupt or normal code temporarily disabling interrupts, your interrupt handler won't run until they are enabled again.
So you could try to work this, but micros() won't work properly for more than a very short time if you shut off the Timer0's interrupt. You could try some very difficult things, like reading timer0 before and after and trying to guess if the interrupt happened and messed up your measurement. Of course, you'd anticipate when your next interrupt might happen and try to schedule any interrupt-disabling activity for times when you're not likely to get an interrupt. But that's a LOT of work, and probably prone to being unreliable at best.
The FreqMeasure library is definitely the way to go!
ps: the multiples of 4 is because micros() is using Timer0, which is configured for 1/16 of the CPU clock... so at 16 MHz you get 4 us resolution. The FreqMeasure library uses one of the other more capable timers running at the full CPU speed, so you'll get 250 ns resolution at 16 MHz.
The Minimus AVR boards are also USB device only, so they're no alternative for the USB Host Shield.
Since I'm the guy who designed Teensy and wrote Teensyduino, my opinion is obviously biased, so take this with a grain of salt....
Minimus AVR will probably only be useful if you're already pretty knowledgeable with AVR development in C and you can use Dean Camera's LUFA library. Or in other words, you're the type who tends to feel like the Arduino IDE is a toy and you want a "real" programming environment like Eclipse or direct control of the Makefiles.
As a quick sanity check (which doesn't cost anything... do this before you buy), I'd suggest you download the LED and button test program for Minimus AVR, and try to compile it yourself. It's at the bottom of this page:
Just move the .hex file somewhere safe, and delete the .elf, .o and .d files. Then try to compile it and see if you can get a new .hex file that is the same. Don't worry if the new .elf and .o files are not perfectly identical, it's the .hex that matters.
You won't find any help in the Minimus instruction manual, as it only documents how to get the .hex file onto the board. In fact, if you look at the .c file, you'll notice in the comments that it was written for the Olimex AVR-USB-162 board, not Minimus AVR. That should give you some indication of the level of documentation, example code and support you'll find for actually using Minimus for any real development.
If you're able to easily figure out how to compile the example and get the same .hex file, then maybe Minimus might work for you? Well, you might also download and peek at Dean Camera's LUFA library before buying, since that is the only code which supports Minimus. But if you get stuck and/or frustrated just compiling the blink hex file, at least you can do so without paying for a Minimus board. Even at the fire sale price, if you can't compile a .hex file, the board will be worthless (other than running .hex files made by other people... which is all Minimus was ever really made for anyway). But if you have the skill to make Minimus work, it's very cheap.
There doesn't seem to be any support for using Minimus with the Arduino IDE. Dean Camera's LUFA library is your only reasonable choice on Minimus. I'm not sure how you'd get the USB Host Shield to work... the library is built on the Arduino platform and makes good use of C++ features. Porting it to a C-based LUFA project sans Arduino stuff seems like a huge task, but at least version 2 has a very nice self-contained abstraction layer built in. If I were to try, I'd definitely focus on version 2.
I'm going to refrain from making a sales pitch for Teensy 2.0 or Teensy++ 2.0. In fact, if you're planning to use the USB Host Shield, the Arduino Uno or Arduino Mini might be a more attractive alternative, since those shields are designed to directly line up. There aren't a lot of wires to connect, as you can see in the photos of how I connected Teensy 2.0 and Teensy++ 2.0, but if you're not handy with a soldering iron and small wire, shields that just plug in or only need headers soldered are a pretty nice way to go. One bad solder joint can make all the difference between a fun project and a terribly frustrating disappointment.
Likewise, what good will that Minimus plastic box do for your project if you're going to add the USB Host Shield, or just about any other electronics?