Digital IO
|
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