1
1
/*
2
- * SPI Master library for arduino .
3
- * Copyright (c) 2014 Arduino.
2
+ * SPI Master library for Arduino .
3
+ * Copyright (c) 2015 Arduino LLC
4
4
*
5
5
* This file is free software; you can redistribute it and/or modify
6
6
* it under the terms of either the GNU General Public License version 2
13
13
#include " assert.h"
14
14
#include " variant.h"
15
15
16
+ #define SPI_IMODE_NONE 0
17
+ #define SPI_IMODE_EXTINT 1
18
+ #define SPI_IMODE_GLOBAL 2
19
+
20
+ const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();
21
+
16
22
SPIClass::SPIClass (SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI)
17
23
{
24
+ initialized = false ;
18
25
assert (p_sercom != NULL );
19
26
_p_sercom = p_sercom;
20
27
@@ -25,40 +32,100 @@ SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint
25
32
26
33
void SPIClass::begin ()
27
34
{
35
+ init ();
36
+
28
37
// PIO init
29
38
pinPeripheral (_uc_pinMiso, g_APinDescription[_uc_pinMiso].ulPinType );
30
39
pinPeripheral (_uc_pinSCK, g_APinDescription[_uc_pinSCK].ulPinType );
31
40
pinPeripheral (_uc_pinMosi, g_APinDescription[_uc_pinMosi].ulPinType );
32
41
33
- // Default speed set to 4Mhz, SPI mode set to MODE 0 and Bit order set to MSB first.
34
- _p_sercom->initSPI (SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, SPI_CHAR_SIZE_8_BITS, MSB_FIRST);
35
- _p_sercom->initSPIClock (SERCOM_SPI_MODE_0, 4000000 );
42
+ config (DEFAULT_SPI_SETTINGS);
43
+ }
44
+
45
+ void SPIClass::init ()
46
+ {
47
+ if (initialized)
48
+ return ;
49
+ interruptMode = SPI_IMODE_NONE;
50
+ interruptSave = 0 ;
51
+ interruptMask = 0 ;
52
+ initialized = true ;
53
+ }
54
+
55
+ void SPIClass::config (SPISettings settings)
56
+ {
57
+ _p_sercom->disableSPI ();
58
+
59
+ _p_sercom->initSPI (SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, SPI_CHAR_SIZE_8_BITS, settings.bitOrder );
60
+ _p_sercom->initSPIClock (settings.dataMode , settings.clockFreq );
36
61
37
62
_p_sercom->enableSPI ();
38
63
}
39
64
40
65
void SPIClass::end ()
41
66
{
42
67
_p_sercom->resetSPI ();
68
+ initialized = false ;
43
69
}
44
70
71
+ #ifndef interruptsStatus
72
+ #define interruptsStatus () __interruptsStatus()
73
+ static inline unsigned char __interruptsStatus (void ) __attribute__((always_inline, unused));
74
+ static inline unsigned char __interruptsStatus (void )
75
+ {
76
+ // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/CHDBIBGJ.html
77
+ return (__get_PRIMASK () ? 0 : 1 );
78
+ }
79
+ #endif
45
80
46
- void SPIClass::usingInterrupt (uint8_t interruptNumber)
81
+ void SPIClass::usingInterrupt (int interruptNumber)
47
82
{
48
- // XXX: TODO
83
+ if ((interruptNumber == NOT_AN_INTERRUPT) || (interruptNumber == EXTERNAL_INT_NMI))
84
+ return ;
85
+
86
+ uint8_t irestore = interruptsStatus ();
87
+ noInterrupts ();
88
+
89
+ if (interruptNumber >= EXTERNAL_NUM_INTERRUPTS)
90
+ interruptMode = SPI_IMODE_GLOBAL;
91
+ else
92
+ {
93
+ interruptMode |= SPI_IMODE_EXTINT;
94
+ interruptMask |= (1 << interruptNumber);
95
+ }
96
+
97
+ if (irestore)
98
+ interrupts ();
49
99
}
50
100
51
101
void SPIClass::beginTransaction (SPISettings settings)
52
102
{
53
- // XXX: TODO
54
- setBitOrder (settings.bitOrder );
55
- setClockDivider (settings.clockDiv );
56
- setDataMode (settings.dataMode );
103
+ if (interruptMode != SPI_IMODE_NONE)
104
+ {
105
+ if (interruptMode & SPI_IMODE_GLOBAL)
106
+ {
107
+ interruptSave = interruptsStatus ();
108
+ noInterrupts ();
109
+ }
110
+ else if (interruptMode & SPI_IMODE_EXTINT)
111
+ EIC->INTENCLR .reg = EIC_INTENCLR_EXTINT (interruptMask);
112
+ }
113
+
114
+ config (settings);
57
115
}
58
116
59
117
void SPIClass::endTransaction (void )
60
118
{
61
- // XXX: TODO
119
+ if (interruptMode != SPI_IMODE_NONE)
120
+ {
121
+ if (interruptMode & SPI_IMODE_GLOBAL)
122
+ {
123
+ if (interruptSave)
124
+ interrupts ();
125
+ }
126
+ else if (interruptMode & SPI_IMODE_EXTINT)
127
+ EIC->INTENSET .reg = EIC_INTENSET_EXTINT (interruptMask);
128
+ }
62
129
}
63
130
64
131
void SPIClass::setBitOrder (BitOrder order)
@@ -110,7 +177,7 @@ byte SPIClass::transfer(uint8_t data)
110
177
_p_sercom->writeDataSPI (data);
111
178
112
179
// Read data
113
- return _p_sercom->readDataSPI ();
180
+ return _p_sercom->readDataSPI () & 0xFF ;
114
181
}
115
182
116
183
void SPIClass::attachInterrupt () {
0 commit comments