| 
				
			 | 
			
			 | 
			@@ -1,6 +1,7 @@ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			/* | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st> | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 * Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 * SPI Master library for arduino. | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 * | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			 * This file is free software; you can redistribute it and/or modify | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -38,6 +39,89 @@ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#define SPI_CLOCK_MASK 0x03  // SPR1 = bit 1, SPR0 = bit 0 on SPCR | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#define SPI_2XCLOCK_MASK 0x01  // SPI2X = bit 0 on SPSR | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			class SPISettings { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			public: | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					if (__builtin_constant_p(clock)) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						init_AlwaysInline(clock, bitOrder, dataMode); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					} else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						init_MightInline(clock, bitOrder, dataMode); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			private: | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					init_AlwaysInline(clock, bitOrder, dataMode); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				  __attribute__((__always_inline__)) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// Clock settings are defined as follows. Note that this shows SPI2X | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// inverted, so the bits form increasing numbers. Also note that | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// fosc/64 appears twice | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// SPR1 SPR0 ~SPI2X Freq | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					//   0    0     0   fosc/2 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					//   0    0     1   fosc/4 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					//   0    1     0   fosc/8 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					//   0    1     1   fosc/16 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					//   1    0     0   fosc/32 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					//   1    0     1   fosc/64 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					//   1    1     0   fosc/64 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					//   1    1     1   fosc/128 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// We find the fastest clock that is less than or equal to the | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// given clock rate. The clock divider that results in clock_setting | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// slowest (128 == 2 ^^ 7, so clock_div = 6). | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					uint8_t clockDiv; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// When the clock is known at compiletime, use this if-then-else | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// cascade, which the compiler knows how to completely optimize | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// away. When clock is not know, use a loop instead, which generates | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// shorter code. | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					if (__builtin_constant_p(clock)) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						if (clock >= F_CPU / 2) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockDiv = 0; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} else if (clock >= F_CPU / 4) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockDiv = 1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} else if (clock >= F_CPU / 8) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockDiv = 2; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} else if (clock >= F_CPU / 16) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockDiv = 3; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} else if (clock >= F_CPU / 32) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockDiv = 4; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} else if (clock >= F_CPU / 64) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockDiv = 5; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockDiv = 6; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					} else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						uint32_t clockSetting = F_CPU / 2; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						clockDiv = 0; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						while (clockDiv < 6 && clock < clockSetting) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockSetting /= 2; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							clockDiv++; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// Compensate for the duplicate fosc/64 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					if (clockDiv == 6) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					clockDiv = 7; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// Invert the SPI2X bit | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					clockDiv ^= 0x1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// Pack into the SPISettings class | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) | | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						(dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					spsr = clockDiv & SPI_2XCLOCK_MASK; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				uint8_t spcr; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				uint8_t spsr; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				friend class SPIClass; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			}; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			class SPIClass { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			public: | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				// Initialize the SPI library | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -56,7 +140,7 @@ public: | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				// Before using SPI.transfer() or asserting chip select pins, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				// this function is used to gain exclusive access to the SPI bus | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				// and configure the correct settings. | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				inline static void beginTransaction(uint8_t clockDiv, uint8_t bitOrder, uint8_t dataMode) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				inline static void beginTransaction(SPISettings settings) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					if (interruptMode > 0) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						#ifdef SPI_AVR_EIMSK | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						if (interruptMode == 1) { | 
		
		
	
	
		
			
			| 
				
			 | 
			
			 | 
			@@ -69,10 +153,8 @@ public: | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
							cli(); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					// these long expressions each compile to only 2 instructions | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					SPCR = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) | | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
						(dataMode & SPI_MODE_MASK) | (clockDiv & SPI_CLOCK_MASK); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					SPSR = (clockDiv >> 2) & SPI_2XCLOCK_MASK; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					SPCR = settings.spcr; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
					SPSR = settings.spsr; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
				// Write to the SPI bus (MOSI pin) and also receive (MISO pin) |