I had an extra copy of the old version of digitalWriteFast.h in another folder within the Library folder. That one was getting used instead of the one that I was modifying. All 3 boards work with the new digitalWriteFast now, when I use the current (arduino 21) wiring.h and wiring_digital.c

When I try to change to the version of those core files that I built a few days ago, digitalWriteFast does not cooperate with them. I will struggle with that at least a little longer before I repost code.

It isn't absolutely critical that I get the two things to work together but it would be nice.

Last night the compiler and I couldn't agree on the exact syntax. the Xcode editor I was using wouldn't help balance the last few }'s.

Surprisingly, this morning the Arduino IDE editor agrees with how I thought the }'s balanced. I broke it up by splitting out atomicWrite this morning but it seems obvious a cast of some sort is missing and I won't test it now.

Handling issue 146 will further diverge performance on ports above F, which already required more code. It struck me overnight that this MIGHT be a reason for continued existence of digitalWriteFast beyond implementation of faster digitalWrite in the core. After all, the vast majority of code I write does not turn the interrupt on. Worth some thought.

It also strikes me that I should probably create test code for whether issue 146 is solved. Maybe I can just add Tone to my current test programs, or something like that. I need something that will generate interrupts 10-1000 times per second, I think. If anyone understands how to write that, or can point me to a forum item I would appreciate that.

Handling issue 146 will further diverge performance on ports above F, which already required more code. It struck me overnight that this MIGHT be a reason for continued existence of digitalWriteFast beyond implementation of faster digitalWrite in the core. After all, the vast majority of code I write does not turn the interrupt on. Worth some thought.

It also strikes me that I should probably create test code for whether issue 146 is solved. Maybe I can just add Tone to my current test programs, or something like that. I need something that will generate interrupts 10-1000 times per second, I think. If anyone understands how to write that, or can point me to a forum item I would appreciate that.

Ah... issue #146. (I was the one that asked Paul to post this bug)

There should be no need to write & run test code to see if this is resolved.Either the foreground bit set/clear operations are atomic or theyaren't. A simple code inspection can determine this.(Ideally, look at the assembler output, it will be obvious)

I recommend code inspection over test code because it is super easy and because with test code there is no guarantee that the exact timing scenario will ever exist to create a problem.

Keep in mind that ensuring that the i/o operation is atomicis not about protecting bits set/cleared in registers by the users foreground (loop) code from being interrupted by interrupt code, it is about protecting the bits set/cleared by the other code done in interrupt routines from the users foreground (loop) code.

It does not matter if the user does not have anycode that runs as an interrupt. It will be his foreground (loop) codethat clobbers the bits set/cleared/used by the interrupt routine.The users foreground (loop) code i/o operations will always complete and work flawlessly with or without the atomic code masking

And so Ironically, the code that runs at interrupt level like the servo library code does not need to have the additional code overhead of masking/clearing interrupts to make the operation "atomic" since the code is running at interrupt level, it is by definition atomic butthe foreground (loop) code running must have it, if they share thesame i/o register.

And that is the dilemma, sometimes you need the extra code overheadto ensure the operation is atomic and sometimes you don't needit to still have atomicity, and yet other times, you may not need atomicity at all.The problem is the only time you can be ensured that you don't needit, is if the code is part of an interrupt routine.

In my view, ALL the i/o operations need to be atomic.Anything else, doesn't really work, and eventually will causeproblems.Yes there are situations where you can be guaranteed that theadditional code to mask/restore interrupt masks isn't needed butthose are only in interrupts routines which are typically library codeand usually not done by the normal/casual arduino user.

If it were desirable to support some thinner/faster i/o routines to be usedby ISR routines, then that is definitely possiblebut again, this goes back to my original suggestion of usinglayering and _ (underbar) functions/macros so that the code writer can pick and choose what level of support his code needs.

I did finally post a significant update to this:http://code.google.com/p/digitalwritefast/downloads/list

In the original version of this library I supplied 2 versions of each command with different behavior around turning off PWM (the analogWrite facility). This version does not turn off PWM--that feature is planned to be removed from future versions of the standard commands.

In this version I only supply 1 version of the commands

Much more importantly this version is interrupt safe.

There are several good descriptions of the need for interrupt safe digitalWrite and pinMode commands. I struck me that I have a disassembly listing of the commands that certainly can be used to describe the situation in a different, not necessarily better, way:

For Ports F and below, a single instruction can be used to set or clear an individual bit that corresponds to the digitalWrite or PinMode setting you want to change. It will look like this:

The problem arises when the port is modified by other means in the microsecond between it being read into the register, modified and rewritten. Most commonly this seems to come up with the Servo library, but any code that has an interrupt routine that itself does a digitalWrite or pinMode might cause the issue.

What happens is that the 'lds r24, 0x0108' would read the current information from the port. Then it might happen that an interrupt would divert the microprocessor to handle another task. Imagine that 0x108 is modified during processing of the interrupt. Then the microprocessor returns to your program, which proceeds with 'ori r24, 0x04' setting the bit you wanted, and 'sts 0x0108, r24' destroying whatever the interrupt routine did. The interrupt could come between the ori and the sts as well, of course. The problems are notoriously hard to debug; the exact timing of the interrupt cannot be replicated and the bits of code that interact are likely to be located far from each other--perhaps even in a library, whose source code you have never read!

This version of the library correctly generates interrupt safe code that looks like this:

Skimming through this thread, all of the examples presented have used only the constants HIGH and LOW as the values being written using digitalWriteFast. This does correspond with the Reference documentation for digitalWrite as well as many of the example sketches but there are some examples (eg, BlinkWithoutDelay) and likely much existing code that use variables instead. In fact, digitalWrite currently maps any non-zero value into a write of '1'. I would like to see that behavior maintained. How will the new "fast" routines handle these cases?