11/*
22 * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
3+ * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
34 * SPI Master library for arduino.
45 *
56 * 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)) :
1819
1920void SPIClass::begin () {
2021 init ();
21-
2222 // NPCS control is left to the user
2323
2424 // Default speed set to 4Mhz
@@ -46,12 +46,88 @@ void SPIClass::begin(uint8_t _pin) {
4646void SPIClass::init () {
4747 if (initialized)
4848 return ;
49+ interruptMode = 0 ;
50+ interruptMask = 0 ;
51+ interruptSave = 0 ;
4952 initCb ();
5053 SPI_Configure (spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
5154 SPI_Enable (spi);
5255 initialized = true ;
5356}
5457
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+
55131void SPIClass::end (uint8_t _pin) {
56132 uint32_t spiPin = BOARD_PIN_TO_SPI_PIN (_pin);
57133 // 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) {
95171
96172 // SPI_Write(spi, _channel, _data);
97173 while ((spi->SPI_SR & SPI_SR_TDRE) == 0 )
98- ;
174+ ;
99175 spi->SPI_TDR = d;
100176
101177 // return SPI_Read(spi);
102178 while ((spi->SPI_SR & SPI_SR_RDRF) == 0 )
103- ;
179+ ;
104180 d = spi->SPI_RDR ;
105181 // Reverse bit order
106182 if (bitOrder[ch] == LSBFIRST)
@@ -137,3 +213,4 @@ static void SPI_0_Init(void) {
137213
138214SPIClass SPI (SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
139215#endif
216+
0 commit comments