mirror of
https://github.com/arduino/Arduino.git
synced 2024-12-01 12:24:14 +01:00
Merge pull request #2223 from PaulStoffregen/ide-1.5.x
SPI Transactions
This commit is contained in:
commit
1824ba1d3b
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
||||||
|
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||||
* SPI Master library for arduino.
|
* SPI Master library for arduino.
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
@ -8,13 +9,20 @@
|
|||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pins_arduino.h"
|
|
||||||
#include "SPI.h"
|
#include "SPI.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
|
|
||||||
SPIClass SPI;
|
SPIClass SPI;
|
||||||
|
|
||||||
void SPIClass::begin() {
|
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()
|
||||||
|
{
|
||||||
// Set SS to high so a connected chip will be "deselected" by default
|
// Set SS to high so a connected chip will be "deselected" by default
|
||||||
digitalWrite(SS, HIGH);
|
digitalWrite(SS, HIGH);
|
||||||
|
|
||||||
@ -39,28 +47,86 @@ void SPIClass::begin() {
|
|||||||
pinMode(MOSI, OUTPUT);
|
pinMode(MOSI, OUTPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SPIClass::end() {
|
void SPIClass::end() {
|
||||||
SPCR &= ~_BV(SPE);
|
SPCR &= ~_BV(SPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::setBitOrder(uint8_t bitOrder)
|
// 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)
|
||||||
{
|
{
|
||||||
if(bitOrder == LSBFIRST) {
|
uint8_t mask;
|
||||||
SPCR |= _BV(DORD);
|
|
||||||
} else {
|
if (interruptMode > 1) return;
|
||||||
SPCR &= ~(_BV(DORD));
|
|
||||||
|
noInterrupts();
|
||||||
|
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;
|
||||||
|
interrupts();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
interruptMode = 1;
|
||||||
|
interruptMask |= mask;
|
||||||
void SPIClass::setDataMode(uint8_t mode)
|
interrupts();
|
||||||
{
|
|
||||||
SPCR = (SPCR & ~SPI_MODE_MASK) | mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIClass::setClockDivider(uint8_t rate)
|
|
||||||
{
|
|
||||||
SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
|
|
||||||
SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
* 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 AVR)
|
||||||
* SPI Master library for arduino.
|
* SPI Master library for arduino.
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
@ -11,9 +13,24 @@
|
|||||||
#ifndef _SPI_H_INCLUDED
|
#ifndef _SPI_H_INCLUDED
|
||||||
#define _SPI_H_INCLUDED
|
#define _SPI_H_INCLUDED
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
|
||||||
|
// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode)
|
||||||
|
#define SPI_HAS_TRANSACTION 1
|
||||||
|
|
||||||
|
// Uncomment this line to add detection of mismatched begin/end transactions.
|
||||||
|
// A mismatch occurs if other libraries fail to use SPI.endTransaction() for
|
||||||
|
// each SPI.beginTransaction(). Connect a LED to this pin. The LED will turn
|
||||||
|
// on if any mismatch is ever detected.
|
||||||
|
//#define SPI_TRANSACTION_MISMATCH_LED 5
|
||||||
|
|
||||||
|
#ifndef LSBFIRST
|
||||||
|
#define LSBFIRST 0
|
||||||
|
#endif
|
||||||
|
#ifndef MSBFIRST
|
||||||
|
#define MSBFIRST 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SPI_CLOCK_DIV4 0x00
|
#define SPI_CLOCK_DIV4 0x00
|
||||||
#define SPI_CLOCK_DIV16 0x01
|
#define SPI_CLOCK_DIV16 0x01
|
||||||
@ -22,7 +39,6 @@
|
|||||||
#define SPI_CLOCK_DIV2 0x04
|
#define SPI_CLOCK_DIV2 0x04
|
||||||
#define SPI_CLOCK_DIV8 0x05
|
#define SPI_CLOCK_DIV8 0x05
|
||||||
#define SPI_CLOCK_DIV32 0x06
|
#define SPI_CLOCK_DIV32 0x06
|
||||||
//#define SPI_CLOCK_DIV64 0x07
|
|
||||||
|
|
||||||
#define SPI_MODE0 0x00
|
#define SPI_MODE0 0x00
|
||||||
#define SPI_MODE1 0x04
|
#define SPI_MODE1 0x04
|
||||||
@ -33,38 +49,236 @@
|
|||||||
#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
|
#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
|
||||||
#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
|
#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
|
||||||
|
|
||||||
|
// define SPI_AVR_EIMSK for AVR boards with external interrupt pins
|
||||||
|
#if defined(EIMSK)
|
||||||
|
#define SPI_AVR_EIMSK EIMSK
|
||||||
|
#elif defined(GICR)
|
||||||
|
#define SPI_AVR_EIMSK GICR
|
||||||
|
#elif defined(GIMSK)
|
||||||
|
#define SPI_AVR_EIMSK GIMSK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SPISettings() {
|
||||||
|
init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
|
||||||
|
}
|
||||||
|
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 known, 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 {
|
class SPIClass {
|
||||||
public:
|
public:
|
||||||
inline static byte transfer(byte _data);
|
// Initialize the SPI library
|
||||||
|
static void begin();
|
||||||
|
|
||||||
// SPI Configuration methods
|
// If SPI is to used from within an interrupt, this function registers
|
||||||
|
// that interrupt with the SPI library, so beginTransaction() can
|
||||||
|
// prevent conflicts. The input interruptNumber is the number used
|
||||||
|
// with attachInterrupt. If SPI is used from a different interrupt
|
||||||
|
// (eg, a timer), interruptNumber should be 255.
|
||||||
|
static void usingInterrupt(uint8_t interruptNumber);
|
||||||
|
|
||||||
inline static void attachInterrupt();
|
// Before using SPI.transfer() or asserting chip select pins,
|
||||||
inline static void detachInterrupt(); // Default
|
// this function is used to gain exclusive access to the SPI bus
|
||||||
|
// and configure the correct settings.
|
||||||
|
inline static void beginTransaction(SPISettings settings) {
|
||||||
|
if (interruptMode > 0) {
|
||||||
|
#ifdef SPI_AVR_EIMSK
|
||||||
|
if (interruptMode == 1) {
|
||||||
|
interruptSave = SPI_AVR_EIMSK;
|
||||||
|
SPI_AVR_EIMSK &= ~interruptMask;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
interruptSave = SREG;
|
||||||
|
cli();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||||
|
if (inTransactionFlag) {
|
||||||
|
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
|
||||||
|
digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
|
||||||
|
}
|
||||||
|
inTransactionFlag = 1;
|
||||||
|
#endif
|
||||||
|
SPCR = settings.spcr;
|
||||||
|
SPSR = settings.spsr;
|
||||||
|
}
|
||||||
|
|
||||||
static void begin(); // Default
|
// Write to the SPI bus (MOSI pin) and also receive (MISO pin)
|
||||||
|
inline static uint8_t transfer(uint8_t data) {
|
||||||
|
SPDR = data;
|
||||||
|
asm volatile("nop");
|
||||||
|
while (!(SPSR & _BV(SPIF))) ; // wait
|
||||||
|
return SPDR;
|
||||||
|
}
|
||||||
|
inline static uint16_t transfer16(uint16_t data) {
|
||||||
|
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
|
||||||
|
in.val = data;
|
||||||
|
if (!(SPCR & _BV(DORD))) {
|
||||||
|
SPDR = in.msb;
|
||||||
|
while (!(SPSR & _BV(SPIF))) ;
|
||||||
|
out.msb = SPDR;
|
||||||
|
SPDR = in.lsb;
|
||||||
|
while (!(SPSR & _BV(SPIF))) ;
|
||||||
|
out.lsb = SPDR;
|
||||||
|
} else {
|
||||||
|
SPDR = in.lsb;
|
||||||
|
while (!(SPSR & _BV(SPIF))) ;
|
||||||
|
out.lsb = SPDR;
|
||||||
|
SPDR = in.msb;
|
||||||
|
while (!(SPSR & _BV(SPIF))) ;
|
||||||
|
out.msb = SPDR;
|
||||||
|
}
|
||||||
|
return out.val;
|
||||||
|
}
|
||||||
|
inline static void transfer(void *buf, size_t count) {
|
||||||
|
if (count == 0) return;
|
||||||
|
uint8_t *p = (uint8_t *)buf;
|
||||||
|
SPDR = *p;
|
||||||
|
while (--count > 0) {
|
||||||
|
uint8_t out = *(p + 1);
|
||||||
|
while (!(SPSR & _BV(SPIF))) ;
|
||||||
|
uint8_t in = SPDR;
|
||||||
|
SPDR = out;
|
||||||
|
*p++ = in;
|
||||||
|
}
|
||||||
|
while (!(SPSR & _BV(SPIF))) ;
|
||||||
|
*p = SPDR;
|
||||||
|
}
|
||||||
|
// After performing a group of transfers and releasing the chip select
|
||||||
|
// signal, this function allows others to access the SPI bus
|
||||||
|
inline static void endTransaction(void) {
|
||||||
|
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||||
|
if (!inTransactionFlag) {
|
||||||
|
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
|
||||||
|
digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
|
||||||
|
}
|
||||||
|
inTransactionFlag = 0;
|
||||||
|
#endif
|
||||||
|
if (interruptMode > 0) {
|
||||||
|
#ifdef SPI_AVR_EIMSK
|
||||||
|
if (interruptMode == 1) {
|
||||||
|
SPI_AVR_EIMSK = interruptSave;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
SREG = interruptSave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the SPI bus
|
||||||
static void end();
|
static void end();
|
||||||
|
|
||||||
static void setBitOrder(uint8_t);
|
// This function is deprecated. New applications should use
|
||||||
static void setDataMode(uint8_t);
|
// beginTransaction() to configure SPI settings.
|
||||||
static void setClockDivider(uint8_t);
|
inline static void setBitOrder(uint8_t bitOrder) {
|
||||||
|
if (bitOrder == LSBFIRST) SPCR |= _BV(DORD);
|
||||||
|
else SPCR &= ~(_BV(DORD));
|
||||||
|
}
|
||||||
|
// This function is deprecated. New applications should use
|
||||||
|
// beginTransaction() to configure SPI settings.
|
||||||
|
inline static void setDataMode(uint8_t dataMode) {
|
||||||
|
SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
|
||||||
|
}
|
||||||
|
// This function is deprecated. New applications should use
|
||||||
|
// beginTransaction() to configure SPI settings.
|
||||||
|
inline static void setClockDivider(uint8_t clockDiv) {
|
||||||
|
SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK);
|
||||||
|
SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK);
|
||||||
|
}
|
||||||
|
// These undocumented functions should not be used. SPI.transfer()
|
||||||
|
// polls the hardware flag which is automatically cleared as the
|
||||||
|
// AVR responds to SPI's interrupt
|
||||||
|
inline static void attachInterrupt() { SPCR |= _BV(SPIE); }
|
||||||
|
inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static uint8_t interruptMode; // 0=none, 1=mask, 2=global
|
||||||
|
static uint8_t interruptMask; // which interrupts to mask
|
||||||
|
static uint8_t interruptSave; // temp storage, to restore state
|
||||||
|
#ifdef SPI_TRANSACTION_MISMATCH_LED
|
||||||
|
static uint8_t inTransactionFlag;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SPIClass SPI;
|
extern SPIClass SPI;
|
||||||
|
|
||||||
byte SPIClass::transfer(byte _data) {
|
|
||||||
SPDR = _data;
|
|
||||||
while (!(SPSR & _BV(SPIF)))
|
|
||||||
;
|
|
||||||
return SPDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIClass::attachInterrupt() {
|
|
||||||
SPCR |= _BV(SPIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIClass::detachInterrupt() {
|
|
||||||
SPCR &= ~_BV(SPIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
||||||
|
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||||
* SPI Master library for arduino.
|
* SPI Master library for arduino.
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* 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)) :
|
|||||||
|
|
||||||
void SPIClass::begin() {
|
void SPIClass::begin() {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
// NPCS control is left to the user
|
// NPCS control is left to the user
|
||||||
|
|
||||||
// Default speed set to 4Mhz
|
// Default speed set to 4Mhz
|
||||||
@ -46,12 +46,100 @@ void SPIClass::begin(uint8_t _pin) {
|
|||||||
void SPIClass::init() {
|
void SPIClass::init() {
|
||||||
if (initialized)
|
if (initialized)
|
||||||
return;
|
return;
|
||||||
|
interruptMode = 0;
|
||||||
|
interruptSave = 0;
|
||||||
|
interruptMask[0] = 0;
|
||||||
|
interruptMask[1] = 0;
|
||||||
|
interruptMask[2] = 0;
|
||||||
|
interruptMask[3] = 0;
|
||||||
initCb();
|
initCb();
|
||||||
SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
|
SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
|
||||||
SPI_Enable(spi);
|
SPI_Enable(spi);
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef interruptsStatus
|
||||||
|
#define interruptsStatus() __interruptsStatus()
|
||||||
|
static inline unsigned char __interruptsStatus(void) __attribute__((always_inline, unused));
|
||||||
|
static inline unsigned char __interruptsStatus(void) {
|
||||||
|
unsigned int primask, faultmask;
|
||||||
|
asm volatile ("mrs %0, primask" : "=r" (primask));
|
||||||
|
if (primask) return 0;
|
||||||
|
asm volatile ("mrs %0, faultmask" : "=r" (faultmask));
|
||||||
|
if (faultmask) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SPIClass::usingInterrupt(uint8_t interruptNumber)
|
||||||
|
{
|
||||||
|
uint8_t irestore;
|
||||||
|
|
||||||
|
irestore = interruptsStatus();
|
||||||
|
noInterrupts();
|
||||||
|
if (interruptMode < 16) {
|
||||||
|
if (interruptNumber > NUM_DIGITAL_PINS) {
|
||||||
|
interruptMode = 16;
|
||||||
|
} else {
|
||||||
|
Pio *pio = g_APinDescription[interruptNumber].pPort;
|
||||||
|
uint32_t mask = g_APinDescription[interruptNumber].ulPin;
|
||||||
|
if (pio == PIOA) {
|
||||||
|
interruptMode |= 1;
|
||||||
|
interruptMask[0] |= mask;
|
||||||
|
} else if (pio == PIOB) {
|
||||||
|
interruptMode |= 2;
|
||||||
|
interruptMask[1] |= mask;
|
||||||
|
} else if (pio == PIOC) {
|
||||||
|
interruptMode |= 4;
|
||||||
|
interruptMask[2] |= mask;
|
||||||
|
} else if (pio == PIOD) {
|
||||||
|
interruptMode |= 8;
|
||||||
|
interruptMask[3] |= mask;
|
||||||
|
} else {
|
||||||
|
interruptMode = 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (irestore) interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIClass::beginTransaction(uint8_t pin, SPISettings settings)
|
||||||
|
{
|
||||||
|
uint8_t mode = interruptMode;
|
||||||
|
if (mode > 0) {
|
||||||
|
if (mode < 16) {
|
||||||
|
if (mode & 1) PIOA->PIO_IDR = interruptMask[0];
|
||||||
|
if (mode & 2) PIOB->PIO_IDR = interruptMask[1];
|
||||||
|
if (mode & 4) PIOC->PIO_IDR = interruptMask[2];
|
||||||
|
if (mode & 8) PIOD->PIO_IDR = interruptMask[3];
|
||||||
|
} else {
|
||||||
|
interruptSave = interruptsStatus();
|
||||||
|
noInterrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(pin);
|
||||||
|
bitOrder[ch] = settings.border;
|
||||||
|
SPI_ConfigureNPCS(spi, ch, settings.config);
|
||||||
|
//setBitOrder(pin, settings.border);
|
||||||
|
//setDataMode(pin, settings.datamode);
|
||||||
|
//setClockDivider(pin, settings.clockdiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIClass::endTransaction(void)
|
||||||
|
{
|
||||||
|
uint8_t mode = interruptMode;
|
||||||
|
if (mode > 0) {
|
||||||
|
if (mode < 16) {
|
||||||
|
if (mode & 1) PIOA->PIO_IER = interruptMask[0];
|
||||||
|
if (mode & 2) PIOB->PIO_IER = interruptMask[1];
|
||||||
|
if (mode & 4) PIOC->PIO_IER = interruptMask[2];
|
||||||
|
if (mode & 8) PIOD->PIO_IER = interruptMask[3];
|
||||||
|
} else {
|
||||||
|
if (interruptSave) interrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SPIClass::end(uint8_t _pin) {
|
void SPIClass::end(uint8_t _pin) {
|
||||||
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
|
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
|
||||||
// Setting the pin as INPUT will disconnect it from SPI peripheral
|
// Setting the pin as INPUT will disconnect it from SPI peripheral
|
||||||
@ -95,12 +183,12 @@ byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
|
|||||||
|
|
||||||
// SPI_Write(spi, _channel, _data);
|
// SPI_Write(spi, _channel, _data);
|
||||||
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
|
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
|
||||||
;
|
;
|
||||||
spi->SPI_TDR = d;
|
spi->SPI_TDR = d;
|
||||||
|
|
||||||
// return SPI_Read(spi);
|
// return SPI_Read(spi);
|
||||||
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
|
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
|
||||||
;
|
;
|
||||||
d = spi->SPI_RDR;
|
d = spi->SPI_RDR;
|
||||||
// Reverse bit order
|
// Reverse bit order
|
||||||
if (bitOrder[ch] == LSBFIRST)
|
if (bitOrder[ch] == LSBFIRST)
|
||||||
@ -137,3 +225,4 @@ static void SPI_0_Init(void) {
|
|||||||
|
|
||||||
SPIClass SPI(SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
|
SPIClass SPI(SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
* Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
|
||||||
|
* Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
|
||||||
* SPI Master library for arduino.
|
* SPI Master library for arduino.
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
@ -14,6 +15,10 @@
|
|||||||
#include "variant.h"
|
#include "variant.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
|
||||||
|
// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode)
|
||||||
|
#define SPI_HAS_TRANSACTION 1
|
||||||
|
|
||||||
#define SPI_MODE0 0x02
|
#define SPI_MODE0 0x02
|
||||||
#define SPI_MODE1 0x00
|
#define SPI_MODE1 0x00
|
||||||
#define SPI_MODE2 0x03
|
#define SPI_MODE2 0x03
|
||||||
@ -24,6 +29,304 @@ enum SPITransferMode {
|
|||||||
SPI_LAST
|
SPI_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SPISettings {
|
||||||
|
public:
|
||||||
|
SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
|
||||||
|
if (__builtin_constant_p(clock)) {
|
||||||
|
init_AlwaysInline(clock, bitOrder, dataMode);
|
||||||
|
} else {
|
||||||
|
init_MightInline(clock, bitOrder, dataMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SPISettings() {
|
||||||
|
init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
|
||||||
|
init_AlwaysInline(clock, bitOrder, dataMode);
|
||||||
|
}
|
||||||
|
void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode)
|
||||||
|
__attribute__((__always_inline__)) {
|
||||||
|
uint8_t div;
|
||||||
|
border = bitOrder;
|
||||||
|
if (__builtin_constant_p(clock)) {
|
||||||
|
if (clock >= F_CPU / 2) div = 2;
|
||||||
|
else if (clock >= F_CPU / 3) div = 3;
|
||||||
|
else if (clock >= F_CPU / 4) div = 4;
|
||||||
|
else if (clock >= F_CPU / 5) div = 5;
|
||||||
|
else if (clock >= F_CPU / 6) div = 6;
|
||||||
|
else if (clock >= F_CPU / 7) div = 7;
|
||||||
|
else if (clock >= F_CPU / 8) div = 8;
|
||||||
|
else if (clock >= F_CPU / 9) div = 9;
|
||||||
|
else if (clock >= F_CPU / 10) div = 10;
|
||||||
|
else if (clock >= F_CPU / 11) div = 11;
|
||||||
|
else if (clock >= F_CPU / 12) div = 12;
|
||||||
|
else if (clock >= F_CPU / 13) div = 13;
|
||||||
|
else if (clock >= F_CPU / 14) div = 14;
|
||||||
|
else if (clock >= F_CPU / 15) div = 15;
|
||||||
|
else if (clock >= F_CPU / 16) div = 16;
|
||||||
|
else if (clock >= F_CPU / 17) div = 17;
|
||||||
|
else if (clock >= F_CPU / 18) div = 18;
|
||||||
|
else if (clock >= F_CPU / 19) div = 19;
|
||||||
|
else if (clock >= F_CPU / 20) div = 20;
|
||||||
|
else if (clock >= F_CPU / 21) div = 21;
|
||||||
|
else if (clock >= F_CPU / 22) div = 22;
|
||||||
|
else if (clock >= F_CPU / 23) div = 23;
|
||||||
|
else if (clock >= F_CPU / 24) div = 24;
|
||||||
|
else if (clock >= F_CPU / 25) div = 25;
|
||||||
|
else if (clock >= F_CPU / 26) div = 26;
|
||||||
|
else if (clock >= F_CPU / 27) div = 27;
|
||||||
|
else if (clock >= F_CPU / 28) div = 28;
|
||||||
|
else if (clock >= F_CPU / 29) div = 29;
|
||||||
|
else if (clock >= F_CPU / 30) div = 30;
|
||||||
|
else if (clock >= F_CPU / 31) div = 31;
|
||||||
|
else if (clock >= F_CPU / 32) div = 32;
|
||||||
|
else if (clock >= F_CPU / 33) div = 33;
|
||||||
|
else if (clock >= F_CPU / 34) div = 34;
|
||||||
|
else if (clock >= F_CPU / 35) div = 35;
|
||||||
|
else if (clock >= F_CPU / 36) div = 36;
|
||||||
|
else if (clock >= F_CPU / 37) div = 37;
|
||||||
|
else if (clock >= F_CPU / 38) div = 38;
|
||||||
|
else if (clock >= F_CPU / 39) div = 39;
|
||||||
|
else if (clock >= F_CPU / 40) div = 40;
|
||||||
|
else if (clock >= F_CPU / 41) div = 41;
|
||||||
|
else if (clock >= F_CPU / 42) div = 42;
|
||||||
|
else if (clock >= F_CPU / 43) div = 43;
|
||||||
|
else if (clock >= F_CPU / 44) div = 44;
|
||||||
|
else if (clock >= F_CPU / 45) div = 45;
|
||||||
|
else if (clock >= F_CPU / 46) div = 46;
|
||||||
|
else if (clock >= F_CPU / 47) div = 47;
|
||||||
|
else if (clock >= F_CPU / 48) div = 48;
|
||||||
|
else if (clock >= F_CPU / 49) div = 49;
|
||||||
|
else if (clock >= F_CPU / 50) div = 50;
|
||||||
|
else if (clock >= F_CPU / 51) div = 51;
|
||||||
|
else if (clock >= F_CPU / 52) div = 52;
|
||||||
|
else if (clock >= F_CPU / 53) div = 53;
|
||||||
|
else if (clock >= F_CPU / 54) div = 54;
|
||||||
|
else if (clock >= F_CPU / 55) div = 55;
|
||||||
|
else if (clock >= F_CPU / 56) div = 56;
|
||||||
|
else if (clock >= F_CPU / 57) div = 57;
|
||||||
|
else if (clock >= F_CPU / 58) div = 58;
|
||||||
|
else if (clock >= F_CPU / 59) div = 59;
|
||||||
|
else if (clock >= F_CPU / 60) div = 60;
|
||||||
|
else if (clock >= F_CPU / 61) div = 61;
|
||||||
|
else if (clock >= F_CPU / 62) div = 62;
|
||||||
|
else if (clock >= F_CPU / 63) div = 63;
|
||||||
|
else if (clock >= F_CPU / 64) div = 64;
|
||||||
|
else if (clock >= F_CPU / 65) div = 65;
|
||||||
|
else if (clock >= F_CPU / 66) div = 66;
|
||||||
|
else if (clock >= F_CPU / 67) div = 67;
|
||||||
|
else if (clock >= F_CPU / 68) div = 68;
|
||||||
|
else if (clock >= F_CPU / 69) div = 69;
|
||||||
|
else if (clock >= F_CPU / 70) div = 70;
|
||||||
|
else if (clock >= F_CPU / 71) div = 71;
|
||||||
|
else if (clock >= F_CPU / 72) div = 72;
|
||||||
|
else if (clock >= F_CPU / 73) div = 73;
|
||||||
|
else if (clock >= F_CPU / 74) div = 74;
|
||||||
|
else if (clock >= F_CPU / 75) div = 75;
|
||||||
|
else if (clock >= F_CPU / 76) div = 76;
|
||||||
|
else if (clock >= F_CPU / 77) div = 77;
|
||||||
|
else if (clock >= F_CPU / 78) div = 78;
|
||||||
|
else if (clock >= F_CPU / 79) div = 79;
|
||||||
|
else if (clock >= F_CPU / 80) div = 80;
|
||||||
|
else if (clock >= F_CPU / 81) div = 81;
|
||||||
|
else if (clock >= F_CPU / 82) div = 82;
|
||||||
|
else if (clock >= F_CPU / 83) div = 83;
|
||||||
|
else if (clock >= F_CPU / 84) div = 84;
|
||||||
|
else if (clock >= F_CPU / 85) div = 85;
|
||||||
|
else if (clock >= F_CPU / 86) div = 86;
|
||||||
|
else if (clock >= F_CPU / 87) div = 87;
|
||||||
|
else if (clock >= F_CPU / 88) div = 88;
|
||||||
|
else if (clock >= F_CPU / 89) div = 89;
|
||||||
|
else if (clock >= F_CPU / 90) div = 90;
|
||||||
|
else if (clock >= F_CPU / 91) div = 91;
|
||||||
|
else if (clock >= F_CPU / 92) div = 92;
|
||||||
|
else if (clock >= F_CPU / 93) div = 93;
|
||||||
|
else if (clock >= F_CPU / 94) div = 94;
|
||||||
|
else if (clock >= F_CPU / 95) div = 95;
|
||||||
|
else if (clock >= F_CPU / 96) div = 96;
|
||||||
|
else if (clock >= F_CPU / 97) div = 97;
|
||||||
|
else if (clock >= F_CPU / 98) div = 98;
|
||||||
|
else if (clock >= F_CPU / 99) div = 99;
|
||||||
|
else if (clock >= F_CPU / 100) div = 100;
|
||||||
|
else if (clock >= F_CPU / 101) div = 101;
|
||||||
|
else if (clock >= F_CPU / 102) div = 102;
|
||||||
|
else if (clock >= F_CPU / 103) div = 103;
|
||||||
|
else if (clock >= F_CPU / 104) div = 104;
|
||||||
|
else if (clock >= F_CPU / 105) div = 105;
|
||||||
|
else if (clock >= F_CPU / 106) div = 106;
|
||||||
|
else if (clock >= F_CPU / 107) div = 107;
|
||||||
|
else if (clock >= F_CPU / 108) div = 108;
|
||||||
|
else if (clock >= F_CPU / 109) div = 109;
|
||||||
|
else if (clock >= F_CPU / 110) div = 110;
|
||||||
|
else if (clock >= F_CPU / 111) div = 111;
|
||||||
|
else if (clock >= F_CPU / 112) div = 112;
|
||||||
|
else if (clock >= F_CPU / 113) div = 113;
|
||||||
|
else if (clock >= F_CPU / 114) div = 114;
|
||||||
|
else if (clock >= F_CPU / 115) div = 115;
|
||||||
|
else if (clock >= F_CPU / 116) div = 116;
|
||||||
|
else if (clock >= F_CPU / 117) div = 117;
|
||||||
|
else if (clock >= F_CPU / 118) div = 118;
|
||||||
|
else if (clock >= F_CPU / 119) div = 119;
|
||||||
|
else if (clock >= F_CPU / 120) div = 120;
|
||||||
|
else if (clock >= F_CPU / 121) div = 121;
|
||||||
|
else if (clock >= F_CPU / 122) div = 122;
|
||||||
|
else if (clock >= F_CPU / 123) div = 123;
|
||||||
|
else if (clock >= F_CPU / 124) div = 124;
|
||||||
|
else if (clock >= F_CPU / 125) div = 125;
|
||||||
|
else if (clock >= F_CPU / 126) div = 126;
|
||||||
|
else if (clock >= F_CPU / 127) div = 127;
|
||||||
|
else if (clock >= F_CPU / 128) div = 128;
|
||||||
|
else if (clock >= F_CPU / 129) div = 129;
|
||||||
|
else if (clock >= F_CPU / 130) div = 130;
|
||||||
|
else if (clock >= F_CPU / 131) div = 131;
|
||||||
|
else if (clock >= F_CPU / 132) div = 132;
|
||||||
|
else if (clock >= F_CPU / 133) div = 133;
|
||||||
|
else if (clock >= F_CPU / 134) div = 134;
|
||||||
|
else if (clock >= F_CPU / 135) div = 135;
|
||||||
|
else if (clock >= F_CPU / 136) div = 136;
|
||||||
|
else if (clock >= F_CPU / 137) div = 137;
|
||||||
|
else if (clock >= F_CPU / 138) div = 138;
|
||||||
|
else if (clock >= F_CPU / 139) div = 139;
|
||||||
|
else if (clock >= F_CPU / 140) div = 140;
|
||||||
|
else if (clock >= F_CPU / 141) div = 141;
|
||||||
|
else if (clock >= F_CPU / 142) div = 142;
|
||||||
|
else if (clock >= F_CPU / 143) div = 143;
|
||||||
|
else if (clock >= F_CPU / 144) div = 144;
|
||||||
|
else if (clock >= F_CPU / 145) div = 145;
|
||||||
|
else if (clock >= F_CPU / 146) div = 146;
|
||||||
|
else if (clock >= F_CPU / 147) div = 147;
|
||||||
|
else if (clock >= F_CPU / 148) div = 148;
|
||||||
|
else if (clock >= F_CPU / 149) div = 149;
|
||||||
|
else if (clock >= F_CPU / 150) div = 150;
|
||||||
|
else if (clock >= F_CPU / 151) div = 151;
|
||||||
|
else if (clock >= F_CPU / 152) div = 152;
|
||||||
|
else if (clock >= F_CPU / 153) div = 153;
|
||||||
|
else if (clock >= F_CPU / 154) div = 154;
|
||||||
|
else if (clock >= F_CPU / 155) div = 155;
|
||||||
|
else if (clock >= F_CPU / 156) div = 156;
|
||||||
|
else if (clock >= F_CPU / 157) div = 157;
|
||||||
|
else if (clock >= F_CPU / 158) div = 158;
|
||||||
|
else if (clock >= F_CPU / 159) div = 159;
|
||||||
|
else if (clock >= F_CPU / 160) div = 160;
|
||||||
|
else if (clock >= F_CPU / 161) div = 161;
|
||||||
|
else if (clock >= F_CPU / 162) div = 162;
|
||||||
|
else if (clock >= F_CPU / 163) div = 163;
|
||||||
|
else if (clock >= F_CPU / 164) div = 164;
|
||||||
|
else if (clock >= F_CPU / 165) div = 165;
|
||||||
|
else if (clock >= F_CPU / 166) div = 166;
|
||||||
|
else if (clock >= F_CPU / 167) div = 167;
|
||||||
|
else if (clock >= F_CPU / 168) div = 168;
|
||||||
|
else if (clock >= F_CPU / 169) div = 169;
|
||||||
|
else if (clock >= F_CPU / 170) div = 170;
|
||||||
|
else if (clock >= F_CPU / 171) div = 171;
|
||||||
|
else if (clock >= F_CPU / 172) div = 172;
|
||||||
|
else if (clock >= F_CPU / 173) div = 173;
|
||||||
|
else if (clock >= F_CPU / 174) div = 174;
|
||||||
|
else if (clock >= F_CPU / 175) div = 175;
|
||||||
|
else if (clock >= F_CPU / 176) div = 176;
|
||||||
|
else if (clock >= F_CPU / 177) div = 177;
|
||||||
|
else if (clock >= F_CPU / 178) div = 178;
|
||||||
|
else if (clock >= F_CPU / 179) div = 179;
|
||||||
|
else if (clock >= F_CPU / 180) div = 180;
|
||||||
|
else if (clock >= F_CPU / 181) div = 181;
|
||||||
|
else if (clock >= F_CPU / 182) div = 182;
|
||||||
|
else if (clock >= F_CPU / 183) div = 183;
|
||||||
|
else if (clock >= F_CPU / 184) div = 184;
|
||||||
|
else if (clock >= F_CPU / 185) div = 185;
|
||||||
|
else if (clock >= F_CPU / 186) div = 186;
|
||||||
|
else if (clock >= F_CPU / 187) div = 187;
|
||||||
|
else if (clock >= F_CPU / 188) div = 188;
|
||||||
|
else if (clock >= F_CPU / 189) div = 189;
|
||||||
|
else if (clock >= F_CPU / 190) div = 190;
|
||||||
|
else if (clock >= F_CPU / 191) div = 191;
|
||||||
|
else if (clock >= F_CPU / 192) div = 192;
|
||||||
|
else if (clock >= F_CPU / 193) div = 193;
|
||||||
|
else if (clock >= F_CPU / 194) div = 194;
|
||||||
|
else if (clock >= F_CPU / 195) div = 195;
|
||||||
|
else if (clock >= F_CPU / 196) div = 196;
|
||||||
|
else if (clock >= F_CPU / 197) div = 197;
|
||||||
|
else if (clock >= F_CPU / 198) div = 198;
|
||||||
|
else if (clock >= F_CPU / 199) div = 199;
|
||||||
|
else if (clock >= F_CPU / 200) div = 200;
|
||||||
|
else if (clock >= F_CPU / 201) div = 201;
|
||||||
|
else if (clock >= F_CPU / 202) div = 202;
|
||||||
|
else if (clock >= F_CPU / 203) div = 203;
|
||||||
|
else if (clock >= F_CPU / 204) div = 204;
|
||||||
|
else if (clock >= F_CPU / 205) div = 205;
|
||||||
|
else if (clock >= F_CPU / 206) div = 206;
|
||||||
|
else if (clock >= F_CPU / 207) div = 207;
|
||||||
|
else if (clock >= F_CPU / 208) div = 208;
|
||||||
|
else if (clock >= F_CPU / 209) div = 209;
|
||||||
|
else if (clock >= F_CPU / 210) div = 210;
|
||||||
|
else if (clock >= F_CPU / 211) div = 211;
|
||||||
|
else if (clock >= F_CPU / 212) div = 212;
|
||||||
|
else if (clock >= F_CPU / 213) div = 213;
|
||||||
|
else if (clock >= F_CPU / 214) div = 214;
|
||||||
|
else if (clock >= F_CPU / 215) div = 215;
|
||||||
|
else if (clock >= F_CPU / 216) div = 216;
|
||||||
|
else if (clock >= F_CPU / 217) div = 217;
|
||||||
|
else if (clock >= F_CPU / 218) div = 218;
|
||||||
|
else if (clock >= F_CPU / 219) div = 219;
|
||||||
|
else if (clock >= F_CPU / 220) div = 220;
|
||||||
|
else if (clock >= F_CPU / 221) div = 221;
|
||||||
|
else if (clock >= F_CPU / 222) div = 222;
|
||||||
|
else if (clock >= F_CPU / 223) div = 223;
|
||||||
|
else if (clock >= F_CPU / 224) div = 224;
|
||||||
|
else if (clock >= F_CPU / 225) div = 225;
|
||||||
|
else if (clock >= F_CPU / 226) div = 226;
|
||||||
|
else if (clock >= F_CPU / 227) div = 227;
|
||||||
|
else if (clock >= F_CPU / 228) div = 228;
|
||||||
|
else if (clock >= F_CPU / 229) div = 229;
|
||||||
|
else if (clock >= F_CPU / 230) div = 230;
|
||||||
|
else if (clock >= F_CPU / 231) div = 231;
|
||||||
|
else if (clock >= F_CPU / 232) div = 232;
|
||||||
|
else if (clock >= F_CPU / 233) div = 233;
|
||||||
|
else if (clock >= F_CPU / 234) div = 234;
|
||||||
|
else if (clock >= F_CPU / 235) div = 235;
|
||||||
|
else if (clock >= F_CPU / 236) div = 236;
|
||||||
|
else if (clock >= F_CPU / 237) div = 237;
|
||||||
|
else if (clock >= F_CPU / 238) div = 238;
|
||||||
|
else if (clock >= F_CPU / 239) div = 239;
|
||||||
|
else if (clock >= F_CPU / 240) div = 240;
|
||||||
|
else if (clock >= F_CPU / 241) div = 241;
|
||||||
|
else if (clock >= F_CPU / 242) div = 242;
|
||||||
|
else if (clock >= F_CPU / 243) div = 243;
|
||||||
|
else if (clock >= F_CPU / 244) div = 244;
|
||||||
|
else if (clock >= F_CPU / 245) div = 245;
|
||||||
|
else if (clock >= F_CPU / 246) div = 246;
|
||||||
|
else if (clock >= F_CPU / 247) div = 247;
|
||||||
|
else if (clock >= F_CPU / 248) div = 248;
|
||||||
|
else if (clock >= F_CPU / 249) div = 249;
|
||||||
|
else if (clock >= F_CPU / 250) div = 250;
|
||||||
|
else if (clock >= F_CPU / 251) div = 251;
|
||||||
|
else if (clock >= F_CPU / 252) div = 252;
|
||||||
|
else if (clock >= F_CPU / 253) div = 253;
|
||||||
|
else if (clock >= F_CPU / 254) div = 254;
|
||||||
|
else /* clock >= F_CPU / 255 */ div = 255;
|
||||||
|
/*
|
||||||
|
#! /usr/bin/perl
|
||||||
|
for ($i=2; $i<256; $i++) {
|
||||||
|
printf "\t\t\telse if (clock >= F_CPU / %3d) div = %3d;\n", $i, $i;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
for (div=2; div<255; div++) {
|
||||||
|
if (clock >= F_CPU / div) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config = (dataMode & 3) | SPI_CSR_CSAAT | SPI_CSR_SCBR(div) | SPI_CSR_DLYBCT(1);
|
||||||
|
//clockdiv = div;
|
||||||
|
//datamode = dataMode;
|
||||||
|
}
|
||||||
|
uint32_t config;
|
||||||
|
//uint8_t clockdiv, datamode;
|
||||||
|
BitOrder border;
|
||||||
|
friend class SPIClass;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SPIClass {
|
class SPIClass {
|
||||||
public:
|
public:
|
||||||
SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void));
|
SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void));
|
||||||
@ -31,8 +334,15 @@ class SPIClass {
|
|||||||
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST) { return transfer(BOARD_SPI_DEFAULT_SS, _data, _mode); }
|
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST) { return transfer(BOARD_SPI_DEFAULT_SS, _data, _mode); }
|
||||||
byte transfer(byte _channel, uint8_t _data, SPITransferMode _mode = SPI_LAST);
|
byte transfer(byte _channel, uint8_t _data, SPITransferMode _mode = SPI_LAST);
|
||||||
|
|
||||||
// SPI Configuration methods
|
// Transaction Functions
|
||||||
|
void usingInterrupt(uint8_t interruptNumber);
|
||||||
|
void beginTransaction(uint8_t pin, SPISettings settings);
|
||||||
|
void beginTransaction(SPISettings settings) {
|
||||||
|
beginTransaction(BOARD_SPI_DEFAULT_SS, settings);
|
||||||
|
}
|
||||||
|
void endTransaction(void);
|
||||||
|
|
||||||
|
// SPI Configuration methods
|
||||||
void attachInterrupt(void);
|
void attachInterrupt(void);
|
||||||
void detachInterrupt(void);
|
void detachInterrupt(void);
|
||||||
|
|
||||||
@ -63,10 +373,23 @@ class SPIClass {
|
|||||||
uint32_t mode[SPI_CHANNELS_NUM];
|
uint32_t mode[SPI_CHANNELS_NUM];
|
||||||
void (*initCb)(void);
|
void (*initCb)(void);
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
uint8_t interruptMode; // 0=none, 1-15=mask, 16=global
|
||||||
|
uint8_t interruptSave; // temp storage, to restore state
|
||||||
|
uint32_t interruptMask[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
#if SPI_INTERFACES_COUNT > 0
|
#if SPI_INTERFACES_COUNT > 0
|
||||||
extern SPIClass SPI;
|
extern SPIClass SPI;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// For compatibility with sketches designed for AVR @ 16 MHz
|
||||||
|
// New programs should use SPI.beginTransaction to set the SPI clock
|
||||||
|
#define SPI_CLOCK_DIV2 11
|
||||||
|
#define SPI_CLOCK_DIV4 21
|
||||||
|
#define SPI_CLOCK_DIV8 42
|
||||||
|
#define SPI_CLOCK_DIV16 84
|
||||||
|
#define SPI_CLOCK_DIV32 168
|
||||||
|
#define SPI_CLOCK_DIV64 255
|
||||||
|
#define SPI_CLOCK_DIV128 255
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,8 +16,10 @@ int EthernetClass::begin(uint8_t *mac_address)
|
|||||||
|
|
||||||
// Initialise the basic info
|
// Initialise the basic info
|
||||||
W5100.init();
|
W5100.init();
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.setMACAddress(mac_address);
|
W5100.setMACAddress(mac_address);
|
||||||
W5100.setIPAddress(IPAddress(0,0,0,0).raw_address());
|
W5100.setIPAddress(IPAddress(0,0,0,0).raw_address());
|
||||||
|
SPI.endTransaction();
|
||||||
|
|
||||||
// Now try to get our config info from a DHCP server
|
// Now try to get our config info from a DHCP server
|
||||||
int ret = _dhcp->beginWithDHCP(mac_address);
|
int ret = _dhcp->beginWithDHCP(mac_address);
|
||||||
@ -25,9 +27,11 @@ int EthernetClass::begin(uint8_t *mac_address)
|
|||||||
{
|
{
|
||||||
// We've successfully found a DHCP server and got our configuration info, so set things
|
// We've successfully found a DHCP server and got our configuration info, so set things
|
||||||
// accordingly
|
// accordingly
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
|
W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
|
||||||
W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
|
W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
|
||||||
W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
|
W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
|
||||||
|
SPI.endTransaction();
|
||||||
_dnsServerAddress = _dhcp->getDnsServerIp();
|
_dnsServerAddress = _dhcp->getDnsServerIp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,10 +65,12 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dn
|
|||||||
void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet)
|
void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet)
|
||||||
{
|
{
|
||||||
W5100.init();
|
W5100.init();
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.setMACAddress(mac);
|
W5100.setMACAddress(mac);
|
||||||
W5100.setIPAddress(local_ip.raw_address());
|
W5100.setIPAddress(local_ip.raw_address());
|
||||||
W5100.setGatewayIp(gateway.raw_address());
|
W5100.setGatewayIp(gateway.raw_address());
|
||||||
W5100.setSubnetMask(subnet.raw_address());
|
W5100.setSubnetMask(subnet.raw_address());
|
||||||
|
SPI.endTransaction();
|
||||||
_dnsServerAddress = dns_server;
|
_dnsServerAddress = dns_server;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,9 +86,11 @@ int EthernetClass::maintain(){
|
|||||||
case DHCP_CHECK_RENEW_OK:
|
case DHCP_CHECK_RENEW_OK:
|
||||||
case DHCP_CHECK_REBIND_OK:
|
case DHCP_CHECK_REBIND_OK:
|
||||||
//we might have got a new IP.
|
//we might have got a new IP.
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
|
W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
|
||||||
W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
|
W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
|
||||||
W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
|
W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
|
||||||
|
SPI.endTransaction();
|
||||||
_dnsServerAddress = _dhcp->getDnsServerIp();
|
_dnsServerAddress = _dhcp->getDnsServerIp();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -96,21 +104,27 @@ int EthernetClass::maintain(){
|
|||||||
IPAddress EthernetClass::localIP()
|
IPAddress EthernetClass::localIP()
|
||||||
{
|
{
|
||||||
IPAddress ret;
|
IPAddress ret;
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.getIPAddress(ret.raw_address());
|
W5100.getIPAddress(ret.raw_address());
|
||||||
|
SPI.endTransaction();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress EthernetClass::subnetMask()
|
IPAddress EthernetClass::subnetMask()
|
||||||
{
|
{
|
||||||
IPAddress ret;
|
IPAddress ret;
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.getSubnetMask(ret.raw_address());
|
W5100.getSubnetMask(ret.raw_address());
|
||||||
|
SPI.endTransaction();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress EthernetClass::gatewayIP()
|
IPAddress EthernetClass::gatewayIP()
|
||||||
{
|
{
|
||||||
IPAddress ret;
|
IPAddress ret;
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.getGatewayIp(ret.raw_address());
|
W5100.getGatewayIp(ret.raw_address());
|
||||||
|
SPI.endTransaction();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < MAX_SOCK_NUM; i++) {
|
for (int i = 0; i < MAX_SOCK_NUM; i++) {
|
||||||
uint8_t s = W5100.readSnSR(i);
|
uint8_t s = socketStatus(i);
|
||||||
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
|
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
|
||||||
_sock = i;
|
_sock = i;
|
||||||
break;
|
break;
|
||||||
@ -88,7 +88,7 @@ size_t EthernetClient::write(const uint8_t *buf, size_t size) {
|
|||||||
|
|
||||||
int EthernetClient::available() {
|
int EthernetClient::available() {
|
||||||
if (_sock != MAX_SOCK_NUM)
|
if (_sock != MAX_SOCK_NUM)
|
||||||
return W5100.getRXReceivedSize(_sock);
|
return recvAvailable(_sock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ uint8_t EthernetClient::connected() {
|
|||||||
|
|
||||||
uint8_t EthernetClient::status() {
|
uint8_t EthernetClient::status() {
|
||||||
if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED;
|
if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED;
|
||||||
return W5100.readSnSR(_sock);
|
return socketStatus(_sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the next function allows us to use the client returned by
|
// the next function allows us to use the client returned by
|
||||||
|
@ -41,7 +41,7 @@ uint8_t EthernetUDP::begin(uint16_t port) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < MAX_SOCK_NUM; i++) {
|
for (int i = 0; i < MAX_SOCK_NUM; i++) {
|
||||||
uint8_t s = W5100.readSnSR(i);
|
uint8_t s = socketStatus(i);
|
||||||
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
|
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
|
||||||
_sock = i;
|
_sock = i;
|
||||||
break;
|
break;
|
||||||
@ -120,7 +120,7 @@ int EthernetUDP::parsePacket()
|
|||||||
// discard any remaining bytes in the last packet
|
// discard any remaining bytes in the last packet
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
if (W5100.getRXReceivedSize(_sock) > 0)
|
if (recvAvailable(_sock) > 0)
|
||||||
{
|
{
|
||||||
//HACK - hand-parse the UDP packet using TCP recv method
|
//HACK - hand-parse the UDP packet using TCP recv method
|
||||||
uint8_t tmpBuf[8];
|
uint8_t tmpBuf[8];
|
||||||
|
@ -12,6 +12,7 @@ uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
|
|||||||
if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE))
|
if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE))
|
||||||
{
|
{
|
||||||
close(s);
|
close(s);
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.writeSnMR(s, protocol | flag);
|
W5100.writeSnMR(s, protocol | flag);
|
||||||
if (port != 0) {
|
if (port != 0) {
|
||||||
W5100.writeSnPORT(s, port);
|
W5100.writeSnPORT(s, port);
|
||||||
@ -22,7 +23,7 @@ uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
W5100.execCmdSn(s, Sock_OPEN);
|
W5100.execCmdSn(s, Sock_OPEN);
|
||||||
|
SPI.endTransaction();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,13 +31,24 @@ uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t socketStatus(SOCKET s)
|
||||||
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
|
uint8_t status = W5100.readSnSR(s);
|
||||||
|
SPI.endTransaction();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function close the socket and parameter is "s" which represent the socket number
|
* @brief This function close the socket and parameter is "s" which represent the socket number
|
||||||
*/
|
*/
|
||||||
void close(SOCKET s)
|
void close(SOCKET s)
|
||||||
{
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.execCmdSn(s, Sock_CLOSE);
|
W5100.execCmdSn(s, Sock_CLOSE);
|
||||||
W5100.writeSnIR(s, 0xFF);
|
W5100.writeSnIR(s, 0xFF);
|
||||||
|
SPI.endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -46,9 +58,13 @@ void close(SOCKET s)
|
|||||||
*/
|
*/
|
||||||
uint8_t listen(SOCKET s)
|
uint8_t listen(SOCKET s)
|
||||||
{
|
{
|
||||||
if (W5100.readSnSR(s) != SnSR::INIT)
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
|
if (W5100.readSnSR(s) != SnSR::INIT) {
|
||||||
|
SPI.endTransaction();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
W5100.execCmdSn(s, Sock_LISTEN);
|
W5100.execCmdSn(s, Sock_LISTEN);
|
||||||
|
SPI.endTransaction();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,9 +86,11 @@ uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// set destination IP
|
// set destination IP
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.writeSnDIPR(s, addr);
|
W5100.writeSnDIPR(s, addr);
|
||||||
W5100.writeSnDPORT(s, port);
|
W5100.writeSnDPORT(s, port);
|
||||||
W5100.execCmdSn(s, Sock_CONNECT);
|
W5100.execCmdSn(s, Sock_CONNECT);
|
||||||
|
SPI.endTransaction();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -85,7 +103,9 @@ uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port)
|
|||||||
*/
|
*/
|
||||||
void disconnect(SOCKET s)
|
void disconnect(SOCKET s)
|
||||||
{
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.execCmdSn(s, Sock_DISCON);
|
W5100.execCmdSn(s, Sock_DISCON);
|
||||||
|
SPI.endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -107,17 +127,21 @@ uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len)
|
|||||||
// if freebuf is available, start.
|
// if freebuf is available, start.
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
freesize = W5100.getTXFreeSize(s);
|
freesize = W5100.getTXFreeSize(s);
|
||||||
status = W5100.readSnSR(s);
|
status = W5100.readSnSR(s);
|
||||||
|
SPI.endTransaction();
|
||||||
if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT))
|
if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT))
|
||||||
{
|
{
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
yield();
|
||||||
}
|
}
|
||||||
while (freesize < ret);
|
while (freesize < ret);
|
||||||
|
|
||||||
// copy data
|
// copy data
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.send_data_processing(s, (uint8_t *)buf, ret);
|
W5100.send_data_processing(s, (uint8_t *)buf, ret);
|
||||||
W5100.execCmdSn(s, Sock_SEND);
|
W5100.execCmdSn(s, Sock_SEND);
|
||||||
|
|
||||||
@ -127,12 +151,17 @@ uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len)
|
|||||||
/* m2008.01 [bj] : reduce code */
|
/* m2008.01 [bj] : reduce code */
|
||||||
if ( W5100.readSnSR(s) == SnSR::CLOSED )
|
if ( W5100.readSnSR(s) == SnSR::CLOSED )
|
||||||
{
|
{
|
||||||
|
SPI.endTransaction();
|
||||||
close(s);
|
close(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
SPI.endTransaction();
|
||||||
|
yield();
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
}
|
}
|
||||||
/* +2008.01 bj */
|
/* +2008.01 bj */
|
||||||
W5100.writeSnIR(s, SnIR::SEND_OK);
|
W5100.writeSnIR(s, SnIR::SEND_OK);
|
||||||
|
SPI.endTransaction();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +175,7 @@ uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len)
|
|||||||
int16_t recv(SOCKET s, uint8_t *buf, int16_t len)
|
int16_t recv(SOCKET s, uint8_t *buf, int16_t len)
|
||||||
{
|
{
|
||||||
// Check how much data is available
|
// Check how much data is available
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
int16_t ret = W5100.getRXReceivedSize(s);
|
int16_t ret = W5100.getRXReceivedSize(s);
|
||||||
if ( ret == 0 )
|
if ( ret == 0 )
|
||||||
{
|
{
|
||||||
@ -172,6 +202,16 @@ int16_t recv(SOCKET s, uint8_t *buf, int16_t len)
|
|||||||
W5100.recv_data_processing(s, buf, ret);
|
W5100.recv_data_processing(s, buf, ret);
|
||||||
W5100.execCmdSn(s, Sock_RECV);
|
W5100.execCmdSn(s, Sock_RECV);
|
||||||
}
|
}
|
||||||
|
SPI.endTransaction();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t recvAvailable(SOCKET s)
|
||||||
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
|
int16_t ret = W5100.getRXReceivedSize(s);
|
||||||
|
SPI.endTransaction();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,8 +223,9 @@ int16_t recv(SOCKET s, uint8_t *buf, int16_t len)
|
|||||||
*/
|
*/
|
||||||
uint16_t peek(SOCKET s, uint8_t *buf)
|
uint16_t peek(SOCKET s, uint8_t *buf)
|
||||||
{
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.recv_data_processing(s, buf, 1, 1);
|
W5100.recv_data_processing(s, buf, 1, 1);
|
||||||
|
SPI.endTransaction();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +254,7 @@ uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint1
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.writeSnDIPR(s, addr);
|
W5100.writeSnDIPR(s, addr);
|
||||||
W5100.writeSnDPORT(s, port);
|
W5100.writeSnDPORT(s, port);
|
||||||
|
|
||||||
@ -227,12 +269,17 @@ uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint1
|
|||||||
{
|
{
|
||||||
/* +2008.01 [bj]: clear interrupt */
|
/* +2008.01 [bj]: clear interrupt */
|
||||||
W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */
|
W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */
|
||||||
|
SPI.endTransaction();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
SPI.endTransaction();
|
||||||
|
yield();
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* +2008.01 bj */
|
/* +2008.01 bj */
|
||||||
W5100.writeSnIR(s, SnIR::SEND_OK);
|
W5100.writeSnIR(s, SnIR::SEND_OK);
|
||||||
|
SPI.endTransaction();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -252,6 +299,7 @@ uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t
|
|||||||
|
|
||||||
if ( len > 0 )
|
if ( len > 0 )
|
||||||
{
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
ptr = W5100.readSnRX_RD(s);
|
ptr = W5100.readSnRX_RD(s);
|
||||||
switch (W5100.readSnMR(s) & 0x07)
|
switch (W5100.readSnMR(s) & 0x07)
|
||||||
{
|
{
|
||||||
@ -306,6 +354,7 @@ uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
W5100.execCmdSn(s, Sock_RECV);
|
W5100.execCmdSn(s, Sock_RECV);
|
||||||
|
SPI.endTransaction();
|
||||||
}
|
}
|
||||||
return data_len;
|
return data_len;
|
||||||
}
|
}
|
||||||
@ -329,6 +378,7 @@ uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
|
|||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.send_data_processing(s, (uint8_t *)buf, ret);
|
W5100.send_data_processing(s, (uint8_t *)buf, ret);
|
||||||
W5100.execCmdSn(s, Sock_SEND);
|
W5100.execCmdSn(s, Sock_SEND);
|
||||||
|
|
||||||
@ -338,18 +388,24 @@ uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
|
|||||||
{
|
{
|
||||||
/* in case of igmp, if send fails, then socket closed */
|
/* in case of igmp, if send fails, then socket closed */
|
||||||
/* if you want change, remove this code. */
|
/* if you want change, remove this code. */
|
||||||
|
SPI.endTransaction();
|
||||||
close(s);
|
close(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
SPI.endTransaction();
|
||||||
|
yield();
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
W5100.writeSnIR(s, SnIR::SEND_OK);
|
W5100.writeSnIR(s, SnIR::SEND_OK);
|
||||||
|
SPI.endTransaction();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
|
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
|
||||||
{
|
{
|
||||||
uint16_t ret =0;
|
uint16_t ret =0;
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
if (len > W5100.getTXFreeSize(s))
|
if (len > W5100.getTXFreeSize(s))
|
||||||
{
|
{
|
||||||
ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size.
|
ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size.
|
||||||
@ -359,6 +415,7 @@ uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
|
|||||||
ret = len;
|
ret = len;
|
||||||
}
|
}
|
||||||
W5100.send_data_processing_offset(s, offset, buf, ret);
|
W5100.send_data_processing_offset(s, offset, buf, ret);
|
||||||
|
SPI.endTransaction();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,14 +431,17 @@ int startUDP(SOCKET s, uint8_t* addr, uint16_t port)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.writeSnDIPR(s, addr);
|
W5100.writeSnDIPR(s, addr);
|
||||||
W5100.writeSnDPORT(s, port);
|
W5100.writeSnDPORT(s, port);
|
||||||
|
SPI.endTransaction();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int sendUDP(SOCKET s)
|
int sendUDP(SOCKET s)
|
||||||
{
|
{
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
W5100.execCmdSn(s, Sock_SEND);
|
W5100.execCmdSn(s, Sock_SEND);
|
||||||
|
|
||||||
/* +2008.01 bj */
|
/* +2008.01 bj */
|
||||||
@ -391,12 +451,17 @@ int sendUDP(SOCKET s)
|
|||||||
{
|
{
|
||||||
/* +2008.01 [bj]: clear interrupt */
|
/* +2008.01 [bj]: clear interrupt */
|
||||||
W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT));
|
W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT));
|
||||||
|
SPI.endTransaction();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
SPI.endTransaction();
|
||||||
|
yield();
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* +2008.01 bj */
|
/* +2008.01 bj */
|
||||||
W5100.writeSnIR(s, SnIR::SEND_OK);
|
W5100.writeSnIR(s, SnIR::SEND_OK);
|
||||||
|
SPI.endTransaction();
|
||||||
|
|
||||||
/* Sent ok */
|
/* Sent ok */
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -4,12 +4,14 @@
|
|||||||
#include "utility/w5100.h"
|
#include "utility/w5100.h"
|
||||||
|
|
||||||
extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode)
|
extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode)
|
||||||
|
extern uint8_t socketStatus(SOCKET s);
|
||||||
extern void close(SOCKET s); // Close socket
|
extern void close(SOCKET s); // Close socket
|
||||||
extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection)
|
extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection)
|
||||||
extern void disconnect(SOCKET s); // disconnect the connection
|
extern void disconnect(SOCKET s); // disconnect the connection
|
||||||
extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection)
|
extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection)
|
||||||
extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP)
|
extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP)
|
||||||
extern int16_t recv(SOCKET s, uint8_t * buf, int16_t len); // Receive data (TCP)
|
extern int16_t recv(SOCKET s, uint8_t * buf, int16_t len); // Receive data (TCP)
|
||||||
|
extern int16_t recvAvailable(SOCKET s);
|
||||||
extern uint16_t peek(SOCKET s, uint8_t *buf);
|
extern uint16_t peek(SOCKET s, uint8_t *buf);
|
||||||
extern uint16_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); // Send data (UDP/IP RAW)
|
extern uint16_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); // Send data (UDP/IP RAW)
|
||||||
extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); // Receive data (UDP/IP RAW)
|
extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); // Receive data (UDP/IP RAW)
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
// W5100 controller instance
|
// W5100 controller instance
|
||||||
W5100Class W5100;
|
W5100Class W5100;
|
||||||
|
|
||||||
#define SPI_CS 10
|
|
||||||
|
|
||||||
#define TX_RX_MAX_BUF_SIZE 2048
|
#define TX_RX_MAX_BUF_SIZE 2048
|
||||||
#define TX_BUF 0x1100
|
#define TX_BUF 0x1100
|
||||||
#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
|
#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
|
||||||
@ -37,9 +35,11 @@ void W5100Class::init(void)
|
|||||||
SPI.setClockDivider(SPI_CS, 21);
|
SPI.setClockDivider(SPI_CS, 21);
|
||||||
SPI.setDataMode(SPI_CS, SPI_MODE0);
|
SPI.setDataMode(SPI_CS, SPI_MODE0);
|
||||||
#endif
|
#endif
|
||||||
|
SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
|
||||||
writeMR(1<<RST);
|
writeMR(1<<RST);
|
||||||
writeTMSR(0x55);
|
writeTMSR(0x55);
|
||||||
writeRMSR(0x55);
|
writeRMSR(0x55);
|
||||||
|
SPI.endTransaction();
|
||||||
|
|
||||||
for (int i=0; i<MAX_SOCK_NUM; i++) {
|
for (int i=0; i<MAX_SOCK_NUM; i++) {
|
||||||
SBASE[i] = TXBUF_BASE + SSIZE * i;
|
SBASE[i] = TXBUF_BASE + SSIZE * i;
|
||||||
|
@ -12,6 +12,14 @@
|
|||||||
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
|
||||||
|
#define SPI_CS 10
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_AVR)
|
||||||
|
#define SPI_ETHERNET_SETTINGS SPISettings(4000000, MSBFIRST, SPI_MODE0)
|
||||||
|
#else
|
||||||
|
#define SPI_ETHERNET_SETTINGS SPI_CS,SPISettings(4000000, MSBFIRST, SPI_MODE0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_SOCK_NUM 4
|
#define MAX_SOCK_NUM 4
|
||||||
|
|
||||||
typedef uint8_t SOCKET;
|
typedef uint8_t SOCKET;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#ifndef SOFTWARE_SPI
|
#ifndef SOFTWARE_SPI
|
||||||
#ifdef USE_SPI_LIB
|
#ifdef USE_SPI_LIB
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
static SPISettings settings;
|
||||||
#endif
|
#endif
|
||||||
// functions for hardware SPI
|
// functions for hardware SPI
|
||||||
/** Send a byte to the card */
|
/** Send a byte to the card */
|
||||||
@ -158,9 +159,15 @@ uint32_t Sd2Card::cardSize(void) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Sd2Card::chipSelectHigh(void) {
|
void Sd2Card::chipSelectHigh(void) {
|
||||||
digitalWrite(chipSelectPin_, HIGH);
|
digitalWrite(chipSelectPin_, HIGH);
|
||||||
|
#ifdef USE_SPI_LIB
|
||||||
|
SPI.endTransaction();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
void Sd2Card::chipSelectLow(void) {
|
void Sd2Card::chipSelectLow(void) {
|
||||||
|
#ifdef USE_SPI_LIB
|
||||||
|
SPI.beginTransaction(settings);
|
||||||
|
#endif
|
||||||
digitalWrite(chipSelectPin_, LOW);
|
digitalWrite(chipSelectPin_, LOW);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -233,7 +240,7 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
|||||||
|
|
||||||
// set pin modes
|
// set pin modes
|
||||||
pinMode(chipSelectPin_, OUTPUT);
|
pinMode(chipSelectPin_, OUTPUT);
|
||||||
chipSelectHigh();
|
digitalWrite(chipSelectPin_, HIGH);
|
||||||
#ifndef USE_SPI_LIB
|
#ifndef USE_SPI_LIB
|
||||||
pinMode(SPI_MISO_PIN, INPUT);
|
pinMode(SPI_MISO_PIN, INPUT);
|
||||||
pinMode(SPI_MOSI_PIN, OUTPUT);
|
pinMode(SPI_MOSI_PIN, OUTPUT);
|
||||||
@ -251,16 +258,18 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
|||||||
SPSR &= ~(1 << SPI2X);
|
SPSR &= ~(1 << SPI2X);
|
||||||
#else // USE_SPI_LIB
|
#else // USE_SPI_LIB
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
#ifdef SPI_CLOCK_DIV128
|
settings = SPISettings(250000, MSBFIRST, SPI_MODE0);
|
||||||
SPI.setClockDivider(SPI_CLOCK_DIV128);
|
|
||||||
#else
|
|
||||||
SPI.setClockDivider(255);
|
|
||||||
#endif
|
|
||||||
#endif // USE_SPI_LIB
|
#endif // USE_SPI_LIB
|
||||||
#endif // SOFTWARE_SPI
|
#endif // SOFTWARE_SPI
|
||||||
|
|
||||||
// must supply min of 74 clock cycles with CS high.
|
// must supply min of 74 clock cycles with CS high.
|
||||||
|
#ifdef USE_SPI_LIB
|
||||||
|
SPI.beginTransaction(settings);
|
||||||
|
#endif
|
||||||
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
|
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
|
||||||
|
#ifdef USE_SPI_LIB
|
||||||
|
SPI.endTransaction();
|
||||||
|
#endif
|
||||||
|
|
||||||
chipSelectLow();
|
chipSelectLow();
|
||||||
|
|
||||||
@ -497,21 +506,15 @@ uint8_t Sd2Card::setSckRate(uint8_t sckRateID) {
|
|||||||
SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0)
|
SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0)
|
||||||
| (sckRateID & 2 ? (1 << SPR0) : 0);
|
| (sckRateID & 2 ? (1 << SPR0) : 0);
|
||||||
#else // USE_SPI_LIB
|
#else // USE_SPI_LIB
|
||||||
int v;
|
|
||||||
#ifdef SPI_CLOCK_DIV128
|
|
||||||
switch (sckRateID) {
|
switch (sckRateID) {
|
||||||
case 0: v=SPI_CLOCK_DIV2; break;
|
case 0: settings = SPISettings(25000000, MSBFIRST, SPI_MODE0); break;
|
||||||
case 1: v=SPI_CLOCK_DIV4; break;
|
case 1: settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); break;
|
||||||
case 2: v=SPI_CLOCK_DIV8; break;
|
case 2: settings = SPISettings(2000000, MSBFIRST, SPI_MODE0); break;
|
||||||
case 3: v=SPI_CLOCK_DIV16; break;
|
case 3: settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); break;
|
||||||
case 4: v=SPI_CLOCK_DIV32; break;
|
case 4: settings = SPISettings(500000, MSBFIRST, SPI_MODE0); break;
|
||||||
case 5: v=SPI_CLOCK_DIV64; break;
|
case 5: settings = SPISettings(250000, MSBFIRST, SPI_MODE0); break;
|
||||||
case 6: v=SPI_CLOCK_DIV128; break;
|
default: settings = SPISettings(125000, MSBFIRST, SPI_MODE0);
|
||||||
}
|
}
|
||||||
#else // SPI_CLOCK_DIV128
|
|
||||||
v = 2 << sckRateID;
|
|
||||||
#endif // SPI_CLOCK_DIV128
|
|
||||||
SPI.setClockDivider(v);
|
|
||||||
#endif // USE_SPI_LIB
|
#endif // USE_SPI_LIB
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user