add spi and eeprom arduino libs
This commit is contained in:
parent
cfca07489d
commit
dfea93b2ff
3 changed files with 671 additions and 0 deletions
201
cpu/avr/dev/arduino/SPI.cpp
Normal file
201
cpu/avr/dev/arduino/SPI.cpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
|
||||
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||
* Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
|
||||
* Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
|
||||
* SPI Master library for arduino.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "SPI.h"
|
||||
|
||||
SPIClass SPI;
|
||||
|
||||
uint8_t SPIClass::initialized = 0;
|
||||
uint8_t SPIClass::interruptMode = 0;
|
||||
uint8_t SPIClass::interruptMask = 0;
|
||||
uint8_t SPIClass::interruptSave = 0;
|
||||
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||
uint8_t SPIClass::inTransactionFlag = 0;
|
||||
#endif
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||
if (!initialized) {
|
||||
// Set SS to high so a connected chip will be "deselected" by default
|
||||
uint8_t port = digitalPinToPort(SS);
|
||||
uint8_t bit = digitalPinToBitMask(SS);
|
||||
volatile uint8_t *reg = portModeRegister(port);
|
||||
|
||||
// if the SS pin is not already configured as an output
|
||||
// then set it high (to enable the internal pull-up resistor)
|
||||
if(!(*reg & bit)){
|
||||
digitalWrite(SS, HIGH);
|
||||
}
|
||||
|
||||
// When the SS pin is set as OUTPUT, it can be used as
|
||||
// a general purpose output port (it doesn't influence
|
||||
// SPI operations).
|
||||
pinMode(SS, OUTPUT);
|
||||
|
||||
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
|
||||
// automatically switches to Slave, so the data direction of
|
||||
// the SS pin MUST be kept as OUTPUT.
|
||||
SPCR |= _BV(MSTR);
|
||||
SPCR |= _BV(SPE);
|
||||
|
||||
// Set direction register for SCK and MOSI pin.
|
||||
// MISO pin automatically overrides to INPUT.
|
||||
// By doing this AFTER enabling SPI, we avoid accidentally
|
||||
// clocking in a single bit since the lines go directly
|
||||
// from "input" to SPI control.
|
||||
// http://code.google.com/p/arduino/issues/detail?id=888
|
||||
pinMode(SCK, OUTPUT);
|
||||
pinMode(MOSI, OUTPUT);
|
||||
}
|
||||
initialized++; // reference count
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
void SPIClass::end() {
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||
// Decrease the reference counter
|
||||
if (initialized)
|
||||
initialized--;
|
||||
// If there are no more references disable SPI
|
||||
if (!initialized) {
|
||||
SPCR &= ~_BV(SPE);
|
||||
interruptMode = 0;
|
||||
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||
inTransactionFlag = 0;
|
||||
#endif
|
||||
}
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
// mapping of interrupt numbers to bits within SPI_AVR_EIMSK
|
||||
#if defined(__AVR_ATmega32U4__)
|
||||
#define SPI_INT0_MASK (1<<INT0)
|
||||
#define SPI_INT1_MASK (1<<INT1)
|
||||
#define SPI_INT2_MASK (1<<INT2)
|
||||
#define SPI_INT3_MASK (1<<INT3)
|
||||
#define SPI_INT4_MASK (1<<INT6)
|
||||
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
#define SPI_INT0_MASK (1<<INT0)
|
||||
#define SPI_INT1_MASK (1<<INT1)
|
||||
#define SPI_INT2_MASK (1<<INT2)
|
||||
#define SPI_INT3_MASK (1<<INT3)
|
||||
#define SPI_INT4_MASK (1<<INT4)
|
||||
#define SPI_INT5_MASK (1<<INT5)
|
||||
#define SPI_INT6_MASK (1<<INT6)
|
||||
#define SPI_INT7_MASK (1<<INT7)
|
||||
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
|
||||
#define SPI_INT0_MASK (1<<INT4)
|
||||
#define SPI_INT1_MASK (1<<INT5)
|
||||
#define SPI_INT2_MASK (1<<INT0)
|
||||
#define SPI_INT3_MASK (1<<INT1)
|
||||
#define SPI_INT4_MASK (1<<INT2)
|
||||
#define SPI_INT5_MASK (1<<INT3)
|
||||
#define SPI_INT6_MASK (1<<INT6)
|
||||
#define SPI_INT7_MASK (1<<INT7)
|
||||
#else
|
||||
#ifdef INT0
|
||||
#define SPI_INT0_MASK (1<<INT0)
|
||||
#endif
|
||||
#ifdef INT1
|
||||
#define SPI_INT1_MASK (1<<INT1)
|
||||
#endif
|
||||
#ifdef INT2
|
||||
#define SPI_INT2_MASK (1<<INT2)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void SPIClass::usingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||
switch (interruptNumber) {
|
||||
#ifdef SPI_INT0_MASK
|
||||
case 0: mask = SPI_INT0_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT1_MASK
|
||||
case 1: mask = SPI_INT1_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT2_MASK
|
||||
case 2: mask = SPI_INT2_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT3_MASK
|
||||
case 3: mask = SPI_INT3_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT4_MASK
|
||||
case 4: mask = SPI_INT4_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT5_MASK
|
||||
case 5: mask = SPI_INT5_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT6_MASK
|
||||
case 6: mask = SPI_INT6_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT7_MASK
|
||||
case 7: mask = SPI_INT7_MASK; break;
|
||||
#endif
|
||||
default:
|
||||
interruptMode = 2;
|
||||
break;
|
||||
}
|
||||
interruptMask |= mask;
|
||||
if (!interruptMode)
|
||||
interruptMode = 1;
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
|
||||
{
|
||||
// Once in mode 2 we can't go back to 0 without a proper reference count
|
||||
if (interruptMode == 2)
|
||||
return;
|
||||
uint8_t mask = 0;
|
||||
uint8_t sreg = SREG;
|
||||
noInterrupts(); // Protect from a scheduler and prevent transactionBegin
|
||||
switch (interruptNumber) {
|
||||
#ifdef SPI_INT0_MASK
|
||||
case 0: mask = SPI_INT0_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT1_MASK
|
||||
case 1: mask = SPI_INT1_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT2_MASK
|
||||
case 2: mask = SPI_INT2_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT3_MASK
|
||||
case 3: mask = SPI_INT3_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT4_MASK
|
||||
case 4: mask = SPI_INT4_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT5_MASK
|
||||
case 5: mask = SPI_INT5_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT6_MASK
|
||||
case 6: mask = SPI_INT6_MASK; break;
|
||||
#endif
|
||||
#ifdef SPI_INT7_MASK
|
||||
case 7: mask = SPI_INT7_MASK; break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
// this case can't be reached
|
||||
}
|
||||
interruptMask &= ~mask;
|
||||
if (!interruptMask)
|
||||
interruptMode = 0;
|
||||
SREG = sreg;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue