Browse files

can now select any 4 pins with card.init(), needs testing

  • Loading branch information...
1 parent dea000f commit 3216c04075860edece362818c9c413e9c061a186 @ladyada ladyada committed Aug 8, 2012
Showing with 99 additions and 25 deletions.
  1. +2 −2 SD.cpp
  2. +1 −1 SD.h
  3. +94 −20 utility/Sd2Card.cpp
  4. +2 −2 utility/Sd2Card.h
View
4 SD.cpp
@@ -332,15 +332,15 @@ boolean callback_rmdir(SdFile& parentDir, char *filePathComponent,
-boolean SDClass::begin(uint8_t csPin) {
+boolean SDClass::begin(uint8_t csPin, int8_t mosi, int8_t miso, int8_t sck) {
/*
Performs the initialisation required by the sdfatlib library.
Return true if initialization succeeds, false otherwise.
*/
- return card.init(SPI_HALF_SPEED, csPin) &&
+ return card.init(SPI_HALF_SPEED, csPin, mosi, miso, sck) &&
volume.init(card) &&
root.openRoot(volume);
}
View
2 SD.h
@@ -75,7 +75,7 @@ class SDClass {
public:
// This needs to be called to set up the connection to the SD card
// before other methods are used.
- boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN);
+ boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN, int8_t mosi = -1, int8_t miso = -1, int8_t sck = -1);
// Open the specified file/directory with the supplied mode (e.g. read or
// write, etc). Returns a File object for interacting with the file.
View
114 utility/Sd2Card.cpp
@@ -24,22 +24,75 @@
#endif
#include "Sd2Card.h"
//------------------------------------------------------------------------------
+
+static int8_t mosiPin_, misoPin_, clockPin_;
+static volatile uint8_t *mosiport, *clkport, *misoport;
+static uint8_t mosipinmask, clkpinmask, misopinmask;
+
+//------------------------------------------------------------------------------
+/** nop to tune soft SPI timing */
+#define nop asm volatile ("nop\n\t")
+
#ifndef SOFTWARE_SPI
// functions for hardware SPI
/** Send a byte to the card */
-static void spiSend(uint8_t b) {
- SPDR = b;
- while (!(SPSR & (1 << SPIF)));
+static void spiSend(uint8_t data) {
+ if (clockPin_ == -1) {
+ SPDR = data;
+ while (!(SPSR & (1 << SPIF)));
+ } else {
+ cli();
+ // Fast SPI bitbang swiped from LPD8806 library
+ for (uint8_t i = 0; i < 8; i++) {
+ *clkport &= ~clkpinmask;
+ if (data & 0x80)
+ *mosiport |= mosipinmask;
+ else
+ *mosiport &= ~mosipinmask;
+ *clkport |= clkpinmask;
+ data <<= 1;
+ }
+ nop;nop;nop;nop;
+ *clkport &= ~clkpinmask;
+
+ sei();
+ }
}
+
/** Receive a byte from the card */
static uint8_t spiRec(void) {
- spiSend(0XFF);
- return SPDR;
+ if (clockPin_ == -1) {
+ spiSend(0XFF);
+ return SPDR;
+ } else {
+ uint8_t data = 0;
+ // no interrupts during byte receive - about 8 us
+ cli();
+ // output pin high - like sending 0XFF
+ *mosiport |= mosipinmask;
+
+ for (uint8_t i = 0; i < 8; i++) {
+ *clkport |= clkpinmask;
+ data <<= 1;
+
+ //if (fastDigitalRead(SPI_MISO_PIN)) data |= 1;
+ if ((*misoport) & misopinmask) data |= 1;
+
+ *clkport &= ~clkpinmask;
+
+ // adjust so SCK is nice
+ nop;
+ nop;
+ }
+ // enable interrupts
+ sei();
+ return data;
+ }
}
+
+
#else // SOFTWARE_SPI
-//------------------------------------------------------------------------------
-/** nop to tune soft SPI timing */
-#define nop asm volatile ("nop\n\t")
+
//------------------------------------------------------------------------------
/** Soft SPI receive */
uint8_t spiRec(void) {
@@ -214,29 +267,47 @@ uint8_t Sd2Card::eraseSingleBlockEnable(void) {
* the value zero, false, is returned for failure. The reason for failure
* can be determined by calling errorCode() and errorData().
*/
-uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
+uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin, int8_t mosiPin, int8_t misoPin, int8_t clockPin) {
+
writeCRC_ = errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
chipSelectPin_ = chipSelectPin;
+ mosiPin_ = mosiPin;
+ misoPin_ = misoPin;
+ clockPin_ = clockPin;
// 16-bit init start time allows over a minute
uint16_t t0 = (uint16_t)millis();
uint32_t arg;
// set pin modes
pinMode(chipSelectPin_, OUTPUT);
chipSelectHigh();
- pinMode(SPI_MISO_PIN, INPUT);
- pinMode(SPI_MOSI_PIN, OUTPUT);
- pinMode(SPI_SCK_PIN, OUTPUT);
+
+ if (clockPin != -1) {
+ // use slow bitbang mode
+ pinMode(misoPin_, INPUT);
+ pinMode(mosiPin_, OUTPUT);
+ pinMode(clockPin_, OUTPUT);
+ clkport = portOutputRegister(digitalPinToPort(clockPin_));
+ clkpinmask = digitalPinToBitMask(clockPin_);
+ mosiport = portOutputRegister(digitalPinToPort(mosiPin_));
+ mosipinmask = digitalPinToBitMask(mosiPin_);
+ misoport = portInputRegister(digitalPinToPort(misoPin_));
+ misopinmask = digitalPinToBitMask(misoPin_);
+ } else {
+ pinMode(SPI_MISO_PIN, INPUT);
+ pinMode(SPI_MOSI_PIN, OUTPUT);
+ pinMode(SPI_SCK_PIN, OUTPUT);
#ifndef SOFTWARE_SPI
- // SS must be in output mode even it is not chip select
- pinMode(SS_PIN, OUTPUT);
- digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
- // Enable SPI, Master, clock rate f_osc/128
- SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
- // clear double speed
- SPSR &= ~(1 << SPI2X);
+ // SS must be in output mode even it is not chip select
+ pinMode(SS_PIN, OUTPUT);
+ digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin
+ // Enable SPI, Master, clock rate f_osc/128
+ SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
+ // clear double speed
+ SPSR &= ~(1 << SPI2X);
#endif // SOFTWARE_SPI
+ }
// must supply min of 74 clock cycles with CS high.
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
@@ -285,7 +356,10 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
chipSelectHigh();
#ifndef SOFTWARE_SPI
- return setSckRate(sckRateID);
+ if (clockPin_ == -1)
+ return setSckRate(sckRateID);
+ else
+ return true;
#else // SOFTWARE_SPI
return true;
#endif // SOFTWARE_SPI
View
4 utility/Sd2Card.h
@@ -82,7 +82,7 @@ uint8_t const SPI_MISO_PIN = MISO_PIN;
/** SPI Clock pin */
uint8_t const SPI_SCK_PIN = SCK_PIN;
/** optimize loops for hardware SPI */
-#define OPTIMIZE_HARDWARE_SPI
+//#define OPTIMIZE_HARDWARE_SPI // MEME FIX ME LATER
#else // SOFTWARE_SPI
// define software SPI pins so Mega/Leonardo can use unmodified GPS Shield
@@ -193,7 +193,7 @@ class Sd2Card {
uint8_t init(uint8_t sckRateID) {
return init(sckRateID, SD_CHIP_SELECT_PIN);
}
- uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin);
+ uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin, int8_t mosiPin = -1, int8_t misoPin = -1, int8_t clockPin = -1);
void partialBlockRead(uint8_t value);
/** Returns the current value, true or false, for partial block read. */
uint8_t partialBlockRead(void) const {return partialBlockRead_;}

0 comments on commit 3216c04

Please sign in to comment.