|
@@ -1,4 +1,4 @@
|
1
|
|
-/**
|
|
1
|
+/*
|
2
|
2
|
* Marlin 3D Printer Firmware
|
3
|
3
|
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
4
|
4
|
*
|
|
@@ -94,7 +94,9 @@ void spiBegin (void) {
|
94
|
94
|
SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1);
|
95
|
95
|
SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X);
|
96
|
96
|
}
|
97
|
|
- //------------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+ //------------------------------------------------------------------------------
|
98
|
100
|
/** SPI receive a byte */
|
99
|
101
|
uint8_t spiRec(void) {
|
100
|
102
|
SPDR = 0xFF;
|
|
@@ -132,6 +134,72 @@ void spiBegin (void) {
|
132
|
134
|
}
|
133
|
135
|
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
134
|
136
|
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+ /** begin spi transaction */
|
|
140
|
+ void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
|
141
|
+ // Based on Arduino SPI library
|
|
142
|
+ // Clock settings are defined as follows. Note that this shows SPI2X
|
|
143
|
+ // inverted, so the bits form increasing numbers. Also note that
|
|
144
|
+ // fosc/64 appears twice
|
|
145
|
+ // SPR1 SPR0 ~SPI2X Freq
|
|
146
|
+ // 0 0 0 fosc/2
|
|
147
|
+ // 0 0 1 fosc/4
|
|
148
|
+ // 0 1 0 fosc/8
|
|
149
|
+ // 0 1 1 fosc/16
|
|
150
|
+ // 1 0 0 fosc/32
|
|
151
|
+ // 1 0 1 fosc/64
|
|
152
|
+ // 1 1 0 fosc/64
|
|
153
|
+ // 1 1 1 fosc/128
|
|
154
|
+
|
|
155
|
+ // We find the fastest clock that is less than or equal to the
|
|
156
|
+ // given clock rate. The clock divider that results in clock_setting
|
|
157
|
+ // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the
|
|
158
|
+ // slowest (128 == 2 ^^ 7, so clock_div = 6).
|
|
159
|
+ uint8_t clockDiv;
|
|
160
|
+
|
|
161
|
+ // When the clock is known at compiletime, use this if-then-else
|
|
162
|
+ // cascade, which the compiler knows how to completely optimize
|
|
163
|
+ // away. When clock is not known, use a loop instead, which generates
|
|
164
|
+ // shorter code.
|
|
165
|
+ if (__builtin_constant_p(spiClock)) {
|
|
166
|
+ if (spiClock >= F_CPU / 2) {
|
|
167
|
+ clockDiv = 0;
|
|
168
|
+ } else if (spiClock >= F_CPU / 4) {
|
|
169
|
+ clockDiv = 1;
|
|
170
|
+ } else if (spiClock >= F_CPU / 8) {
|
|
171
|
+ clockDiv = 2;
|
|
172
|
+ } else if (spiClock >= F_CPU / 16) {
|
|
173
|
+ clockDiv = 3;
|
|
174
|
+ } else if (spiClock >= F_CPU / 32) {
|
|
175
|
+ clockDiv = 4;
|
|
176
|
+ } else if (spiClock >= F_CPU / 64) {
|
|
177
|
+ clockDiv = 5;
|
|
178
|
+ } else {
|
|
179
|
+ clockDiv = 6;
|
|
180
|
+ }
|
|
181
|
+ } else {
|
|
182
|
+ uint32_t clockSetting = F_CPU / 2;
|
|
183
|
+ clockDiv = 0;
|
|
184
|
+ while (clockDiv < 6 && spiClock < clockSetting) {
|
|
185
|
+ clockSetting /= 2;
|
|
186
|
+ clockDiv++;
|
|
187
|
+ }
|
|
188
|
+ }
|
|
189
|
+
|
|
190
|
+ // Compensate for the duplicate fosc/64
|
|
191
|
+ if (clockDiv == 6)
|
|
192
|
+ clockDiv = 7;
|
|
193
|
+
|
|
194
|
+ // Invert the SPI2X bit
|
|
195
|
+ clockDiv ^= 0x1;
|
|
196
|
+
|
|
197
|
+ SPCR = _BV(SPE) | _BV(MSTR) | ((bitOrder == SPI_LSBFIRST) ? _BV(DORD) : 0) |
|
|
198
|
+ (dataMode << CPHA) | ((clockDiv >> 1) << SPR0);
|
|
199
|
+ SPSR = clockDiv | 0x01;
|
|
200
|
+ }
|
|
201
|
+
|
|
202
|
+
|
135
|
203
|
//------------------------------------------------------------------------------
|
136
|
204
|
#else // SOFTWARE_SPI
|
137
|
205
|
//------------------------------------------------------------------------------
|
|
@@ -144,6 +212,12 @@ void spiBegin (void) {
|
144
|
212
|
UNUSED(spiRate);
|
145
|
213
|
}
|
146
|
214
|
|
|
215
|
+ /** Begin SPI transaction, set clock, bit order, data mode */
|
|
216
|
+ void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
|
217
|
+ // nothing to do
|
|
218
|
+ UNUSED(spiBeginTransaction);
|
|
219
|
+ }
|
|
220
|
+
|
147
|
221
|
//------------------------------------------------------------------------------
|
148
|
222
|
/** Soft SPI receive byte */
|
149
|
223
|
uint8_t spiRec() {
|
|
@@ -206,7 +280,7 @@ void spiBegin (void) {
|
206
|
280
|
spiSend(token);
|
207
|
281
|
for (uint16_t i = 0; i < 512; i++)
|
208
|
282
|
spiSend(buf[i]);
|
209
|
|
- }
|
|
283
|
+ }
|
210
|
284
|
#endif // SOFTWARE_SPI
|
211
|
285
|
|
212
|
286
|
|