Digital IO
SoftSPI.h
Go to the documentation of this file.
1 /* Arduino DigitalIO Library
2  * Copyright (C) 2013 by William Greiman
3  *
4  * This file is part of the Arduino DigitalIO Library
5  *
6  * This Library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This Library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with the Arduino DigitalIO Library. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
29 #ifndef SoftSPI_h
30 #define SoftSPI_h
31 #include "DigitalPin.h"
32 //------------------------------------------------------------------------------
34 #define nop asm volatile ("nop\n\t")
35 //------------------------------------------------------------------------------
37 #define MISO_MODE INPUT
38 
39 #define MISO_LEVEL false
40 
41 #define MOSI_MODE OUTPUT
42 
43 #define SCK_MODE OUTPUT
44 //------------------------------------------------------------------------------
49 template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
50 class SoftSPI {
51  public:
52  //----------------------------------------------------------------------------
54  void begin() {
56  fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
57  fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
58  }
59  //----------------------------------------------------------------------------
63  inline __attribute__((always_inline))
64  uint8_t receive() {
65  uint8_t data = 0;
66  receiveBit(7, &data);
67  receiveBit(6, &data);
68  receiveBit(5, &data);
69  receiveBit(4, &data);
70  receiveBit(3, &data);
71  receiveBit(2, &data);
72  receiveBit(1, &data);
73  receiveBit(0, &data);
74  return data;
75  }
76  //----------------------------------------------------------------------------
80  inline __attribute__((always_inline))
81  void send(uint8_t data) {
82  sendBit(7, data);
83  sendBit(6, data);
84  sendBit(5, data);
85  sendBit(4, data);
86  sendBit(3, data);
87  sendBit(2, data);
88  sendBit(1, data);
89  sendBit(0, data);
90  }
91  //----------------------------------------------------------------------------
96  inline __attribute__((always_inline))
97  uint8_t transfer(uint8_t txData) {
98  uint8_t rxData = 0;
99  transferBit(7, &rxData, txData);
100  transferBit(6, &rxData, txData);
101  transferBit(5, &rxData, txData);
102  transferBit(4, &rxData, txData);
103  transferBit(3, &rxData, txData);
104  transferBit(2, &rxData, txData);
105  transferBit(1, &rxData, txData);
106  transferBit(0, &rxData, txData);
107  return rxData;
108  }
109 
110  private:
111  //----------------------------------------------------------------------------
112  inline __attribute__((always_inline))
113  bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
114  inline __attribute__((always_inline))
115  bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
116  inline __attribute__((always_inline))
117  void receiveBit(uint8_t bit, uint8_t* data) {
118  if (MODE_CPHA(Mode)) {
119  fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
120  }
121  nop;
122  nop;
123  fastDigitalWrite(SckPin,
124  MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
125  if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
126  if (!MODE_CPHA(Mode)) {
127  fastDigitalWrite(SckPin, MODE_CPOL(Mode));
128  }
129  }
130  //----------------------------------------------------------------------------
131  inline __attribute__((always_inline))
132  void sendBit(uint8_t bit, uint8_t data) {
133  if (MODE_CPHA(Mode)) {
134  fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
135  }
136  fastDigitalWrite(MosiPin, data & (1 << bit));
137  fastDigitalWrite(SckPin,
138  MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
139  nop;
140  nop;
141  if (!MODE_CPHA(Mode)) {
142  fastDigitalWrite(SckPin, MODE_CPOL(Mode));
143  }
144  }
145  //----------------------------------------------------------------------------
146  inline __attribute__((always_inline))
147  void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
148  if (MODE_CPHA(Mode)) {
149  fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
150  }
151  fastDigitalWrite(MosiPin, txData & (1 << bit));
152  fastDigitalWrite(SckPin,
153  MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
154  if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
155  if (!MODE_CPHA(Mode)) {
156  fastDigitalWrite(SckPin, MODE_CPOL(Mode));
157  }
158  }
159  //----------------------------------------------------------------------------
160 };
161 #endif // SoftSPI_h
162 
uint8_t transfer(uint8_t txData)
Definition: SoftSPI.h:97
#define SCK_MODE
Definition: SoftSPI.h:43
void send(uint8_t data)
Definition: SoftSPI.h:81
#define fastPinConfig(pin, mode, level)
Definition: DigitalPin.h:289
#define MOSI_MODE
Definition: SoftSPI.h:41
#define MISO_LEVEL
Definition: SoftSPI.h:39
#define MISO_MODE
Definition: SoftSPI.h:37
static void fastDigitalWrite(uint8_t pin, bool level)
Definition: DigitalPin.h:153
static bool fastDigitalRead(uint8_t pin)
Definition: DigitalPin.h:127
#define nop
Definition: SoftSPI.h:34
Fast Digital Pin functions.
Fast software SPI.
Definition: SoftSPI.h:50
void begin()
Definition: SoftSPI.h:54
uint8_t receive()
Definition: SoftSPI.h:64