11/*
2- * SPI Master library for arduino .
3- * Copyright (c) 2014 Arduino.
2+ * SPI Master library for Arduino .
3+ * Copyright (c) 2015 Arduino LLC
44 *
55 * This file is free software; you can redistribute it and/or modify
66 * it under the terms of either the GNU General Public License version 2
1313#include " assert.h"
1414#include " variant.h"
1515
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+
1622SPIClass::SPIClass (SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI)
1723{
24+ initialized = false ;
1825 assert (p_sercom != NULL );
1926 _p_sercom = p_sercom;
2027
@@ -25,40 +32,100 @@ SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint
2532
2633void SPIClass::begin ()
2734{
35+ init ();
36+
2837 // PIO init
2938 pinPeripheral (_uc_pinMiso, g_APinDescription[_uc_pinMiso].ulPinType );
3039 pinPeripheral (_uc_pinSCK, g_APinDescription[_uc_pinSCK].ulPinType );
3140 pinPeripheral (_uc_pinMosi, g_APinDescription[_uc_pinMosi].ulPinType );
3241
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 );
3661
3762 _p_sercom->enableSPI ();
3863}
3964
4065void SPIClass::end ()
4166{
4267 _p_sercom->resetSPI ();
68+ initialized = false ;
4369}
4470
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
4580
46- void SPIClass::usingInterrupt (uint8_t interruptNumber)
81+ void SPIClass::usingInterrupt (int interruptNumber)
4782{
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 ();
4999}
50100
51101void SPIClass::beginTransaction (SPISettings settings)
52102{
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);
57115}
58116
59117void SPIClass::endTransaction (void )
60118{
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+ }
62129}
63130
64131void SPIClass::setBitOrder (BitOrder order)
@@ -110,7 +177,7 @@ byte SPIClass::transfer(uint8_t data)
110177 _p_sercom->writeDataSPI (data);
111178
112179 // Read data
113- return _p_sercom->readDataSPI ();
180+ return _p_sercom->readDataSPI () & 0xFF ;
114181}
115182
116183void SPIClass::attachInterrupt () {
0 commit comments