|
- // RHGenericSPI.h
- // Author: Mike McCauley (mikem@airspayce.com)
- // Copyright (C) 2011 Mike McCauley
- // Contributed by Joanna Rutkowska
- // $Id: RHGenericSPI.h,v 1.7 2014/04/14 08:37:11 mikem Exp $
-
- #ifndef RHGenericSPI_h
- #define RHGenericSPI_h
-
- #include <RadioHead.h>
-
- #if (RH_PLATFORM == RH_PLATFORM_ARDUINO)
- #include <SPI.h> // for SPI_HAS_TRANSACTION and SPISettings
- #endif
-
- /////////////////////////////////////////////////////////////////////
- /// \class RHGenericSPI RHGenericSPI.h <RHGenericSPI.h>
- /// \brief Base class for SPI interfaces
- ///
- /// This generic abstract class is used to encapsulate hardware or software SPI interfaces for
- /// a variety of platforms.
- /// The intention is so that driver classes can be configured to use hardware or software SPI
- /// without changing the main code.
- ///
- /// You must provide a subclass of this class to driver constructors that require SPI.
- /// A concrete subclass that encapsualates the standard Arduino hardware SPI and a bit-banged
- /// software implementation is included.
- ///
- /// Do not directly use this class: it must be subclassed and the following abstract functions at least
- /// must be implmented:
- /// - begin()
- /// - end()
- /// - transfer()
- class RHGenericSPI
- {
- public:
-
- /// \brief Defines constants for different SPI modes
- ///
- /// Defines constants for different SPI modes
- /// that can be passed to the constructor or setMode()
- /// We need to define these in a device and platform independent way, because the
- /// SPI implementation is different on each platform.
- typedef enum
- {
- DataMode0 = 0, ///< SPI Mode 0: CPOL = 0, CPHA = 0
- DataMode1, ///< SPI Mode 1: CPOL = 0, CPHA = 1
- DataMode2, ///< SPI Mode 2: CPOL = 1, CPHA = 0
- DataMode3, ///< SPI Mode 3: CPOL = 1, CPHA = 1
- } DataMode;
-
- /// \brief Defines constants for different SPI bus frequencies
- ///
- /// Defines constants for different SPI bus frequencies
- /// that can be passed to setFrequency().
- /// The frequency you get may not be exactly the one according to the name.
- /// We need to define these in a device and platform independent way, because the
- /// SPI implementation is different on each platform.
- typedef enum
- {
- Frequency1MHz = 0, ///< SPI bus frequency close to 1MHz
- Frequency2MHz, ///< SPI bus frequency close to 2MHz
- Frequency4MHz, ///< SPI bus frequency close to 4MHz
- Frequency8MHz, ///< SPI bus frequency close to 8MHz
- Frequency16MHz ///< SPI bus frequency close to 16MHz
- } Frequency;
-
- /// \brief Defines constants for different SPI endianness
- ///
- /// Defines constants for different SPI endianness
- /// that can be passed to setBitOrder()
- /// We need to define these in a device and platform independent way, because the
- /// SPI implementation is different on each platform.
- typedef enum
- {
- BitOrderMSBFirst = 0, ///< SPI MSB first
- BitOrderLSBFirst, ///< SPI LSB first
- } BitOrder;
-
- /// Constructor
- /// Creates an instance of an abstract SPI interface.
- /// Do not use this contructor directly: you must instead use on of the concrete subclasses provided
- /// such as RHHardwareSPI or RHSoftwareSPI
- /// \param[in] frequency One of RHGenericSPI::Frequency to select the SPI bus frequency. The frequency
- /// is mapped to the closest available bus frequency on the platform.
- /// \param[in] bitOrder Select the SPI bus bit order, one of RHGenericSPI::BitOrderMSBFirst or
- /// RHGenericSPI::BitOrderLSBFirst.
- /// \param[in] dataMode Selects the SPI bus data mode. One of RHGenericSPI::DataMode
- RHGenericSPI(Frequency frequency = Frequency1MHz, BitOrder bitOrder = BitOrderMSBFirst, DataMode dataMode = DataMode0);
-
- /// Transfer a single octet to and from the SPI interface
- /// \param[in] data The octet to send
- /// \return The octet read from SPI while the data octet was sent
- virtual uint8_t transfer(uint8_t data) = 0;
-
- /// SPI Configuration methods
- /// Enable SPI interrupts (if supported)
- /// This can be used in an SPI slave to indicate when an SPI message has been received
- virtual void attachInterrupt() {};
-
- /// Disable SPI interrupts (if supported)
- /// This can be used to diable the SPI interrupt in slaves where that is supported.
- virtual void detachInterrupt() {};
-
- /// Initialise the SPI library.
- /// Call this after configuring and before using the SPI library
- virtual void begin() = 0;
-
- /// Disables the SPI bus (leaving pin modes unchanged).
- /// Call this after you have finished using the SPI interface
- virtual void end() = 0;
-
- /// Sets the bit order the SPI interface will use
- /// Sets the order of the bits shifted out of and into the SPI bus, either
- /// LSBFIRST (least-significant bit first) or MSBFIRST (most-significant bit first).
- /// \param[in] bitOrder Bit order to be used: one of RHGenericSPI::BitOrder
- virtual void setBitOrder(BitOrder bitOrder);
-
- /// Sets the SPI data mode: that is, clock polarity and phase.
- /// See the Wikipedia article on SPI for details.
- /// \param[in] dataMode The mode to use: one of RHGenericSPI::DataMode
- virtual void setDataMode(DataMode dataMode);
-
- /// Sets the SPI clock divider relative to the system clock.
- /// On AVR based boards, the dividers available are 2, 4, 8, 16, 32, 64 or 128.
- /// The default setting is SPI_CLOCK_DIV4, which sets the SPI clock to one-quarter
- /// the frequency of the system clock (4 Mhz for the boards at 16 MHz).
- /// \param[in] frequency The data rate to use: one of RHGenericSPI::Frequency
- virtual void setFrequency(Frequency frequency);
-
- // Try to add SPI Transaction support
- // Note: Maybe add some way to set SPISettings?
- virtual void beginTransaction() {};
- virtual void endTransaction() {};
- protected:
- /// The configure SPI Bus frequency, one of RHGenericSPI::Frequency
- Frequency _frequency; // Bus frequency, one of RHGenericSPI::Frequency
-
- /// Bit order, one of RHGenericSPI::BitOrder
- BitOrder _bitOrder;
-
- /// SPI bus mode, one of RHGenericSPI::DataMode
- DataMode _dataMode;
-
- };
- #endif
|