MySensors Library & Examples  2.3.2-42-g423b9d7
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 {
52 public:
53  //----------------------------------------------------------------------------
55  void begin()
56  {
58  fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
59  fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
60  }
61  //----------------------------------------------------------------------------
65  inline __attribute__((always_inline))
66  uint8_t receive()
67  {
68  uint8_t data = 0;
69  receiveBit(7, &data);
70  receiveBit(6, &data);
71  receiveBit(5, &data);
72  receiveBit(4, &data);
73  receiveBit(3, &data);
74  receiveBit(2, &data);
75  receiveBit(1, &data);
76  receiveBit(0, &data);
77  return data;
78  }
79  //----------------------------------------------------------------------------
83  inline __attribute__((always_inline))
84  void send(uint8_t data)
85  {
86  sendBit(7, data);
87  sendBit(6, data);
88  sendBit(5, data);
89  sendBit(4, data);
90  sendBit(3, data);
91  sendBit(2, data);
92  sendBit(1, data);
93  sendBit(0, data);
94  }
95  //----------------------------------------------------------------------------
100  inline __attribute__((always_inline))
101  uint8_t transfer(uint8_t txData)
102  {
103  uint8_t rxData = 0;
104  transferBit(7, &rxData, txData);
105  transferBit(6, &rxData, txData);
106  transferBit(5, &rxData, txData);
107  transferBit(4, &rxData, txData);
108  transferBit(3, &rxData, txData);
109  transferBit(2, &rxData, txData);
110  transferBit(1, &rxData, txData);
111  transferBit(0, &rxData, txData);
112  return rxData;
113  }
114 
115 private:
116  //----------------------------------------------------------------------------
117  inline __attribute__((always_inline))
118  bool MODE_CPHA(uint8_t mode)
119  {
120  return (mode & 1) != 0;
121  }
122  inline __attribute__((always_inline))
123  bool MODE_CPOL(uint8_t mode)
124  {
125  return (mode & 2) != 0;
126  }
127  inline __attribute__((always_inline))
128  void receiveBit(uint8_t bit, uint8_t* data)
129  {
130  if (MODE_CPHA(Mode)) {
131  fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
132  }
133  nop;
134  nop;
135  fastDigitalWrite(SckPin,
136  MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
137  if (fastDigitalRead(MisoPin)) {
138  *data |= 1 << bit;
139  }
140  if (!MODE_CPHA(Mode)) {
141  fastDigitalWrite(SckPin, MODE_CPOL(Mode));
142  }
143  }
144  //----------------------------------------------------------------------------
145  inline __attribute__((always_inline))
146  void sendBit(uint8_t bit, uint8_t data)
147  {
148  if (MODE_CPHA(Mode)) {
149  fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
150  }
151  fastDigitalWrite(MosiPin, data & (1 << bit));
152  fastDigitalWrite(SckPin,
153  MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
154  nop;
155  nop;
156  if (!MODE_CPHA(Mode)) {
157  fastDigitalWrite(SckPin, MODE_CPOL(Mode));
158  }
159  }
160  //----------------------------------------------------------------------------
161  inline __attribute__((always_inline))
162  void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData)
163  {
164  if (MODE_CPHA(Mode)) {
165  fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
166  }
167  fastDigitalWrite(MosiPin, txData & (1 << bit));
168  fastDigitalWrite(SckPin,
169  MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
170  if (fastDigitalRead(MisoPin)) {
171  *rxData |= 1 << bit;
172  }
173  if (!MODE_CPHA(Mode)) {
174  fastDigitalWrite(SckPin, MODE_CPOL(Mode));
175  }
176  }
177  //----------------------------------------------------------------------------
178 };
179 #endif // SoftSPI_h
180 
data
char data[MAX_PAYLOAD_SIZE+1]
Buffer for raw payload data.
Definition: MyMessage.h:654
fastPinConfig
#define fastPinConfig(pin, mode, level)
Definition: DigitalPin.h:310
SoftSPI::__attribute__
__attribute__((always_inline)) uint8_t transfer(uint8_t txData)
Definition: SoftSPI.h:100
SoftSPI::begin
void begin()
Definition: SoftSPI.h:55
receive
void receive(const MyMessage &) __attribute__((weak))
Callback for incoming messages.
Definition: DimmableLEDActuator.ino:87
MISO_LEVEL
#define MISO_LEVEL
Definition: SoftSPI.h:39
MISO_MODE
#define MISO_MODE
Definition: SoftSPI.h:37
send
bool send(MyMessage &msg, const bool requestEcho=false)
SoftSPI::__attribute__
__attribute__((always_inline)) void send(uint8_t data)
Definition: SoftSPI.h:83
SoftSPI::__attribute__
__attribute__((always_inline)) uint8_t receive()
Definition: SoftSPI.h:65
SCK_MODE
#define SCK_MODE
Definition: SoftSPI.h:43
SoftSPI
Fast software SPI.
Definition: SoftSPI.h:50
MOSI_MODE
#define MOSI_MODE
Definition: SoftSPI.h:41
DigitalPin.h
Fast Digital Pin functions.