1
1
/*
2
2
* Copyright (c) 2010 by Cristian Maglie <[email protected] >
3
+ * Copyright (c) 2014 by Paul Stoffregen <[email protected] > (Transaction API)
3
4
* SPI Master library for arduino.
4
5
*
5
6
* This file is free software; you can redistribute it and/or modify
@@ -18,7 +19,6 @@ SPIClass::SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)) :
18
19
19
20
void SPIClass::begin () {
20
21
init ();
21
-
22
22
// NPCS control is left to the user
23
23
24
24
// Default speed set to 4Mhz
@@ -46,12 +46,88 @@ void SPIClass::begin(uint8_t _pin) {
46
46
void SPIClass::init () {
47
47
if (initialized)
48
48
return ;
49
+ interruptMode = 0 ;
50
+ interruptMask = 0 ;
51
+ interruptSave = 0 ;
49
52
initCb ();
50
53
SPI_Configure (spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
51
54
SPI_Enable (spi);
52
55
initialized = true ;
53
56
}
54
57
58
+ #ifndef interruptsStatus
59
+ #define interruptsStatus () __interruptsStatus()
60
+ static inline unsigned char __interruptsStatus (void ) __attribute__((always_inline, unused));
61
+ static inline unsigned char __interruptsStatus (void ) {
62
+ unsigned int primask;
63
+ asm volatile (" mrs %0, primask" : " =r" (primask));
64
+ if (primask) return 0 ;
65
+ return 1 ;
66
+ }
67
+ #endif
68
+
69
+ void SPIClass::usingInterrupt (uint8_t interruptNumber)
70
+ {
71
+ uint8_t irestore;
72
+
73
+ irestore = interruptsStatus ();
74
+ noInterrupts ();
75
+ if (interruptMode < 2 ) {
76
+ if (interruptNumber > NUM_DIGITAL_PINS) {
77
+ interruptMode = 2 ;
78
+ } else {
79
+ uint8_t imask = interruptMask;
80
+ Pio *pio = g_APinDescription[interruptNumber].pPort ;
81
+ if (pio == PIOA) {
82
+ imask |= 1 ;
83
+ } else if (pio == PIOB) {
84
+ imask |= 2 ;
85
+ } else if (pio == PIOC) {
86
+ imask |= 4 ;
87
+ } else if (pio == PIOD) {
88
+ imask |= 8 ;
89
+ }
90
+ interruptMask = imask;
91
+ interruptMode = 1 ;
92
+ }
93
+ }
94
+ if (irestore) interrupts ();
95
+ }
96
+
97
+ void SPIClass::beginTransaction (uint8_t pin, SPISettings settings)
98
+ {
99
+ if (interruptMode > 0 ) {
100
+ if (interruptMode == 1 ) {
101
+ uint8_t imask = interruptMask;
102
+ if (imask & 1 ) NVIC_DisableIRQ (PIOA_IRQn);
103
+ if (imask & 2 ) NVIC_DisableIRQ (PIOB_IRQn);
104
+ if (imask & 4 ) NVIC_DisableIRQ (PIOC_IRQn);
105
+ if (imask & 8 ) NVIC_DisableIRQ (PIOD_IRQn);
106
+ } else {
107
+ interruptSave = interruptsStatus ();
108
+ noInterrupts ();
109
+ }
110
+ }
111
+ uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL (pin);
112
+ bitOrder[ch] = settings.border ;
113
+ SPI_ConfigureNPCS (spi, ch, settings.config );
114
+ }
115
+
116
+ void SPIClass::endTransaction (void )
117
+ {
118
+ if (interruptMode > 0 ) {
119
+ if (interruptMode == 1 ) {
120
+ uint8_t imask = interruptMask;
121
+ if (imask & 1 ) NVIC_EnableIRQ (PIOA_IRQn);
122
+ if (imask & 2 ) NVIC_EnableIRQ (PIOB_IRQn);
123
+ if (imask & 4 ) NVIC_EnableIRQ (PIOC_IRQn);
124
+ if (imask & 8 ) NVIC_EnableIRQ (PIOD_IRQn);
125
+ } else {
126
+ if (interruptSave) interrupts ();
127
+ }
128
+ }
129
+ }
130
+
55
131
void SPIClass::end (uint8_t _pin) {
56
132
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN (_pin);
57
133
// Setting the pin as INPUT will disconnect it from SPI peripheral
@@ -95,12 +171,12 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
95
171
96
172
// SPI_Write(spi, _channel, _data);
97
173
while ((spi->SPI_SR & SPI_SR_TDRE) == 0 )
98
- ;
174
+ ;
99
175
spi->SPI_TDR = d;
100
176
101
177
// return SPI_Read(spi);
102
178
while ((spi->SPI_SR & SPI_SR_RDRF) == 0 )
103
- ;
179
+ ;
104
180
d = spi->SPI_RDR ;
105
181
// Reverse bit order
106
182
if (bitOrder[ch] == LSBFIRST)
@@ -137,3 +213,4 @@ static void SPI_0_Init(void) {
137
213
138
214
SPIClass SPI (SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
139
215
#endif
216
+
0 commit comments