Sunday, March 3, 2013

The Pin Classes; An Introduction

Cosa contains a rich set of classes and member functions for handling the Arduino Pins. The object-oriented nature of Cosa allows both strong data typing, a declarative style of the definition of pins in a sketch or library but also a higher level of compiler optimization and code size reduction.

The Arduino/Wiring digital and analog I/O functions are replaced with an instance of a Pin class and member functions. Cosa provides several synonyms for the basic functions to allow natural expression depending on the type of application and coding style.

Fig. 1: InputPin Member Functions

The InputPin class has a wide range of member functions for reading the pin value. The Arduino/Wiring function digitalRead() corresponds directly to aPin.read() but can also be expressed as aPin.is_set(), aPin.is_high() and aPin.is_on(). The selection is yours and should depend on the context of your sketch and what you want to express. There is no extra overhead involved. And the actual reading of the pin is several times faster than Arduino/Wiring's implementation of digitalRead(). It is also possible to use C++ operator>> syntax for reading an InputPin.

  InputPin aPin(Board::D7);
  uint8_t var;
  aPin >> var;

In the example code above the operator>> will read the InputPin aPin and assign the value to the given variable, var. Note the definition of the board pin symbol. There is a mode parameter for the InputPin constructor. It has the default value NORMAL_MODE. The full, expanded, statement for the above example is:

  InputPin aPin(Board::D7, InputPin::NORMAL_MODE);

To define an InputPin with internal pullup resistor use the following statement:

  InputPin aPin(Board::D7, InputPin::PULLUP_MODE); 

C++ also allows overloading of member functions. The compiler determines which function to use from the actual parameter list. An example of usage of this is the member function read() which has two implementations. The first (Fig.1) which corresponds to the Arduino/Wiring function digitalRead() and the second with two parameters (OutputPin and data direction) corresponds to Arduino/Wiring shiftIn().

Fig. 2: OutputPin Member Functions

The OutputPin class has the above member functions. Several have implicit new values associated with them such as set() and clear() which are synonym with write(1) and write(0). There are other logical named member functions to choose from; high()-low(), on()-off(). All to make you program easier to read depending on the context. The fastest possible change to an OutputPin is the member function toggle().

The operator<< is defined for writing to the OutputPin as if it was a stream. The example below reads an InputPin inPin and writes the complement value to the OutputPin outPin.

  InputPin inPin(Board::D7); 
  OutputPin outPin(Board::D8);
  uint8_t var;
  inPin >> var;
  outPin << !var;

All pin value change functions are protected with a synchronized block. Interrupt handling is not allowed when changing a pin value. The Cosa/Types.h file adds some syntactic sugar to make it easy to express. 

  /**
   * Set the output pin.
   */
  void set()
  {
    synchronized {
      *PORT() |= m_mask;
    }
  }

The keyword synchronized marks the block as protected from interrupts. Please see Cosa/Types.h for further details. Last a few words on the usage of enum data types in Cosa. Most Arduino libraries and source code use global enum or #define for constant values. To increase scalability and readability Cosa, whenever possible, uses the class as a name space.

The Board class collects all the Arduino pin symbols as a set of local enum declarations. The usage is Board::symbol which allows the compiler to further check your code. For instance, it is not possible to select any digital pin as a PWM pin. The PWM class with only allow the PWM pins defined in the Board class. This improves code but also allows runtime checks to be removed and more optimized code to be generated by the compiler. 

Fig. 3: Cosa Documentation (Doxygen)

Learn more about the Cosa Pin class hierarchy in the online documentation.

2 comments:

  1. Hi Mikael,

    This all looks excellent - congrats!

    I had some similar ideas but haven't got so far... OOPS is definitely the right approach when faced with the multiplicity of board types and i/o, timer etc. capabilities.

    Regards,
    Jim

    ReplyDelete
  2. Hi Jim, thanks for your interest in this project. I hope to get around to presenting and documenting the full scale of Cosa during this spring. There are some 50 classes in total right now so this will take some effort.

    If you have the time to evaluation or test Cosa I would appreciate any comments or suggestions you might have.

    Cheers!
    Mikael

    ReplyDelete