I have developed a new C++ library for fast digital I/O and would appreciate any comments and suggestions. The library is posted here code.google.com/p/beta-lib/downloads/list as the file DigitalPinBeta20120113.zip.

A number of people have developed fast versions of digitalRead/digitalWrite using C macros to generate fast inline code.

I decided to to design a new API and use a template class. Here is an example program that generates two 125 ns wide pulses for a scope timing test, assuming a 16 MHz CPU.

I should have waited a few weeks... Your previous FastDigitalIO class allowed me to scrap my re-invention of a wheel. But I recently added this same functionality and moved the files into one... Anyway your new code is nice n tidy so I might put mine in the archive now.

As a c++ programmer, macros as long as some of the port map versions are just a headache. As i'm writing a template HAL library, this code almost seems custom written for me I have a system I'm deriving off parts of this to allow my HAL to write pins on like ports in one operation. I will post it when done if you would like a look.

Now I have a request, how about a "pingroup" class where you define a random selection of pins and can then apply a value to them. Maybe limited to 8 bits eg

I too see the value in something implementing those ideas.

That is essentially what I have started making.

I have a class 'WriteMany' specialised for up to 8 template paramaters, using compile time logic it determines which pins are on like ports and writes them together, any unique pins generate FastDigitalIO/digitalPin write methods. I have hit a small block as I rethink the port grouping logic, after specialising a four pin write I noticed how the next 4 specialisations will have quite a bit of code to them and would increase compile time dramatically. Not good as I plan to have it handling 69 pins.

Unfortunatly the pins have to be defined in template parameters too,If you use a formal parameter in a non-type template specification you will get an error ( XXX cannot appear in a constant-expression ). Meaning the DigitalPin library can not be used this way.

I'm overcoming this with a few macros to combine the pin numbers into one data block. So each template parameter contains a number of pins. I still have testing to see if large data types are compatible ( 64-bit integer ), should be as they are implemented by the compiler rather than the arduino.

A pin grouping system is definitely a task I would like to utilise and help create if needed.

EDIT: this task seems to be hindered by the arduino ide itself, if it supported c++0x ( or whatever the new standard is ) variadic templates would be perfect for this situation

I have played with multiple pins for timing tests. Scope tests with the following five pin example show that a single call to writeGroup() takes 2.5 microseconds. That is faster than a call to digitalWrite() for a single pin.

It takes 80 microseconds for the loop to go through all 32 possible values for five pins.

I thought of a DigitalPort class for multiple bits on one port. Trying to combine bits that are on the same port in PinGroup has a very high overhead since you can't arrange for the compiler to optimize to efficient I/O instructions.

Yes, I have looked at v3 GLCD and it contains the kind of macros I am trying to avoid.

DigitalPin generates the fastest and smallest possible code for reading and writing I/O port on 328 Arduinos and ports A-G on the Mega.

Sorry I don't think I made myself clear. I was referring to the discussion on pin groups. v3 GLCD has some clever code for recognising groups of pins are on the same port and generating faster code than accessing pins individually.

I think the DigitalPin template will be really useful but at present where speed is important I'm accessing the ports directly.

On a Mega a PinGroup could become quite large so a pingroup should have its max size as param:

I would suggest limiting to 8 pins anyway.

Quote

Furthermore must it set pins of the same register simultaneously? If pins are in different registers this is not possible ...

Not necessarily, if the fact that pins are on the same port can be detected great, but even if behind the scenes it degenerates to a stack of single pin writes (as you show) at least the application code will be simpler and more readable.

Quote

You could write a templates for a given number of pins. Not so neat but works.TwoPinGroup<Pin0, Pin1>ThreePinGroup<Pin0, Pin1, Pin2>

I'm not strong on C++ but can't you have 8 constructors with different numbers of parms, that way there is only a single pinGroup object and the syntax is the same up to 8 pins.

As for simultaneous writes, it would be nice if the class auto detected pins on the same port but I don't think that's really important, maybe a second Port class that boils down to simple "PORTx =" code with .bitSet() and .bitClear() methods that just do "PORTx != val" etc. At least that will add to the current HAL and isolate beginners from such "complex" ideas.

As for simultaneous writes, it would be nice if the class auto detected pins on the same port

The only purpose for my WriteMany class it to write like pins. A convenience factor is not really on my list at all.

Quote

imho a pingroup would have an internal collection to which runtime pins can be added and removed (don't know the purpose for remove yet)The collection is not sorted, so the adding order applies.

Also pins probably should not be runtime, assigning runtime pins more than once doesn't really make sense unless you are physically re-wiring your hardware while the Arduino is on.

Also they are not usable values with digitalPin library and will have to resort to some slower lookup table version. making it more efficient to just individually write the pins.

Non-type template parameters also have no storage overhead, no SRAM is used to store the parameters past compilation as the compiled code is completely customised to those parameters. The alternative is a generic read/write that must look up the contents with every operation.

My code as tested for 3 and 4 pins produces less instructions on like pins rather than doing an individual write on each pin. When I finish the 4 & 5 pin writer I'll post it.

I'm not limiting this code to 8 pins though, The benefits my HAL will theoretically receive from writing any number of pins out ways this limitation by far.

Writing multiple pins seems like a good idea, at least in the abstract. There are cases where dedicating an entire 8-bit port to a device makes sense but this is not write multiple pins.

I have written a lot of bit-bang code for SPI, I2C, and various devices. When I get to real hardware, my abstract write multiple ideas never seem to help.

Does anyone have a situation with real hardware where an existing implementation would be improved by write multiple with three or four pins. The pins must be restricted to a single port.

The best example I have is something like an LCD display. In this case the restriction that all pins are on the same port is too severe. The library LiquidCrystal allows any pins and that doesn't add much complication. Here are the byte and nibble write functions.