| @@ -75,12 +75,13 @@ void setup() { | |||
| #if WAIT_TO_START | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // Discard input. | |||
| do { | |||
| delay(10); | |||
| } while(Serial.read() >= 0); | |||
| } while(Serial.available() && Serial.read() >= 0); | |||
| #endif // WAIT_TO_START | |||
| #if USE_DS1307 | |||
| @@ -21,7 +21,7 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| Serial.println("type any character to start"); | |||
| while (Serial.read() < 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| if (!sd.begin()) { | |||
| @@ -36,11 +36,14 @@ void loop() { | |||
| uint32_t minLatency; | |||
| uint32_t totalLatency; | |||
| while (Serial.read() >= 0) { | |||
| } | |||
| // Read any existing Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| // F() stores strings in flash to save RAM | |||
| Serial.println(F("Type any character to start")); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| yield(); | |||
| } | |||
| @@ -32,7 +32,7 @@ void setup() { | |||
| } | |||
| // F() stores strings in flash to save RAM | |||
| cout << endl << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -61,7 +61,7 @@ void setup() { | |||
| } | |||
| // F() stores strings in flash to save RAM | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -39,15 +39,15 @@ void loop() { | |||
| uint32_t minLatency; | |||
| uint32_t totalLatency; | |||
| // discard any input | |||
| // Discard any input. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| // F() stores strings in flash to save RAM | |||
| Serial.println(F("Type any character to start")); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| yield(); | |||
| } | |||
| if (!SD.begin(chipSelect)) { | |||
| @@ -42,7 +42,7 @@ void setup() { | |||
| } | |||
| // F() stores strings in flash to save RAM | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| delay(400); // catch Due reset problem | |||
| @@ -91,7 +91,7 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -791,10 +791,10 @@ void setup(void) { | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| void loop(void) { | |||
| // discard any input | |||
| // Read any Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| Serial.println(); | |||
| Serial.println(F("type:")); | |||
| Serial.println(F("c - convert file to csv")); | |||
| @@ -809,10 +809,10 @@ void loop(void) { | |||
| if (ERROR_LED_PIN >= 0) { | |||
| digitalWrite(ERROR_LED_PIN, LOW); | |||
| } | |||
| // Read any extra Serial data. | |||
| // Read any Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| if (c == 'c') { | |||
| binaryToCsv(); | |||
| @@ -63,13 +63,16 @@ void setup() { | |||
| void loop() { | |||
| int c; | |||
| // Discard any Serial input. | |||
| while (Serial.read() > 0) {} | |||
| // Read any existing Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| Serial.print(F("\r\nEnter File Number: ")); | |||
| while ((c = Serial.read()) < 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| c = Serial.read(); | |||
| uint8_t i = c - '0'; | |||
| if (!isdigit(c) || i >= n) { | |||
| Serial.println(F("Invald number")); | |||
| @@ -16,6 +16,7 @@ | |||
| #include <SPI.h> | |||
| #include "SdFat.h" | |||
| #include "FreeStack.h" | |||
| #include "UserDataType.h" // Edit this include file to change data_t. | |||
| //------------------------------------------------------------------------------ | |||
| // Set useSharedSpi true for use of an SPI sensor. | |||
| const bool useSharedSpi = false; | |||
| @@ -24,7 +25,6 @@ const bool useSharedSpi = false; | |||
| uint32_t startMicros; | |||
| //------------------------------------------------------------------------------ | |||
| // User data functions. Modify these functions for your data items. | |||
| #include "UserDataType.h" // Edit this include file to change data_t. | |||
| // Acquire a data record. | |||
| void acquireData(data_t* data) { | |||
| @@ -67,6 +67,7 @@ const uint8_t SD_CS_PIN = SS; | |||
| // Digital pin to indicate an error, set to -1 if not used. | |||
| // The led blinks for fatal errors. The led goes on solid for SD write | |||
| // overrun errors and logging continues. | |||
| #undef ERROR_LED_PIN | |||
| const int8_t ERROR_LED_PIN = -1; | |||
| //------------------------------------------------------------------------------ | |||
| // File definitions. | |||
| @@ -544,10 +545,10 @@ void setup(void) { | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| void loop(void) { | |||
| // discard any input | |||
| // Read any Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| Serial.println(); | |||
| Serial.println(F("type:")); | |||
| Serial.println(F("c - convert file to csv")); | |||
| @@ -563,7 +564,7 @@ void loop(void) { | |||
| // Discard extra Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| if (ERROR_LED_PIN >= 0) { | |||
| digitalWrite(ERROR_LED_PIN, LOW); | |||
| @@ -21,7 +21,7 @@ void setup() { | |||
| } | |||
| Serial.println("Type any character to start"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -36,11 +36,14 @@ void loop() { | |||
| uint32_t minLatency; | |||
| uint32_t totalLatency; | |||
| while (Serial.read() >= 0) { | |||
| } | |||
| // Read any existing Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| // F stores strings in flash to save RAM | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| delay(400); // catch Due reset problem | |||
| @@ -67,10 +67,10 @@ void setup() { | |||
| bool firstTry = true; | |||
| void loop() { | |||
| // read any existing Serial data | |||
| // Read any existing Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| if (!firstTry) { | |||
| cout << F("\nRestarting\n"); | |||
| @@ -155,10 +155,12 @@ void loop() { | |||
| reformatMsg(); | |||
| return; | |||
| } | |||
| // read any existing Serial data | |||
| while (Serial.read() >= 0) {} | |||
| // Read any extra Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| cout << F("\nSuccess! Type any character to restart.\n"); | |||
| while (Serial.read() < 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| } | |||
| @@ -59,12 +59,13 @@ void setup(void) { | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| void loop(void) { | |||
| // Read any extra Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| // F stores strings in flash to save RAM | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -57,7 +57,7 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| Serial.println("Type any character to start"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // Initialize the SD. | |||
| @@ -54,7 +54,7 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| Serial.println("Type any character to start"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // Initialize the SD. | |||
| @@ -33,7 +33,7 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| Serial.println("Type any character to start"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // Initialize SdFat or print a detailed error message and halt | |||
| @@ -445,11 +445,13 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // Discard any extra characters. | |||
| do {delay(10);} while (Serial.read() >= 0); | |||
| do { | |||
| delay(10); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| cout << F( | |||
| "\n" | |||
| "This program can erase and/or format SD/SDHC cards.\n" | |||
| @@ -473,10 +475,10 @@ void setup() { | |||
| cout << F("Quiting, you did not enter 'Y'.\n"); | |||
| return; | |||
| } | |||
| // read any existing Serial data | |||
| // Read any existing Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| cout << F( | |||
| "\n" | |||
| @@ -171,14 +171,14 @@ void setup() { | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| void loop() { | |||
| // read any existing Serial data | |||
| // Read any existing Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| // F stores strings in flash to save RAM | |||
| cout << F("\ntype any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -28,7 +28,7 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| Serial.println("Type any character to start"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -58,7 +58,7 @@ void setup() { | |||
| buf[i] = i; | |||
| } | |||
| Serial.println(F("type any character to start")); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // disable sd2 while initializing sd1 | |||
| @@ -38,7 +38,7 @@ void setup() { | |||
| } | |||
| Serial.println(F("type any character to start")); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -46,7 +46,7 @@ void setup() { | |||
| } | |||
| // F stores strings in flash to save RAM | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with | |||
| @@ -15,10 +15,10 @@ const size_t BUF_SIZE = 512; | |||
| const uint32_t FILE_SIZE_MB = 5; | |||
| // Write pass count. | |||
| const uint8_t WRITE_COUNT = 10; | |||
| const uint8_t WRITE_COUNT = 2; | |||
| // Read pass count. | |||
| const uint8_t READ_COUNT = 5; | |||
| const uint8_t READ_COUNT = 2; | |||
| //============================================================================== | |||
| // End of configuration constants. | |||
| //------------------------------------------------------------------------------ | |||
| @@ -29,6 +29,10 @@ uint8_t buf[BUF_SIZE]; | |||
| // file system | |||
| SdFat sd; | |||
| // Set SD_SPI_CONFIGURATION to three to test next two definitions. | |||
| // SdFatLibSpi sd; | |||
| // Args are misoPin, mosiPin, sckPin. | |||
| // SdFatSoftSpi<6, 7, 5> sd; | |||
| // test file | |||
| SdFile file; | |||
| @@ -81,14 +85,14 @@ void loop() { | |||
| uint32_t minLatency; | |||
| uint32_t totalLatency; | |||
| // discard any input | |||
| // Discard any input. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| // F( stores strings in flash to save RAM | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -102,9 +102,10 @@ void setup() { | |||
| if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) { | |||
| error("file.open"); | |||
| } | |||
| // Read any Serial data. | |||
| do { | |||
| delay(10); | |||
| } while (Serial.read() >= 0); | |||
| } while (Serial.available() && Serial.read() >= 0); | |||
| Serial.print(F("Logging to: ")); | |||
| Serial.println(fileName); | |||
| @@ -67,7 +67,9 @@ void setup(void) { | |||
| } | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) {} | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| delay(400); // catch Due reset problem | |||
| // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with | |||
| @@ -62,8 +62,9 @@ void setup(void) { | |||
| // F stores strings in flash to save RAM | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) {} | |||
| delay(400); // catch Due reset problem | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with | |||
| // breadboards. use SPI_FULL_SPEED for better performance. | |||
| @@ -97,8 +97,9 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| cout << F("Type any character to start\n"); | |||
| while (Serial.read() <= 0) {} | |||
| delay(400); // catch Due reset problem | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with | |||
| // breadboards. use SPI_FULL_SPEED for better performance | |||
| @@ -25,7 +25,7 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| cout << F("Insert an empty SD. Type any character to start.") << endl; | |||
| while (Serial.read() <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| @@ -13,9 +13,10 @@ void setup() { | |||
| SysCall::yield(); | |||
| } | |||
| Serial.println("Type 'Y' to wipe all data."); | |||
| while ((c = Serial.read()) <= 0) { | |||
| while (!Serial.available()) { | |||
| SysCall::yield(); | |||
| } | |||
| c = Serial.read(); | |||
| if (c != 'Y') { | |||
| sd.errorHalt("Quitting, you did not type 'Y'."); | |||
| } | |||
| @@ -32,7 +32,7 @@ | |||
| #endif // ARDUINO | |||
| //------------------------------------------------------------------------------ | |||
| /** SdFat version YYYYMMDD */ | |||
| #define SD_FAT_VERSION 20160411 | |||
| #define SD_FAT_VERSION 20160422 | |||
| //============================================================================== | |||
| /** | |||
| * \class SdBaseFile | |||
| @@ -229,28 +229,34 @@ void fastDigitalWrite(uint8_t pin, bool value) { | |||
| //------------------------------------------------------------------------------ | |||
| /** Set pin value | |||
| * @param[in] pin Arduino pin number | |||
| * @param[in] level value to write | |||
| * @param[in] val value to write | |||
| */ | |||
| static inline __attribute__((always_inline)) | |||
| void fastDigitalWrite(uint8_t pin, uint8_t val) { | |||
| if(pin < 16){ | |||
| if(val) GPOS = (1 << pin); | |||
| else GPOC = (1 << pin); | |||
| } else if(pin == 16){ | |||
| if(val) GP16O |= 1; | |||
| else GP16O &= ~1; | |||
| if (pin < 16) { | |||
| if (val) { | |||
| GPOS = (1 << pin); | |||
| } else { | |||
| GPOC = (1 << pin); | |||
| } | |||
| } else if (pin == 16) { | |||
| if (val) { | |||
| GP16O |= 1; | |||
| } else { | |||
| GP16O &= ~1; | |||
| } | |||
| } | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| /** read pin value | |||
| /** Read pin value | |||
| * @param[in] pin Arduino pin number | |||
| * @return value read | |||
| */ | |||
| static inline __attribute__((always_inline)) | |||
| bool fastDigitalRead(uint8_t pin) { | |||
| if(pin < 16){ | |||
| if (pin < 16) { | |||
| return GPIP(pin); | |||
| } else if(pin == 16){ | |||
| } else if (pin == 16) { | |||
| return GP16I & 0x01; | |||
| } | |||
| return 0; | |||
| @@ -268,7 +274,7 @@ inline void fastDigitalToggle(uint8_t pin) { | |||
| fastDigitalWrite(pin, !fastDigitalRead(pin)); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| inline void fastPinMode(uint8_t pin, uint8_t mode) {pinMode(pin, mode);} | |||
| #define fastPinMode(pin, mode) pinMode(pin, mode) | |||
| #endif // __AVR__ | |||
| //------------------------------------------------------------------------------ | |||
| /** set pin configuration | |||
| @@ -277,11 +283,8 @@ inline void fastPinMode(uint8_t pin, uint8_t mode) {pinMode(pin, mode);} | |||
| * @param[in] level If mode is output, set level high/low. | |||
| * If mode is input, enable or disable the pin's 20K pullup. | |||
| */ | |||
| static inline __attribute__((always_inline)) | |||
| void fastPinConfig(uint8_t pin, uint8_t mode, bool level) { | |||
| fastPinMode(pin, mode); | |||
| fastDigitalWrite(pin, level); | |||
| } | |||
| #define fastPinConfig(pin, mode, level)\ | |||
| {fastPinMode(pin, mode); fastDigitalWrite(pin, level);} | |||
| //============================================================================== | |||
| /** | |||
| * @class DigitalPin | |||
| @@ -1,8 +1,6 @@ | |||
| /* Arduino SdSpi Library | |||
| * Copyright (C) 2013 by William Greiman | |||
| * | |||
| * STM32F1 code for Maple and Maple Mini support, 2015 by Victor Perez | |||
| * | |||
| * This file is part of the Arduino SdSpi Library | |||
| * | |||
| * This Library is free software: you can redistribute it and/or modify | |||
| @@ -21,162 +19,104 @@ | |||
| */ | |||
| #if defined(__STM32F1__) | |||
| #include "SdSpi.h" | |||
| #include <libmaple/dma.h> | |||
| /** Use STM32 DMAC if nonzero */ | |||
| #define USE_STM32F1_DMAC 1 | |||
| /** Time in ms for DMA receive timeout */ | |||
| #define STM32F1_DMA_TIMEOUT 100 | |||
| /** DMAC receive channel */ | |||
| #define SPI1_DMAC_RX_CH DMA_CH2 | |||
| /** DMAC transmit channel */ | |||
| #define SPI1_DMAC_TX_CH DMA_CH3 | |||
| volatile bool SPI_DMA_TX_Active = false; | |||
| volatile bool SPI_DMA_RX_Active = false; | |||
| /** ISR for DMA TX event. */ | |||
| inline void SPI_DMA_TX_Event() { | |||
| SPI_DMA_TX_Active = false; | |||
| dma_disable(DMA1, SPI_DMAC_TX_CH); | |||
| } | |||
| /** ISR for DMA RX event. */ | |||
| inline void SPI_DMA_RX_Event() { | |||
| SPI_DMA_RX_Active = false; | |||
| dma_disable(DMA1, SPI1_DMAC_RX_CH); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| /** Disable DMA Channel. */ | |||
| static void dmac_channel_disable(dma_channel ul_num) { | |||
| dma_disable(DMA1, ul_num); | |||
| } | |||
| /** Enable DMA Channel. */ | |||
| static void dmac_channel_enable(dma_channel ul_num) { | |||
| dma_enable(DMA1, ul_num); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| /** Initialize the SPI bus. | |||
| * | |||
| * \param[in] chipSelectPin SD card chip select pin. | |||
| */ | |||
| void SdSpi::begin(uint8_t chipSelectPin) { | |||
| pinMode(chipSelectPin, OUTPUT); | |||
| digitalWrite(chipSelectPin, HIGH); | |||
| SPI.begin(); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| // start RX DMA | |||
| static void spiDmaRX(uint8_t* dst, uint16_t count) { | |||
| // spi_rx_dma_enable(SPI1); | |||
| if (count < 1) return; | |||
| dma_setup_transfer(DMA1, SPI1_DMAC_RX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS, | |||
| dst, DMA_SIZE_8BITS, (DMA_MINC_MODE | DMA_TRNS_CMPLT)); | |||
| dma_set_num_transfers(DMA1, SPI1_DMAC_RX_CH, count); // 2 bytes per pixel | |||
| SPI_DMA_RX_Active = true; | |||
| dma_enable(DMA1, SPI1_DMAC_RX_CH); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| // start TX DMA | |||
| static void spiDmaTX(const uint8_t* src, uint16_t count) { | |||
| if (count < 1) return; | |||
| static uint8_t ff = 0XFF; | |||
| if (!src) { | |||
| src = &ff; | |||
| dma_setup_transfer(DMA1, SPI1_DMAC_TX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS, | |||
| const_cast<uint8_t*>(src), DMA_SIZE_8BITS, | |||
| (DMA_FROM_MEM | DMA_TRNS_CMPLT)); | |||
| } else { | |||
| dma_setup_transfer(DMA1, SPI1_DMAC_TX_CH, &SPI1->regs->DR, DMA_SIZE_8BITS, | |||
| const_cast<uint8_t*>(src), DMA_SIZE_8BITS, | |||
| (DMA_MINC_MODE | DMA_FROM_MEM | DMA_TRNS_CMPLT)); | |||
| } | |||
| dma_set_num_transfers(DMA1, SPI1_DMAC_TX_CH, count); // 2 bytes per pixel | |||
| SPI_DMA_TX_Active = true; | |||
| dma_enable(DMA1, SPI1_DMAC_TX_CH); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| // initialize SPI controller STM32F1 | |||
| void SdSpi::beginTransaction(uint8_t sckDivisor) { | |||
| /** Set SPI options for access to SD/SDHC cards. | |||
| * | |||
| * \param[in] divisor SCK clock divider relative to the APB1 or APB2 clock. | |||
| */ | |||
| void SdSpi::beginTransaction(uint8_t divisor) { | |||
| #if ENABLE_SPI_TRANSACTIONS | |||
| SPI.beginTransaction(SPISettings()); | |||
| // Correct divisor will be set below. | |||
| SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); | |||
| #endif // ENABLE_SPI_TRANSACTIONS | |||
| if (sckDivisor < SPI_CLOCK_DIV2 || sckDivisor > SPI_CLOCK_DIV256) { | |||
| sckDivisor = SPI_CLOCK_DIV2; // may not be needed, testing. | |||
| uint32_t br; // Baud rate control field in SPI_CR1. | |||
| if (divisor <= 2) { | |||
| br = SPI_CLOCK_DIV2; | |||
| } else if (divisor <= 4) { | |||
| br = SPI_CLOCK_DIV4; | |||
| } else if (divisor <= 8) { | |||
| br = SPI_CLOCK_DIV8; | |||
| } else if (divisor <= 16) { | |||
| br = SPI_CLOCK_DIV16; | |||
| } else if (divisor <= 32) { | |||
| br = SPI_CLOCK_DIV32; | |||
| } else if (divisor <= 64) { | |||
| br = SPI_CLOCK_DIV64; | |||
| } else if (divisor <= 128) { | |||
| br = SPI_CLOCK_DIV128; | |||
| } else { | |||
| br = SPI_CLOCK_DIV256; | |||
| } | |||
| SPI.setClockDivider(sckDivisor); | |||
| SPI.setClockDivider(br); | |||
| #if !ENABLE_SPI_TRANSACTIONS | |||
| SPI.setBitOrder(MSBFIRST); | |||
| SPI.setDataMode(SPI_MODE0); | |||
| #if USE_STM32F1_DMAC | |||
| dma_init(DMA1); | |||
| dma_attach_interrupt(DMA1, SPI1_DMAC_TX_CH, SPI_DMA_TX_Event); | |||
| dma_attach_interrupt(DMA1, SPI1_DMAC_RX_CH, SPI_DMA_RX_Event); | |||
| spi_tx_dma_enable(SPI1); | |||
| spi_rx_dma_enable(SPI1); | |||
| #endif // USE_STM32F1_DMAC | |||
| #endif // !ENABLE_SPI_TRANSACTIONS | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| /** | |||
| * End SPI transaction. | |||
| */ | |||
| void SdSpi::endTransaction() { | |||
| #if ENABLE_SPI_TRANSACTIONS | |||
| SPI.endTransaction(); | |||
| #endif // ENABLE_SPI_TRANSACTIONS | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| // STM32 | |||
| static inline uint8_t spiTransfer(uint8_t b) { | |||
| return SPI.transfer(b); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| // should be valid for STM32 | |||
| /** SPI receive a byte */ | |||
| /** Receive a byte. | |||
| * | |||
| * \return The byte. | |||
| */ | |||
| uint8_t SdSpi::receive() { | |||
| return spiTransfer(0xFF); | |||
| return SPI.transfer(0XFF); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| /** SPI receive multiple bytes */ | |||
| // check and finish. | |||
| /** Receive multiple bytes. | |||
| * | |||
| * \param[out] buf Buffer to receive the data. | |||
| * \param[in] n Number of bytes to receive. | |||
| * | |||
| * \return Zero for no error or nonzero error code. | |||
| */ | |||
| uint8_t SdSpi::receive(uint8_t* buf, size_t n) { | |||
| int rtn = 0; | |||
| #if USE_STM32F1_DMAC | |||
| spiDmaRX(buf, n); | |||
| spiDmaTX(0, n); | |||
| uint32_t m = millis(); | |||
| while (SPI_DMA_RX_Active) { | |||
| if ((millis() - m) > STM32F1_DMA_TIMEOUT) { | |||
| dmac_channel_disable(SPI_DMAC_RX_CH); | |||
| dmac_channel_disable(SPI_DMAC_TX_CH); | |||
| rtn = 2; | |||
| break; | |||
| } | |||
| } | |||
| rtn = SPI.dmaTransfer(0, const_cast<uint8*>(buf), n); | |||
| #else // USE_STM32F1_DMAC | |||
| for (size_t i = 0; i < n; i++) { | |||
| buf[i] = SPI.transfer(0xFF); | |||
| } | |||
| SPI.read(buf, n); | |||
| #endif // USE_STM32F1_DMAC | |||
| return rtn; | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| /** SPI send a byte */ | |||
| /** Send a byte. | |||
| * | |||
| * \param[in] b Byte to send | |||
| */ | |||
| void SdSpi::send(uint8_t b) { | |||
| spiTransfer(b); | |||
| SPI.transfer(b); | |||
| } | |||
| //------------------------------------------------------------------------------ | |||
| /** Send multiple bytes. | |||
| * | |||
| * \param[in] buf Buffer for data to be sent. | |||
| * \param[in] n Number of bytes to send. | |||
| */ | |||
| void SdSpi::send(const uint8_t* buf , size_t n) { | |||
| #if USE_STM32F1_DMAC | |||
| spiDmaTX(buf, n); | |||
| while (SPI_DMA_TX_Active) {} | |||
| SPI.dmaSend(const_cast<uint8*>(buf), n); | |||
| #else // #if USE_STM32F1_DMAC | |||
| SPI.write(buf, n); | |||
| #endif // #if USE_STM32F1_DMAC | |||
| // leave RX register empty | |||
| // while (spi_is_rx_nonempty(SPI1)) | |||
| uint8_t b = spi_rx_reg(SPI1); | |||
| #endif // USE_STM32F1_DMAC | |||
| } | |||
| #endif // USE_NATIVE_STM32F1_SPI | |||
| @@ -34,13 +34,13 @@ | |||
| #define nop asm volatile ("nop\n\t") | |||
| //------------------------------------------------------------------------------ | |||
| /** Pin Mode for MISO is input.*/ | |||
| const bool MISO_MODE = false; | |||
| #define MISO_MODE INPUT | |||
| /** Pullups disabled for MISO are disabled. */ | |||
| const bool MISO_LEVEL = false; | |||
| #define MISO_LEVEL false | |||
| /** Pin Mode for MOSI is output.*/ | |||
| const bool MOSI_MODE = true; | |||
| #define MOSI_MODE OUTPUT | |||
| /** Pin Mode for SCK is output. */ | |||
| const bool SCK_MODE = true; | |||
| #define SCK_MODE OUTPUT | |||
| //------------------------------------------------------------------------------ | |||
| /** | |||
| * @class SoftSPI | |||