LCOV - code coverage report
Current view: top level - src/AH/Hardware/ExtendedInputOutput - ExtendedIOElement.hpp (source / functions) Hit Total Coverage
Test: e224b347cd670555e44f06608ac41bd1ace9d9d8 Lines: 19 19 100.0 %
Date: 2020-09-08 17:44:46 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* ✔ */
       2             : 
       3             : #pragma once
       4             : 
       5             : #include <AH/Settings/Warnings.hpp>
       6             : AH_DIAGNOSTIC_WERROR() // Enable errors on warnings
       7             : 
       8             : #include "ExtendedInputOutput.hpp"
       9             : #include <AH/Containers/Updatable.hpp>
      10             : #include <AH/Hardware/Hardware-Types.hpp>
      11             : 
      12             : BEGIN_AH_NAMESPACE
      13             : 
      14             : /**
      15             :  * @brief   An abstract base class for Extended Input/Output elements.
      16             :  *
      17             :  * The limited number of IO pins of the Arduino can be extended by
      18             :  * adding multiplexers, shift registers, IO expanders, etc.  
      19             :  * ExtendedIOElement serves as a base class for all these expanders.
      20             :  *
      21             :  * The pins of each extended IO element are mapped to a pin number
      22             :  * greater than the greatest Arduino pin number.  
      23             :  * You can supply this pin number to the IO functions in the ExtIO
      24             :  * namespace.  
      25             :  * If the pin number corresponds to an actual Arduino pin,
      26             :  * the default Arduino IO function (digitalRead, digitalWrite, ...)
      27             :  * will be called.  
      28             :  * If the pin is not an Arduino pin, it is an extended IO pin number,
      29             :  * so the extended IO element that this pin belongs to is looked up,
      30             :  * and the IO function for this element is executed with the correct
      31             :  * pin number.
      32             :  *
      33             :  * For example:
      34             :  * Imagine an Arduino with 20 pins (e.g. the Arduino UNO).
      35             :  * Pins 0 - 19 will correspond to the Arduino pins, and
      36             :  * `ExtIO::digitalRead(pin)` will have the exact same effect as
      37             :  * the standard `digitalRead(pin)` function (albeit a little slower).  
      38             :  * Now, we'll add two 8-channel analog multiplexers, let's call them
      39             :  * `mux1` and `mux2`.  
      40             :  * The first pin (pin 0) of `mux1` will be extended IO pin number 20,
      41             :  * the last pin (pin 7) of `mux1` will be extended IO pin number 27,
      42             :  * etc.
      43             :  * The first pin of `mux2` will be extended IO pin number 28, you get
      44             :  * the idea.
      45             :  * If you now call `ExtIO::digitalRead(mux1.#pin (7))` or
      46             :  * `ExtIO::digitalRead(27)`, both will be
      47             :  * translated to `mux1.digitalRead(7)`.
      48             :  *
      49             :  * The number of extended IO elements is limited only by the size of
      50             :  * `pin_t`. However, looking up the extended IO element for a given
      51             :  * extended IO pin number uses linear search, so that might add
      52             :  * some noticable overhead for large pin numbers.  
      53             :  * 
      54             :  * The design here is a compromise: saving a pointer to each extended IO element
      55             :  * to find it directly would be much faster than having to search all elements
      56             :  * each time. On the other hand, it would require each `pin_t` variable to be
      57             :  * at least one byte larger. Since almost all other classes in this library 
      58             :  * store pin variables, the memory penalty would be too large, especially on AVR
      59             :  * microcontrollers.  
      60             :  * Another reason to do it this way, is that this approach is still fast enough
      61             :  * to make sure it is not noticable to human users.
      62             :  */
      63          34 : class ExtendedIOElement : public UpdatableCRTP<ExtendedIOElement> {
      64             :   protected:
      65             :     /**
      66             :      * @brief   Create an ExtendedIOElement with the given number of pins.
      67             :      * 
      68             :      * @param   length
      69             :      *          The number of pins this element has.
      70             :      */
      71             :     ExtendedIOElement(pin_t length);
      72             : 
      73             :   public:
      74             :     /** 
      75             :      * @brief   Set the mode of a given pin.
      76             :      * 
      77             :      * @note    This function might not be implemented by all subclasses.  
      78             :      *          Some extended IO types, such as shift registers, can only be 
      79             :      *          used as outputs.  
      80             :      *          On others, it might be implemented, but it could impact all pins
      81             :      *          of the IO element. For example, enabling the internal pull-up 
      82             :      *          resistor on an analog multiplexer affects all pins of the mux.
      83             :      * 
      84             :      * @param   pin
      85             :      *          The (zero-based) pin of this IO element.
      86             :      * @param   mode
      87             :      *          The mode to set the pin to (e.g. `INPUT`, `OUTPUT` or 
      88             :      *          `INPUT_PULLUP`).
      89             :      */
      90           1 :     virtual void pinMode(pin_t pin, PinMode_t mode) {
      91           1 :         pinModeBuffered(pin, mode);
      92           1 :         updateBufferedOutputs();
      93           1 :     }
      94             : 
      95             :     /**
      96             :      * @brief   Set the mode of a given pin in the software buffer.
      97             :      * The buffer is written to the ExtIO device when @ref updateBufferedOutputs
      98             :      * is called.
      99             :      * @copydetails pinMode
     100             :      */
     101             :     virtual void pinModeBuffered(pin_t pin, PinMode_t mode) = 0;
     102             : 
     103             :     /** 
     104             :      * @brief   Set the output of the given pin to the given state.
     105             :      * 
     106             :      * @param   pin
     107             :      *          The (zero-based) pin of this IO element.
     108             :      * @param   state
     109             :      *          The new state to set the pin to.
     110             :      */
     111           1 :     virtual void digitalWrite(pin_t pin, PinStatus_t state) {
     112           1 :         digitalWriteBuffered(pin, state);
     113           1 :         updateBufferedOutputs();
     114           1 :     }
     115             : 
     116             :     /**
     117             :      * @brief   Set the output of a given pin in the software buffer.
     118             :      * The buffer is written to the ExtIO device when @ref updateBufferedOutputs
     119             :      * is called.
     120             :      * @copydetails digitalWrite
     121             :      */
     122             :     virtual void digitalWriteBuffered(pin_t pin, PinStatus_t state) = 0;
     123             : 
     124             :     /** 
     125             :      * @brief   Read the state of the given pin.
     126             :      * 
     127             :      * @param   pin
     128             :      *          The (zero-based) pin of this IO element.
     129             :      * @return  The state of the given pin.
     130             :      */
     131           1 :     virtual int digitalRead(pin_t pin) {
     132           1 :         updateBufferedInputs();
     133           1 :         return digitalReadBuffered(pin);
     134             :     }
     135             : 
     136             :     /** 
     137             :      * @brief   Read the state of the given pin from the software buffer.
     138             :      * To update the buffer, you have to call @ref updateBufferedInputs first.
     139             :      * @copydetails digitalRead
     140             :      */
     141             :     virtual int digitalReadBuffered(pin_t pin) = 0;
     142             : 
     143             :     /**
     144             :      * @brief   Write an analog (or PWM) value to the given pin.
     145             :      * 
     146             :      * @param   pin 
     147             :      *          The (zero-based) pin of this IO element.
     148             :      * @param   val 
     149             :      *          The new analog value to set the pin to.
     150             :      */
     151           1 :     virtual void analogWrite(pin_t pin, analog_t val) {
     152           1 :         analogWriteBuffered(pin, val);
     153           1 :         updateBufferedOutputs();
     154           1 :     }
     155             : 
     156             :     /**
     157             :      * @brief   Write an analog (or PWM) value to the software buffer given pin.
     158             :      * The buffer is written to the ExtIO device when @ref updateBufferedOutputs
     159             :      * is called.
     160             :      * @copydetails analogWrite
     161             :      */
     162             :     virtual void analogWriteBuffered(pin_t pin, analog_t val) = 0;
     163             : 
     164             :     /**
     165             :      * @brief   Read the analog value of the given pin.
     166             :      * 
     167             :      * @param   pin 
     168             :      *          The (zero-based) pin of this IO element.
     169             :      * @return  The new analog value of pin.
     170             :      */
     171           1 :     virtual analog_t analogRead(pin_t pin) {
     172           1 :         updateBufferedInputs();
     173           1 :         return analogReadBuffered(pin);
     174             :     }
     175             : 
     176             :     /** 
     177             :      * @brief   Read the analog value of the given pin from the software buffer.
     178             :      * To update the buffer, you have to call @ref updateBufferedInputs first.
     179             :      * @copydetails analogRead
     180             :      */
     181             :     virtual analog_t analogReadBuffered(pin_t pin) = 0;
     182             : 
     183             :     /**
     184             :      * @brief   Initialize the extended IO element.
     185             :      */
     186             :     virtual void begin() = 0;
     187             : 
     188             :     /**
     189             :      * @brief   Initialize all extended IO elements.
     190             :      */
     191             :     static void beginAll();
     192             : 
     193             :     /**
     194             :      * @brief   Write the internal state to the physical outputs.
     195             :      */
     196             :     virtual void updateBufferedOutputs() = 0;
     197             : 
     198             :     /**
     199             :      * @brief   Write the internal states to the physical outputs for all 
     200             :      *          extended IO elements.
     201             :      */
     202             :     static void updateAllBufferedOutputs();
     203             : 
     204             :     /** 
     205             :      * @brief   Read the physical state into the input buffers.
     206             :      */
     207             :     virtual void updateBufferedInputs() = 0;
     208             : 
     209             :     /** 
     210             :      * @brief   Read the physical state into the input buffers for all extended
     211             :      *          IO elements.
     212             :      */
     213             :     static void updateAllBufferedInputs();
     214             : 
     215             :     /**
     216             :      * @brief   Get the extended IO pin number of a given physical pin of this
     217             :      *          extended IO element.
     218             :      * @param   pin
     219             :      *          The zero-based physical pin number of this IO element.
     220             :      * @return  The global, unique extended IO pin number for the given pin.
     221             :      */
     222             :     pin_t pin(pin_t pin) const;
     223             : 
     224             :     /**
     225             :      * @brief   Get the extended IO pin number of a given physical pin of this
     226             :      *          extended IO element.  
     227             :      *          It is alias for `ExtendedIOElement::pin`.
     228             :      * @param   pin
     229             :      *          The zero-based physical pin number of this IO element.
     230             :      * @return  The global, unique extended IO pin number for the given pin.
     231             :      */
     232             :     pin_t operator[](pin_t pin) const;
     233             : 
     234             :     /**
     235             :      * @brief Get the number of pins this IO element has.
     236             :      * 
     237             :      * @return The number of pins this IO element has. 
     238             :      */
     239             :     pin_t getLength() const;
     240             : 
     241             :     /**
     242             :      * @brief   Get the largest global extended IO pin number that belongs to
     243             :      *          this extended IO element.
     244             :      */
     245             :     pin_t getEnd() const;
     246             : 
     247             :     /**
     248             :      * @brief   Get the smallest global extended IO pin number that belongs to
     249             :      *          this extended IO element.
     250             :      */
     251             :     pin_t getStart() const;
     252             : 
     253             :     /**
     254             :      * @brief   Get the list of all Extended IO elements.
     255             :      */
     256             :     static DoublyLinkedList<ExtendedIOElement> &getAll();
     257             : 
     258             :   private:
     259             :     const pin_t length;
     260             :     const pin_t start;
     261             :     const pin_t end;
     262             :     static pin_t offset;
     263             : };
     264             : 
     265             : END_AH_NAMESPACE
     266             : 
     267             : AH_DIAGNOSTIC_POP()

Generated by: LCOV version 1.14-6-g40580cd