Skip to content

Commit 015d84b

Browse files
authored
Merge pull request #58 from soburi/spi
Reimplements SPI class.
2 parents 641482d + c17b0e1 commit 015d84b

File tree

12 files changed

+540
-369
lines changed

12 files changed

+540
-369
lines changed

cores/arduino/wiring_private.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
extern "C" {
2323
#endif
2424

25+
#include <stdint.h>
26+
#include <stdbool.h>
27+
2528
#include "platform.h"
2629
#include <sys/mt.h>
2730
#include <sys/process.h>
@@ -94,6 +97,17 @@ struct i2c_device {
9497
void* devinfo;
9598
};
9699

100+
struct spi_device {
101+
int (*init)(void*);
102+
int (*configure)(void*, bool, bool, bool, uint32_t);
103+
int (*start)(void*);
104+
void (*stop)(void*);
105+
uint8_t (*transfer)(void*, uint8_t);
106+
int (*mask_interrupt_on_transaction)(void*, int);
107+
int (*deinit)(void*);
108+
void* devinfo;
109+
};
110+
97111
#ifdef __cplusplus
98112
} // extern "C"
99113
#endif

libraries/SPI/SPI.cpp

Lines changed: 173 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,181 @@
11
/*
2-
Copyright (c) TOKITA Hiroshi. All right reserved.
2+
* SPI Master library for Arduino Zero.
3+
* Copyright (c) 2015 Arduino LLC
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
319

4-
This library is free software; you can redistribute it and/or
5-
modify it under the terms of the GNU Lesser General Public
6-
License as published by the Free Software Foundation; either
7-
version 2.1 of the License, or (at your option) any later version.
20+
#include "SPI.h"
21+
#include "variant.h"
822

9-
This library is distributed in the hope that it will be useful,
10-
but WITHOUT ANY WARRANTY; without even the implied warranty of
11-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12-
See the GNU Lesser General Public License for more details.
23+
#ifndef SPI_CLOCK
24+
#define SPI_CLOCK SystemCoreClock
25+
#endif
1326

14-
You should have received a copy of the GNU Lesser General Public
15-
License along with this library; if not, write to the Free Software
16-
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17-
*/
27+
const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
1828

19-
#include "platform.h"
29+
SPIClass::SPIClass(struct spi_device* _spi)
30+
: spi(_spi)
31+
, divider(SPI_CLOCK/DEFAULT_SPI_SETTINGS.clock)
32+
, bitOrder(DEFAULT_SPI_SETTINGS.bitOrder)
33+
, dataMode(DEFAULT_SPI_SETTINGS.dataMode)
34+
, initialized(false)
35+
{
36+
DBG_PRINTF("SPIClass::SPIClass\r\n");
37+
}
2038

21-
#ifndef PLATFORM_SPI_HEADER
39+
void SPIClass::begin()
40+
{
41+
init();
2242

23-
/* TODO implement */
43+
divider = SPI_CLOCK/DEFAULT_SPI_SETTINGS.clock;
44+
bitOrder = DEFAULT_SPI_SETTINGS.bitOrder;
45+
dataMode = DEFAULT_SPI_SETTINGS.dataMode;
46+
47+
config(DEFAULT_SPI_SETTINGS);
48+
}
49+
50+
void SPIClass::init()
51+
{
52+
DBG_PRINTF("SystemCoreClock %d\r\n", SystemCoreClock);
53+
DBG_PRINTF("DEFAULT_SPI_SETTINGS.clock %d\r\n", DEFAULT_SPI_SETTINGS.clock);
54+
if (initialized)
55+
return;
56+
57+
spi->init(spi->devinfo);
58+
initialized = true;
59+
}
60+
61+
void SPIClass::config(SPISettings settings)
62+
{
63+
spi->configure(spi->devinfo,
64+
settings.bitOrder == MSBFIRST ? 1 : 0,
65+
settings.dataMode & 0x1 ? 1 : 0,
66+
settings.dataMode & 0x2 ? 0 : 1,
67+
settings.clock);
68+
}
69+
70+
void SPIClass::end()
71+
{
72+
spi->deinit(spi->devinfo);
73+
initialized = false;
74+
}
75+
76+
#if 0
77+
#ifndef interruptsStatus
78+
#define interruptsStatus() __interruptsStatus()
79+
static inline unsigned char __interruptsStatus(void) __attribute__((always_inline, unused));
80+
static inline unsigned char __interruptsStatus(void)
81+
{
82+
// See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/CHDBIBGJ.html
83+
return (__get_PRIMASK() ? 0 : 1);
84+
}
85+
#endif
86+
#endif
87+
88+
void SPIClass::usingInterrupt(int interruptNumber)
89+
{
90+
spi->mask_interrupt_on_transaction(spi->devinfo, interruptNumber);
91+
}
92+
93+
void SPIClass::beginTransaction(SPISettings settings)
94+
{
95+
config(settings);
96+
spi->start(spi->devinfo);
97+
}
98+
99+
void SPIClass::endTransaction(void)
100+
{
101+
spi->stop(spi->devinfo);
102+
}
103+
104+
void SPIClass::setBitOrder(BitOrder order)
105+
{
106+
bitOrder = order;
107+
if(initialized)
108+
config(SPISettings(SPI_CLOCK/divider, bitOrder, dataMode) );
109+
}
110+
111+
void SPIClass::setDataMode(uint8_t mode)
112+
{
113+
dataMode = mode;
114+
if(initialized)
115+
config(SPISettings(SPI_CLOCK/divider, bitOrder, dataMode) );
116+
}
117+
118+
void SPIClass::setClockDivider(uint8_t div)
119+
{
120+
divider = div;
121+
if(initialized)
122+
config(SPISettings(SPI_CLOCK/divider, bitOrder, dataMode) );
123+
}
124+
125+
byte SPIClass::transfer(uint8_t data)
126+
{
127+
return spi->transfer(spi->devinfo, data);
128+
}
129+
130+
uint16_t SPIClass::transfer16(uint16_t data) {
131+
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } t;
132+
133+
t.val = data;
134+
135+
if (bitOrder == LSBFIRST) {
136+
t.lsb = transfer(t.lsb);
137+
t.msb = transfer(t.msb);
138+
} else {
139+
t.msb = transfer(t.msb);
140+
t.lsb = transfer(t.lsb);
141+
}
142+
143+
return t.val;
144+
}
145+
146+
void SPIClass::transfer(void *buf, size_t count)
147+
{
148+
uint8_t *buffer = reinterpret_cast<uint8_t *>(buf);
149+
for (size_t i=0; i<count; i++) {
150+
*buffer = transfer(*buffer);
151+
buffer++;
152+
}
153+
}
154+
155+
void SPIClass::attachInterrupt() {
156+
// Should be enableInterrupt()
157+
}
158+
159+
void SPIClass::detachInterrupt() {
160+
// Should be disableInterrupt()
161+
}
162+
163+
#if SPI_INTERFACES_COUNT > 0
164+
SPIClass SPI(SPI_INTERFACE);
165+
#endif
166+
#if SPI_INTERFACES_COUNT > 1
167+
SPIClass SPI1(SPI1_INTERFACE);
168+
#endif
169+
#if SPI_INTERFACES_COUNT > 2
170+
SPIClass SPI2(SPI2_INTERFACE);
171+
#endif
172+
#if SPI_INTERFACES_COUNT > 3
173+
SPIClass SPI2(SPI2_INTERFACE);
174+
#endif
175+
#if SPI_INTERFACES_COUNT > 4
176+
SPIClass SPI3(SPI3_INTERFACE);
177+
#endif
178+
#if SPI_INTERFACES_COUNT > 5
179+
SPIClass SPI4(SPI4_INTERFACE);
180+
#endif
24181

25-
#endif // PLATFORM_SPI_HEADER

0 commit comments

Comments
 (0)