Digital IO
Arduino/libraries/DigitalIO/SoftSPI.h
Go to the documentation of this file.
00001 /* Arduino DigitalIO Library
00002  * Copyright (C) 2013 by William Greiman
00003  *
00004  * This file is part of the Arduino DigitalIO Library
00005  *
00006  * This Library is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This Library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with the Arduino DigitalIO Library.  If not, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00029 #ifndef SoftSPI_h
00030 #define SoftSPI_h
00031 #include <DigitalPin.h>
00032 //------------------------------------------------------------------------------
00034 #define nop asm volatile ("nop\n\t")
00035 //------------------------------------------------------------------------------
00037 const bool MISO_MODE  = false;
00039 const bool MISO_LEVEL = false;
00041 const bool MOSI_MODE  = true;
00043 const bool SCK_MODE   = true;
00044 //------------------------------------------------------------------------------
00049 template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
00050 class SoftSPI {
00051  public:
00052   //----------------------------------------------------------------------------
00054   void begin() {
00055     fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
00056     fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
00057     fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
00058   }
00059   //----------------------------------------------------------------------------
00063   inline __attribute__((always_inline))
00064   uint8_t receive() {
00065     uint8_t data = 0;
00066     receiveBit(7, &data);
00067     receiveBit(6, &data);
00068     receiveBit(5, &data);
00069     receiveBit(4, &data);
00070     receiveBit(3, &data);
00071     receiveBit(2, &data);
00072     receiveBit(1, &data);
00073     receiveBit(0, &data);
00074     return data;
00075   }
00076   //----------------------------------------------------------------------------
00080   inline __attribute__((always_inline))
00081   void send(uint8_t data) {
00082     sendBit(7, data);
00083     sendBit(6, data);
00084     sendBit(5, data);
00085     sendBit(4, data);
00086     sendBit(3, data);
00087     sendBit(2, data);
00088     sendBit(1, data);
00089     sendBit(0, data);
00090   }
00091   //----------------------------------------------------------------------------
00096   inline __attribute__((always_inline))
00097   uint8_t transfer(uint8_t txData) {
00098     uint8_t rxData = 0;
00099     transferBit(7, &rxData, txData);
00100     transferBit(6, &rxData, txData);
00101     transferBit(5, &rxData, txData);
00102     transferBit(4, &rxData, txData);
00103     transferBit(3, &rxData, txData);
00104     transferBit(2, &rxData, txData);
00105     transferBit(1, &rxData, txData);
00106     transferBit(0, &rxData, txData);
00107     return rxData;
00108   }
00109 
00110  private:
00111   //----------------------------------------------------------------------------
00112   inline __attribute__((always_inline))
00113   bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
00114   inline __attribute__((always_inline))
00115   bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
00116   inline __attribute__((always_inline))
00117   void receiveBit(uint8_t bit, uint8_t* data) {
00118     if (MODE_CPHA(Mode)) {
00119       fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
00120     }
00121     nop;
00122     nop;
00123     fastDigitalWrite(SckPin,
00124       MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
00125     if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
00126     if (!MODE_CPHA(Mode)) {
00127       fastDigitalWrite(SckPin, MODE_CPOL(Mode));
00128     }
00129   }
00130   //----------------------------------------------------------------------------
00131   inline __attribute__((always_inline))
00132   void sendBit(uint8_t bit, uint8_t data) {
00133     if (MODE_CPHA(Mode)) {
00134       fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
00135     }
00136     fastDigitalWrite(MosiPin, data & (1 << bit));
00137     fastDigitalWrite(SckPin,
00138       MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
00139     nop;
00140     nop;
00141     if (!MODE_CPHA(Mode)) {
00142       fastDigitalWrite(SckPin, MODE_CPOL(Mode));
00143     }
00144   }
00145   //----------------------------------------------------------------------------
00146   inline __attribute__((always_inline))
00147   void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
00148     if (MODE_CPHA(Mode)) {
00149       fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
00150     }
00151     fastDigitalWrite(MosiPin, txData & (1 << bit));
00152     fastDigitalWrite(SckPin,
00153       MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
00154     if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
00155     if (!MODE_CPHA(Mode)) {
00156       fastDigitalWrite(SckPin, MODE_CPOL(Mode));
00157     }
00158   }
00159   //----------------------------------------------------------------------------
00160 };
00161 #endif  // SoftSPI_h
00162 
 All Classes Files Functions Variables Defines