diff --git a/.gitignore b/.gitignore index b9d6bd92..6dae7474 100644 --- a/.gitignore +++ b/.gitignore @@ -1,215 +1,36 @@ -################# -## Eclipse -################# - -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - - -################# -## Visual Studio -################# - -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results - -[Dd]ebug/ -[Rr]elease/ -x64/ -build/ -[Bb]in/ -[Oo]bj/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.log -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -*.ncrunch* -.*crunch*.local.xml - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml - -# NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line -#packages/ - -# Windows Azure Build Output -csx -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -*.pfx -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf - -############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + .DS_Store +.AppleDouble +.LSOverride +# Icon must ends with two \r. +Icon -############# -## Python -############# - -*.py[co] - -# Packages -*.egg -*.egg-info -dist/ -build/ -eggs/ -parts/ -var/ -sdist/ -develop-eggs/ -.installed.cfg - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox - -#Translations -*.mo +# Thumbnails +._* -#Mr Developer -.mr.developer.cfg +# Files that might appear on external disk +.Spotlight-V100 +.Trashes diff --git a/AnalogBinLoggerExtras/ADC_ENOB.PNG b/AnalogBinLoggerExtras/ADC_ENOB.PNG deleted file mode 100644 index 8f23768d..00000000 Binary files a/AnalogBinLoggerExtras/ADC_ENOB.PNG and /dev/null differ diff --git a/AnalogBinLoggerExtras/ADCdocs/ATmegaADCAccuracy.pdf b/AnalogBinLoggerExtras/ADCdocs/ATmegaADCAccuracy.pdf deleted file mode 100644 index 46ede856..00000000 Binary files a/AnalogBinLoggerExtras/ADCdocs/ATmegaADCAccuracy.pdf and /dev/null differ diff --git a/AnalogBinLoggerExtras/ADCdocs/ExcelFFT.pdf b/AnalogBinLoggerExtras/ADCdocs/ExcelFFT.pdf deleted file mode 100644 index 5e7c94b9..00000000 Binary files a/AnalogBinLoggerExtras/ADCdocs/ExcelFFT.pdf and /dev/null differ diff --git a/AnalogBinLoggerExtras/AdcErrorStudy.txt b/AnalogBinLoggerExtras/AdcErrorStudy.txt deleted file mode 100644 index d24d1f68..00000000 --- a/AnalogBinLoggerExtras/AdcErrorStudy.txt +++ /dev/null @@ -1,98 +0,0 @@ -Static Tests of the Arduino Internal ADC. - -Several people have asked about the DC accuracy of the Arduino ADC when used in my data logging applications at slow sample rates. - -Here are my results of some "hobby level" measurements of the Arduino ADC. - -One question is how important is the ADC clock rate. I did measurents for an ADC clock rate of 125 kHz to 2MHz. - -Another question is how much does Noise Reduction Mode help. I did a series of measurements using this mode. - -Noise Reduction Mode only reduced the mean absolute error slightly. - -I do calibration to remove Offset Error and Gain Error. Calibration is very important for good accuracy. - -These tests depend on the Arduino voltage regulator providing a stable voltage during the tests. The Arduino ADC reference voltage is Vcc for these tests. This may not be realistic for practical applications - -Integral Non-linearity (INL) is the main remaining source of error. - -Here are my results for static (DC) tests of the internal ADC for three UNOs. - -The Arduinos are powered by a high quality nine volt power supply. - -These tests measure a DC level so do not include problems due to time jitter, S/H time, and other dynamic errors. -There are several studies of the dynamic behavior of the Arduino ADC that determine ENOB (Effective Number Of Bits). - -I used a shield with a 12-bit MCP4921 DAC to generate voltage levels. This ADC has an output buffer so it provides a very low impedance source. - -I measured the voltage of the DAC with a calibrated 18-bit MCP3422 ADC on the shield. - -I used DAC levels from 20 to 4075 to avoid zero offset errors at low voltages and DAC buffer problems at high voltages. - -Each series of measurements has 4056 data points. - -This is a voltage range of about 0.023 to 4.972 volts. - -I calibrated the Arduino ADC for each series of measurements with a linear fit of the form. - -v = a + b*adcValue - -Errors are the difference between the value measured with the 18-bit ADC and the calibrated value measured with the AVR ADC. - -I also show the results for no calibration, the NoCal column, using the datasheet formula. - -Vin = Vref*adcValue/1024 - - -The rows in the tables tables are. - -Min - minimum error in millivolts - -Max - maximum error in millivolts - -MAE - mean absolute error in millivolts - - -The columns in the tables are: - -Ideal - results for a perfect 10-bit ADC for comparison. - -NoCal - datasheet formula (5/1024)*adcValue with Noise Reduction Mode. - -NR128 - Noise Reduction mode with Prescaler of 128 (ADC clock of 125 kHz). - -PS128 - analogRead with Prescaler of 128 (ADC clock of 125 kHz). - -PS64 - analogRead with Prescaler of 64 (ADC clock of 250 kHz). - -PS32 - analogRead with Prescaler of 32 (ADC clock of 500 kHz). - -PS16 - analogRead with Prescaler of 16 (ADC clock of 1 MHz). - -PS8 - analogRead with Prescaler of 8 (ADC clock of 2 MHz). - - -Results for three UNO Arduinos - - First Arduino - Error Millivolts - - Ideal NoCal NR128 PS128 PS64 PS32 PS16 PS8 -Min -2.44 -2.43 -3.72 -4.01 -3.88 -4.53 -6.57 -27.18 -Max 2.44 11.69 3.74 4.24 4.15 5.17 8.69 23.21 -MAE 1.22 5.02 1.33 1.38 1.37 1.44 1.96 4.11 - - Second Arduino - Error Millivolts - - Ideal NoCal NR128 PS128 PS64 PS32 PS16 PS8 -Min -2.44 -9.24 -4.87 -4.86 -5.05 -5.34 -6.52 -24.04 -Max 2.44 11.62 3.95 4.64 4.69 5.71 8.41 21.29 -MAE 1.22 5.33 1.41 1.43 1.44 1.53 2.02 4.05 - - Third Arduino - Error Millivolts - - Ideal NoCal NR128 PS128 PS64 PS32 PS16 PS8 -Min -2.44 -7.88 -4.12 -4.40 -4.32 -4.41 -6.97 -26.93 -Max 2.44 12.53 3.80 4.04 4.18 5.27 8.84 24.59 -MAE 1.22 4.85 1.29 1.33 1.34 1.42 1.91 4.10 - - diff --git a/AnalogBinLoggerExtras/DATA.png b/AnalogBinLoggerExtras/DATA.png deleted file mode 100644 index a9b31aa1..00000000 Binary files a/AnalogBinLoggerExtras/DATA.png and /dev/null differ diff --git a/AnalogBinLoggerExtras/FFT.png b/AnalogBinLoggerExtras/FFT.png deleted file mode 100644 index dc481a66..00000000 Binary files a/AnalogBinLoggerExtras/FFT.png and /dev/null differ diff --git a/AnalogBinLoggerExtras/RateTable.txt b/AnalogBinLoggerExtras/RateTable.txt deleted file mode 100644 index 554ba114..00000000 --- a/AnalogBinLoggerExtras/RateTable.txt +++ /dev/null @@ -1,21 +0,0 @@ -Maximum Sample Rate Table - - ADC clock kHz - 125 250 500 1000 -pins -1 7692 14286 25000 40000 -2 3810 6667 11111 16667 -3 2572 4790 8421 13559 -4 1942 3636 6452 10526 -5 1559 2930 5229 8602 -6 1303 2454 4396 7273 -7 1119 2111 3791 6299 -8 980 1852 3333 5556 -9 872 1649 2974 4969 -10 786 1487 2685 4494 -11 715 1354 2446 4103 -12 656 1242 2247 3774 -13 606 1148 2078 3493 -14 563 1067 1932 3252 -15 525 996 1806 3042 -16 493 935 1695 2857 diff --git a/AnalogBinLoggerExtras/bintocsv/AnalogBinLogger.h b/AnalogBinLoggerExtras/bintocsv/AnalogBinLogger.h deleted file mode 100644 index da4d448c..00000000 --- a/AnalogBinLoggerExtras/bintocsv/AnalogBinLogger.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef AnalogBinLogger_h -#define AnalogBinLogger_h -//------------------------------------------------------------------------------ -// First block of file. -struct metadata_t { - unsigned long adcFrequency; // ADC clock frequency - unsigned long cpuFrequency; // CPU clock frequency - unsigned long sampleInterval; // Sample interval in CPU cycles. - unsigned long recordEightBits; // Size of ADC values, nonzero for 8-bits. - unsigned long pinCount; // Number of analog pins in a sample. - unsigned long pinNumber[123]; // List of pin numbers in a sample. -}; -//------------------------------------------------------------------------------ -// Data block for 8-bit ADC mode. -const size_t DATA_DIM8 = 508; -struct block8_t { - unsigned short count; // count of data bytes - unsigned short overrun; // count of overruns since last block - unsigned char data[DATA_DIM8]; -}; -//------------------------------------------------------------------------------ -// Data block for 10-bit ADC mode. -const size_t DATA_DIM16 = 254; -struct block16_t { - unsigned short count; // count of data bytes - unsigned short overrun; // count of overruns since last block - unsigned short data[DATA_DIM16]; -}; -//------------------------------------------------------------------------------ -// Data block for PC use -struct adcdata_t { - unsigned short count; // count of data bytes - unsigned short overrun; // count of overruns since last block - union { - unsigned char u8[DATA_DIM8]; - unsigned short u16[DATA_DIM16]; - } data; -}; -#endif // AnalogBinLogger_h \ No newline at end of file diff --git a/AnalogBinLoggerExtras/bintocsv/bintocsv.cpp b/AnalogBinLoggerExtras/bintocsv/bintocsv.cpp deleted file mode 100644 index 922644b4..00000000 --- a/AnalogBinLoggerExtras/bintocsv/bintocsv.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include "AnalogBinLogger.h" -FILE *source; -FILE *destination; -int count = 0; - -int main(int argc, char** argv) { - metadata_t meta; - adcdata_t adc; - // Make sure no padding/size problems. - if (sizeof(meta) != 512 || sizeof(adc) != 512) { - printf("block size error\n"); - return 0; - } - if (argc != 3) { - printf("missing arguments:\n"); - printf("%s binFile csvFile\n", argv[0]); - return 0; - } - source = fopen(argv[1], "rb"); - if (!source) { - printf("open failed for %s\n", argv[1]); - return 0; - } - if (fread(&meta, sizeof(meta), 1, source) != 1) { - printf("read meta data failed\n"); - return 0; - } - if ( meta.pinCount == 0 - || meta.pinCount > (sizeof(meta.pinNumber)/sizeof(meta.pinNumber[0])) - || meta.adcFrequency < 50000 || meta.adcFrequency > 4000000) { - printf("Invalid meta data\n"); - return 0; - } - destination = fopen(argv[2], "w"); - if (!destination) { - printf("open failed for %s\n", argv[2]); - return 0; - } - int pinCount = meta.pinCount; - printf("pinCount: %d\n", pinCount); - printf("Sample pins:"); - for (unsigned i = 0; i < meta.pinCount; i++) { - printf(" %d", meta.pinNumber[i]); - } - printf("\n"); - printf("ADC clock rate: %g kHz\n", 0.001*meta.adcFrequency); - float sampleInterval = (float)meta.sampleInterval/(float)meta.cpuFrequency; - printf("Sample rate: %g per sec\n", 1.0/sampleInterval); - printf("Sample interval: %.4f usec\n", 1.0e6*sampleInterval); - - fprintf(destination, "Interval,%.4f,usec\n", 1.0e6*sampleInterval); - // Write header with pin numbers - for (int i = 0; i < ((int)meta.pinCount - 1); i++) { - fprintf(destination, "pin%d,", meta.pinNumber[i]); - } - fprintf(destination, "pin%d\n", meta.pinNumber[meta.pinCount - 1]); - unsigned maxCount = meta.recordEightBits ? DATA_DIM8 : DATA_DIM16; - while (!feof(source)) { - if (fread(&adc, sizeof(adc), 1, source) != 1) break; - if (adc.count > maxCount) { - printf("****Invalid data block****\n"); - return 0; - } - if (adc.overrun) { - fprintf(destination, "Overruns,%d\n", adc.overrun); - } - for (int i = 0; i < adc.count; i++) { - unsigned value = meta.recordEightBits ? adc.data.u8[i] : adc.data.u16[i]; - if ((i + 1)%pinCount) { - fprintf(destination, "%d,", value); - } else { - fprintf(destination, "%d\n", value); - } - } - count += adc.count; - } - printf("%d ADC values read\n", count); - fclose(source); - fclose(destination); - return 0; -} \ No newline at end of file diff --git a/AnalogBinLoggerExtras/bintocsv/bintocsv.exe b/AnalogBinLoggerExtras/bintocsv/bintocsv.exe deleted file mode 100644 index cccc192e..00000000 Binary files a/AnalogBinLoggerExtras/bintocsv/bintocsv.exe and /dev/null differ diff --git a/AnalogBinLoggerExtras/readme.txt b/AnalogBinLoggerExtras/readme.txt deleted file mode 100644 index e7a6fe20..00000000 --- a/AnalogBinLoggerExtras/readme.txt +++ /dev/null @@ -1,96 +0,0 @@ -AnalogBinLogger.ino logs analog data to a binary SD file at high rates. - -Samples are logged at regular intervals by using timer1. Timer/Counter1 -Compare Match B is used to trigger the ADC for the first pin in a sample. -The ADC is triggered for remaining sample pins in the ADC conversion complete -interrupt routine. - -Data is captured in the ADC interrupt routine and saved in 512 byte buffers. - -Buffered data is written to the SD in a function called from loop(). The -entire data set is written to a large contiguous file as a single multi-block -write. This reduces write latency problems. - -Many inexpensive SD cards work well at lower rates. I used a $6.00 -SanDisk 4 GB class 4 card for testing. - -SanDisk class 4 cards work well at fairly high rates. I used the 4 GB SanDisk -card to log a single pin at 40,000 samples per second. - -You may need to increase the time between samples if your card has higher -latency. Using a Mega Arduino can help since it has more buffering. - -The bintocsv folder contains a PC program for converting binary files to -CSV files. I have included a executable for Windows. Linux and Mac users -can build from the included source files. bintocvs is a command line program. - -bintocsv binFile csvFile - -AnalogBinLogger requires a recent version of the SdFat library. The SdFat -folder contains a beta version I used for development. - -The latest stable version is here: -http://code.google.com/p/sdfatlib/downloads/list - -You also need to install the included BufferedWriter library. It provides -fast text formatting. - -Example data for a 2 kHz sine wave logged at 40,000 samples per second is -shown in DATA.PNG and FFT.PNG shows a FFT of the data. See ExcelFFT.pdf -in the ADCdocs folder for details on calculating a FFT. - -The accuracy of the ADC samples depends on the ADC clock rate. See the -ADC_ENOB.PNG file for a plot of accuracy vs ADC clock frequency. - -See files in the ADCdocs folder for more information on ADC accuracy. - -To modify this program you will need a good knowledge of the Arduino -ADC, timer1 and C++ programming. This is not for the newbie. - -I have an LED and resistor connected to pin 3 to signal fatal errors and -data overruns. Fatal errors are indicated by a blinking led. Overrun errors -are indicated by a solid lit led. The count of samples dropped is written -to the SD and data logging continues. - -You can disable the error led feature by setting the error pin number negative: - -To use AnalogBinLogger, install these items. - -Place the BufferWriter and SdFat folders in your sketchbook libraries folder. - -Place the AnalogIsrLogger folder in your sketchbook folder. - -You must edit the configuration constants at the beginning of the program -to set the sample pins, sample rate, and other configuration values. - -Initially the program is setup to log the first five analog pins at 5000 -samples per second. Change these values to suit your needs. - -See RateTable.txt for maximum allowed sample rates vs pin count and ADC clock -frequency. - -The program has four commands: - -c - convert file to CSV -d - dump data to Serial -e - overrun error details -r - record ADC data - -All commands can be terminated by entering a character from the serial monitor. - -The c command converts the current binary file to a text file. Entering a -character on the serial monitor terminates the command. - -The d command converts the binary file to text and displays it on the serial -monitor. Entering a character on the serial monitor terminates the command. - -The e command displays details about overruns in the current binary file. -Data overruns happen when data samples are lost due to long write latency -of the SD. - -The r command will record ADC data to a binary file. It will terminate -when a character is entered on the serial monitor or the the maximum file -block count has been reached. - -A number of program options can be set by changing constants at the beginning -of the program. \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..a8147353 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2011..2020 Bill Greiman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..03c829b9 --- /dev/null +++ b/README.md @@ -0,0 +1,194 @@ +### Warning: This version has major internal changes. +SdFat version 2.3.1 corrects handling of the exFAT fields validLength +and dataLength. + +In exFAT, validLength represents how far user data has been written and +dataLength represents the total space allocated to the file. + +These two fields are equal unless space has been preallocated. In the past, I +returned EOF when a read hit validLength and didn't allow seek beyond +validLength. This does not conform to the exFat specification here: + +https://learn.microsoft.com/en-us/windows/win32/fileio/exfat-specification + +Now read will return zeroes beyond validLength and EOF at dataLength. If a +file is positioned beyond validLength, write will fill the area between +validLength and the current position with zeroes and then write user data. + +If you are preallocating space with the preAllocate() call, you should remove +unused space with the truncate() call so applications do not read zeroes +beyond validLength. + +Support has been added for the SDIO on RP2350B QFN-80 with 48 GPIO pins. +Each PIO block is still limited to 32 GPIOs at a time, but GPIOBASE +selects which 32. + +GPIOBASE can only have value of zero or 16 so all SDIO pins must be in the +range 0-31 or 16-47. + +Run the Rp2040SdioSetup example to try RP2040/RP2350 SDIO. + +This example requires a SDIO Card socket with the following six lines. + +* CLK - A clock signal sent to the card by the MCU. +* CMD - A bidirectional line for for commands and responses. +* DAT[0:3] - Four bidirectional lines for data transfer. + +CLK and CMD can be connected to any GPIO pins. DAT[0:3] can be connected +to any four consecutive GPIO pins in the order DAT0, DAT1, DAT2, DAT3. + +Here is an example of SDIO for Pico using an Adafruit socket, PiCowbell +Proto and PiCowbell Proto Doubler. + +![Alt text](images/SdioSpi.jpg) + +This Socket supports SDIO with: +``` +#define RP_CLK_GPIO 10 +#define RP_CMD_GPIO 11 +#define RP_DAT0_GPIO 12 // DAT1: GPIO13 DAT2: GPIO14, DAT3: GPIO15. +``` +It also can be used on SPI1 with: +``` +const uint8_t SD_CS_PIN = 15; +#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK, &SPI1) + + // In setup + SPI1.setSCK(10); + SPI1.setTX(11); + SPI1.setRX(12); +``` + +This setup gets the following result in the bench example using SDIO. + +
+FILE_SIZE_MB = 5
+BUF_SIZE = 512 bytes
+Starting write test, please wait.
+
+write speed and latency
+speed,max,min,avg
+KB/Sec,usec,usec,usec
+15014.05,1165,32,32
+15289.54,1249,32,32
+
+Starting read test, please wait.
+
+read speed and latency
+speed,max,min,avg
+KB/Sec,usec,usec,usec
+15624.00,58,32,32
+15624.00,51,32,32
+
+ + +File copy constructors and file assignment operators have been made private by +default in 2.2.3 to prevent call by value and multiple copies of file instances. + +SdFatConfig.h has options to make file constructors and assignment operators +public. + +UTF-8 encoded filenames are supported in v2.1.0 or later. + +Try the UnicodeFilenames example. Here is output from ls: +
+Type any character to begin
+ls:
+         0 😀/
+          20 россиянин
+          17 très élégant
+           9 狗.txt
+
+ +SdFat Version 2 supports FAT16/FAT32 and exFAT SD cards. It is mostly +backward compatible with SdFat Version 1 for FAT16/FAT32 cards. + +exFAT supports files larger than 4GB so files sizes and positions are +type uint64_t for classes that support exFAT. + +exFAT has many features not available in FAT16/FAT32. exFAT has excellent +support for contiguous files on flash devices and supports preallocation. + +If the SD card is the only SPI device, use dedicated SPI mode. This can +greatly improve performance. See the bench example. + +Here is write performance for an old, 2011, card on a Due board. +``` +Shared SPI: +write speed and latency +speed,max,min,avg +KB/Sec,usec,usec,usec +294.45,24944,1398,1737 + +Dedicated SPI: +write speed and latency +speed,max,min,avg +KB/Sec,usec,usec,usec +3965.11,16733,110,127 +``` +The default version of SdFatConfig.h enables support for dedicated SPI and +optimized access to contiguous files. This makes SdFat Version 2 slightly +larger than Version 1. If these features are disabled, Version 2 is smaller +than Version 1. + +The types for the classes SdFat and File are defined in SdFatConfig.h. +The default version of SdFatConfig.h defines SdFat to only support FAT16/FAT32. +SdFat and File are defined in terms of more basic classes by typedefs. You +can use these basic classes in applications. + +Support for exFAT requires a substantial amount of flash. Here are sizes on +an UNO for a simple program that opens a file, prints one line, and closes +the file. +``` +FAT16/FAT32 only: 9780 bytes flash, 875 bytes SRAM. + +exFAT only: 13830 bytes flash, 938 bytes SRAM. + +FAT16/FAT32/exFAT: 19326 bytes flash, 928 bytes SRAM. +``` +The section below of SdFatConfig.h has been edited to uses FAT16/FAT32 for +small AVR boards and FAT16/FAT32/exFAT for all other boards. +``` +/** + * File types for SdFat, File, SdFile, SdBaseFile, fstream, + * ifstream, and ofstream. + * + * Set SDFAT_FILE_TYPE to: + * + * 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. + */ +#if defined(__AVR__) && FLASHEND < 0X8000 +// FAT16/FAT32 for 32K AVR boards. +#define SDFAT_FILE_TYPE 1 +#else // defined(__AVR__) && FLASHEND < 0X8000 +// FAT16/FAT32 and exFAT for all other boards. +#define SDFAT_FILE_TYPE 3 +#endif // defined(__AVR__) && FLASHEND < 0X8000 +``` +The SdBaseFile class has no Arduino Stream or Print support. + +The File class is derived from Stream and SdBaseFile. + +The SdFile class is derived from SdBaseFile and Print. + +Please try the examples. Start with SdInfo, bench, and ExFatLogger. + +To use SdFat Version 2, unzip the download file, rename the library folder +SdFat and place the SdFat folder into the libraries sub-folder in your main +sketch folder. + +For more information see the Manual installation section of this guide: + +http://arduino.cc/en/Guide/Libraries + +A number of configuration options can be set by editing SdFatConfig.h +define macros. See the html documentation File tab for details. + +Please read the html documentation for this library in SdFat/doc/SdFat.html. +Start with the Main Page. Next go to the Classes tab and read the +documentation for the classes SdFat32, SdExFat, SdFs, File32, ExFile, FsFile. + +The SdFat and File classes are defined in terms of the above classes by +typedefs. Edit SdFatConfig.h to select class options. + +Please continue by reading the html documentation in the SdFat/doc folder. diff --git a/SdFat/MinimumSerial.cpp b/SdFat/MinimumSerial.cpp deleted file mode 100644 index 1218566e..00000000 --- a/SdFat/MinimumSerial.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#include -#if defined(UDR0) || defined(DOXYGEN) -#include "MinimumSerial.h" -const uint16_t MIN_2X_BAUD = F_CPU/(4*(2*0XFFF + 1)) + 1; -//------------------------------------------------------------------------------ -void MinimumSerial::begin(uint32_t baud) { - uint16_t baud_setting; - // don't worry, the compiler will squeeze out F_CPU != 16000000UL - if ((F_CPU != 16000000UL || baud != 57600) && baud > MIN_2X_BAUD) { - // Double the USART Transmission Speed - UCSR0A = 1 << U2X0; - baud_setting = (F_CPU / 4 / baud - 1) / 2; - } else { - // hardcoded exception for compatibility with the bootloader shipped - // with the Duemilanove and previous boards and the firmware on the 8U2 - // on the Uno and Mega 2560. - UCSR0A = 0; - baud_setting = (F_CPU / 8 / baud - 1) / 2; - } - // assign the baud_setting - UBRR0H = baud_setting >> 8; - UBRR0L = baud_setting; - // enable transmit and receive - UCSR0B |= (1 << TXEN0) | (1 << RXEN0); -} -//------------------------------------------------------------------------------ -int MinimumSerial::read() { - if (UCSR0A & (1 << RXC0)) { - return UDR0; - } - return -1; -} -//------------------------------------------------------------------------------ -size_t MinimumSerial::write(uint8_t b) { - while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {} - UDR0 = b; - return 1; -} -#endif // defined(UDR0) || defined(DOXYGEN) diff --git a/SdFat/MinimumSerial.h b/SdFat/MinimumSerial.h deleted file mode 100644 index 667668f9..00000000 --- a/SdFat/MinimumSerial.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#ifndef MinimumSerial_h -#define MinimumSerial_h -#include -//============================================================================== -/** - * \class MinimumSerial - * \brief mini serial class for the %SdFat library. - */ -class MinimumSerial : public Print { - public: - /** - * Set baud rate for serial port zero and enable in non interrupt mode. - * Do not call this function if you use another serial library. - * \param[in] baud rate - */ - void begin(uint32_t baud); - /** - * Unbuffered read - * \return -1 if no character is available or an available character. - */ - int read(); - /** - * Unbuffered write - * - * \param[in] b byte to write. - * \return 1 - */ - size_t write(uint8_t b); - using Print::write; -}; -#endif // MinimumSerial_h diff --git a/SdFat/SdFat.h b/SdFat/SdFat.h deleted file mode 100644 index b6724a4d..00000000 --- a/SdFat/SdFat.h +++ /dev/null @@ -1,341 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFat_h -#define SdFat_h -/** - * \file - * \brief SdFat class - */ -#include "SdSpiCard.h" -#include "utility/FatLib.h" -//------------------------------------------------------------------------------ -/** SdFat version YYYYMMDD */ -#define SD_FAT_VERSION 20150324 -//============================================================================== -/** - * \class SdBaseFile - * \brief Class for backward compatibility. - */ -class SdBaseFile : public FatFile { - public: - SdBaseFile() {} - /** Create a file object and open it in the current working directory. - * - * \param[in] path A path for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a - * bitwise-inclusive OR of open flags. see - * FatFile::open(FatFile*, const char*, uint8_t). - */ - SdBaseFile(const char* path, uint8_t oflag) : FatFile(path, oflag) {} -}; -#if ENABLE_ARDUINO_FEATURES -/** - * \class SdFile - * \brief Class for backward compatibility. - */ - -class SdFile : public PrintFile { - public: - SdFile() {} - /** Create a file object and open it in the current working directory. - * - * \param[in] path A path for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a - * bitwise-inclusive OR of open flags. see - * FatFile::open(FatFile*, const char*, uint8_t). - */ - SdFile(const char* path, uint8_t oflag) : PrintFile(path, oflag) {} -}; -#endif // #if ENABLE_ARDUINO_FEATURES -/** - * \class SdFatBase - * \brief Virtual base class for %SdFat library. - */ -class SdFatBase : public FatFileSystem { - public: - /** Initialize SD card and file system. - * \param[in] spi SPI object for the card. - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool begin(SdSpiCard::m_spi_t* spi, uint8_t csPin = SS, uint8_t divisor = 2) { - return m_sdCard.begin(spi, csPin, divisor) && - FatFileSystem::begin(); - } - /** \return Pointer to SD card object */ - SdSpiCard *card() { - return &m_sdCard; - } - /** %Print any SD error code to Serial and halt. */ - void errorHalt() { - errorHalt(&Serial); - } - /** %Print any SD error code and halt. - * - * \param[in] pr Print destination. - */ - void errorHalt(Print* pr); - /** %Print msg, any SD error code and halt. - * - * \param[in] msg Message to print. - */ - void errorHalt(char const* msg) { - errorHalt(&Serial, msg); - } - /** %Print msg, any SD error code, and halt. - * - * \param[in] pr Print destination. - * \param[in] msg Message to print. - */ - void errorHalt(Print* pr, char const* msg); - /** %Print msg, any SD error code, and halt. - * - * \param[in] msg Message to print. - */ - void errorHalt(const __FlashStringHelper* msg) { - errorHalt(&Serial, msg); - } - /** %Print msg, any SD error code, and halt. - * - * \param[in] pr Print destination. - * \param[in] msg Message to print. - */ - void errorHalt(Print* pr, const __FlashStringHelper* msg); - /** %Print any SD error code to Serial */ - void errorPrint() { - errorPrint(&Serial); - } - /** %Print any SD error code. - * \param[in] pr Print device. - */ - void errorPrint(Print* pr); - /** %Print msg, any SD error code. - * - * \param[in] msg Message to print. - */ - void errorPrint(const char* msg) { - errorPrint(&Serial, msg); - } - /** %Print msg, any SD error code. - * - * \param[in] pr Print destination. - * \param[in] msg Message to print. - */ - void errorPrint(Print* pr, char const* msg); - /** %Print msg, any SD error code. - * - * \param[in] msg Message to print. - */ - void errorPrint(const __FlashStringHelper* msg) { - errorPrint(&Serial, msg); - } - /** %Print msg, any SD error code. - * - * \param[in] pr Print destination. - * \param[in] msg Message to print. - */ - void errorPrint(Print* pr, const __FlashStringHelper* msg); - /** Diagnostic call to initialize FatFileSystem - use for - * diagnostic purposes only. - * \return true for success else false. - */ - bool fsBegin() { - return FatFileSystem::begin(); - } - /** %Print any SD error code and halt. */ - void initErrorHalt() { - initErrorHalt(&Serial); - } - /** %Print error details and halt after begin fails. - * - * \param[in] pr Print destination. - */ - void initErrorHalt(Print* pr); - /**Print message, error details, and halt after SdFat::init() fails. - * - * \param[in] msg Message to print. - */ - void initErrorHalt(char const *msg) { - initErrorHalt(&Serial, msg); - } - /**Print message, error details, and halt after SdFatBase::init() fails. - * \param[in] pr Print device. - * \param[in] msg Message to print. - */ - void initErrorHalt(Print* pr, char const *msg); - /**Print message, error details, and halt after SdFat::init() fails. - * - * \param[in] msg Message to print. - */ - void initErrorHalt(const __FlashStringHelper* msg) { - initErrorHalt(&Serial, msg); - } - /**Print message, error details, and halt after SdFatBase::init() fails. - * \param[in] pr Print device for message. - * \param[in] msg Message to print. - */ - void initErrorHalt(Print* pr, const __FlashStringHelper* msg); - /** Print error details after SdFat::init() fails. */ - void initErrorPrint() { - initErrorPrint(&Serial); - } - /** Print error details after SdFatBase::init() fails. - * - * \param[in] pr Print destination. - */ - void initErrorPrint(Print* pr); - /**Print message and error details and halt after SdFat::init() fails. - * - * \param[in] msg Message to print. - */ - void initErrorPrint(char const *msg) { - initErrorPrint(&Serial, msg); - } - /**Print message and error details and halt after SdFatBase::init() fails. - * - * \param[in] pr Print destination. - * \param[in] msg Message to print. - */ - void initErrorPrint(Print* pr, char const *msg); - /**Print message and error details and halt after SdFat::init() fails. - * - * \param[in] msg Message to print. - */ - void initErrorPrint(const __FlashStringHelper* msg) { - initErrorPrint(&Serial, msg); - } - /**Print message and error details and halt after SdFatBase::init() fails. - * - * \param[in] pr Print destination. - * \param[in] msg Message to print. - */ - void initErrorPrint(Print* pr, const __FlashStringHelper* msg); - - private: - uint8_t cardErrorCode() { - return m_sdCard.errorCode(); - } - uint8_t cardErrorData() { - return m_sdCard.errorData(); - } - bool readBlock(uint32_t block, uint8_t* dst) { - return m_sdCard.readBlock(block, dst); - } - bool writeBlock(uint32_t block, const uint8_t* src) { - return m_sdCard.writeBlock(block, src); - } - bool readBlocks(uint32_t block, uint8_t* dst, size_t n) { - return m_sdCard.readBlocks(block, dst, n); - } - bool writeBlocks(uint32_t block, const uint8_t* src, size_t n) { - return m_sdCard.writeBlocks(block, src, n); - } - SdSpiCard m_sdCard; -}; -//============================================================================== -/** - * \class SdFat - * \brief Main file system class for %SdFat library. - */ -class SdFat : public SdFatBase { - public: - /** Initialize SD card and file system. - * - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool begin(uint8_t csPin = SS, uint8_t divisor = 2) { - return SdFatBase::begin(&m_spi, csPin, divisor); - } - /** Diagnostic call to initialize SD card - use for diagnostic purposes only. - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool cardBegin(uint8_t csPin = SS, uint8_t divisor = 2) { - return card()->begin(&m_spi, csPin, divisor); - } - private: - SpiDefault_t m_spi; -}; -//============================================================================== -#if SD_SPI_CONFIGURATION >= 3 || defined(DOXYGEN) -/** - * \class SdFatLibSpi - * \brief SdFat class using the standard Arduino SPI library. - */ -class SdFatLibSpi: public SdFatBase { - public: - /** Initialize SD card and file system. - * - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool begin(uint8_t csPin = SS, uint8_t divisor = 2) { - return SdFatBase::begin(&m_spi, csPin, divisor); - } - /** Diagnostic call to initialize SD card - use for diagnostic purposes only. - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool cardBegin(uint8_t csPin = SS, uint8_t divisor = 2) { - return card()->begin(&m_spi, csPin, divisor); - } - - private: - SdSpiLib m_spi; -}; -//============================================================================== -/** - * \class SdFatSoftSpi - * \brief SdFat class using software SPI. - */ -template -class SdFatSoftSpi : public SdFatBase { - public: - /** Initialize SD card and file system. - * - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool begin(uint8_t csPin = SS, uint8_t divisor = 2) { - return SdFatBase::begin(&m_spi, csPin, divisor); - } - /** Diagnostic call to initialize SD card - use for diagnostic purposes only. - * \param[in] csPin SD card chip select pin. - * \param[in] divisor SPI divisor. - * \return true for success else false. - */ - bool cardBegin(uint8_t csPin = SS, uint8_t divisor = 2) { - return card()->begin(&m_spi, csPin, divisor); - } - - private: - SdSpiSoft m_spi; -}; -#endif /// SD_SPI_CONFIGURATION >= 3 || defined(DOXYGEN) -#endif // SdFat_h diff --git a/SdFat/SdFatBase.cpp b/SdFat/SdFatBase.cpp deleted file mode 100644 index 1727b0ac..00000000 --- a/SdFat/SdFatBase.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#include "SdFat.h" -//------------------------------------------------------------------------------ -void SdFatBase::errorHalt(Print* pr) { - errorPrint(pr); - while (1) {} -} -//------------------------------------------------------------------------------ -void SdFatBase::errorHalt(Print* pr, char const* msg) { - errorPrint(pr, msg); - while (1) {} -} -//------------------------------------------------------------------------------ -void SdFatBase::errorHalt(Print* pr, const __FlashStringHelper* msg) { - errorPrint(pr, msg); - while (1) {} -} -//------------------------------------------------------------------------------ -void SdFatBase::errorPrint(Print* pr) { - if (!cardErrorCode()) { - return; - } - pr->print(F("SD errorCode: 0X")); - pr->print(cardErrorCode(), HEX); - pr->print(F(",0X")); - pr->println(cardErrorData(), HEX); -} -//------------------------------------------------------------------------------ -void SdFatBase::errorPrint(Print* pr, char const* msg) { - pr->print(F("error: ")); - pr->println(msg); - errorPrint(pr); -} -//------------------------------------------------------------------------------ -void SdFatBase::errorPrint(Print* pr, const __FlashStringHelper* msg) { - pr->print(F("error: ")); - pr->println(msg); - errorPrint(pr); -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorHalt(Print* pr) { - initErrorPrint(pr); - while (1) {} -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorHalt(Print* pr, char const *msg) { - pr->println(msg); - initErrorHalt(pr); -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorHalt(Print* pr, const __FlashStringHelper* msg) { - pr->println(msg); - initErrorHalt(pr); -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorPrint(Print* pr) { - if (cardErrorCode()) { - pr->println(F("Can't access SD card. Do not reformat.")); - if (cardErrorCode() == SD_CARD_ERROR_CMD0) { - pr->println(F("No card, wrong chip select pin, or SPI problem?")); - } - errorPrint(pr); - } else if (vol()->fatType() == 0) { - pr->println(F("Invalid format, reformat SD.")); - } else if (!vwd()->isOpen()) { - pr->println(F("Can't open root directory.")); - } else { - pr->println(F("No error found.")); - } -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorPrint(Print* pr, char const *msg) { - pr->println(msg); - initErrorPrint(pr); -} -//------------------------------------------------------------------------------ -void SdFatBase::initErrorPrint(Print* pr, const __FlashStringHelper* msg) { - pr->println(msg); - initErrorPrint(pr); -} - diff --git a/SdFat/SdFatConfig.h b/SdFat/SdFatConfig.h deleted file mode 100644 index 431d493d..00000000 --- a/SdFat/SdFatConfig.h +++ /dev/null @@ -1,188 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -/** - * \file - * \brief configuration definitions - */ -#ifndef SdFatConfig_h -#define SdFatConfig_h -#include -#ifdef __AVR__ -#include -#endif // __AVR__ -//------------------------------------------------------------------------------ -/** - * Set USE_LONG_FILE_NAMES nonzero to use long file names (LFN). - * Long File Name are limited to a maximum length of 255 characters. - * - * This implementation allows 7-bit characters in the range - * 0X20 to 0X7E except the following characters are not allowed: - * - * < (less than) - * > (greater than) - * : (colon) - * " (double quote) - * / (forward slash) - * \ (backslash) - * | (vertical bar or pipe) - * ? (question mark) - * * (asterisk) - * - */ -#define USE_LONG_FILE_NAMES 1 -//------------------------------------------------------------------------------ -/** - * Set ARDUINO_FILE_USES_STREAM nonzero to use Stream as the base class - * for the Arduino File class. If ARDUINO_FILE_USES_STREAM is zero, Print - * will be used as the base class for the Arduino File class. - * - * You can save some flash if you do not use Stream input functions such as - * find(), findUntil(), readBytesUntil(), readString(), readStringUntil(), - * parseInt(), and parseFloat(). - */ -#define ARDUINO_FILE_USES_STREAM 1 -//------------------------------------------------------------------------------ -/** - * The symbol SD_SPI_CONFIGURATION defines SPI access to the SD card. - * - * IF SD_SPI_CONFIGUTATION is define to be zero, only the SdFat class - * is define and SdFat uses a fast custom SPI implementation. - * - * If SD_SPI_CONFIGURATION is define to be one, only the SdFat class is - * define and SdFat uses the standard Arduino SPI.h library. - * - * If SD_SPI_CONFIGURATION is define to be two, only the SdFat class is - * define and SdFat uses software SPI on the pins defined below. - * - * If SD_SPI_CONFIGURATION is define to be three, the three classes, SdFat, - * SdFatLibSpi, and SdFatSoftSpi are defined. SdFat uses the fast - * custom SPI implementation. SdFatLibSpi uses the standard Arduino SPI - * library. SdFatSoftSpi is a template class that uses Software SPI. The - * template parameters define the software SPI pins. See the ThreeCard - * example for simultaneous use of all three classes. - */ -#define SD_SPI_CONFIGURATION 0 -//------------------------------------------------------------------------------ -/** - * If SD_SPI_CONFIGURATION is defined to be two, these definitions - * will define the pins used for software SPI. - * - * The default definition allows Uno shields to be used on other boards. - */ -/** Software SPI Master Out Slave In pin */ -uint8_t const SOFT_SPI_MOSI_PIN = 11; -/** Software SPI Master In Slave Out pin */ -uint8_t const SOFT_SPI_MISO_PIN = 12; -/** Software SPI Clock pin */ -uint8_t const SOFT_SPI_SCK_PIN = 13; -//------------------------------------------------------------------------------ -/** - * To enable SD card CRC checking set USE_SD_CRC nonzero. - * - * Set USE_SD_CRC to 1 to use a smaller slower CRC-CCITT function. - * - * Set USE_SD_CRC to 2 to used a larger faster table driven CRC-CCITT function. - */ -#define USE_SD_CRC 0 -//------------------------------------------------------------------------------ -/** - * Set ENABLE_SPI_TRANSACTION nonzero to enable the SPI transaction feature - * of the standard Arduino SPI library. You must include SPI.h in your - * programs when ENABLE_SPI_TRANSACTION is nonzero. - */ -#define ENABLE_SPI_TRANSACTION 0 -//------------------------------------------------------------------------------ -/** - * Set ENABLE_SPI_YIELD nonzero to enable release of the SPI bus during - * SD card busy waits. - * - * This will allow interrupt routines to access the SPI bus if - * ENABLE_SPI_TRANSACTION is nonzero. - * - * Setting ENABLE_SPI_YIELD will introduce some extra overhead and will - * slightly slow transfer rates. A few older SD cards may fail when - * ENABLE_SPI_YIELD is nonzero. - */ -#define ENABLE_SPI_YIELD 0 -//------------------------------------------------------------------------------ -/** - * Set FAT12_SUPPORT nonzero to enable use if FAT12 volumes. - * FAT12 has not been well tested and requires additional flash. - */ -#define FAT12_SUPPORT 0 -//------------------------------------------------------------------------------ -/** - * Set DESTRUCTOR_CLOSES_FILE nonzero to close a file in its destructor. - * - * Causes use of lots of heap in ARM. - */ -#define DESTRUCTOR_CLOSES_FILE 0 -//------------------------------------------------------------------------------ -/** - * Call flush for endl if ENDL_CALLS_FLUSH is nonzero - * - * The standard for iostreams is to call flush. This is very costly for - * SdFat. Each call to flush causes 2048 bytes of I/O to the SD. - * - * SdFat has a single 512 byte buffer for SD I/O so it must write the current - * data block to the SD, read the directory block from the SD, update the - * directory entry, write the directory block to the SD and read the data - * block back into the buffer. - * - * The SD flash memory controller is not designed for this many rewrites - * so performance may be reduced by more than a factor of 100. - * - * If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force - * all data to be written to the SD. - */ -#define ENDL_CALLS_FLUSH 0 -//------------------------------------------------------------------------------ -/** - * SPI SCK divisor for SD initialization commands. - * or greater - */ -#ifdef __AVR__ -const uint8_t SPI_SCK_INIT_DIVISOR = 64; -#else -const uint8_t SPI_SCK_INIT_DIVISOR = 128; -#endif -//------------------------------------------------------------------------------ -/** - * Set USE_SEPARATE_FAT_CACHE nonzero to use a second 512 byte cache - * for FAT table entries. This improves performance for large writes - * that are not a multiple of 512 bytes. - */ -#ifdef __arm__ -#define USE_SEPARATE_FAT_CACHE 1 -#else // __arm__ -#define USE_SEPARATE_FAT_CACHE 0 -#endif // __arm__ -//------------------------------------------------------------------------------ -/** - * Set USE_MULTI_BLOCK_IO nonzero to use multi-block SD read/write. - * - * Don't use mult-block read/write on small AVR boards. - */ -#if defined(RAMEND) && RAMEND < 3000 -#define USE_MULTI_BLOCK_IO 0 -#else // RAMEND -#define USE_MULTI_BLOCK_IO 1 -#endif // RAMEND -#endif // SdFatConfig_h diff --git a/SdFat/SdFatUtil.cpp b/SdFat/SdFatUtil.cpp deleted file mode 100644 index eb29c006..00000000 --- a/SdFat/SdFatUtil.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#include -#include "SdFat.h" -#include "SdFatUtil.h" -//------------------------------------------------------------------------------ -#ifdef __arm__ -extern "C" char* sbrk(int incr); -int SdFatUtil::FreeRam() { - char top; - return &top - reinterpret_cast(sbrk(0)); -} -#else // __arm__ -extern char *__brkval; -extern char __bss_end; -/** Amount of free RAM - * \return The number of free bytes. - */ -int SdFatUtil::FreeRam() { - char top; - return __brkval ? &top - __brkval : &top - &__bss_end; -} -#endif // __arm -//------------------------------------------------------------------------------ -void SdFatUtil::print_P(Print* pr, PGM_P str) { - for (uint8_t c; (c = pgm_read_byte(str)); str++) { - pr->write(c); - } -} -//------------------------------------------------------------------------------ -void SdFatUtil::println_P(Print* pr, PGM_P str) { - print_P(pr, str); - pr->println(); -} diff --git a/SdFat/SdFatUtil.h b/SdFat/SdFatUtil.h deleted file mode 100644 index 11932188..00000000 --- a/SdFat/SdFatUtil.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFatUtil_h -#define SdFatUtil_h -/** - * \file - * \brief Useful utility functions. - */ -#include "SdFat.h" -/** Store and print a string in flash memory.*/ -#define PgmPrint(x) SerialPrint_P(PSTR(x)) -/** Store and print a string in flash memory followed by a CR/LF.*/ -#define PgmPrintln(x) SerialPrintln_P(PSTR(x)) - -namespace SdFatUtil { - /** Amount of free RAM - * \return The number of free bytes. - */ - int FreeRam(); - /** %Print a string in flash memory. - * - * \param[in] pr Print object for output. - * \param[in] str Pointer to string stored in flash memory. - */ - void print_P(Print* pr, PGM_P str); - /** %Print a string in flash memory followed by a CR/LF. - * - * \param[in] pr Print object for output. - * \param[in] str Pointer to string stored in flash memory. - */ - void println_P(Print* pr, PGM_P str); - //---------------------------------------------------------------------------- - /** %Print a string in flash memory to Serial. - * - * \param[in] str Pointer to string stored in flash memory. - */ - inline void SerialPrint_P(PGM_P str) { - print_P(&Serial, str); - } - //---------------------------------------------------------------------------- - /** %Print a string in flash memory to Serial followed by a CR/LF. - * - * \param[in] str Pointer to string stored in flash memory. - */ - inline void SerialPrintln_P(PGM_P str) { - println_P(&Serial, str); - } -} // namespace SdFatUtil -using namespace SdFatUtil; // NOLINT -#endif // #define SdFatUtil_h diff --git a/SdFat/SdFatmainpage.h b/SdFat/SdFatmainpage.h deleted file mode 100644 index b758f335..00000000 --- a/SdFat/SdFatmainpage.h +++ /dev/null @@ -1,392 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ - -/** -\mainpage Arduino %SdFat Library -
Copyright © 2012, 2013, 2014, 2015 by William Greiman -
- -\section Intro Introduction -The Arduino %SdFat Library is a minimal implementation of FAT16 and FAT32 -file systems on SD flash memory cards. Standard SD and high capacity SDHC -cards are supported. - -Experimental support for FAT12 can be enabled by setting FAT12_SUPPORT -nonzero in SdFatConfig.h. - -The %SdFat library supports Long %File Names or short 8.3 names. -Edit the SdFatConfig.h file to select short or long file names. - -The main classes in %SdFat are SdFat, SdFatSoftSpi, SdFatLibSpi, -SdBaseFile, SdFile, File, StdioStream, \ref fstream, \ref ifstream, -and \ref ofstream. - -The SdFat, SdFatLibSpi, and SdFatSoftSpi classes maintain a FAT volume, -a current working directory, and simplifies initialization of other classes. -The SdFat class uses a fast custom hardware SPI implementation. The -SdFatLibSpi class uses the standard Arduino SPI library. The SdFatSoftSpi -class uses software SPI. - -The SdBaseFile class provides basic file access functions such as open(), -binary read(), binary write(), close(), remove(), and sync(). SdBaseFile -is the smallest file class. - -The SdFile class has all the SdBaseFile class functions plus the Arduino -Print class functions. - -The File class has all the SdBaseFile functions plus the functions in -the Arduino SD.h File class. This provides compatibility with the -Arduino SD.h library. - -The StdioStream class implements functions similar to Linux/Unix standard -buffered input/output. - -The \ref fstream class implements C++ iostreams for both reading and writing -text files. - -The \ref ifstream class implements C++ iostreams for reading text files. - -The \ref ofstream class implements C++ iostreams for writing text files. - -The classes \ref ifstream, \ref ofstream, \ref istream, and \ref ostream -follow the C++ \ref iostream standard when possible. - -There are many tutorials and much documentation about using C++ iostreams -on the web. - -http://www.cplusplus.com/ is a good C++ site for learning iostreams. - -The classes \ref ibufstream and \ref obufstream format and parse character - strings in memory buffers. - -the classes ArduinoInStream and ArduinoOutStream provide iostream functions -for Serial, LiquidCrystal, and other devices. - -A number of example are provided in the %SdFat/examples folder. These were -developed to test %SdFat and illustrate its use. - -\section Install Installation - -You must manually install SdFat by copying the SdFat folder from the download -package to the Arduino libraries folder in you sketch folder. - -See the Manual installation section of this guide. - -http://arduino.cc/en/Guide/Libraries - -\section SDconfig SdFat Configuration - -Several configuration options may be changed by editing the SdFatConfig.h -file in the %SdFat folder. - -Set USE_LONG_FILE_NAMES nonzero to enable Long %File Names. By default, -Long %File Names are enabled. For the leanest fastest library disable -Long %File Names. Long %File names require extra flash but no extra RAM. -Opening Long %File Names can be slower than opening Short %File Names. -Data read and write performance is not changed by the type of %File Name. - -Set SD_SPI_CONFIGURATION to enable various SPI options. The SdFatSoftSpi -and SdFatLibSpi classes can be enabled. SdFatLibSpi uses the standard -Arduino SPI library and SdFatSoftSpi uses software SPI. - -To enable SD card CRC checking set USE_SD_CRC nonzero. - -Set FAT12_SUPPORT nonzero to enable use of FAT12 volumes. -FAT12 has not been well tested and requires additional flash. - -Set ENABLE_SPI_TRANSACTION nonzero to enable the SPI transaction feature -of the standard Arduino SPI library. You must include SPI.h in your -programs when ENABLE_SPI_TRANSACTION is nonzero. - -Set ENABLE_SPI_YIELD nonzero to enable release of the SPI bus during -SD card busy waits. - -\section SDPath Paths and Working Directories - -Relative paths in SdFat are resolved in a manner similar to Windows. - -Each instance of SdFat has a current directory. In SdFat this directory -is called the volume working directory, vwd. Initially this directory is -the root directory for the volume. - -The volume working directory is changed by calling SdFat::chdir(path). - -The call sd.chdir("/2014") will change the volume working directory -for sd to "/2014", assuming "/2014" exists. - -Relative paths for SdFat member functions are resolved by starting at -the volume working directory. - -For example, the call sd.mkdir("April") will create the directory -"/2014/April" assuming the volume working directory is "/2014". - -SdFat has a current working directory, cwd, that is used to resolve paths -for file.open() calls. - -For a single SD card the current working directory is always the volume -working directory for that card. - -For multiple SD cards the current working directory is set to the volume -working directory of a card by calling the SdFat::chvol() member function. -The chvol() call is like the Windows \: command. - -The call sd2.chvol() will set the current working directory to the volume -working directory for sd2. - -If the volume working directory for sd2 is "/music" the call - -file.open("BigBand.wav", O_READ); - -will then open "/music/BigBand.wav" on sd2. - -The following functions are used to change or get current directories. -See the html documentation for more information. -@code -bool SdFat::chdir(bool set_cwd = false); -bool SdFat::chdir(const char* path, bool set_cwd = false); -void SdFat::chvol(); -SdBaseFile* SdFat::vwd(); -static SdBaseFile* SdBaseFile::cwd(); -@endcode - -\section SDcard SD\SDHC Cards - -Arduinos access SD cards using the cards SPI protocol. PCs, Macs, and -most consumer devices use the 4-bit parallel SD protocol. A card that -functions well on A PC or Mac may not work well on the Arduino. - -Most cards have good SPI read performance but cards vary widely in SPI -write performance. Write performance is limited by how efficiently the -card manages internal erase/remapping operations. The Arduino cannot -optimize writes to reduce erase operations because of its limit RAM. - -SanDisk cards generally have good write performance. They seem to have -more internal RAM buffering than other cards and therefore can limit -the number of flash erase operations that the Arduino forces due to its -limited RAM. - -\section Hardware Hardware Configuration - -%SdFat was developed using an - Adafruit Industries -Data Logging Shield. - -The hardware interface to the SD card should not use a resistor based level -shifter. %SdFat sets the SPI bus frequency to 8 MHz which results in signal -rise times that are too slow for the edge detectors in many newer SD card -controllers when resistor voltage dividers are used. - -The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the -74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave Shield -uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based on the -74LCX245. - -If you are using a resistor based level shifter and are having problems try -setting the SPI bus frequency to 4 MHz. This can be done by using -card.init(SPI_HALF_SPEED) to initialize the SD card. - -A feature to use software SPI is available. Software SPI is slower -than hardware SPI but allows any digital pins to be used. See -SdFatConfig.h for software SPI definitions. - -\section comment Bugs and Comments - -If you wish to report bugs or have comments, send email to -fat16lib@sbcglobal.net. If possible, include a simple program that illustrates -the bug or problem. - -\section Trouble Troubleshooting - -The two example programs QuickStart, and SdInfo are useful for troubleshooting. - -A message like this from SdInfo with erorCode 0X1 indicates the SD card -is not seen by SdFat. This is often caused by a wiring error and reformatting -the card will not solve the problem. -
-cardBegin failed
-SD errorCode: 0X1
-SD errorData: 0XFF
-
-Here is a similar message from QuickStart: -
-SD initialization failed.
-Do not reformat the card!
-Is the card correctly inserted?
-Is chipSelect set to the correct value?
-Does another SPI device need to be disabled?
-Is there a wiring/soldering problem?
-
-errorCode: 0x1, errorData: 0xff
-
-Here is a message from QuickStart that indicates a formatting problem: -
-Card successfully initialized.
-Can't find a valid FAT16/FAT32 partition.
-Try reformatting the card.  For best results use
-the SdFormatter program in SdFat/examples or download
-and use SDFormatter from www.sdcard.org/downloads.
-
- -The best source of recent information and help is the Arduino forum. - -http://arduino.cc/forum/ - -Also search the Adafruit forum. - -http://forums.adafruit.com/ - -If you are using a Teensy try. - -http://forum.pjrc.com/forum.php - -\section SdFatClass SdFat Usage - -SdFat supports Long File Names. Long names in SdFat are limited to 7-bit -ASCII characters in the range 0X20 - 0XFE The following are reserved characters: -
    -
  • < (less than) -
  • > (greater than) -
  • : (colon) -
  • " (double quote) -
  • / (forward slash) -
  • \ (backslash) -
  • | (vertical bar or pipe) -
  • ? (question mark) -
  • * (asterisk) -
-%SdFat uses a slightly restricted form of short names. -Short names are limited to 8 characters followed by an optional period (.) -and extension of up to 3 characters. The characters may be any combination -of letters and digits. The following special characters are also allowed: - -$ % ' - _ @ ~ ` ! ( ) { } ^ # & - -Short names are always converted to upper case and their original case -value is lost. Files that have a base-name where all characters have the -same case and an extension where all characters have the same case will -display properly. Examples this type name are UPPER.low, lower.TXT, -UPPER.TXT, and lower.txt. - -An application which writes to a file using print(), println() or -\link SdFile::write write() \endlink must close the file or call -\link SdFile::sync() sync() \endlink at the appropriate time to -force data and directory information to be written to the SD Card. - -Applications must use care calling \link SdFile::sync() sync() \endlink -since 2048 bytes of I/O is required to update file and -directory information. This includes writing the current data block, reading -the block that contains the directory entry for update, writing the directory -block back and reading back the current data block. - -It is possible to open a file with two or more instances of a file object. -A file may be corrupted if data is written to the file by more than one -instance of a file object. - -\section HowTo How to format SD Cards as FAT Volumes - -The best way to restore an SD card's format on a PC or Mac is to use -SDFormatter which can be downloaded from: - -http://www.sdcard.org/downloads - -A formatter program, SdFormatter.ino, is included in the -%SdFat/examples/SdFormatter directory. This program attempts to -emulate SD Association's SDFormatter. - -SDFormatter aligns flash erase boundaries with file -system structures which reduces write latency and file system overhead. - -The PC/Mac SDFormatter does not have an option for FAT type so it may format -very small cards as FAT12. Use the SdFat formatter to force FAT16 -formatting of small cards. - -Do not format the SD card with an OS utility, OS utilities do not format SD -cards in conformance with the SD standard. - -You should use a freshly formatted SD card for best performance. FAT -file systems become slower if many files have been created and deleted. -This is because the directory entry for a deleted file is marked as deleted, -but is not deleted. When a new file is created, these entries must be scanned -before creating the file. Also files can become -fragmented which causes reads and writes to be slower. - -\section ExampleFilder Examples - -A number of examples are provided in the SdFat/examples folder. -See the html documentation for a list. - -To access these examples from the Arduino development environment -go to: %File -> Examples -> %SdFat -> \ - -Compile, upload to your Arduino and click on Serial Monitor to run -the example. - -Here is a list: - -AnalogBinLogger - Fast AVR ADC logger - see the AnalogBinLoggerExtras folder. - -bench - A read/write benchmark. - -cin_cout - Demo of ArduinoInStream and ArduinoOutStream. - -dataLogger - A simple modifiable data logger. - -directoryFunctions - Demo of chdir(), ls(), mkdir(), and rmdir(). - -fgets - Demo of the fgets read line/string function. - -formating - Print a table with various formatting options. - -getline - Example of getline from section 27.7.1.3 of the C++ standard. - -LongFileName - Example use of openNext, printName, and open by index. - -LowLatencyLogger - A modifiable data logger for higher data rates. - -OpenNext - Open all files in the root dir and print their filename. - -PrintBenchmark - A simple benchmark for printing to a text file. - -QuickStart - A program to quickly test your SD card and SD shield/module. - -RawWrite - A test of raw write functions for contiguous files. - -readCSV - Read a comma-separated value file using iostream extractors. - -ReadWriteSdFat - SdFat version of Arduino SD ReadWrite example. - -rename - A demo of SdFat::rename(old, new) and SdFile::rename(dirFile, newPath). - -SdFormatter - This program will format an SD or SDHC card. - -SoftwareSpi - Simple demonstration of the SdFatSoftSpi template class. - -SdInfo - Initialize an SD card and analyze its structure for trouble shooting. - -StdioBench - Demo and test of stdio style stream. - -StreamParseInt - Demo of the SD.h API and the File class parseInt() function. - -ThreeCards - Demonstrate simultaneous use of SdFat, SdFatLibSpi, SdFatSoftSpi. - -Timestamp - Sets file create, modify, and access timestamps. - -TwoCards - Example using two SD cards. - */ diff --git a/SdFat/SdInfo.h b/SdFat/SdInfo.h deleted file mode 100644 index d502c2f4..00000000 --- a/SdFat/SdInfo.h +++ /dev/null @@ -1,381 +0,0 @@ -/* Arduino SdSpiCard Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdSpiCard Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdSpiCard Library. If not, see - * . - */ -#ifndef SdInfo_h -#define SdInfo_h -#include -// Based on the document: -// -// SD Specifications -// Part 1 -// Physical Layer -// Simplified Specification -// Version 3.01 -// May 18, 2010 -// -// http://www.sdcard.org/developers/tech/sdcard/pls/simplified_specs -//------------------------------------------------------------------------------ -// SD card errors -/** timeout error for command CMD0 (initialize card in SPI mode) */ -uint8_t const SD_CARD_ERROR_CMD0 = 0X1; -/** CMD8 was not accepted - not a valid SD card*/ -uint8_t const SD_CARD_ERROR_CMD8 = 0X2; -/** card returned an error response for CMD12 (stop multiblock read) */ -uint8_t const SD_CARD_ERROR_CMD12 = 0X3; -/** card returned an error response for CMD17 (read block) */ -uint8_t const SD_CARD_ERROR_CMD17 = 0X4; -/** card returned an error response for CMD18 (read multiple block) */ -uint8_t const SD_CARD_ERROR_CMD18 = 0X5; -/** card returned an error response for CMD24 (write block) */ -uint8_t const SD_CARD_ERROR_CMD24 = 0X6; -/** WRITE_MULTIPLE_BLOCKS command failed */ -uint8_t const SD_CARD_ERROR_CMD25 = 0X7; -/** card returned an error response for CMD58 (read OCR) */ -uint8_t const SD_CARD_ERROR_CMD58 = 0X8; -/** SET_WR_BLK_ERASE_COUNT failed */ -uint8_t const SD_CARD_ERROR_ACMD23 = 0X9; -/** ACMD41 initialization process timeout */ -uint8_t const SD_CARD_ERROR_ACMD41 = 0XA; -/** card returned a bad CSR version field */ -uint8_t const SD_CARD_ERROR_BAD_CSD = 0XB; -/** erase block group command failed */ -uint8_t const SD_CARD_ERROR_ERASE = 0XC; -/** card not capable of single block erase */ -uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0XD; -/** Erase sequence timed out */ -uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0XE; -/** card returned an error token instead of read data */ -uint8_t const SD_CARD_ERROR_READ = 0XF; -/** read CID or CSD failed */ -uint8_t const SD_CARD_ERROR_READ_REG = 0X10; -/** timeout while waiting for start of read data */ -uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X11; -/** card did not accept STOP_TRAN_TOKEN */ -uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X12; -/** card returned an error token as a response to a write operation */ -uint8_t const SD_CARD_ERROR_WRITE = 0X13; -/** attempt to write protected block zero */ -uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X14; // REMOVE - not used -/** card did not go ready for a multiple block write */ -uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X15; -/** card returned an error to a CMD13 status check after a write */ -uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X16; -/** timeout occurred during write programming */ -uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X17; -/** incorrect rate selected */ -uint8_t const SD_CARD_ERROR_SCK_RATE = 0X18; -/** init() not called */ -uint8_t const SD_CARD_ERROR_INIT_NOT_CALLED = 0X19; -/** card returned an error for CMD59 (CRC_ON_OFF) */ -uint8_t const SD_CARD_ERROR_CMD59 = 0X1A; -/** invalid read CRC */ -uint8_t const SD_CARD_ERROR_READ_CRC = 0X1B; -/** SPI DMA error */ -uint8_t const SD_CARD_ERROR_SPI_DMA = 0X1C; -//------------------------------------------------------------------------------ -// card types -/** Standard capacity V1 SD card */ -uint8_t const SD_CARD_TYPE_SD1 = 1; -/** Standard capacity V2 SD card */ -uint8_t const SD_CARD_TYPE_SD2 = 2; -/** High Capacity SD card */ -uint8_t const SD_CARD_TYPE_SDHC = 3; -//------------------------------------------------------------------------------ -// SPI divisor constants -/** Set SCK to max rate of F_CPU/2. */ -uint8_t const SPI_FULL_SPEED = 2; -/** Set SCK rate to F_CPU/3 for Due */ -uint8_t const SPI_DIV3_SPEED = 3; -/** Set SCK rate to F_CPU/4. */ -uint8_t const SPI_HALF_SPEED = 4; -/** Set SCK rate to F_CPU/6 for Due */ -uint8_t const SPI_DIV6_SPEED = 6; -/** Set SCK rate to F_CPU/8. */ -uint8_t const SPI_QUARTER_SPEED = 8; -/** Set SCK rate to F_CPU/16. */ -uint8_t const SPI_EIGHTH_SPEED = 16; -/** Set SCK rate to F_CPU/32. */ -uint8_t const SPI_SIXTEENTH_SPEED = 32; -//------------------------------------------------------------------------------ -// SD operation timeouts -/** init timeout ms */ -uint16_t const SD_INIT_TIMEOUT = 2000; -/** erase timeout ms */ -uint16_t const SD_ERASE_TIMEOUT = 10000; -/** read timeout ms */ -uint16_t const SD_READ_TIMEOUT = 300; -/** write time out ms */ -uint16_t const SD_WRITE_TIMEOUT = 600; -//------------------------------------------------------------------------------ -// SD card commands -/** GO_IDLE_STATE - init card in spi mode if CS low */ -uint8_t const CMD0 = 0X00; -/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/ -uint8_t const CMD8 = 0X08; -/** SEND_CSD - read the Card Specific Data (CSD register) */ -uint8_t const CMD9 = 0X09; -/** SEND_CID - read the card identification information (CID register) */ -uint8_t const CMD10 = 0X0A; -/** STOP_TRANSMISSION - end multiple block read sequence */ -uint8_t const CMD12 = 0X0C; -/** SEND_STATUS - read the card status register */ -uint8_t const CMD13 = 0X0D; -/** READ_SINGLE_BLOCK - read a single data block from the card */ -uint8_t const CMD17 = 0X11; -/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */ -uint8_t const CMD18 = 0X12; -/** WRITE_BLOCK - write a single data block to the card */ -uint8_t const CMD24 = 0X18; -/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */ -uint8_t const CMD25 = 0X19; -/** ERASE_WR_BLK_START - sets the address of the first block to be erased */ -uint8_t const CMD32 = 0X20; -/** ERASE_WR_BLK_END - sets the address of the last block of the continuous - range to be erased*/ -uint8_t const CMD33 = 0X21; -/** ERASE - erase all previously selected blocks */ -uint8_t const CMD38 = 0X26; -/** APP_CMD - escape for application specific command */ -uint8_t const CMD55 = 0X37; -/** READ_OCR - read the OCR register of a card */ -uint8_t const CMD58 = 0X3A; -/** CRC_ON_OFF - enable or disable CRC checking */ -uint8_t const CMD59 = 0X3B; -/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be - pre-erased before writing */ -uint8_t const ACMD23 = 0X17; -/** SD_SEND_OP_COMD - Sends host capacity support information and - activates the card's initialization process */ -uint8_t const ACMD41 = 0X29; -//============================================================================== -/** status for card in the ready state */ -uint8_t const R1_READY_STATE = 0X00; -/** status for card in the idle state */ -uint8_t const R1_IDLE_STATE = 0X01; -/** status bit for illegal command */ -uint8_t const R1_ILLEGAL_COMMAND = 0X04; -/** start data token for read or write single block*/ -uint8_t const DATA_START_BLOCK = 0XFE; -/** stop token for write multiple blocks*/ -uint8_t const STOP_TRAN_TOKEN = 0XFD; -/** start data token for write multiple blocks*/ -uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC; -/** mask for data response tokens after a write block operation */ -uint8_t const DATA_RES_MASK = 0X1F; -/** write data accepted token */ -uint8_t const DATA_RES_ACCEPTED = 0X05; -//============================================================================== -/** - * \class CID - * \brief Card IDentification (CID) register. - */ -typedef struct CID { - // byte 0 - /** Manufacturer ID */ - unsigned char mid; - // byte 1-2 - /** OEM/Application ID */ - char oid[2]; - // byte 3-7 - /** Product name */ - char pnm[5]; - // byte 8 - /** Product revision least significant digit */ - unsigned char prv_m : 4; - /** Product revision most significant digit */ - unsigned char prv_n : 4; - // byte 9-12 - /** Product serial number */ - uint32_t psn; - // byte 13 - /** Manufacturing date year low digit */ - unsigned char mdt_year_high : 4; - /** not used */ - unsigned char reserved : 4; - // byte 14 - /** Manufacturing date month */ - unsigned char mdt_month : 4; - /** Manufacturing date year low digit */ - unsigned char mdt_year_low : 4; - // byte 15 - /** not used always 1 */ - unsigned char always1 : 1; - /** CRC7 checksum */ - unsigned char crc : 7; -} __attribute__((packed)) cid_t; -//============================================================================== -/** - * \class CSDV1 - * \brief CSD register for version 1.00 cards . - */ -typedef struct CSDV1 { - // byte 0 - unsigned char reserved1 : 6; - unsigned char csd_ver : 2; - // byte 1 - unsigned char taac; - // byte 2 - unsigned char nsac; - // byte 3 - unsigned char tran_speed; - // byte 4 - unsigned char ccc_high; - // byte 5 - unsigned char read_bl_len : 4; - unsigned char ccc_low : 4; - // byte 6 - unsigned char c_size_high : 2; - unsigned char reserved2 : 2; - unsigned char dsr_imp : 1; - unsigned char read_blk_misalign : 1; - unsigned char write_blk_misalign : 1; - unsigned char read_bl_partial : 1; - // byte 7 - unsigned char c_size_mid; - // byte 8 - unsigned char vdd_r_curr_max : 3; - unsigned char vdd_r_curr_min : 3; - unsigned char c_size_low : 2; - // byte 9 - unsigned char c_size_mult_high : 2; - unsigned char vdd_w_cur_max : 3; - unsigned char vdd_w_curr_min : 3; - // byte 10 - unsigned char sector_size_high : 6; - unsigned char erase_blk_en : 1; - unsigned char c_size_mult_low : 1; - // byte 11 - unsigned char wp_grp_size : 7; - unsigned char sector_size_low : 1; - // byte 12 - unsigned char write_bl_len_high : 2; - unsigned char r2w_factor : 3; - unsigned char reserved3 : 2; - unsigned char wp_grp_enable : 1; - // byte 13 - unsigned char reserved4 : 5; - unsigned char write_partial : 1; - unsigned char write_bl_len_low : 2; - // byte 14 - unsigned char reserved5: 2; - unsigned char file_format : 2; - unsigned char tmp_write_protect : 1; - unsigned char perm_write_protect : 1; - unsigned char copy : 1; - /** Indicates the file format on the card */ - unsigned char file_format_grp : 1; - // byte 15 - unsigned char always1 : 1; - unsigned char crc : 7; -} __attribute__((packed)) csd1_t; -//============================================================================== -/** - * \class CSDV2 - * \brief CSD register for version 2.00 cards. - */ -typedef struct CSDV2 { - // byte 0 - unsigned char reserved1 : 6; - unsigned char csd_ver : 2; - // byte 1 - /** fixed to 0X0E */ - unsigned char taac; - // byte 2 - /** fixed to 0 */ - unsigned char nsac; - // byte 3 - unsigned char tran_speed; - // byte 4 - unsigned char ccc_high; - // byte 5 - /** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */ - unsigned char read_bl_len : 4; - unsigned char ccc_low : 4; - // byte 6 - /** not used */ - unsigned char reserved2 : 4; - unsigned char dsr_imp : 1; - /** fixed to 0 */ - unsigned char read_blk_misalign : 1; - /** fixed to 0 */ - unsigned char write_blk_misalign : 1; - /** fixed to 0 - no partial read */ - unsigned char read_bl_partial : 1; - // byte 7 - /** high part of card size */ - unsigned char c_size_high : 6; - /** not used */ - unsigned char reserved3 : 2; - // byte 8 - /** middle part of card size */ - unsigned char c_size_mid; - // byte 9 - /** low part of card size */ - unsigned char c_size_low; - // byte 10 - /** sector size is fixed at 64 KB */ - unsigned char sector_size_high : 6; - /** fixed to 1 - erase single is supported */ - unsigned char erase_blk_en : 1; - /** not used */ - unsigned char reserved4 : 1; - // byte 11 - unsigned char wp_grp_size : 7; - /** sector size is fixed at 64 KB */ - unsigned char sector_size_low : 1; - // byte 12 - /** write_bl_len fixed for 512 byte blocks */ - unsigned char write_bl_len_high : 2; - /** fixed value of 2 */ - unsigned char r2w_factor : 3; - /** not used */ - unsigned char reserved5 : 2; - /** fixed value of 0 - no write protect groups */ - unsigned char wp_grp_enable : 1; - // byte 13 - unsigned char reserved6 : 5; - /** always zero - no partial block read*/ - unsigned char write_partial : 1; - /** write_bl_len fixed for 512 byte blocks */ - unsigned char write_bl_len_low : 2; - // byte 14 - unsigned char reserved7: 2; - /** Do not use always 0 */ - unsigned char file_format : 2; - unsigned char tmp_write_protect : 1; - unsigned char perm_write_protect : 1; - unsigned char copy : 1; - /** Do not use always 0 */ - unsigned char file_format_grp : 1; - // byte 15 - /** not used always 1 */ - unsigned char always1 : 1; - /** checksum */ - unsigned char crc : 7; -} __attribute__((packed)) csd2_t; -//============================================================================== -/** - * \class csd_t - * \brief Union of old and new style CSD register. - */ -union csd_t { - csd1_t v1; - csd2_t v2; -}; -#endif // SdInfo_h diff --git a/SdFat/SdSpi.h b/SdFat/SdSpi.h deleted file mode 100644 index b87cf1e6..00000000 --- a/SdFat/SdSpi.h +++ /dev/null @@ -1,370 +0,0 @@ -/* Arduino SdSpi Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino SdSpi Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdSpi Library. If not, see - * . - */ -/** -* \file -* \brief SdSpi class for V2 SD/SDHC cards -*/ -#ifndef SdSpi_h -#define SdSpi_h -#include -#include "SdFatConfig.h" - -//------------------------------------------------------------------------------ -/** - * \class SdSpiBase - * \brief Virtual SPI class for access to SD and SDHC flash memory cards. - */ -class SdSpiBase { - public: - /** Initialize the SPI bus */ - virtual void begin() = 0; - /** Set SPI options for access to SD/SDHC cards. - * - * \param[in] divisor SCK clock divider relative to the system clock. - */ - virtual void init(uint8_t divisor); - /** Receive a byte. - * - * \return The byte. - */ - virtual uint8_t receive() = 0; - /** 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. - */ - virtual uint8_t receive(uint8_t* buf, size_t n) = 0; - /** Send a byte. - * - * \param[in] data Byte to send - */ - virtual void send(uint8_t data) = 0; - /** Send multiple bytes. - * - * \param[in] buf Buffer for data to be sent. - * \param[in] n Number of bytes to send. - */ - virtual void send(const uint8_t* buf, size_t n) = 0; - /** \return true if hardware SPI else false */ - virtual bool useSpiTransactions() = 0; -}; -//------------------------------------------------------------------------------ -/** - * \class SdSpi - * \brief SPI class for access to SD and SDHC flash memory cards. - */ -#if SD_SPI_CONFIGURATION >= 3 -class SdSpi : public SdSpiBase { -#else // SD_SPI_CONFIGURATION >= 3 -class SdSpi { -#endif // SD_SPI_CONFIGURATION >= 3 - public: - /** Initialize the SPI bus */ - void begin(); - /** Set SPI options for access to SD/SDHC cards. - * - * \param[in] divisor SCK clock divider relative to the system clock. - */ - void init(uint8_t divisor); - /** Receive a byte. - * - * \return The byte. - */ - uint8_t receive(); - /** 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 receive(uint8_t* buf, size_t n); - /** Send a byte. - * - * \param[in] data Byte to send - */ - void send(uint8_t data); - /** Send multiple bytes. - * - * \param[in] buf Buffer for data to be sent. - * \param[in] n Number of bytes to send. - */ - void send(const uint8_t* buf, size_t n); - /** \return true - uses SPI transactions */ - bool useSpiTransactions() { - return true; - } -}; -//------------------------------------------------------------------------------ -/** - * \class SdSpiLib - * \brief Arduino SPI library class for access to SD and SDHC flash - * memory cards. - */ -#if SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1 || defined(DOXYGEN) -#include -#if SD_SPI_CONFIGURATION >= 3 -class SdSpiLib : public SdSpiBase { -#else // SD_SPI_CONFIGURATION >= 3 -class SdSpiLib { -#endif // SD_SPI_CONFIGURATION >= 3 - public: - /** - * Initialize SPI pins. - */ - void begin() { - SPI.begin(); - } - /** Set SPI options for access to SD/SDHC cards. - * - * \param[in] divisor SCK clock divider relative to the system clock. - */ - void init(uint8_t divisor) { - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); -#ifndef SPI_CLOCK_DIV128 - SPI.setClockDivider(divisor); -#else // SPI_CLOCK_DIV128 - int v; - if (divisor <= 2) { - v = SPI_CLOCK_DIV2; - } else if (divisor <= 4) { - v = SPI_CLOCK_DIV4; - } else if (divisor <= 8) { - v = SPI_CLOCK_DIV8; - } else if (divisor <= 16) { - v = SPI_CLOCK_DIV16; - } else if (divisor <= 32) { - v = SPI_CLOCK_DIV32; - } else if (divisor <= 64) { - v = SPI_CLOCK_DIV64; - } else { - v = SPI_CLOCK_DIV128; - } - SPI.setClockDivider(v); -#endif // SPI_CLOCK_DIV128 - } - /** Receive a byte. - * - * \return The byte. - */ - uint8_t receive() { - return SPI.transfer(0XFF); - } - /** 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 receive(uint8_t* buf, size_t n) { - for (size_t i = 0; i < n; i++) { - buf[i] = SPI.transfer(0XFF); - } - return 0; - } - /** Send a byte. - * - * \param[in] b Byte to send - */ - void send(uint8_t 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 send(const uint8_t* buf , size_t n) { - for (size_t i = 0; i < n; i++) { - SPI.transfer(buf[i]); - } - } - /** \return true - uses SPI transactions */ - bool useSpiTransactions() { - return true; - } -}; -#endif // SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1 -//------------------------------------------------------------------------------ -#if SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN) -#include "utility/SoftSPI.h" -/** - * \class SdSpiSoft - * \brief Software SPI class for access to SD and SDHC flash memory cards. - */ -template -class SdSpiSoft : public SdSpiBase { - public: - /** - * initialize SPI pins - */ - void begin() { - m_spi.begin(); - } - /** - * Initialize hardware SPI - dummy for soft SPI - * \param[in] divisor SCK divisor - ignored. - */ - void init(uint8_t divisor) {} - /** Receive a byte. - * - * \return The byte. - */ - uint8_t receive() { - return m_spi.receive(); - } - /** 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 receive(uint8_t* buf, size_t n) { - for (size_t i = 0; i < n; i++) { - buf[i] = receive(); - } - return 0; - } - /** Send a byte. - * - * \param[in] data Byte to send - */ - void send(uint8_t data) { - m_spi.send(data); - } - /** Send multiple bytes. - * - * \param[in] buf Buffer for data to be sent. - * \param[in] n Number of bytes to send. - */ - void send(const uint8_t* buf , size_t n) { - for (size_t i = 0; i < n; i++) { - send(buf[i]); - } - } - /** \return false - no SPI transactions */ - bool useSpiTransactions() { - return false; - } - - private: - SoftSPI m_spi; -}; -#endif // SD_SPI_CONFIGURATION > 1 || defined(DOXYGEN) -//------------------------------------------------------------------------------ -#if SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3 -/** Default is custom fast SPI. */ -typedef SdSpi SpiDefault_t; -#elif SD_SPI_CONFIGURATION == 1 -/** Default is Arduino library SPI. */ -typedef SdSpiLib SpiDefault_t; -#elif SD_SPI_CONFIGURATION == 2 -/** Default is software SPI. */ -typedef SdSpiSoft -SpiDefault_t; -#else // SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3 -#error bad SD_SPI_CONFIGURATION -#endif // SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3 -//------------------------------------------------------------------------------ -// Use of in-line for AVR to save flash. -#ifdef __AVR__ -//------------------------------------------------------------------------------ -inline void SdSpi::begin() { -#ifdef __AVR_ATmega328P__ - // Save a few bytes for 328 CPU - gcc optimizes single bit '|' to sbi. - PORTB |= 1 << 2; // SS high - DDRB |= 1 << 2; // SS output mode - DDRB |= 1 << 3; // MOSI output mode - DDRB |= 1 << 5; // SCK output mode -#else // __AVR_ATmega328P__ - - // set SS high - may be chip select for another SPI device - digitalWrite(SS, HIGH); - - // SS must be in output mode even it is not chip select - pinMode(SS, OUTPUT); - pinMode(MOSI, OUTPUT); - pinMode(SCK, OUTPUT); -#endif // __AVR_ATmega328P__ -} -//------------------------------------------------------------------------------ -inline void SdSpi::init(uint8_t divisor) { - uint8_t b = 2; - uint8_t r = 0; - - // See AVR processor documentation. - for (; divisor > b && r < 7; b <<= 1, r += r < 5 ? 1 : 2) {} - SPCR = (1 << SPE) | (1 << MSTR) | (r >> 1); - SPSR = r & 1 ? 0 : 1 << SPI2X; -} -//------------------------------------------------------------------------------ -inline uint8_t SdSpi::receive() { - SPDR = 0XFF; - while (!(SPSR & (1 << SPIF))) {} - return SPDR; -} -//------------------------------------------------------------------------------ -inline uint8_t SdSpi::receive(uint8_t* buf, size_t n) { - if (n-- == 0) { - return 0; - } - SPDR = 0XFF; - for (size_t i = 0; i < n; i++) { - while (!(SPSR & (1 << SPIF))) {} - uint8_t b = SPDR; - SPDR = 0XFF; - buf[i] = b; - } - while (!(SPSR & (1 << SPIF))) {} - buf[n] = SPDR; - return 0; -} -//------------------------------------------------------------------------------ -inline void SdSpi::send(uint8_t data) { - SPDR = data; - while (!(SPSR & (1 << SPIF))) {} -} -//------------------------------------------------------------------------------ -inline void SdSpi::send(const uint8_t* buf , size_t n) { - if (n == 0) { - return; - } - SPDR = buf[0]; - if (n > 1) { - uint8_t b = buf[1]; - size_t i = 2; - while (1) { - while (!(SPSR & (1 << SPIF))) {} - SPDR = b; - if (i == n) { - break; - } - b = buf[i++]; - } - } - while (!(SPSR & (1 << SPIF))) {} -} -#endif // __AVR__ -#endif // SdSpi_h diff --git a/SdFat/SdSpiCard.cpp b/SdFat/SdSpiCard.cpp deleted file mode 100644 index 1747484a..00000000 --- a/SdFat/SdSpiCard.cpp +++ /dev/null @@ -1,636 +0,0 @@ -/* Arduino SdSpiCard Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdSpiCard Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdSpiCard Library. If not, see - * . - */ -#include "SdSpiCard.h" -#include "SdSpi.h" -#if ENABLE_SPI_TRANSACTION -#include -#endif // ENABLE_SPI_TRANSACTION -// debug trace macro -#define SD_TRACE(m, b) -// #define SD_TRACE(m, b) Serial.print(m);Serial.println(b); -//============================================================================== -#if USE_SD_CRC -// CRC functions -//------------------------------------------------------------------------------ -static uint8_t CRC7(const uint8_t* data, uint8_t n) { - uint8_t crc = 0; - for (uint8_t i = 0; i < n; i++) { - uint8_t d = data[i]; - for (uint8_t j = 0; j < 8; j++) { - crc <<= 1; - if ((d & 0x80) ^ (crc & 0x80)) { - crc ^= 0x09; - } - d <<= 1; - } - } - return (crc << 1) | 1; -} -//------------------------------------------------------------------------------ -#if USE_SD_CRC == 1 -// slower CRC-CCITT -// uses the x^16,x^12,x^5,x^1 polynomial. -static uint16_t CRC_CCITT(const uint8_t *data, size_t n) { - uint16_t crc = 0; - for (size_t i = 0; i < n; i++) { - crc = (uint8_t)(crc >> 8) | (crc << 8); - crc ^= data[i]; - crc ^= (uint8_t)(crc & 0xff) >> 4; - crc ^= crc << 12; - crc ^= (crc & 0xff) << 5; - } - return crc; -} -#elif USE_SD_CRC > 1 // CRC_CCITT -//------------------------------------------------------------------------------ -// faster CRC-CCITT -// uses the x^16,x^12,x^5,x^1 polynomial. -#ifdef __AVR__ -static const uint16_t crctab[] PROGMEM = { -#else // __AVR__ -static const uint16_t crctab[] = { -#endif // __AVR__ - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 -}; -static uint16_t CRC_CCITT(const uint8_t* data, size_t n) { - uint16_t crc = 0; - for (size_t i = 0; i < n; i++) { -#ifdef __AVR__ - crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0XFF]) ^ (crc << 8); -#else // __AVR__ - crc = crctab[(crc >> 8 ^ data[i]) & 0XFF] ^ (crc << 8); -#endif // __AVR__ - } - return crc; -} -#endif // CRC_CCITT -#endif // USE_SD_CRC -//============================================================================== -// SdSpiCard member functions -//------------------------------------------------------------------------------ -bool SdSpiCard::begin(m_spi_t* spi, uint8_t chipSelectPin, uint8_t sckDivisor) { - m_errorCode = m_type = 0; - m_spi = spi; - m_chipSelectPin = chipSelectPin; - // 16-bit init start time allows over a minute - uint16_t t0 = (uint16_t)millis(); - uint32_t arg; - - pinMode(m_chipSelectPin, OUTPUT); - digitalWrite(m_chipSelectPin, HIGH); - spiBegin(); - - // set SCK rate for initialization commands - m_sckDivisor = SPI_SCK_INIT_DIVISOR; - spiInit(m_sckDivisor); - - // must supply min of 74 clock cycles with CS high. - for (uint8_t i = 0; i < 10; i++) { - spiSend(0XFF); - } - - // command to go idle in SPI mode - while (cardCommand(CMD0, 0) != R1_IDLE_STATE) { - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_CMD0); - goto fail; - } - } -#if USE_SD_CRC - if (cardCommand(CMD59, 1) != R1_IDLE_STATE) { - error(SD_CARD_ERROR_CMD59); - goto fail; - } -#endif // USE_SD_CRC - // check SD version - while (1) { - if (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) { - type(SD_CARD_TYPE_SD1); - break; - } - for (uint8_t i = 0; i < 4; i++) { - m_status = spiReceive(); - } - if (m_status == 0XAA) { - type(SD_CARD_TYPE_SD2); - break; - } - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_CMD8); - goto fail; - } - } - // initialize card and send host supports SDHC if SD2 - arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; - - while (cardAcmd(ACMD41, arg) != R1_READY_STATE) { - // check for timeout - if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) { - error(SD_CARD_ERROR_ACMD41); - goto fail; - } - } - // if SD2 read OCR register to check for SDHC card - if (type() == SD_CARD_TYPE_SD2) { - if (cardCommand(CMD58, 0)) { - error(SD_CARD_ERROR_CMD58); - goto fail; - } - if ((spiReceive() & 0XC0) == 0XC0) { - type(SD_CARD_TYPE_SDHC); - } - // Discard rest of ocr - contains allowed voltage range. - for (uint8_t i = 0; i < 3; i++) { - spiReceive(); - } - } - chipSelectHigh(); - m_sckDivisor = sckDivisor; - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -// send command and return error code. Return zero for OK -uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) { - // select card - chipSelectLow(); - - // wait if busy - waitNotBusy(SD_WRITE_TIMEOUT); - - uint8_t *pa = reinterpret_cast(&arg); - -#if USE_SD_CRC - // form message - uint8_t d[6] = {cmd | 0X40, pa[3], pa[2], pa[1], pa[0]}; - - // add crc - d[5] = CRC7(d, 5); - - // send message - for (uint8_t k = 0; k < 6; k++) { - spiSend(d[k]); - } -#else // USE_SD_CRC - // send command - spiSend(cmd | 0x40); - - // send argument - for (int8_t i = 3; i >= 0; i--) { - spiSend(pa[i]); - } - - // send CRC - correct for CMD0 with arg zero or CMD8 with arg 0X1AA - spiSend(cmd == CMD0 ? 0X95 : 0X87); -#endif // USE_SD_CRC - - // skip stuff byte for stop read - if (cmd == CMD12) { - spiReceive(); - } - - // wait for response - for (uint8_t i = 0; ((m_status = spiReceive()) & 0X80) && i != 0XFF; i++) { - } - return m_status; -} -//------------------------------------------------------------------------------ -uint32_t SdSpiCard::cardSize() { - csd_t csd; - if (!readCSD(&csd)) { - return 0; - } - if (csd.v1.csd_ver == 0) { - uint8_t read_bl_len = csd.v1.read_bl_len; - uint16_t c_size = (csd.v1.c_size_high << 10) - | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; - uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) - | csd.v1.c_size_mult_low; - return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); - } else if (csd.v2.csd_ver == 1) { - uint32_t c_size = 0X10000L * csd.v2.c_size_high + 0X100L - * (uint32_t)csd.v2.c_size_mid + csd.v2.c_size_low; - return (c_size + 1) << 10; - } else { - error(SD_CARD_ERROR_BAD_CSD); - return 0; - } -} -//------------------------------------------------------------------------------ -void SdSpiCard::spiYield() { -#if ENABLE_SPI_TRANSACTION && ENABLE_SPI_YIELD && defined(SPI_HAS_TRANSACTION) - chipSelectHigh(); - chipSelectLow(); -#endif // ENABLE_SPI_TRANSACTION && ENABLE_SPI_YIELD && SPI_HAS_TRANSACTION -} -//------------------------------------------------------------------------------ -void SdSpiCard::chipSelectHigh() { - digitalWrite(m_chipSelectPin, HIGH); - // insure MISO goes high impedance - spiSend(0XFF); -#if ENABLE_SPI_TRANSACTION && defined(SPI_HAS_TRANSACTION) - if (useSpiTransactions()) { - SPI.endTransaction(); - } -#endif // ENABLE_SPI_TRANSACTION && defined(SPI_HAS_TRANSACTION) -} -//------------------------------------------------------------------------------ -void SdSpiCard::chipSelectLow() { -#if ENABLE_SPI_TRANSACTION && defined(SPI_HAS_TRANSACTION) - if (useSpiTransactions()) { - SPI.beginTransaction(SPISettings()); - } -#endif // ENABLE_SPI_TRANSACTION && defined(SPI_HAS_TRANSACTION) - spiInit(m_sckDivisor); - digitalWrite(m_chipSelectPin, LOW); -} -//------------------------------------------------------------------------------ -bool SdSpiCard::erase(uint32_t firstBlock, uint32_t lastBlock) { - csd_t csd; - if (!readCSD(&csd)) { - goto fail; - } - // check for single block erase - if (!csd.v1.erase_blk_en) { - // erase size mask - uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low; - if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) { - // error card can't erase specified area - error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); - goto fail; - } - } - if (m_type != SD_CARD_TYPE_SDHC) { - firstBlock <<= 9; - lastBlock <<= 9; - } - if (cardCommand(CMD32, firstBlock) - || cardCommand(CMD33, lastBlock) - || cardCommand(CMD38, 0)) { - error(SD_CARD_ERROR_ERASE); - goto fail; - } - if (!waitNotBusy(SD_ERASE_TIMEOUT)) { - error(SD_CARD_ERROR_ERASE_TIMEOUT); - goto fail; - } - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::eraseSingleBlockEnable() { - csd_t csd; - return readCSD(&csd) ? csd.v1.erase_blk_en : false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::isBusy() { - bool rtn; - chipSelectLow(); - for (uint8_t i = 0; i < 8; i++) { - rtn = spiReceive() != 0XFF; - if (!rtn) { - break; - } - } - chipSelectHigh(); - return rtn; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::readBlock(uint32_t blockNumber, uint8_t* dst) { - SD_TRACE("RB", blockNumber); - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) { - blockNumber <<= 9; - } - if (cardCommand(CMD17, blockNumber)) { - error(SD_CARD_ERROR_CMD17); - goto fail; - } - return readData(dst, 512); - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::readBlocks(uint32_t block, uint8_t* dst, size_t count) { - if (!readStart(block)) { - return false; - } - for (uint16_t b = 0; b < count; b++, dst += 512) { - if (!readData(dst)) { - return false; - } - } - return readStop(); -} -//------------------------------------------------------------------------------ -bool SdSpiCard::readData(uint8_t *dst) { - chipSelectLow(); - return readData(dst, 512); -} -//------------------------------------------------------------------------------ -bool SdSpiCard::readData(uint8_t* dst, size_t count) { -#if USE_SD_CRC - uint16_t crc; -#endif // USE_SD_CRC - // wait for start block token - uint16_t t0 = millis(); - while ((m_status = spiReceive()) == 0XFF) { - if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) { - error(SD_CARD_ERROR_READ_TIMEOUT); - goto fail; - } - } - if (m_status != DATA_START_BLOCK) { - error(SD_CARD_ERROR_READ); - goto fail; - } - // transfer data - if ((m_status = spiReceive(dst, count))) { - error(SD_CARD_ERROR_SPI_DMA); - goto fail; - } - -#if USE_SD_CRC - // get crc - crc = (spiReceive() << 8) | spiReceive(); - if (crc != CRC_CCITT(dst, count)) { - error(SD_CARD_ERROR_READ_CRC); - goto fail; - } -#else - // discard crc - spiReceive(); - spiReceive(); -#endif // USE_SD_CRC - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::readOCR(uint32_t* ocr) { - uint8_t *p = reinterpret_cast(ocr); - if (cardCommand(CMD58, 0)) { - error(SD_CARD_ERROR_CMD58); - goto fail; - } - for (uint8_t i = 0; i < 4; i++) { - p[3 - i] = spiReceive(); - } - - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -/** read CID or CSR register */ -bool SdSpiCard::readRegister(uint8_t cmd, void* buf) { - uint8_t* dst = reinterpret_cast(buf); - if (cardCommand(cmd, 0)) { - error(SD_CARD_ERROR_READ_REG); - goto fail; - } - return readData(dst, 16); - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::readStart(uint32_t blockNumber) { - SD_TRACE("RS", blockNumber); - if (type() != SD_CARD_TYPE_SDHC) { - blockNumber <<= 9; - } - if (cardCommand(CMD18, blockNumber)) { - error(SD_CARD_ERROR_CMD18); - goto fail; - } - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::readStop() { - if (cardCommand(CMD12, 0)) { - error(SD_CARD_ERROR_CMD12); - goto fail; - } - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -// wait for card to go not busy -bool SdSpiCard::waitNotBusy(uint16_t timeoutMillis) { - uint16_t t0 = millis(); - while (spiReceive() != 0XFF) { - if (((uint16_t)millis() - t0) >= timeoutMillis) { - goto fail; - } - spiYield(); - } - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::writeBlock(uint32_t blockNumber, const uint8_t* src) { - SD_TRACE("WB", blockNumber); - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) { - blockNumber <<= 9; - } - if (cardCommand(CMD24, blockNumber)) { - error(SD_CARD_ERROR_CMD24); - goto fail; - } - if (!writeData(DATA_START_BLOCK, src)) { - goto fail; - } - -#define CHECK_PROGRAMMING 0 -#if CHECK_PROGRAMMING - // wait for flash programming to complete - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - error(SD_CARD_ERROR_WRITE_TIMEOUT); - goto fail; - } - // response is r2 so get and check two bytes for nonzero - if (cardCommand(CMD13, 0) || spiReceive()) { - error(SD_CARD_ERROR_WRITE_PROGRAMMING); - goto fail; - } -#endif // CHECK_PROGRAMMING - - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::writeBlocks(uint32_t block, const uint8_t* src, size_t count) { - if (!writeStart(block, count)) { - return false; - } - for (size_t b = 0; b < count; b++, src += 512) { - if (!writeData(src)) { - return false; - } - } - return writeStop(); -} -//------------------------------------------------------------------------------ -bool SdSpiCard::writeData(const uint8_t* src) { - chipSelectLow(); - // wait for previous write to finish - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - goto fail; - } - if (!writeData(WRITE_MULTIPLE_TOKEN, src)) { - goto fail; - } - chipSelectHigh(); - return true; - -fail: - error(SD_CARD_ERROR_WRITE_MULTIPLE); - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -// send one block of data for write block or write multiple blocks -bool SdSpiCard::writeData(uint8_t token, const uint8_t* src) { -#if USE_SD_CRC - uint16_t crc = CRC_CCITT(src, 512); -#else // USE_SD_CRC - uint16_t crc = 0XFFFF; -#endif // USE_SD_CRC - spiSend(token); - spiSend(src, 512); - spiSend(crc >> 8); - spiSend(crc & 0XFF); - - m_status = spiReceive(); - if ((m_status & DATA_RES_MASK) != DATA_RES_ACCEPTED) { - error(SD_CARD_ERROR_WRITE); - goto fail; - } - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::writeStart(uint32_t blockNumber, uint32_t eraseCount) { - SD_TRACE("WS", blockNumber); - // send pre-erase count - if (cardAcmd(ACMD23, eraseCount)) { - error(SD_CARD_ERROR_ACMD23); - goto fail; - } - // use address if not SDHC card - if (type() != SD_CARD_TYPE_SDHC) { - blockNumber <<= 9; - } - if (cardCommand(CMD25, blockNumber)) { - error(SD_CARD_ERROR_CMD25); - goto fail; - } - chipSelectHigh(); - return true; - -fail: - chipSelectHigh(); - return false; -} -//------------------------------------------------------------------------------ -bool SdSpiCard::writeStop() { - chipSelectLow(); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - goto fail; - } - spiSend(STOP_TRAN_TOKEN); - if (!waitNotBusy(SD_WRITE_TIMEOUT)) { - goto fail; - } - chipSelectHigh(); - return true; - -fail: - error(SD_CARD_ERROR_STOP_TRAN); - chipSelectHigh(); - return false; -} diff --git a/SdFat/SdSpiCard.h b/SdFat/SdSpiCard.h deleted file mode 100644 index ab2d0a32..00000000 --- a/SdFat/SdSpiCard.h +++ /dev/null @@ -1,308 +0,0 @@ -/* Arduino SdSpiCard Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdSpiCard Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdSpiCard Library. If not, see - * . - */ -#ifndef SpiCard_h -#define SpiCard_h -/** - * \file - * \brief SdSpiCard class for V2 SD/SDHC cards - */ -#include -#include -#include -#include -//============================================================================== -/** - * \class SdSpiCard - * \brief Raw access to SD and SDHC flash memory cards via SPI protocol. - */ -class SdSpiCard { - public: - /** typedef for SPI class. */ -#if SD_SPI_CONFIGURATION < 3 - typedef SpiDefault_t m_spi_t; -#else // SD_SPI_CONFIGURATION < 3 - typedef SdSpiBase m_spi_t; -#endif // SD_SPI_CONFIGURATION < 3 - /** Construct an instance of SdSpiCard. */ - SdSpiCard() : m_errorCode(SD_CARD_ERROR_INIT_NOT_CALLED), m_type(0) {} - /** Initialize the SD card. - * \param[in] spi SPI object. - * \param[in] chipSelectPin SD chip select pin. - * \param[in] sckDivisor SPI clock divisor. - * \return true for success else false. - */ - bool begin(m_spi_t* spi, uint8_t chipSelectPin = SS, - uint8_t sckDivisor = SPI_FULL_SPEED); - /** - * Determine the size of an SD flash memory card. - * - * \return The number of 512 byte data blocks in the card - * or zero if an error occurs. - */ - uint32_t cardSize(); - /** Erase a range of blocks. - * - * \param[in] firstBlock The address of the first block in the range. - * \param[in] lastBlock The address of the last block in the range. - * - * \note This function requests the SD card to do a flash erase for a - * range of blocks. The data on the card after an erase operation is - * either 0 or 1, depends on the card vendor. The card must support - * single block erase. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool erase(uint32_t firstBlock, uint32_t lastBlock); - /** Determine if card supports single block erase. - * - * \return true is returned if single block erase is supported. - * false is returned if single block erase is not supported. - */ - bool eraseSingleBlockEnable(); - /** - * Set SD error code. - * \param[in] code value for error code. - */ - void error(uint8_t code) { - m_errorCode = code; - } - /** - * \return code for the last error. See SdSpiCard.h for a list of error codes. - */ - int errorCode() const { - return m_errorCode; - } - /** \return error data for last error. */ - int errorData() const { - return m_status; - } - /** - * Check for busy. MISO low indicates the card is busy. - * - * \return true if busy else false. - */ - bool isBusy(); - /** - * Read a 512 byte block from an SD card. - * - * \param[in] block Logical block to be read. - * \param[out] dst Pointer to the location that will receive the data. - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool readBlock(uint32_t block, uint8_t* dst); - /** - * Read multiple 512 byte blocks from an SD card. - * - * \param[in] block Logical block to be read. - * \param[in] count Number of blocks to be read. - * \param[out] dst Pointer to the location that will receive the data. - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool readBlocks(uint32_t block, uint8_t* dst, size_t count); - /** - * Read a card's CID register. The CID contains card identification - * information such as Manufacturer ID, Product name, Product serial - * number and Manufacturing date. - * - * \param[out] cid pointer to area for returned data. - * - * \return true for success or false for failure. - */ - bool readCID(cid_t* cid) { - return readRegister(CMD10, cid); - } - /** - * Read a card's CSD register. The CSD contains Card-Specific Data that - * provides information regarding access to the card's contents. - * - * \param[out] csd pointer to area for returned data. - * - * \return true for success or false for failure. - */ - bool readCSD(csd_t* csd) { - return readRegister(CMD9, csd); - } - /** Read one data block in a multiple block read sequence - * - * \param[out] dst Pointer to the location for the data to be read. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool readData(uint8_t *dst); - /** Read OCR register. - * - * \param[out] ocr Value of OCR register. - * \return true for success else false. - */ - bool readOCR(uint32_t* ocr); - /** Start a read multiple blocks sequence. - * - * \param[in] blockNumber Address of first block in sequence. - * - * \note This function is used with readData() and readStop() for optimized - * multiple block reads. SPI chipSelect must be low for the entire sequence. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool readStart(uint32_t blockNumber); - /** End a read multiple blocks sequence. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool readStop(); - /** Return SCK divisor. - * - * \return Requested SCK divisor. - */ - uint8_t sckDivisor() { - return m_sckDivisor; - } - /** Return the card type: SD V1, SD V2 or SDHC - * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC. - */ - int type() const { - return m_type; - } - /** - * Writes a 512 byte block to an SD card. - * - * \param[in] blockNumber Logical block to be written. - * \param[in] src Pointer to the location of the data to be written. - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool writeBlock(uint32_t blockNumber, const uint8_t* src); - /** - * Write multiple 512 byte blocks to an SD card. - * - * \param[in] block Logical block to be written. - * \param[in] count Number of blocks to be written. - * \param[in] src Pointer to the location of the data to be written. - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool writeBlocks(uint32_t block, const uint8_t* src, size_t count); - /** Write one data block in a multiple block write sequence - * \param[in] src Pointer to the location of the data to be written. - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool writeData(const uint8_t* src); - /** Start a write multiple blocks sequence. - * - * \param[in] blockNumber Address of first block in sequence. - * \param[in] eraseCount The number of blocks to be pre-erased. - * - * \note This function is used with writeData() and writeStop() - * for optimized multiple block writes. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool writeStart(uint32_t blockNumber, uint32_t eraseCount); - /** End a write multiple blocks sequence. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool writeStop(); - - private: - // private functions - uint8_t cardAcmd(uint8_t cmd, uint32_t arg) { - cardCommand(CMD55, 0); - return cardCommand(cmd, arg); - } - uint8_t cardCommand(uint8_t cmd, uint32_t arg); - bool readData(uint8_t* dst, size_t count); - bool readRegister(uint8_t cmd, void* buf); - void chipSelectHigh(); - void chipSelectLow(); - void spiYield(); - void type(uint8_t value) { - m_type = value; - } - bool waitNotBusy(uint16_t timeoutMillis); - bool writeData(uint8_t token, const uint8_t* src); - void spiBegin() { - m_spi->begin(); - } - void spiInit(uint8_t spiDivisor) { - m_spi->init(spiDivisor); - } - uint8_t spiReceive() { - return m_spi->receive(); - } - uint8_t spiReceive(uint8_t* buf, size_t n) { - return m_spi->receive(buf, n); - } - void spiSend(uint8_t data) { - m_spi->send(data); - } - void spiSend(const uint8_t* buf, size_t n) { - m_spi->send(buf, n); - } - bool useSpiTransactions() { - return m_spi->useSpiTransactions(); - } - m_spi_t* m_spi; - uint8_t m_chipSelectPin; - uint8_t m_errorCode; - uint8_t m_sckDivisor; - uint8_t m_status; - uint8_t m_type; -}; -//============================================================================== -/** - * \class Sd2Card - * \brief Raw access to SD and SDHC card using default SPI library. - */ -class Sd2Card : public SdSpiCard { - public: - /** Initialize the SD card. - * \param[in] chipSelectPin SD chip select pin. - * \param[in] sckDivisor SPI clock divisor. - * \return true for success else false. - */ - bool begin(uint8_t chipSelectPin = SS, uint8_t sckDivisor = 2) { - return SdSpiCard::begin(&m_spi, chipSelectPin, sckDivisor); - } - /** Initialize the SD card. Obsolete form. - * \param[in] chipSelectPin SD chip select pin. - * \param[in] sckDivisor SPI clock divisor. - * \return true for success else false. - */ - bool init(uint8_t sckDivisor = 2, uint8_t chipSelectPin = SS) { - return begin(chipSelectPin, sckDivisor); - } - private: - bool begin(m_spi_t* spi, uint8_t chipSelectPin = SS, - uint8_t sckDivisor = SPI_FULL_SPEED) { - return false; - } - SpiDefault_t m_spi; -}; -#endif // SpiCard_h diff --git a/SdFat/SdSpiSAM3X.cpp b/SdFat/SdSpiSAM3X.cpp deleted file mode 100644 index 22980096..00000000 --- a/SdFat/SdSpiSAM3X.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* Arduino SdSpi Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino SdSpi Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdSpi Library. If not, see - * . - */ -#include "SdSpi.h" -#if defined(__SAM3X8E__) || defined(__SAM3X8H__) -/** Use SAM3X DMAC if nonzero */ -#define USE_SAM3X_DMAC 1 -/** Use extra Bus Matrix arbitration fix if nonzero */ -#define USE_SAM3X_BUS_MATRIX_FIX 0 -/** Time in ms for DMA receive timeout */ -#define SAM3X_DMA_TIMEOUT 100 -/** chip select register number */ -#define SPI_CHIP_SEL 3 -/** DMAC receive channel */ -#define SPI_DMAC_RX_CH 1 -/** DMAC transmit channel */ -#define SPI_DMAC_TX_CH 0 -/** DMAC Channel HW Interface Number for SPI TX. */ -#define SPI_TX_IDX 1 -/** DMAC Channel HW Interface Number for SPI RX. */ -#define SPI_RX_IDX 2 -//------------------------------------------------------------------------------ -/** Disable DMA Controller. */ -static void dmac_disable() { - DMAC->DMAC_EN &= (~DMAC_EN_ENABLE); -} -/** Enable DMA Controller. */ -static void dmac_enable() { - DMAC->DMAC_EN = DMAC_EN_ENABLE; -} -/** Disable DMA Channel. */ -static void dmac_channel_disable(uint32_t ul_num) { - DMAC->DMAC_CHDR = DMAC_CHDR_DIS0 << ul_num; -} -/** Enable DMA Channel. */ -static void dmac_channel_enable(uint32_t ul_num) { - DMAC->DMAC_CHER = DMAC_CHER_ENA0 << ul_num; -} -/** Poll for transfer complete. */ -static bool dmac_channel_transfer_done(uint32_t ul_num) { - return (DMAC->DMAC_CHSR & (DMAC_CHSR_ENA0 << ul_num)) ? false : true; -} -//------------------------------------------------------------------------------ -void SdSpi::begin() { - PIO_Configure( - g_APinDescription[PIN_SPI_MOSI].pPort, - g_APinDescription[PIN_SPI_MOSI].ulPinType, - g_APinDescription[PIN_SPI_MOSI].ulPin, - g_APinDescription[PIN_SPI_MOSI].ulPinConfiguration); - PIO_Configure( - g_APinDescription[PIN_SPI_MISO].pPort, - g_APinDescription[PIN_SPI_MISO].ulPinType, - g_APinDescription[PIN_SPI_MISO].ulPin, - g_APinDescription[PIN_SPI_MISO].ulPinConfiguration); - PIO_Configure( - g_APinDescription[PIN_SPI_SCK].pPort, - g_APinDescription[PIN_SPI_SCK].ulPinType, - g_APinDescription[PIN_SPI_SCK].ulPin, - g_APinDescription[PIN_SPI_SCK].ulPinConfiguration); - pmc_enable_periph_clk(ID_SPI0); -#if USE_SAM3X_DMAC - pmc_enable_periph_clk(ID_DMAC); - dmac_disable(); - DMAC->DMAC_GCFG = DMAC_GCFG_ARB_CFG_FIXED; - dmac_enable(); -#if USE_SAM3X_BUS_MATRIX_FIX - MATRIX->MATRIX_WPMR = 0x4d415400; - MATRIX->MATRIX_MCFG[1] = 1; - MATRIX->MATRIX_MCFG[2] = 1; - MATRIX->MATRIX_SCFG[0] = 0x01000010; - MATRIX->MATRIX_SCFG[1] = 0x01000010; - MATRIX->MATRIX_SCFG[7] = 0x01000010; -#endif // USE_SAM3X_BUS_MATRIX_FIX -#endif // USE_SAM3X_DMAC -} -//------------------------------------------------------------------------------ -// start RX DMA -static void spiDmaRX(uint8_t* dst, uint16_t count) { - dmac_channel_disable(SPI_DMAC_RX_CH); - DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_SADDR = (uint32_t)&SPI0->SPI_RDR; - DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_DADDR = (uint32_t)dst; - DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_DSCR = 0; - DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CTRLA = count | - DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE; - DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR | - DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_PER2MEM_DMA_FC | - DMAC_CTRLB_SRC_INCR_FIXED | DMAC_CTRLB_DST_INCR_INCREMENTING; - DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CFG = DMAC_CFG_SRC_PER(SPI_RX_IDX) | - DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG; - dmac_channel_enable(SPI_DMAC_RX_CH); -} -//------------------------------------------------------------------------------ -// start TX DMA -static void spiDmaTX(const uint8_t* src, uint16_t count) { - static uint8_t ff = 0XFF; - uint32_t src_incr = DMAC_CTRLB_SRC_INCR_INCREMENTING; - if (!src) { - src = &ff; - src_incr = DMAC_CTRLB_SRC_INCR_FIXED; - } - dmac_channel_disable(SPI_DMAC_TX_CH); - DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_SADDR = (uint32_t)src; - DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DADDR = (uint32_t)&SPI0->SPI_TDR; - DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DSCR = 0; - DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLA = count | - DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE; - - DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR | - DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC | - src_incr | DMAC_CTRLB_DST_INCR_FIXED; - - DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CFG = DMAC_CFG_DST_PER(SPI_TX_IDX) | - DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG; - - dmac_channel_enable(SPI_DMAC_TX_CH); -} -//------------------------------------------------------------------------------ -// initialize SPI controller -void SdSpi::init(uint8_t sckDivisor) { - uint8_t scbr = sckDivisor; - Spi* pSpi = SPI0; - // disable SPI - pSpi->SPI_CR = SPI_CR_SPIDIS; - // reset SPI - pSpi->SPI_CR = SPI_CR_SWRST; - // no mode fault detection, set master mode - pSpi->SPI_MR = SPI_PCS(SPI_CHIP_SEL) | SPI_MR_MODFDIS | SPI_MR_MSTR; - // mode 0, 8-bit, - pSpi->SPI_CSR[SPI_CHIP_SEL] = SPI_CSR_SCBR(scbr) | SPI_CSR_NCPHA; - // enable SPI - pSpi->SPI_CR |= SPI_CR_SPIEN; -} -//------------------------------------------------------------------------------ -static inline uint8_t spiTransfer(uint8_t b) { - Spi* pSpi = SPI0; - - pSpi->SPI_TDR = b; - while ((pSpi->SPI_SR & SPI_SR_RDRF) == 0) {} - b = pSpi->SPI_RDR; - return b; -} -//------------------------------------------------------------------------------ -/** SPI receive a byte */ -uint8_t SdSpi::receive() { - return spiTransfer(0XFF); -} -//------------------------------------------------------------------------------ -/** SPI receive multiple bytes */ -uint8_t SdSpi::receive(uint8_t* buf, size_t n) { - Spi* pSpi = SPI0; - int rtn = 0; -#if USE_SAM3X_DMAC - // clear overrun error - uint32_t s = pSpi->SPI_SR; - - spiDmaRX(buf, n); - spiDmaTX(0, n); - - uint32_t m = millis(); - while (!dmac_channel_transfer_done(SPI_DMAC_RX_CH)) { - if ((millis() - m) > SAM3X_DMA_TIMEOUT) { - dmac_channel_disable(SPI_DMAC_RX_CH); - dmac_channel_disable(SPI_DMAC_TX_CH); - rtn = 2; - break; - } - } - if (pSpi->SPI_SR & SPI_SR_OVRES) { - rtn |= 1; - } -#else // USE_SAM3X_DMAC - for (size_t i = 0; i < n; i++) { - pSpi->SPI_TDR = 0XFF; - while ((pSpi->SPI_SR & SPI_SR_RDRF) == 0) {} - buf[i] = pSpi->SPI_RDR; - } -#endif // USE_SAM3X_DMAC - return rtn; -} -//------------------------------------------------------------------------------ -/** SPI send a byte */ -void SdSpi::send(uint8_t b) { - spiTransfer(b); -} -//------------------------------------------------------------------------------ -void SdSpi::send(const uint8_t* buf , size_t n) { - Spi* pSpi = SPI0; -#if USE_SAM3X_DMAC - spiDmaTX(buf, n); - while (!dmac_channel_transfer_done(SPI_DMAC_TX_CH)) {} -#else // #if USE_SAM3X_DMAC - while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {} - for (size_t i = 0; i < n; i++) { - pSpi->SPI_TDR = buf[i]; - while ((pSpi->SPI_SR & SPI_SR_TDRE) == 0) {} - } -#endif // #if USE_SAM3X_DMAC - while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {} - // leave RDR empty - uint8_t b = pSpi->SPI_RDR; -} -#endif // defined(__SAM3X8E__) || defined(__SAM3X8H__) diff --git a/SdFat/SdSpiSTM32F1.cpp b/SdFat/SdSpiSTM32F1.cpp deleted file mode 100644 index a36d5a1a..00000000 --- a/SdFat/SdSpiSTM32F1.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* 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 - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdSpi Library. If not, see - * . - */ -#if defined(__STM32F1__) -#include "SdSpi.h" -#include -#include -/** 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); -} -//------------------------------------------------------------------------------ -void SdSpi::begin() { - 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(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(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::init(uint8_t sckDivisor) { - if (sckDivisor < SPI_CLOCK_DIV2 || sckDivisor > SPI_CLOCK_DIV256) { - sckDivisor = SPI_CLOCK_DIV2; // may not be needed, testing. - } - SPI.setClockDivider(sckDivisor); - 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 -} -//------------------------------------------------------------------------------ -// STM32 -static inline uint8_t spiTransfer(uint8_t b) { - return SPI.transfer(b); -} -//------------------------------------------------------------------------------ -// should be valid for STM32 -/** SPI receive a byte */ -uint8_t SdSpi::receive() { - return spiTransfer(0xFF); -} -//------------------------------------------------------------------------------ -/** SPI receive multiple bytes */ -// check and finish. - -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; - } - } - -#else // USE_STM32F1_DMAC - for (size_t i = 0; i < n; i++) { - buf[i] = SPI.transfer(0xFF); - } -#endif // USE_STM32F1_DMAC - return rtn; -} -//------------------------------------------------------------------------------ -/** SPI send a byte */ -void SdSpi::send(uint8_t b) { - spiTransfer(b); -} -//------------------------------------------------------------------------------ -void SdSpi::send(const uint8_t* buf , size_t n) { -#if USE_STM32F1_DMAC - spiDmaTX(buf, n); - while (SPI_DMA_TX_Active) {} - -#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_NATIVE_STM32F1_SPI diff --git a/SdFat/SdSpiTeensy3.cpp b/SdFat/SdSpiTeensy3.cpp deleted file mode 100644 index a9fe8b35..00000000 --- a/SdFat/SdSpiTeensy3.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* Arduino SdSpi Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino SdSpi Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdSpi Library. If not, see - * . - */ -#include "SdSpi.h" -#if defined(__arm__) && defined(CORE_TEENSY) -// SPI definitions -#include "kinetis.h" -#ifdef KINETISK -// use 16-bit frame if SPI_USE_8BIT_FRAME is zero -#define SPI_USE_8BIT_FRAME 0 -// Limit initial fifo to three entries to avoid fifo overrun -#define SPI_INITIAL_FIFO_DEPTH 3 -// define some symbols that are not in mk20dx128.h -#ifndef SPI_SR_RXCTR -#define SPI_SR_RXCTR 0XF0 -#endif // SPI_SR_RXCTR -#ifndef SPI_PUSHR_CONT -#define SPI_PUSHR_CONT 0X80000000 -#endif // SPI_PUSHR_CONT -#ifndef SPI_PUSHR_CTAS -#define SPI_PUSHR_CTAS(n) (((n) & 7) << 28) -#endif // SPI_PUSHR_CTAS -//------------------------------------------------------------------------------ -/** - * initialize SPI pins - */ -void SdSpi::begin() { - SIM_SCGC6 |= SIM_SCGC6_SPI0; -} -//------------------------------------------------------------------------------ -/** - * Initialize hardware SPI - * - */ -void SdSpi::init(uint8_t sckDivisor) { - uint32_t ctar, ctar0, ctar1; - - if (sckDivisor <= 2) { - // 1/2 speed - ctar = SPI_CTAR_DBR | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0); - } else if (sckDivisor <= 4) { - // 1/4 speed - ctar = SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0); - } else if (sckDivisor <= 8) { - // 1/8 speed - ctar = SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1); - } else if (sckDivisor <= 12) { - // 1/12 speed - ctar = SPI_CTAR_BR(2) | SPI_CTAR_CSSCK(2); - } else if (sckDivisor <= 16) { - // 1/16 speed - ctar = SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(3); - } else if (sckDivisor <= 32) { - // 1/32 speed - ctar = SPI_CTAR_PBR(1) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(4); - } else if (sckDivisor <= 64) { - // 1/64 speed - ctar = SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(5); - } else { - // 1/128 speed - ctar = SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(6); - } - // CTAR0 - 8 bit transfer - ctar0 = ctar | SPI_CTAR_FMSZ(7); - - // CTAR1 - 16 bit transfer - ctar1 = ctar | SPI_CTAR_FMSZ(15); - - if (SPI0_CTAR0 != ctar0 || SPI0_CTAR1 != ctar1) { - SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F); - SPI0_CTAR0 = ctar0; - SPI0_CTAR1 = ctar1; - } - SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F); - CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); - CORE_PIN12_CONFIG = PORT_PCR_MUX(2); - CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); -} -//------------------------------------------------------------------------------ -/** SPI receive a byte */ -uint8_t SdSpi::receive() { - SPI0_MCR |= SPI_MCR_CLR_RXF; - SPI0_SR = SPI_SR_TCF; - SPI0_PUSHR = 0xFF; - while (!(SPI0_SR & SPI_SR_TCF)) {} - return SPI0_POPR; -} -//------------------------------------------------------------------------------ -/** SPI receive multiple bytes */ -uint8_t SdSpi::receive(uint8_t* buf, size_t n) { - // clear any data in RX FIFO - SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F); -#if SPI_USE_8BIT_FRAME - // initial number of bytes to push into TX FIFO - int nf = n < SPI_INITIAL_FIFO_DEPTH ? n : SPI_INITIAL_FIFO_DEPTH; - for (int i = 0; i < nf; i++) { - SPI0_PUSHR = 0XFF; - } - // limit for pushing dummy data into TX FIFO - uint8_t* limit = buf + n - nf; - while (buf < limit) { - while (!(SPI0_SR & SPI_SR_RXCTR)) {} - SPI0_PUSHR = 0XFF; - *buf++ = SPI0_POPR; - } - // limit for rest of RX data - limit += nf; - while (buf < limit) { - while (!(SPI0_SR & SPI_SR_RXCTR)) {} - *buf++ = SPI0_POPR; - } -#else // SPI_USE_8BIT_FRAME - // use 16 bit frame to avoid TD delay between frames - // get one byte if n is odd - if (n & 1) { - *buf++ = receive(); - n--; - } - // initial number of words to push into TX FIFO - int nf = n/2 < SPI_INITIAL_FIFO_DEPTH ? n/2 : SPI_INITIAL_FIFO_DEPTH; - for (int i = 0; i < nf; i++) { - SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | 0XFFFF; - } - uint8_t* limit = buf + n - 2*nf; - while (buf < limit) { - while (!(SPI0_SR & SPI_SR_RXCTR)) {} - SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | 0XFFFF; - uint16_t w = SPI0_POPR; - *buf++ = w >> 8; - *buf++ = w & 0XFF; - } - // limit for rest of RX data - limit += 2*nf; - while (buf < limit) { - while (!(SPI0_SR & SPI_SR_RXCTR)) {} - uint16_t w = SPI0_POPR; - *buf++ = w >> 8; - *buf++ = w & 0XFF; - } -#endif // SPI_USE_8BIT_FRAME - return 0; -} -//------------------------------------------------------------------------------ -/** SPI send a byte */ -void SdSpi::send(uint8_t b) { - SPI0_MCR |= SPI_MCR_CLR_RXF; - SPI0_SR = SPI_SR_TCF; - SPI0_PUSHR = b; - while (!(SPI0_SR & SPI_SR_TCF)) {} -} -//------------------------------------------------------------------------------ -/** SPI send multiple bytes */ -void SdSpi::send(const uint8_t* buf , size_t n) { - // clear any data in RX FIFO - SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F); -#if SPI_USE_8BIT_FRAME - // initial number of bytes to push into TX FIFO - int nf = n < SPI_INITIAL_FIFO_DEPTH ? n : SPI_INITIAL_FIFO_DEPTH; - // limit for pushing data into TX fifo - const uint8_t* limit = buf + n; - for (int i = 0; i < nf; i++) { - SPI0_PUSHR = *buf++; - } - // write data to TX FIFO - while (buf < limit) { - while (!(SPI0_SR & SPI_SR_RXCTR)) {} - SPI0_PUSHR = *buf++; - SPI0_POPR; - } - // wait for data to be sent - while (nf) { - while (!(SPI0_SR & SPI_SR_RXCTR)) {} - SPI0_POPR; - nf--; - } -#else // SPI_USE_8BIT_FRAME - // use 16 bit frame to avoid TD delay between frames - // send one byte if n is odd - if (n & 1) { - send(*buf++); - n--; - } - // initial number of words to push into TX FIFO - int nf = n/2 < SPI_INITIAL_FIFO_DEPTH ? n/2 : SPI_INITIAL_FIFO_DEPTH; - // limit for pushing data into TX fifo - const uint8_t* limit = buf + n; - for (int i = 0; i < nf; i++) { - uint16_t w = (*buf++) << 8; - w |= *buf++; - SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | w; - } - // write data to TX FIFO - while (buf < limit) { - uint16_t w = *buf++ << 8; - w |= *buf++; - while (!(SPI0_SR & SPI_SR_RXCTR)) {} - SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | w; - SPI0_POPR; - } - // wait for data to be sent - while (nf) { - while (!(SPI0_SR & SPI_SR_RXCTR)) {} - SPI0_POPR; - nf--; - } -#endif // SPI_USE_8BIT_FRAME -} -#else // KINETISK -//============================================================================== -// Use standard SPI library if not KINETISK -#include "SPI.h" -/** - * Initialize SPI pins. - */ -void SdSpi::begin() { - SPI.begin(); -} -/** Set SPI options for access to SD/SDHC cards. - * - * \param[in] divisor SCK clock divider relative to the system clock. - */ -void SdSpi::init(uint8_t divisor) { - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); -#ifndef SPI_CLOCK_DIV128 - SPI.setClockDivider(divisor); -#else // SPI_CLOCK_DIV128 - int v; - if (divisor <= 2) { - v = SPI_CLOCK_DIV2; - } else if (divisor <= 4) { - v = SPI_CLOCK_DIV4; - } else if (divisor <= 8) { - v = SPI_CLOCK_DIV8; - } else if (divisor <= 16) { - v = SPI_CLOCK_DIV16; - } else if (divisor <= 32) { - v = SPI_CLOCK_DIV32; - } else if (divisor <= 64) { - v = SPI_CLOCK_DIV64; - } else { - v = SPI_CLOCK_DIV128; - } - SPI.setClockDivider(v); -#endif // SPI_CLOCK_DIV128 -} -/** Receive a byte. - * - * \return The byte. - */ -uint8_t SdSpi::receive() { - return SPI.transfer(0XFF); -} -/** 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) { - for (size_t i = 0; i < n; i++) { - buf[i] = SPI.transfer(0XFF); - } - return 0; -} -/** Send a byte. - * - * \param[in] b Byte to send - */ -void SdSpi::send(uint8_t 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) { - for (size_t i = 0; i < n; i++) { - SPI.transfer(buf[i]); - } -} -#endif // KINETISK -#endif // defined(__arm__) && defined(CORE_TEENSY) diff --git a/SdFat/SdVolume.h b/SdFat/SdVolume.h deleted file mode 100644 index f76db7a6..00000000 --- a/SdFat/SdVolume.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdVolume_h -#include "SdSpiCard.h" -#include "utility/FatLib.h" -#define SdVolume_h -#ifndef USE_SD_VOLUME -#error SdVolume is deperacated. Remove this line to continue using this class. -#endif // USE_SD_VOLUME -//============================================================================== -/** - * \class SdVolume - * \brief SdVolume Soon to be removed. - */ -class SdVolume : public FatVolume { - public: - /** Initialize a FAT volume. Try partition one first then try super - * floppy format. - * - * \param[in] dev The Sd2Card where the volume is located. - * - * \return true for success else false. - */ - bool init(Sd2Card* dev) { - return init(dev, 1) ? true : init(dev, 0); - } - /** Initialize a FAT volume. - * - * \param[in] dev The Sd2Card where the volume is located. - * \param[in] part the partition to use. Zero for super floppy or 1-4. - * \return true for success else false. - */ - bool init(Sd2Card* dev, uint8_t part) { - m_sdCard = dev; - return FatVolume::init(part); - } - - private: -// friend class FatFile; - bool readBlock(uint32_t block, uint8_t* dst) { - return m_sdCard->readBlock(block, dst); - } - bool writeBlock(uint32_t block, const uint8_t* src) { - return m_sdCard->writeBlock(block, src); - } - bool readBlocks(uint32_t block, uint8_t* dst, size_t n) { - return m_sdCard->readBlocks(block, dst, n); - } - bool writeBlocks(uint32_t block, const uint8_t* src, size_t n) { - return m_sdCard->writeBlocks(block, src, n); - } - Sd2Card* m_sdCard; // Sd2Card object for cache -}; -#endif // SdVolume_h diff --git a/SdFat/examples/#attic/AnalogLogger/AnalogLogger.ino b/SdFat/examples/#attic/AnalogLogger/AnalogLogger.ino deleted file mode 100644 index 1a18228c..00000000 --- a/SdFat/examples/#attic/AnalogLogger/AnalogLogger.ino +++ /dev/null @@ -1,188 +0,0 @@ -// A simple data logger for the Arduino analog pins with optional DS1307 -// uses RTClib from https://github.com/adafruit/RTClib -#include -#include -#include // define FreeRam() - -#define SD_CHIP_SELECT SS // SD chip select pin -#define USE_DS1307 0 // set nonzero to use DS1307 RTC -#define LOG_INTERVAL 1000 // mills between entries -#define SENSOR_COUNT 3 // number of analog pins to log -#define ECHO_TO_SERIAL 1 // echo data to serial port if nonzero -#define WAIT_TO_START 1 // Wait for serial input in setup() -#define ADC_DELAY 10 // ADC delay for high impedence sensors - -// file system object -SdFat sd; - -// text file for logging -ofstream logfile; - -// Serial print stream -ArduinoOutStream cout(Serial); - -// buffer to format data - makes it eaiser to echo to Serial -char buf[80]; -//------------------------------------------------------------------------------ -#if SENSOR_COUNT > 6 -#error SENSOR_COUNT too large -#endif // SENSOR_COUNT -//------------------------------------------------------------------------------ -// store error strings in flash to save RAM -#define error(s) sd.errorHalt(F(s)) -//------------------------------------------------------------------------------ -#if USE_DS1307 -// use RTClib from Adafruit -// https://github.com/adafruit/RTClib - -// The Arduino IDE has a bug that causes Wire and RTClib to be loaded even -// if USE_DS1307 is false. - -#error remove this line and uncomment the next two lines. -//#include -//#include -RTC_DS1307 RTC; // define the Real Time Clock object -//------------------------------------------------------------------------------ -// call back for file timestamps -void dateTime(uint16_t* date, uint16_t* time) { - DateTime now = RTC.now(); - - // return date using FAT_DATE macro to format fields - *date = FAT_DATE(now.year(), now.month(), now.day()); - - // return time using FAT_TIME macro to format fields - *time = FAT_TIME(now.hour(), now.minute(), now.second()); -} -//------------------------------------------------------------------------------ -// format date/time -ostream& operator << (ostream& os, DateTime& dt) { - os << dt.year() << '/' << int(dt.month()) << '/' << int(dt.day()) << ','; - os << int(dt.hour()) << ':' << setfill('0') << setw(2) << int(dt.minute()); - os << ':' << setw(2) << int(dt.second()) << setfill(' '); - return os; -} -#endif // USE_DS1307 -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - - // F() stores strings in flash to save RAM - cout << endl << F("FreeRam: ") << FreeRam() << endl; - -#if WAIT_TO_START - cout << F("Type any character to start\n"); - while (Serial.read() <= 0) {} - delay(400); // catch Due reset problem - while (Serial.read() >= 0) {} -#endif // WAIT_TO_START - -#if USE_DS1307 - // connect to RTC - Wire.begin(); - if (!RTC.begin()) { - error("RTC failed"); - } - - // set date time callback function - SdFile::dateTimeCallback(dateTime); - DateTime now = RTC.now(); - cout << now << endl; -#endif // USE_DS1307 - - // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - // create a new file in root, the current working directory - char name[] = "logger00.csv"; - - for (uint8_t i = 0; i < 100; i++) { - name[6] = i/10 + '0'; - name[7] = i%10 + '0'; - if (sd.exists(name)) { - continue; - } - logfile.open(name); - break; - } - if (!logfile.is_open()) { - error("file.open"); - } - - cout << F("Logging to: ") << name << endl; - cout << F("Type any character to stop\n\n"); - - // format header in buffer - obufstream bout(buf, sizeof(buf)); - - bout << F("millis"); - -#if USE_DS1307 - bout << F(",date,time"); -#endif // USE_DS1307 - - for (uint8_t i = 0; i < SENSOR_COUNT; i++) { - bout << F(",sens") << int(i); - } - logfile << buf << endl; - -#if ECHO_TO_SERIAL - cout << buf << endl; -#endif // ECHO_TO_SERIAL -} -//------------------------------------------------------------------------------ -void loop() { - uint32_t m; - - // wait for time to be a multiple of interval - do { - m = millis(); - } while (m % LOG_INTERVAL); - - // use buffer stream to format line - obufstream bout(buf, sizeof(buf)); - - // start with time in millis - bout << m; - -#if USE_DS1307 - DateTime now = RTC.now(); - bout << ',' << now; -#endif // USE_DS1307 - - // read analog pins and format data - for (uint8_t ia = 0; ia < SENSOR_COUNT; ia++) { -#if ADC_DELAY - analogRead(ia); - delay(ADC_DELAY); -#endif // ADC_DELAY - bout << ',' << analogRead(ia); - } - bout << endl; - - // log data and flush to SD - logfile << buf << flush; - - // check for error - if (!logfile) { - error("write data failed"); - } - -#if ECHO_TO_SERIAL - cout << buf; -#endif // ECHO_TO_SERIAL - - // don't log two points in the same millis - if (m == millis()) { - delay(1); - } - - if (!Serial.available()) { - return; - } - logfile.close(); - cout << F("Done!"); - while (1); -} \ No newline at end of file diff --git a/SdFat/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino b/SdFat/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino deleted file mode 100644 index 8dad3372..00000000 --- a/SdFat/examples/#attic/BaseExtCaseTest/BaseExtCaseTest.ino +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Program to test Short File Name character case flags. - */ -#include -#include - -SdFat sd; - -SdFile file; -char* name[] = { - "low.low", "low.Mix", "low.UP", - "Mix.low", "Mix.Mix", "Mix.UP", - "UP.low", "UP.Mix", "UP.UP" -}; -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - Serial.println("type any character to start"); - while (Serial.read() < 0) {} - if (!sd.begin()) { - Serial.println("begin failed"); - return; - } - for (uint8_t i = 0; i < 9; i++) { - sd.remove(name[i]); - if (!file.open(name[i], O_RDWR | O_CREAT | O_EXCL)) { - sd.errorHalt(name[i]); - } - file.println(name[i]); - - file.close(); - } - sd.ls(LS_DATE|LS_SIZE); - Serial.println("Done"); -} -//------------------------------------------------------------------------------ -void loop() {} diff --git a/SdFat/examples/#attic/HelloWorld/HelloWorld.ino b/SdFat/examples/#attic/HelloWorld/HelloWorld.ino deleted file mode 100644 index 1162f0fb..00000000 --- a/SdFat/examples/#attic/HelloWorld/HelloWorld.ino +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include - -// create a serial output stream -ArduinoOutStream cout(Serial); - -void setup() { - Serial.begin(9600); - - while (!Serial) {} // wait for Leonardo - delay(2000); - - cout << "Hello, World!\n"; -} - -void loop() {} diff --git a/SdFat/examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino b/SdFat/examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino deleted file mode 100644 index 96f7179a..00000000 --- a/SdFat/examples/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This program is a simple Print benchmark. - */ -#include -#include - -// SD chip select pin -const uint8_t chipSelect = SS; - -// number of lines to print -const uint16_t N_PRINT = 20000; - - -// test file -File file; - -//------------------------------------------------------------------------------ -void error(char* s) { - Serial.println(s); - while(1); -} -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) { - // wait for Leonardo - } -} -//------------------------------------------------------------------------------ -void loop() { - uint32_t maxLatency; - uint32_t minLatency; - uint32_t totalLatency; - - while (Serial.read() >= 0) { - } - // F() stores strings in flash to save RAM - Serial.println(F("Type any character to start")); - while (Serial.read() <= 0) { - } - delay(400); // catch Due reset problem - - - // initialize the SD card - - if (!SD.begin(chipSelect)) { - error("begin"); - } - - - Serial.println(F("Starting print test. Please wait.\n")); - - // do write test - for (int test = 0; test < 2; test++) { - file = SD.open("bench.txt", FILE_WRITE); - - if (!file) { - error("open failed"); - } - switch(test) { - case 0: - Serial.println(F("Test of println(uint16_t)")); - break; - - case 1: - Serial.println(F("Test of println(double)")); - break; - } - maxLatency = 0; - minLatency = 999999; - totalLatency = 0; - uint32_t t = millis(); - for (uint16_t i = 0; i < N_PRINT; i++) { - uint32_t m = micros(); - - switch(test) { - case 0: - file.println(i); - break; - - case 1: - file.println((double)0.01*i); - break; - } - - if (file.getWriteError()) { - error("write failed"); - } - m = micros() - m; - if (maxLatency < m) { - maxLatency = m; - } - if (minLatency > m) { - minLatency = m; - } - totalLatency += m; - } - file.flush(); - t = millis() - t; - double s = file.size(); - Serial.print(F("Time ")); - Serial.print(0.001*t); - Serial.println(F(" sec")); - Serial.print(F("File size ")); - Serial.print(0.001*s); - Serial.print(F(" KB\n")); - Serial.print(F("Write ")); - Serial.print(s/t); - Serial.print(F(" KB/sec\n")); - Serial.print(F("Maximum latency: ")); - Serial.print(maxLatency); - Serial.print(F(" usec, Minimum Latency: ")); - Serial.print(minLatency); - Serial.print(F(" usec, Avg Latency: ")); - Serial.print(totalLatency/N_PRINT); - Serial.println(F(" usec\n")); - SD.remove("bench.txt"); - } - file.close(); - Serial.println(F("Done!\n")); -} \ No newline at end of file diff --git a/SdFat/examples/#attic/SdFatSize/SdFatSize.ino b/SdFat/examples/#attic/SdFatSize/SdFatSize.ino deleted file mode 100644 index cbaf1be6..00000000 --- a/SdFat/examples/#attic/SdFatSize/SdFatSize.ino +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Program to compare size of SdFat with Arduino SD library. - * See SD_Size.ino for Arduino SD program. - * - */ -#include -#include - -SdFat sd; - -SdFile file; -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - - if (!sd.begin()) { - Serial.println("begin failed"); - return; - } - file.open("SizeTest.txt", O_RDWR | O_CREAT | O_AT_END); - - file.println("Hello"); - - file.close(); - Serial.println("Done"); -} -//------------------------------------------------------------------------------ -void loop() {} diff --git a/SdFat/examples/#attic/benchSD/benchSD.ino b/SdFat/examples/#attic/benchSD/benchSD.ino deleted file mode 100644 index 647b2fc7..00000000 --- a/SdFat/examples/#attic/benchSD/benchSD.ino +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This program is a simple binary write/read benchmark - * for the standard Arduino SD.h library. - */ -#include -#include - -// SD chip select pin -const uint8_t chipSelect = SS; - -#define FILE_SIZE_MB 5 -#define FILE_SIZE (1000000UL*FILE_SIZE_MB) -#define BUF_SIZE 100 - -uint8_t buf[BUF_SIZE]; - -// test file -File file; - -//------------------------------------------------------------------------------ -void error(char* s) { - Serial.println(s); - while(1); -} -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo -} -//------------------------------------------------------------------------------ -void loop() { - uint32_t maxLatency; - uint32_t minLatency; - uint32_t totalLatency; - - // discard any input - while (Serial.read() >= 0) {} - - // F() stores strings in flash to save RAM - Serial.println(F("Type any character to start")); - while (Serial.read() <= 0) {} - delay(400); // catch Due reset problem - - if (!SD.begin(chipSelect)) { - error("begin"); - } - - // open or create file - truncate existing file. - file = SD.open("Bench.dat", O_RDWR | O_TRUNC | O_CREAT); - if (!file) { - error("open failed"); - } - - // fill buf with known data - for (uint16_t i = 0; i < (BUF_SIZE-2); i++) { - buf[i] = 'A' + (i % 26); - } - buf[BUF_SIZE-2] = '\r'; - buf[BUF_SIZE-1] = '\n'; - - Serial.print(F("File size ")); - Serial.print(FILE_SIZE_MB); - Serial.println(F("MB")); - Serial.print(F("Buffer size ")); - Serial.print(BUF_SIZE); - Serial.println(F(" bytes")); - Serial.println(F("Starting write test. Please wait up to a minute")); - - // do write test - uint32_t n = FILE_SIZE/sizeof(buf); - maxLatency = 0; - minLatency = 999999; - totalLatency = 0; - uint32_t t = millis(); - for (uint32_t i = 0; i < n; i++) { - uint32_t m = micros(); - if (file.write(buf, sizeof(buf)) != sizeof(buf)) { - error("write failed"); - } - m = micros() - m; - if (maxLatency < m) { - maxLatency = m; - } - if (minLatency > m) { - minLatency = m; - } - totalLatency += m; - } - file.flush(); - t = millis() - t; - double s = file.size(); - Serial.print(F("Write ")); - Serial.print(s/t); - Serial.print(F(" KB/sec\n")); - Serial.print(F("Maximum latency: ")); - Serial.print(maxLatency); - Serial.print(F(" usec, Minimum Latency: ")); - Serial.print(minLatency); - Serial.print(F(" usec, Avg Latency: ")); - Serial.print(totalLatency/n); - Serial.print(F(" usec\n\n")); - Serial.println(F("Starting read test. Please wait up to a minute")); - // do read test - file.seek(0); - maxLatency = 0; - minLatency = 99999; - totalLatency = 0; - t = millis(); - for (uint32_t i = 0; i < n; i++) { - buf[BUF_SIZE-1] = 0; - uint32_t m = micros(); - if (file.read(buf, sizeof(buf)) != sizeof(buf)) { - error("read failed"); - } - m = micros() - m; - if (maxLatency < m) { - maxLatency = m; - } - if (minLatency > m) { - minLatency = m; - } - totalLatency += m; - if (buf[BUF_SIZE-1] != '\n') { - error("data check"); - } - } - t = millis() - t; - Serial.print(F("Read ")); - Serial.print(s/t); - Serial.print(F(" KB/sec\n")); - Serial.print(F("Maximum latency: ")); - Serial.print(maxLatency); - Serial.print(F(" usec, Minimum Latency: ")); - Serial.print(minLatency); - Serial.print(F(" usec, Avg Latency: ")); - Serial.print(totalLatency/n); - Serial.print(F(" usec\n\n")); - Serial.print(F("Done\n\n")); - file.close(); -} \ No newline at end of file diff --git a/SdFat/examples/#attic/fgetsRewrite/fgetsRewrite.ino b/SdFat/examples/#attic/fgetsRewrite/fgetsRewrite.ino deleted file mode 100644 index 2c6cdac6..00000000 --- a/SdFat/examples/#attic/fgetsRewrite/fgetsRewrite.ino +++ /dev/null @@ -1,106 +0,0 @@ -// Demo of rewriting a line read by fgets -#include -#include - -// SD card chip select pin -const uint8_t chipSelect = SS; - -// file system -SdFat sd; - -// print stream -ArduinoOutStream cout(Serial); -//------------------------------------------------------------------------------ -// store error strings in flash memory -#define error(s) sd.errorHalt(F(s)) -//------------------------------------------------------------------------------ -void demoFgets() { - char line[25]; - int c; - uint32_t pos; - - // open test file - SdFile rdfile("fgets.txt", O_RDWR); - - // check for open error - if (!rdfile.isOpen()) { - error("demoFgets"); - } - - // list file - cout << F("-----Before Rewrite\r\n"); - while ((c = rdfile.read()) >= 0) { - Serial.write(c); - } - - rdfile.rewind(); - // read lines from the file to get position - while (1) { - pos = rdfile.curPosition(); - if (rdfile.fgets(line, sizeof(line)) < 0) { - error("Line not found"); - } - // find line that contains "Line C" - if (strstr(line, "Line C")) { - break; - } - } - - // rewrite line with 'C' - if (!rdfile.seekSet(pos)) { - error("seekSet"); - } - rdfile.println("Line R"); - rdfile.rewind(); - - // list file - cout << F("\r\n-----After Rewrite\r\n"); - while ((c = rdfile.read()) >= 0) { - Serial.write(c); - } - - // close so rewrite is not lost - rdfile.close(); -} -//------------------------------------------------------------------------------ -void makeTestFile() { - // create or open test file - SdFile wrfile("fgets.txt", O_WRITE | O_CREAT | O_TRUNC); - - // check for open error - if (!wrfile.isOpen()) { - error("MakeTestFile"); - } - - // write test file - wrfile.print(F( - "Line A\r\n" - "Line B\r\n" - "Line C\r\n" - "Line D\r\n" - "Line E\r\n" - )); - wrfile.close(); -} -//------------------------------------------------------------------------------ -void setup(void) { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - - cout << F("Type any character to start\n"); - while (Serial.read() <= 0) {} - delay(400); // catch Due reset problem - - // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - // breadboards. use SPI_FULL_SPEED for better performance. - if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - makeTestFile(); - - demoFgets(); - - cout << F("\nDone\n"); -} -void loop(void) {} diff --git a/SdFat/examples/#attic/readme.txt b/SdFat/examples/#attic/readme.txt deleted file mode 100644 index dc457505..00000000 --- a/SdFat/examples/#attic/readme.txt +++ /dev/null @@ -1,28 +0,0 @@ -Old and debug examples. - -AnalogLogger - A simple data logger for one or more analog pins. - -append - This sketch creates a large file by successive - open/write/close operations. - -average - A demonstration of parsing floating point numbers. - -benchSD - A read/write benchmark for the standard Arduino SD.h library. - -bufstream - ibufsteam to parse a line and obufstream to format a line. - -eventlog - Append a line to a file - demo of pathnames and streams. - -fgetsRewrite - Demo of rewriting a line read by fgets. - -HelloWorld - Create a serial output stream. - -MiniSerial - SdFat minimal serial support for debug. - -PrintBenchmarkSD - Bench mark SD.h print. - -readlog - Read file. Demo of pathnames and current working directory. - -SD_Size - Determine flash used by SD.h example. - -SdFatSize - Determine flash used by SdFat. diff --git a/SdFat/examples/AnalogBinLogger/AnalogBinLogger.h b/SdFat/examples/AnalogBinLogger/AnalogBinLogger.h deleted file mode 100644 index 35a34e54..00000000 --- a/SdFat/examples/AnalogBinLogger/AnalogBinLogger.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef AnalogBinLogger_h -#define AnalogBinLogger_h -//------------------------------------------------------------------------------ -// First block of file. -struct metadata_t { - unsigned long adcFrequency; // ADC clock frequency - unsigned long cpuFrequency; // CPU clock frequency - unsigned long sampleInterval; // Sample interval in CPU cycles. - unsigned long recordEightBits; // Size of ADC values, nonzero for 8-bits. - unsigned long pinCount; // Number of analog pins in a sample. - unsigned long pinNumber[123]; // List of pin numbers in a sample. -}; -//------------------------------------------------------------------------------ -// Data block for 8-bit ADC mode. -const size_t DATA_DIM8 = 508; -struct block8_t { - unsigned short count; // count of data values - unsigned short overrun; // count of overruns since last block - unsigned char data[DATA_DIM8]; -}; -//------------------------------------------------------------------------------ -// Data block for 10-bit ADC mode. -const size_t DATA_DIM16 = 254; -struct block16_t { - unsigned short count; // count of data values - unsigned short overrun; // count of overruns since last block - unsigned short data[DATA_DIM16]; -}; -//------------------------------------------------------------------------------ -// Data block for PC use -struct adcdata_t { - unsigned short count; // count of data values - unsigned short overrun; // count of overruns since last block - union { - unsigned char u8[DATA_DIM8]; - unsigned short u16[DATA_DIM16]; - } data; -}; -#endif // AnalogBinLogger_h \ No newline at end of file diff --git a/SdFat/examples/AnalogBinLogger/AnalogBinLogger.ino b/SdFat/examples/AnalogBinLogger/AnalogBinLogger.ino deleted file mode 100644 index eda85413..00000000 --- a/SdFat/examples/AnalogBinLogger/AnalogBinLogger.ino +++ /dev/null @@ -1,829 +0,0 @@ -/** - * This program logs data from the Arduino ADC to a binary file. - * - * Samples are logged at regular intervals. Each Sample consists of the ADC - * values for the analog pins defined in the PIN_LIST array. The pins numbers - * may be in any order. - * - * Edit the configuration constants below to set the sample pins, sample rate, - * and other configuration values. - * - * If your SD card has a long write latency, it may be necessary to use - * slower sample rates. Using a Mega Arduino helps overcome latency - * problems since 13 512 byte buffers will be used. - * - * Each 512 byte data block in the file has a four byte header followed by up - * to 508 bytes of data. (508 values in 8-bit mode or 254 values in 10-bit mode) - * Each block contains an integral number of samples with unused space at the - * end of the block. - * - * Data is written to the file using a SD multiple block write command. - */ -#ifdef __AVR__ -#include -#include -#include -#include "AnalogBinLogger.h" -//------------------------------------------------------------------------------ -// Analog pin number list for a sample. Pins may be in any order and pin -// numbers may be repeated. -const uint8_t PIN_LIST[] = {0, 1, 2, 3, 4}; -//------------------------------------------------------------------------------ -// Sample rate in samples per second. -const float SAMPLE_RATE = 5000; // Must be 0.25 or greater. - -// The interval between samples in seconds, SAMPLE_INTERVAL, may be set to a -// constant instead of being calculated from SAMPLE_RATE. SAMPLE_RATE is not -// used in the code below. For example, setting SAMPLE_INTERVAL = 2.0e-4 -// will result in a 200 microsecond sample interval. -const float SAMPLE_INTERVAL = 1.0/SAMPLE_RATE; - -// Setting ROUND_SAMPLE_INTERVAL non-zero will cause the sample interval to -// be rounded to a a multiple of the ADC clock period and will reduce sample -// time jitter. -#define ROUND_SAMPLE_INTERVAL 1 -//------------------------------------------------------------------------------ -// ADC clock rate. -// The ADC clock rate is normally calculated from the pin count and sample -// interval. The calculation attempts to use the lowest possible ADC clock -// rate. -// -// You can select an ADC clock rate by defining the symbol ADC_PRESCALER to -// one of these values. You must choose an appropriate ADC clock rate for -// your sample interval. -// #define ADC_PRESCALER 7 // F_CPU/128 125 kHz on an Uno -// #define ADC_PRESCALER 6 // F_CPU/64 250 kHz on an Uno -// #define ADC_PRESCALER 5 // F_CPU/32 500 kHz on an Uno -// #define ADC_PRESCALER 4 // F_CPU/16 1000 kHz on an Uno -// #define ADC_PRESCALER 3 // F_CPU/8 2000 kHz on an Uno (8-bit mode only) -//------------------------------------------------------------------------------ -// Reference voltage. See the processor data-sheet for reference details. -// uint8_t const ADC_REF = 0; // External Reference AREF pin. -uint8_t const ADC_REF = (1 << REFS0); // Vcc Reference. -// uint8_t const ADC_REF = (1 << REFS1); // Internal 1.1 (only 644 1284P Mega) -// uint8_t const ADC_REF = (1 << REFS1) | (1 << REFS0); // Internal 1.1 or 2.56 -//------------------------------------------------------------------------------ -// File definitions. -// -// Maximum file size in blocks. -// The program creates a contiguous file with FILE_BLOCK_COUNT 512 byte blocks. -// This file is flash erased using special SD commands. The file will be -// truncated if logging is stopped early. -const uint32_t FILE_BLOCK_COUNT = 256000; - -// log file base name. Must be six characters or less. -#define FILE_BASE_NAME "analog" - -// Set RECORD_EIGHT_BITS non-zero to record only the high 8-bits of the ADC. -#define RECORD_EIGHT_BITS 0 -//------------------------------------------------------------------------------ -// Pin definitions. -// -// 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. -const int8_t ERROR_LED_PIN = 3; - -// SD chip select pin. -const uint8_t SD_CS_PIN = SS; -//------------------------------------------------------------------------------ -// Buffer definitions. -// -// The logger will use SdFat's buffer plus BUFFER_BLOCK_COUNT additional -// buffers. QUEUE_DIM must be a power of two larger than -//(BUFFER_BLOCK_COUNT + 1). -// -#if RAMEND < 0X8FF -#error Too little SRAM -// -#elif RAMEND < 0X10FF -// Use total of two 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 1; -// Dimension for queues of 512 byte SD blocks. -const uint8_t QUEUE_DIM = 4; // Must be a power of two! -// -#elif RAMEND < 0X20FF -// Use total of five 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 4; -// Dimension for queues of 512 byte SD blocks. -const uint8_t QUEUE_DIM = 8; // Must be a power of two! -// -#elif RAMEND < 0X40FF -// Use total of 13 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 12; -// Dimension for queues of 512 byte SD blocks. -const uint8_t QUEUE_DIM = 16; // Must be a power of two! -// -#else // RAMEND -// Use total of 29 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 28; -// Dimension for queues of 512 byte SD blocks. -const uint8_t QUEUE_DIM = 32; // Must be a power of two! -#endif // RAMEND -//============================================================================== -// End of configuration constants. -//============================================================================== -// Temporary log file. Will be deleted if a reset or power failure occurs. -#define TMP_FILE_NAME "tmp_log.bin" - -// Size of file base name. Must not be larger than six. -const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1; - -// Number of analog pins to log. -const uint8_t PIN_COUNT = sizeof(PIN_LIST)/sizeof(PIN_LIST[0]); - -// Minimum ADC clock cycles per sample interval -const uint16_t MIN_ADC_CYCLES = 15; - -// Extra cpu cycles to setup ADC with more than one pin per sample. -const uint16_t ISR_SETUP_ADC = 100; - -// Maximum cycles for timer0 system interrupt, millis, micros. -const uint16_t ISR_TIMER0 = 160; -//============================================================================== -SdFat sd; - -SdBaseFile binFile; - -char binName[13] = FILE_BASE_NAME "00.bin"; - -#if RECORD_EIGHT_BITS -const size_t SAMPLES_PER_BLOCK = DATA_DIM8/PIN_COUNT; -typedef block8_t block_t; -#else // RECORD_EIGHT_BITS -const size_t SAMPLES_PER_BLOCK = DATA_DIM16/PIN_COUNT; -typedef block16_t block_t; -#endif // RECORD_EIGHT_BITS - -block_t* emptyQueue[QUEUE_DIM]; -uint8_t emptyHead; -uint8_t emptyTail; - -block_t* fullQueue[QUEUE_DIM]; -volatile uint8_t fullHead; // volatile insures non-interrupt code sees changes. -uint8_t fullTail; - -// queueNext assumes QUEUE_DIM is a power of two -inline uint8_t queueNext(uint8_t ht) { - return (ht + 1) & (QUEUE_DIM -1); -} -//============================================================================== -// Interrupt Service Routines - -// Pointer to current buffer. -block_t* isrBuf; - -// Need new buffer if true. -bool isrBufNeeded = true; - -// overrun count -uint16_t isrOver = 0; - -// ADC configuration for each pin. -uint8_t adcmux[PIN_COUNT]; -uint8_t adcsra[PIN_COUNT]; -uint8_t adcsrb[PIN_COUNT]; -uint8_t adcindex = 1; - -// Insure no timer events are missed. -volatile bool timerError = false; -volatile bool timerFlag = false; -//------------------------------------------------------------------------------ -// ADC done interrupt. -ISR(ADC_vect) { - // Read ADC data. -#if RECORD_EIGHT_BITS - uint8_t d = ADCH; -#else // RECORD_EIGHT_BITS - // This will access ADCL first. - uint16_t d = ADC; -#endif // RECORD_EIGHT_BITS - - if (isrBufNeeded && emptyHead == emptyTail) { - // no buffers - count overrun - if (isrOver < 0XFFFF) { - isrOver++; - } - - // Avoid missed timer error. - timerFlag = false; - return; - } - // Start ADC - if (PIN_COUNT > 1) { - ADMUX = adcmux[adcindex]; - ADCSRB = adcsrb[adcindex]; - ADCSRA = adcsra[adcindex]; - if (adcindex == 0) { - timerFlag = false; - } - adcindex = adcindex < (PIN_COUNT - 1) ? adcindex + 1 : 0; - } else { - timerFlag = false; - } - // Check for buffer needed. - if (isrBufNeeded) { - // Remove buffer from empty queue. - isrBuf = emptyQueue[emptyTail]; - emptyTail = queueNext(emptyTail); - isrBuf->count = 0; - isrBuf->overrun = isrOver; - isrBufNeeded = false; - } - // Store ADC data. - isrBuf->data[isrBuf->count++] = d; - - // Check for buffer full. - if (isrBuf->count >= PIN_COUNT*SAMPLES_PER_BLOCK) { - // Put buffer isrIn full queue. - uint8_t tmp = fullHead; // Avoid extra fetch of volatile fullHead. - fullQueue[tmp] = (block_t*)isrBuf; - fullHead = queueNext(tmp); - - // Set buffer needed and clear overruns. - isrBufNeeded = true; - isrOver = 0; - } -} -//------------------------------------------------------------------------------ -// timer1 interrupt to clear OCF1B -ISR(TIMER1_COMPB_vect) { - // Make sure ADC ISR responded to timer event. - if (timerFlag) { - timerError = true; - } - timerFlag = true; -} -//============================================================================== -// Error messages stored in flash. -#define error(msg) errorFlash(F(msg)) -//------------------------------------------------------------------------------ -void errorFlash(const __FlashStringHelper* msg) { - sd.errorPrint(msg); - fatalBlink(); -} -//------------------------------------------------------------------------------ -// -void fatalBlink() { - while (true) { - if (ERROR_LED_PIN >= 0) { - digitalWrite(ERROR_LED_PIN, HIGH); - delay(200); - digitalWrite(ERROR_LED_PIN, LOW); - delay(200); - } - } -} -//============================================================================== -#if ADPS0 != 0 || ADPS1 != 1 || ADPS2 != 2 -#error unexpected ADC prescaler bits -#endif -//------------------------------------------------------------------------------ -// initialize ADC and timer1 -void adcInit(metadata_t* meta) { - uint8_t adps; // prescaler bits for ADCSRA - uint32_t ticks = F_CPU*SAMPLE_INTERVAL + 0.5; // Sample interval cpu cycles. - - if (ADC_REF & ~((1 << REFS0) | (1 << REFS1))) { - error("Invalid ADC reference"); - } -#ifdef ADC_PRESCALER - if (ADC_PRESCALER > 7 || ADC_PRESCALER < 2) { - error("Invalid ADC prescaler"); - } - adps = ADC_PRESCALER; -#else // ADC_PRESCALER - // Allow extra cpu cycles to change ADC settings if more than one pin. - int32_t adcCycles = (ticks - ISR_TIMER0)/PIN_COUNT; - - (PIN_COUNT > 1 ? ISR_SETUP_ADC : 0); - - for (adps = 7; adps > 0; adps--) { - if (adcCycles >= (MIN_ADC_CYCLES << adps)) { - break; - } - } -#endif // ADC_PRESCALER - meta->adcFrequency = F_CPU >> adps; - if (meta->adcFrequency > (RECORD_EIGHT_BITS ? 2000000 : 1000000)) { - error("Sample Rate Too High"); - } -#if ROUND_SAMPLE_INTERVAL - // Round so interval is multiple of ADC clock. - ticks += 1 << (adps - 1); - ticks >>= adps; - ticks <<= adps; -#endif // ROUND_SAMPLE_INTERVAL - - if (PIN_COUNT > sizeof(meta->pinNumber)/sizeof(meta->pinNumber[0])) { - error("Too many pins"); - } - meta->pinCount = PIN_COUNT; - meta->recordEightBits = RECORD_EIGHT_BITS; - - for (int i = 0; i < PIN_COUNT; i++) { - uint8_t pin = PIN_LIST[i]; - if (pin >= NUM_ANALOG_INPUTS) { - error("Invalid Analog pin number"); - } - meta->pinNumber[i] = pin; - - // Set ADC reference and low three bits of analog pin number. - adcmux[i] = (pin & 7) | ADC_REF; - if (RECORD_EIGHT_BITS) { - adcmux[i] |= 1 << ADLAR; - } - - // If this is the first pin, trigger on timer/counter 1 compare match B. - adcsrb[i] = i == 0 ? (1 << ADTS2) | (1 << ADTS0) : 0; -#ifdef MUX5 - if (pin > 7) { - adcsrb[i] |= (1 << MUX5); - } -#endif // MUX5 - adcsra[i] = (1 << ADEN) | (1 << ADIE) | adps; - adcsra[i] |= i == 0 ? 1 << ADATE : 1 << ADSC; - } - - // Setup timer1 - TCCR1A = 0; - uint8_t tshift; - if (ticks < 0X10000) { - // no prescale, CTC mode - TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10); - tshift = 0; - } else if (ticks < 0X10000*8) { - // prescale 8, CTC mode - TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); - tshift = 3; - } else if (ticks < 0X10000*64) { - // prescale 64, CTC mode - TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11) | (1 << CS10); - tshift = 6; - } else if (ticks < 0X10000*256) { - // prescale 256, CTC mode - TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12); - tshift = 8; - } else if (ticks < 0X10000*1024) { - // prescale 1024, CTC mode - TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12) | (1 << CS10); - tshift = 10; - } else { - error("Sample Rate Too Slow"); - } - // divide by prescaler - ticks >>= tshift; - // set TOP for timer reset - ICR1 = ticks - 1; - // compare for ADC start - OCR1B = 0; - - // multiply by prescaler - ticks <<= tshift; - - // Sample interval in CPU clock ticks. - meta->sampleInterval = ticks; - meta->cpuFrequency = F_CPU; - float sampleRate = (float)meta->cpuFrequency/meta->sampleInterval; - Serial.print(F("Sample pins:")); - for (int i = 0; i < meta->pinCount; i++) { - Serial.print(' '); - Serial.print(meta->pinNumber[i], DEC); - } - Serial.println(); - Serial.print(F("ADC bits: ")); - Serial.println(meta->recordEightBits ? 8 : 10); - Serial.print(F("ADC clock kHz: ")); - Serial.println(meta->adcFrequency/1000); - Serial.print(F("Sample Rate: ")); - Serial.println(sampleRate); - Serial.print(F("Sample interval usec: ")); - Serial.println(1000000.0/sampleRate, 4); -} -//------------------------------------------------------------------------------ -// enable ADC and timer1 interrupts -void adcStart() { - // initialize ISR - isrBufNeeded = true; - isrOver = 0; - adcindex = 1; - - // Clear any pending interrupt. - ADCSRA |= 1 << ADIF; - - // Setup for first pin. - ADMUX = adcmux[0]; - ADCSRB = adcsrb[0]; - ADCSRA = adcsra[0]; - - // Enable timer1 interrupts. - timerError = false; - timerFlag = false; - TCNT1 = 0; - TIFR1 = 1 << OCF1B; - TIMSK1 = 1 << OCIE1B; -} -//------------------------------------------------------------------------------ -void adcStop() { - TIMSK1 = 0; - ADCSRA = 0; -} -//------------------------------------------------------------------------------ -// Convert binary file to csv file. -void binaryToCsv() { - uint8_t lastPct = 0; - block_t buf; - metadata_t* pm; - uint32_t t0 = millis(); - char csvName[13]; - StdioStream csvStream; - - if (!binFile.isOpen()) { - Serial.println(F("No current binary file")); - return; - } - binFile.rewind(); - if (!binFile.read(&buf , 512) == 512) { - error("Read metadata failed"); - } - // Create a new csv file. - strcpy(csvName, binName); - strcpy(&csvName[BASE_NAME_SIZE + 3], "csv"); - - if (!csvStream.fopen(csvName, "w")) { - error("open csvStream failed"); - } - Serial.println(); - Serial.print(F("Writing: ")); - Serial.print(csvName); - Serial.println(F(" - type any character to stop")); - pm = (metadata_t*)&buf; - csvStream.print(F("Interval,")); - float intervalMicros = 1.0e6*pm->sampleInterval/(float)pm->cpuFrequency; - csvStream.print(intervalMicros, 4); - csvStream.println(F(",usec")); - for (uint8_t i = 0; i < pm->pinCount; i++) { - if (i) { - csvStream.putc(','); - } - csvStream.print(F("pin")); - csvStream.print(pm->pinNumber[i]); - } - csvStream.println(); - uint32_t tPct = millis(); - while (!Serial.available() && binFile.read(&buf, 512) == 512) { - uint16_t i; - if (buf.count == 0) { - break; - } - if (buf.overrun) { - csvStream.print(F("OVERRUN,")); - csvStream.println(buf.overrun); - } - for (uint16_t j = 0; j < buf.count; j += PIN_COUNT) { - for (uint16_t i = 0; i < PIN_COUNT; i++) { - if (i) { - csvStream.putc(','); - } - csvStream.print(buf.data[i + j]); - } - csvStream.println(); - } - if ((millis() - tPct) > 1000) { - uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100); - if (pct != lastPct) { - tPct = millis(); - lastPct = pct; - Serial.print(pct, DEC); - Serial.println('%'); - } - } - if (Serial.available()) { - break; - } - } - csvStream.fclose(); - Serial.print(F("Done: ")); - Serial.print(0.001*(millis() - t0)); - Serial.println(F(" Seconds")); -} -//------------------------------------------------------------------------------ -// read data file and check for overruns -void checkOverrun() { - bool headerPrinted = false; - block_t buf; - uint32_t bgnBlock, endBlock; - uint32_t bn = 0; - - if (!binFile.isOpen()) { - Serial.println(F("No current binary file")); - return; - } - if (!binFile.contiguousRange(&bgnBlock, &endBlock)) { - error("contiguousRange failed"); - } - binFile.rewind(); - Serial.println(); - Serial.println(F("Checking overrun errors - type any character to stop")); - if (!binFile.read(&buf , 512) == 512) { - error("Read metadata failed"); - } - bn++; - while (binFile.read(&buf, 512) == 512) { - if (buf.count == 0) { - break; - } - if (buf.overrun) { - if (!headerPrinted) { - Serial.println(); - Serial.println(F("Overruns:")); - Serial.println(F("fileBlockNumber,sdBlockNumber,overrunCount")); - headerPrinted = true; - } - Serial.print(bn); - Serial.print(','); - Serial.print(bgnBlock + bn); - Serial.print(','); - Serial.println(buf.overrun); - } - bn++; - } - if (!headerPrinted) { - Serial.println(F("No errors found")); - } else { - Serial.println(F("Done")); - } -} -//------------------------------------------------------------------------------ -// dump data file to Serial -void dumpData() { - block_t buf; - if (!binFile.isOpen()) { - Serial.println(F("No current binary file")); - return; - } - binFile.rewind(); - if (binFile.read(&buf , 512) != 512) { - error("Read metadata failed"); - } - Serial.println(); - Serial.println(F("Type any character to stop")); - delay(1000); - while (!Serial.available() && binFile.read(&buf , 512) == 512) { - if (buf.count == 0) { - break; - } - if (buf.overrun) { - Serial.print(F("OVERRUN,")); - Serial.println(buf.overrun); - } - for (uint16_t i = 0; i < buf.count; i++) { - Serial.print(buf.data[i], DEC); - if ((i+1)%PIN_COUNT) { - Serial.print(','); - } else { - Serial.println(); - } - } - } - Serial.println(F("Done")); -} -//------------------------------------------------------------------------------ -// log data -// max number of blocks to erase per erase call -uint32_t const ERASE_SIZE = 262144L; -void logData() { - uint32_t bgnBlock, endBlock; - - // Allocate extra buffer space. - block_t block[BUFFER_BLOCK_COUNT]; - - Serial.println(); - - // Initialize ADC and timer1. - adcInit((metadata_t*) &block[0]); - - // Find unused file name. - if (BASE_NAME_SIZE > 6) { - error("FILE_BASE_NAME too long"); - } - while (sd.exists(binName)) { - if (binName[BASE_NAME_SIZE + 1] != '9') { - binName[BASE_NAME_SIZE + 1]++; - } else { - binName[BASE_NAME_SIZE + 1] = '0'; - if (binName[BASE_NAME_SIZE] == '9') { - error("Can't create file name"); - } - binName[BASE_NAME_SIZE]++; - } - } - // Delete old tmp file. - if (sd.exists(TMP_FILE_NAME)) { - Serial.println(F("Deleting tmp file")); - if (!sd.remove(TMP_FILE_NAME)) { - error("Can't remove tmp file"); - } - } - // Create new file. - Serial.println(F("Creating new file")); - binFile.close(); - if (!binFile.createContiguous(sd.vwd(), - TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) { - error("createContiguous failed"); - } - // Get the address of the file on the SD. - if (!binFile.contiguousRange(&bgnBlock, &endBlock)) { - error("contiguousRange failed"); - } - // Use SdFat's internal buffer. - uint8_t* cache = (uint8_t*)sd.vol()->cacheClear(); - if (cache == 0) { - error("cacheClear failed"); - } - - // Flash erase all data in the file. - Serial.println(F("Erasing all data")); - uint32_t bgnErase = bgnBlock; - uint32_t endErase; - while (bgnErase < endBlock) { - endErase = bgnErase + ERASE_SIZE; - if (endErase > endBlock) { - endErase = endBlock; - } - if (!sd.card()->erase(bgnErase, endErase)) { - error("erase failed"); - } - bgnErase = endErase + 1; - } - // Start a multiple block write. - if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) { - error("writeBegin failed"); - } - // Write metadata. - if (!sd.card()->writeData((uint8_t*)&block[0])) { - error("Write metadata failed"); - } - // Initialize queues. - emptyHead = emptyTail = 0; - fullHead = fullTail = 0; - - // Use SdFat buffer for one block. - emptyQueue[emptyHead] = (block_t*)cache; - emptyHead = queueNext(emptyHead); - - // Put rest of buffers in the empty queue. - for (uint8_t i = 0; i < BUFFER_BLOCK_COUNT; i++) { - emptyQueue[emptyHead] = &block[i]; - emptyHead = queueNext(emptyHead); - } - // Give SD time to prepare for big write. - delay(1000); - Serial.println(F("Logging - type any character to stop")); - // Wait for Serial Idle. - Serial.flush(); - delay(10); - uint32_t bn = 1; - uint32_t t0 = millis(); - uint32_t t1 = t0; - uint32_t overruns = 0; - uint32_t count = 0; - uint32_t maxLatency = 0; - - // Start logging interrupts. - adcStart(); - while (1) { - if (fullHead != fullTail) { - // Get address of block to write. - block_t* pBlock = fullQueue[fullTail]; - - // Write block to SD. - uint32_t usec = micros(); - if (!sd.card()->writeData((uint8_t*)pBlock)) { - error("write data failed"); - } - usec = micros() - usec; - t1 = millis(); - if (usec > maxLatency) { - maxLatency = usec; - } - count += pBlock->count; - - // Add overruns and possibly light LED. - if (pBlock->overrun) { - overruns += pBlock->overrun; - if (ERROR_LED_PIN >= 0) { - digitalWrite(ERROR_LED_PIN, HIGH); - } - } - // Move block to empty queue. - emptyQueue[emptyHead] = pBlock; - emptyHead = queueNext(emptyHead); - fullTail = queueNext(fullTail); - bn++; - if (bn == FILE_BLOCK_COUNT) { - // File full so stop ISR calls. - adcStop(); - break; - } - } - if (timerError) { - error("Missed timer event - rate too high"); - } - if (Serial.available()) { - // Stop ISR calls. - adcStop(); - if (isrBuf != 0 && isrBuf->count >= PIN_COUNT) { - // Truncate to last complete sample. - isrBuf->count = PIN_COUNT*(isrBuf->count/PIN_COUNT); - // Put buffer in full queue. - fullQueue[fullHead] = isrBuf; - fullHead = queueNext(fullHead); - isrBuf = 0; - } - if (fullHead == fullTail) { - break; - } - } - } - if (!sd.card()->writeStop()) { - error("writeStop failed"); - } - // Truncate file if recording stopped early. - if (bn != FILE_BLOCK_COUNT) { - Serial.println(F("Truncating file")); - if (!binFile.truncate(512L * bn)) { - error("Can't truncate file"); - } - } - if (!binFile.rename(sd.vwd(), binName)) { - error("Can't rename file"); - } - Serial.print(F("File renamed: ")); - Serial.println(binName); - Serial.print(F("Max block write usec: ")); - Serial.println(maxLatency); - Serial.print(F("Record time sec: ")); - Serial.println(0.001*(t1 - t0), 3); - Serial.print(F("Sample count: ")); - Serial.println(count/PIN_COUNT); - Serial.print(F("Samples/sec: ")); - Serial.println((1000.0/PIN_COUNT)*count/(t1-t0)); - Serial.print(F("Overruns: ")); - Serial.println(overruns); - Serial.println(F("Done")); -} -//------------------------------------------------------------------------------ -void setup(void) { - if (ERROR_LED_PIN >= 0) { - pinMode(ERROR_LED_PIN, OUTPUT); - } - Serial.begin(9600); - - // Read the first sample pin to init the ADC. - analogRead(PIN_LIST[0]); - - Serial.print(F("FreeRam: ")); - Serial.println(FreeRam()); - - // initialize file system. - if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) { - sd.initErrorPrint(); - fatalBlink(); - } -} -//------------------------------------------------------------------------------ -void loop(void) { - // discard any input - while (Serial.read() >= 0) {} - Serial.println(); - Serial.println(F("type:")); - Serial.println(F("c - convert file to csv")); - Serial.println(F("d - dump data to Serial")); - Serial.println(F("e - overrun error details")); - Serial.println(F("r - record ADC data")); - - while(!Serial.available()) {} - char c = tolower(Serial.read()); - if (ERROR_LED_PIN >= 0) { - digitalWrite(ERROR_LED_PIN, LOW); - } - // Read any extra Serial data. - do { - delay(10); - } while (Serial.read() >= 0); - - if (c == 'c') { - binaryToCsv(); - } else if (c == 'd') { - dumpData(); - } else if (c == 'e') { - checkOverrun(); - } else if (c == 'r') { - logData(); - } else { - Serial.println(F("Invalid entry")); - } -} -#else // __AVR__ -#error This program is only for AVR. -#endif // __AVR__ \ No newline at end of file diff --git a/SdFat/examples/LongFileName/LongFileName.ino b/SdFat/examples/LongFileName/LongFileName.ino deleted file mode 100644 index 81c9a47a..00000000 --- a/SdFat/examples/LongFileName/LongFileName.ino +++ /dev/null @@ -1,94 +0,0 @@ -// Example use of lfnOpenNext and open by index. -// You can use test files located in -// SdFat/examples/LongFileName/testFiles. -#include -#include -#include - -// SD card chip select pin. -const uint8_t SD_CS_PIN = SS; - -SdFat sd; -SdFile file; -SdFile dirFile; - -// Number of files found. -uint16_t n = 0; - -// Max of ten files since files are selected with a single digit. -const uint16_t nMax = 10; - -// Position of file's directory entry. -uint16_t dirIndex[nMax]; -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} - delay(1000); - - // Print the location of some test files. - Serial.println(F("\r\n" - "You can use test files located in\r\n" - "SdFat/examples/LongFileName/testFiles")); - - if (!sd.begin(SD_CS_PIN)) { - sd.initErrorHalt(); - } - Serial.print(F("Free RAM: ")); - Serial.println(FreeRam()); - Serial.println(); - - // List files in root directory. - if (!dirFile.open("/", O_READ)) { - sd.errorHalt("open root failed"); - } - while (n < nMax && file.openNext(&dirFile, O_READ)) { - - // Skip directories and hidden files. - if (!file.isSubDir() && !file.isHidden()) { - - // Save dirIndex of file in directory. - dirIndex[n] = file.dirIndex(); - - // Print the file number and name. - Serial.print(n++); - Serial.write(' '); - file.printName(&Serial); - Serial.println(); - } - file.close(); - } -} -//------------------------------------------------------------------------------ -void loop() { - int c; - - // Discard any Serial input. - while (Serial.read() > 0) {} - Serial.print(F("\r\nEnter File Number: ")); - - while ((c = Serial.read()) < 0) {}; - if (!isdigit(c) || (c -= '0') >= n) { - Serial.println(F("Invald number")); - return; - } - Serial.println(c); - if (!file.open(&dirFile, dirIndex[c], O_READ)) { - sd.errorHalt(F("open")); - } - Serial.println(); - - char last; - - // Copy up to 500 characters to Serial. - for (int i = 0; i < 500 && (c = file.read()) > 0; i++) { - Serial.write(last = (char)c); - } - // Add new line if missing from last line. - if (last != '\n') { - Serial.println(); - } - file.close(); - Serial.flush(); - delay(100); -} \ No newline at end of file diff --git a/SdFat/examples/LowLatencyLogger/LowLatencyLogger.ino b/SdFat/examples/LowLatencyLogger/LowLatencyLogger.ino deleted file mode 100644 index dee2b8c4..00000000 --- a/SdFat/examples/LowLatencyLogger/LowLatencyLogger.ino +++ /dev/null @@ -1,555 +0,0 @@ -/** - * This program logs data to a binary file. Functions are included - * to convert the binary file to a csv text file. - * - * Samples are logged at regular intervals. The maximum logging rate - * depends on the quality of your SD card and the time required to - * read sensor data. This example has been tested at 500 Hz with - * good SD card on an Uno. 4000 HZ is possible on a Due. - * - * If your SD card has a long write latency, it may be necessary to use - * slower sample rates. Using a Mega Arduino helps overcome latency - * problems since 13 512 byte buffers will be used. - * - * Data is written to the file using a SD multiple block write command. - */ -#include -#include -#include -//------------------------------------------------------------------------------ -// 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) { - data->time = micros(); - for (int i = 0; i < ADC_DIM; i++) { - data->adc[i] = analogRead(i); - } -} - -// Print a data record. -void printData(Print* pr, data_t* data) { - pr->print(data->time); - for (int i = 0; i < ADC_DIM; i++) { - pr->write(','); - pr->print(data->adc[i]); - } - pr->println(); -} - -// Print data header. -void printHeader(Print* pr) { - pr->print(F("time")); - for (int i = 0; i < ADC_DIM; i++) { - pr->print(F(",adc")); - pr->print(i); - } - pr->println(); -} -//============================================================================== -// Start of configuration constants. -//============================================================================== -//Interval between data records in microseconds. -const uint32_t LOG_INTERVAL_USEC = 2000; -//------------------------------------------------------------------------------ -// Pin definitions. -// -// SD chip select pin. -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. -const int8_t ERROR_LED_PIN = -1; -//------------------------------------------------------------------------------ -// File definitions. -// -// Maximum file size in blocks. -// The program creates a contiguous file with FILE_BLOCK_COUNT 512 byte blocks. -// This file is flash erased using special SD commands. The file will be -// truncated if logging is stopped early. -const uint32_t FILE_BLOCK_COUNT = 256000; - -// log file base name. Must be six characters or less. -#define FILE_BASE_NAME "data" -//------------------------------------------------------------------------------ -// Buffer definitions. -// -// The logger will use SdFat's buffer plus BUFFER_BLOCK_COUNT additional -// buffers. -// -#ifndef RAMEND -// Assume ARM. Use total of nine 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 8; -// -#elif RAMEND < 0X8FF -#error Too little SRAM -// -#elif RAMEND < 0X10FF -// Use total of two 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 1; -// -#elif RAMEND < 0X20FF -// Use total of five 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 4; -// -#else // RAMEND -// Use total of 13 512 byte buffers. -const uint8_t BUFFER_BLOCK_COUNT = 12; -#endif // RAMEND -//============================================================================== -// End of configuration constants. -//============================================================================== -// Temporary log file. Will be deleted if a reset or power failure occurs. -#define TMP_FILE_NAME "tmp_log.bin" - -// Size of file base name. Must not be larger than six. -const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1; - -SdFat sd; - -SdBaseFile binFile; - -char binName[13] = FILE_BASE_NAME "00.bin"; - -// Number of data records in a block. -const uint16_t DATA_DIM = (512 - 4)/sizeof(data_t); - -//Compute fill so block size is 512 bytes. FILL_DIM may be zero. -const uint16_t FILL_DIM = 512 - 4 - DATA_DIM*sizeof(data_t); - -struct block_t { - uint16_t count; - uint16_t overrun; - data_t data[DATA_DIM]; - uint8_t fill[FILL_DIM]; -}; - -const uint8_t QUEUE_DIM = BUFFER_BLOCK_COUNT + 2; - -block_t* emptyQueue[QUEUE_DIM]; -uint8_t emptyHead; -uint8_t emptyTail; - -block_t* fullQueue[QUEUE_DIM]; -uint8_t fullHead; -uint8_t fullTail; - -// Advance queue index. -inline uint8_t queueNext(uint8_t ht) { - return ht < (QUEUE_DIM - 1) ? ht + 1 : 0; -} -//============================================================================== -// Error messages stored in flash. -#define error(msg) errorFlash(F(msg)) -//------------------------------------------------------------------------------ -void errorFlash(const __FlashStringHelper* msg) { - sd.errorPrint(msg); - fatalBlink(); -} -//------------------------------------------------------------------------------ -// -void fatalBlink() { - while (true) { - if (ERROR_LED_PIN >= 0) { - digitalWrite(ERROR_LED_PIN, HIGH); - delay(200); - digitalWrite(ERROR_LED_PIN, LOW); - delay(200); - } - } -} -//============================================================================== -// Convert binary file to csv file. -void binaryToCsv() { - uint8_t lastPct = 0; - block_t block; - uint32_t t0 = millis(); - uint32_t syncCluster = 0; - SdFile csvFile; - char csvName[13]; - - if (!binFile.isOpen()) { - Serial.println(); - Serial.println(F("No current binary file")); - return; - } - binFile.rewind(); - // Create a new csvFile. - strcpy(csvName, binName); - strcpy(&csvName[BASE_NAME_SIZE + 3], "csv"); - - if (!csvFile.open(csvName, O_WRITE | O_CREAT | O_TRUNC)) { - error("open csvFile failed"); - } - Serial.println(); - Serial.print(F("Writing: ")); - Serial.print(csvName); - Serial.println(F(" - type any character to stop")); - printHeader(&csvFile); - uint32_t tPct = millis(); - while (!Serial.available() && binFile.read(&block, 512) == 512) { - uint16_t i; - if (block.count == 0) { - break; - } - if (block.overrun) { - csvFile.print(F("OVERRUN,")); - csvFile.println(block.overrun); - } - for (i = 0; i < block.count; i++) { - printData(&csvFile, &block.data[i]); - } - if (csvFile.curCluster() != syncCluster) { - csvFile.sync(); - syncCluster = csvFile.curCluster(); - } - if ((millis() - tPct) > 1000) { - uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100); - if (pct != lastPct) { - tPct = millis(); - lastPct = pct; - Serial.print(pct, DEC); - Serial.println('%'); - } - } - if (Serial.available()) { - break; - } - } - csvFile.close(); - Serial.print(F("Done: ")); - Serial.print(0.001*(millis() - t0)); - Serial.println(F(" Seconds")); -} -//------------------------------------------------------------------------------ -// read data file and check for overruns -void checkOverrun() { - bool headerPrinted = false; - block_t block; - uint32_t bgnBlock, endBlock; - uint32_t bn = 0; - - if (!binFile.isOpen()) { - Serial.println(); - Serial.println(F("No current binary file")); - return; - } - if (!binFile.contiguousRange(&bgnBlock, &endBlock)) { - error("contiguousRange failed"); - } - binFile.rewind(); - Serial.println(); - Serial.println(F("Checking overrun errors - type any character to stop")); - while (binFile.read(&block, 512) == 512) { - if (block.count == 0) { - break; - } - if (block.overrun) { - if (!headerPrinted) { - Serial.println(); - Serial.println(F("Overruns:")); - Serial.println(F("fileBlockNumber,sdBlockNumber,overrunCount")); - headerPrinted = true; - } - Serial.print(bn); - Serial.print(','); - Serial.print(bgnBlock + bn); - Serial.print(','); - Serial.println(block.overrun); - } - bn++; - } - if (!headerPrinted) { - Serial.println(F("No errors found")); - } else { - Serial.println(F("Done")); - } -} -//------------------------------------------------------------------------------ -// dump data file to Serial -void dumpData() { - block_t block; - if (!binFile.isOpen()) { - Serial.println(); - Serial.println(F("No current binary file")); - return; - } - binFile.rewind(); - Serial.println(); - Serial.println(F("Type any character to stop")); - delay(1000); - printHeader(&Serial); - while (!Serial.available() && binFile.read(&block , 512) == 512) { - if (block.count == 0) { - break; - } - if (block.overrun) { - Serial.print(F("OVERRUN,")); - Serial.println(block.overrun); - } - for (uint16_t i = 0; i < block.count; i++) { - printData(&Serial, &block.data[i]); - } - } - Serial.println(F("Done")); -} -//------------------------------------------------------------------------------ -// log data -// max number of blocks to erase per erase call -uint32_t const ERASE_SIZE = 262144L; -void logData() { - uint32_t bgnBlock, endBlock; - - // Allocate extra buffer space. - block_t block[BUFFER_BLOCK_COUNT]; - block_t* curBlock = 0; - Serial.println(); - - // Find unused file name. - if (BASE_NAME_SIZE > 6) { - error("FILE_BASE_NAME too long"); - } - while (sd.exists(binName)) { - if (binName[BASE_NAME_SIZE + 1] != '9') { - binName[BASE_NAME_SIZE + 1]++; - } else { - binName[BASE_NAME_SIZE + 1] = '0'; - if (binName[BASE_NAME_SIZE] == '9') { - error("Can't create file name"); - } - binName[BASE_NAME_SIZE]++; - } - } - // Delete old tmp file. - if (sd.exists(TMP_FILE_NAME)) { - Serial.println(F("Deleting tmp file")); - if (!sd.remove(TMP_FILE_NAME)) { - error("Can't remove tmp file"); - } - } - // Create new file. - Serial.println(F("Creating new file")); - binFile.close(); - if (!binFile.createContiguous(sd.vwd(), - TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) { - error("createContiguous failed"); - } - // Get the address of the file on the SD. - if (!binFile.contiguousRange(&bgnBlock, &endBlock)) { - error("contiguousRange failed"); - } - // Use SdFat's internal buffer. - uint8_t* cache = (uint8_t*)sd.vol()->cacheClear(); - if (cache == 0) { - error("cacheClear failed"); - } - - // Flash erase all data in the file. - Serial.println(F("Erasing all data")); - uint32_t bgnErase = bgnBlock; - uint32_t endErase; - while (bgnErase < endBlock) { - endErase = bgnErase + ERASE_SIZE; - if (endErase > endBlock) { - endErase = endBlock; - } - if (!sd.card()->erase(bgnErase, endErase)) { - error("erase failed"); - } - bgnErase = endErase + 1; - } - // Start a multiple block write. - if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) { - error("writeBegin failed"); - } - // Initialize queues. - emptyHead = emptyTail = 0; - fullHead = fullTail = 0; - - // Use SdFat buffer for one block. - emptyQueue[emptyHead] = (block_t*)cache; - emptyHead = queueNext(emptyHead); - - // Put rest of buffers in the empty queue. - for (uint8_t i = 0; i < BUFFER_BLOCK_COUNT; i++) { - emptyQueue[emptyHead] = &block[i]; - emptyHead = queueNext(emptyHead); - } - Serial.println(F("Logging - type any character to stop")); - // Wait for Serial Idle. - Serial.flush(); - delay(10); - uint32_t bn = 0; - uint32_t t0 = millis(); - uint32_t t1 = t0; - uint32_t overrun = 0; - uint32_t overrunTotal = 0; - uint32_t count = 0; - uint32_t maxLatency = 0; - int32_t diff; - // Start at a multiple of interval. - uint32_t logTime = micros()/LOG_INTERVAL_USEC + 1; - logTime *= LOG_INTERVAL_USEC; - bool closeFile = false; - while (1) { - // Time for next data record. - logTime += LOG_INTERVAL_USEC; - if (Serial.available()) { - closeFile = true; - } - - if (closeFile) { - if (curBlock != 0 && curBlock->count >= 0) { - // Put buffer in full queue. - fullQueue[fullHead] = curBlock; - fullHead = queueNext(fullHead); - curBlock = 0; - } - } else { - if (curBlock == 0 && emptyTail != emptyHead) { - curBlock = emptyQueue[emptyTail]; - emptyTail = queueNext(emptyTail); - curBlock->count = 0; - curBlock->overrun = overrun; - overrun = 0; - } - do { - diff = logTime - micros(); - } while(diff > 0); - if (diff < -10) { - error("LOG_INTERVAL_USEC too small"); - } - if (curBlock == 0) { - overrun++; - } else { - acquireData(&curBlock->data[curBlock->count++]); - if (curBlock->count == DATA_DIM) { - fullQueue[fullHead] = curBlock; - fullHead = queueNext(fullHead); - curBlock = 0; - } - } - } - - if (fullHead == fullTail) { - // Exit loop if done. - if (closeFile) { - break; - } - } else if (!sd.card()->isBusy()) { - // Get address of block to write. - block_t* pBlock = fullQueue[fullTail]; - fullTail = queueNext(fullTail); - // Write block to SD. - uint32_t usec = micros(); - if (!sd.card()->writeData((uint8_t*)pBlock)) { - error("write data failed"); - } - usec = micros() - usec; - t1 = millis(); - if (usec > maxLatency) { - maxLatency = usec; - } - count += pBlock->count; - - // Add overruns and possibly light LED. - if (pBlock->overrun) { - overrunTotal += pBlock->overrun; - if (ERROR_LED_PIN >= 0) { - digitalWrite(ERROR_LED_PIN, HIGH); - } - } - // Move block to empty queue. - emptyQueue[emptyHead] = pBlock; - emptyHead = queueNext(emptyHead); - bn++; - if (bn == FILE_BLOCK_COUNT) { - // File full so stop - break; - } - } - } - if (!sd.card()->writeStop()) { - error("writeStop failed"); - } - // Truncate file if recording stopped early. - if (bn != FILE_BLOCK_COUNT) { - Serial.println(F("Truncating file")); - if (!binFile.truncate(512L * bn)) { - error("Can't truncate file"); - } - } - if (!binFile.rename(sd.vwd(), binName)) { - error("Can't rename file"); - } - Serial.print(F("File renamed: ")); - Serial.println(binName); - Serial.print(F("Max block write usec: ")); - Serial.println(maxLatency); - Serial.print(F("Record time sec: ")); - Serial.println(0.001*(t1 - t0), 3); - Serial.print(F("Sample count: ")); - Serial.println(count); - Serial.print(F("Samples/sec: ")); - Serial.println((1000.0)*count/(t1-t0)); - Serial.print(F("Overruns: ")); - Serial.println(overrunTotal); - Serial.println(F("Done")); -} -//------------------------------------------------------------------------------ -void setup(void) { - if (ERROR_LED_PIN >= 0) { - pinMode(ERROR_LED_PIN, OUTPUT); - } - Serial.begin(9600); - while (!Serial) {} - - Serial.print(F("FreeRam: ")); - Serial.println(FreeRam()); - Serial.print(F("Records/block: ")); - Serial.println(DATA_DIM); - if (sizeof(block_t) != 512) { - error("Invalid block size"); - } - // initialize file system. - if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) { - sd.initErrorPrint(); - fatalBlink(); - } -} -//------------------------------------------------------------------------------ -void loop(void) { - // discard any input - while (Serial.read() >= 0) {} - Serial.println(); - Serial.println(F("type:")); - Serial.println(F("c - convert file to csv")); - Serial.println(F("d - dump data to Serial")); - Serial.println(F("e - overrun error details")); - Serial.println(F("r - record data")); - - while(!Serial.available()) {} - char c = tolower(Serial.read()); - - // Discard extra Serial data. - do { - delay(10); - } while (Serial.read() >= 0); - - if (ERROR_LED_PIN >= 0) { - digitalWrite(ERROR_LED_PIN, LOW); - } - if (c == 'c') { - binaryToCsv(); - } else if (c == 'd') { - dumpData(); - } else if (c == 'e') { - checkOverrun(); - } else if (c == 'r') { - logData(); - } else { - Serial.println(F("Invalid entry")); - } -} diff --git a/SdFat/examples/LowLatencyLogger/UserDataType.h b/SdFat/examples/LowLatencyLogger/UserDataType.h deleted file mode 100644 index 8e161e28..00000000 --- a/SdFat/examples/LowLatencyLogger/UserDataType.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef UserDataType_h -#define UserDataType_h -const uint8_t ADC_DIM = 4; -struct data_t { - unsigned long time; - unsigned short adc[ADC_DIM]; -}; -#endif // UserDataType_h diff --git a/SdFat/examples/OpenNext/OpenNext.ino b/SdFat/examples/OpenNext/OpenNext.ino deleted file mode 100644 index 814a496e..00000000 --- a/SdFat/examples/OpenNext/OpenNext.ino +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Print size, modify date/time, and name for all files in root. - */ -#include -#include - -// SD chip select pin -const uint8_t chipSelect = SS; - -// file system object -SdFat sd; - -SdFile file; -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - delay(1000); - Serial.println(); - - // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - // breadboards. use SPI_FULL_SPEED for better performance. - if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - // open next file in root. The volume working directory, vwd, is root - while (file.openNext(sd.vwd(), O_READ)) { - file.printFileSize(&Serial); - Serial.write(' '); - file.printModifyDateTime(&Serial); - Serial.write(' '); - file.printName(&Serial); - if (file.isDir()) { - // Indicate a directory. - Serial.write('/'); - } - Serial.println(); - file.close(); - } - Serial.println("Done!"); -} -//------------------------------------------------------------------------------ -void loop() {} diff --git a/SdFat/examples/QuickStart/QuickStart.ino b/SdFat/examples/QuickStart/QuickStart.ino deleted file mode 100644 index 80767809..00000000 --- a/SdFat/examples/QuickStart/QuickStart.ino +++ /dev/null @@ -1,157 +0,0 @@ -// Quick hardware test. -// -#include -#include -// -// Set DISABLE_CHIP_SELECT to disable a second SPI device. -// For example, with the Ethernet shield, set DISABLE_CHIP_SELECT -// to 10 to disable the Ethernet controller. -const int8_t DISABLE_CHIP_SELECT = -1; -// -// Test with reduced SPI speed for breadboards. -// Change spiSpeed to SPI_FULL_SPEED for better performance -// Use SPI_QUARTER_SPEED for even slower SPI bus speed -const uint8_t spiSpeed = SPI_HALF_SPEED; -//------------------------------------------------------------------------------ -// File system object. -SdFat sd; - -// Serial streams -ArduinoOutStream cout(Serial); - -// input buffer for line -char cinBuf[40]; -ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf)); - -// SD card chip select -int chipSelect; - -void cardOrSpeed() { - cout << F("Try another SD card or reduce the SPI bus speed.\n"); - cout << F("Edit spiSpeed in this program to change it.\n"); -} - -void reformatMsg() { - cout << F("Try reformatting the card. For best results use\n"); - cout << F("the SdFormatter program in SdFat/examples or download\n"); - cout << F("and use SDFormatter from www.sdcard.org/downloads.\n"); -} - -void setup() { - Serial.begin(9600); - while (!Serial) {} // Wait for Leonardo. - - cout << F("\nSPI pins:\n"); - cout << F("MISO: ") << int(MISO) << endl; - cout << F("MOSI: ") << int(MOSI) << endl; - cout << F("SCK: ") << int(SCK) << endl; - cout << F("SS: ") << int(SS) << endl; - - if (DISABLE_CHIP_SELECT < 0) { - cout << F( - "\nBe sure to edit DISABLE_CHIP_SELECT if you have\n" - "a second SPI device. For example, with the Ethernet\n" - "shield, DISABLE_CHIP_SELECT should be set to 10\n" - "to disable the Ethernet controller.\n"); - } - cout << F( - "\nSD chip select is the key hardware option.\n" - "Common values are:\n" - "Arduino Ethernet shield, pin 4\n" - "Sparkfun SD shield, pin 8\n" - "Adafruit SD shields and modules, pin 10\n"); -} - -bool firstTry = true; -void loop() { - // read any existing Serial data - while (Serial.read() >= 0) {} - - if (!firstTry) { - cout << F("\nRestarting\n"); - } - firstTry = false; - - cout << F("\nEnter the chip select pin number: "); - while (!Serial.available()) {} - delay(400); // catch Due restart problem - - cin.readline(); - if (cin >> chipSelect) { - cout << chipSelect << endl; - } else { - cout << F("\nInvalid pin number\n"); - return; - } - if (DISABLE_CHIP_SELECT < 0) { - cout << F( - "\nAssuming the SD is the only SPI device.\n" - "Edit DISABLE_CHIP_SELECT to disable another device.\n"); - } else { - cout << F("\nDisabling SPI device on pin "); - cout << int(DISABLE_CHIP_SELECT) << endl; - pinMode(DISABLE_CHIP_SELECT, OUTPUT); - digitalWrite(DISABLE_CHIP_SELECT, HIGH); - } - if (!sd.begin(chipSelect, spiSpeed)) { - if (sd.card()->errorCode()) { - cout << F( - "\nSD initialization failed.\n" - "Do not reformat the card!\n" - "Is the card correctly inserted?\n" - "Is chipSelect set to the correct value?\n" - "Does another SPI device need to be disabled?\n" - "Is there a wiring/soldering problem?\n"); - cout << F("\nerrorCode: ") << hex << showbase; - cout << int(sd.card()->errorCode()); - cout << F(", errorData: ") << int(sd.card()->errorData()); - cout << dec << noshowbase << endl; - return; - } - cout << F("\nCard successfully initialized.\n"); - if (sd.vol()->fatType() == 0) { - cout << F("Can't find a valid FAT16/FAT32 partition.\n"); - reformatMsg(); - return; - } - if (!sd.vwd()->isOpen()) { - cout << F("Can't open root directory.\n"); - reformatMsg(); - return; - } - cout << F("Can't determine error type\n"); - return; - } - cout << F("\nCard successfully initialized.\n"); - cout << endl; - - uint32_t size = sd.card()->cardSize(); - if (size == 0) { - cout << F("Can't determine the card size.\n"); - cardOrSpeed(); - return; - } - uint32_t sizeMB = 0.000512 * size + 0.5; - cout << F("Card size: ") << sizeMB; - cout << F(" MB (MB = 1,000,000 bytes)\n"); - cout << endl; - cout << F("Volume is FAT") << int(sd.vol()->fatType()); - cout << F(", Cluster size (bytes): ") << 512L * sd.vol()->blocksPerCluster(); - cout << endl << endl; - - cout << F("Files found (date time size name):\n"); - sd.ls(LS_R | LS_DATE | LS_SIZE); - - if ((sizeMB > 1100 && sd.vol()->blocksPerCluster() < 64) - || (sizeMB < 2200 && sd.vol()->fatType() == 32)) { - cout << F("\nThis card should be reformatted for best performance.\n"); - cout << F("Use a cluster size of 32 KB for cards larger than 1 GB.\n"); - cout << F("Only cards larger than 2 GB should be formatted FAT32.\n"); - reformatMsg(); - return; - } - // read any existing Serial data - while (Serial.read() >= 0) {} - cout << F("\nSuccess! Type any character to restart.\n"); - while (Serial.read() < 0) {} -} \ No newline at end of file diff --git a/SdFat/examples/RawWrite/RawWrite.ino b/SdFat/examples/RawWrite/RawWrite.ino deleted file mode 100644 index 03207d0b..00000000 --- a/SdFat/examples/RawWrite/RawWrite.ino +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This program illustrates raw write functions in SdFat that - * can be used for high speed data logging. - * - * This program simulates logging from a source that produces - * data at a constant rate of one block every MICROS_PER_BLOCK. - * - * If a high quality SanDisk card is used with this program - * no overruns occur and the maximum block write time is - * under 2000 micros. - * - * Note: Apps should create a very large file then truncates it - * to the length that is used for a logging. It only takes - * a few seconds to erase a 500 MB file since the card only - * marks the blocks as erased; no data transfer is required. - */ -#include -#include -#include - -// SD chip select pin -const uint8_t chipSelect = SS; - -// number of blocks in the contiguous file -const uint32_t BLOCK_COUNT = 10000UL; - -// time to produce a block of data -const uint32_t MICROS_PER_BLOCK = 10000; - -// file system -SdFat sd; - -// test file -SdFile file; - -// file extent -uint32_t bgnBlock, endBlock; - -// Serial output stream -ArduinoOutStream cout(Serial); -//------------------------------------------------------------------------------ -// store error strings in flash to save RAM -#define error(s) sd.errorHalt(F(s)) -//------------------------------------------------------------------------------ -// log of first overruns -#define OVER_DIM 20 -struct { - uint32_t block; - uint32_t micros; -} over[OVER_DIM]; -//------------------------------------------------------------------------------ -void setup(void) { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo -} -//------------------------------------------------------------------------------ -void loop(void) { - while (Serial.read() >= 0) {} - // pstr 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 - - cout << F("Free RAM: ") << FreeRam() << endl; - - // initialize the SD card at SPI_FULL_SPEED for best performance. - // try SPI_HALF_SPEED if bus errors occur. - if (!sd.begin(chipSelect, SPI_FULL_SPEED)) { - sd.initErrorHalt(); - } - - // delete possible existing file - sd.remove("RawWrite.txt"); - - // create a contiguous file - if (!file.createContiguous(sd.vwd(), "RawWrite.txt", 512UL*BLOCK_COUNT)) { - error("createContiguous failed"); - } - // get the location of the file's blocks - if (!file.contiguousRange(&bgnBlock, &endBlock)) { - error("contiguousRange failed"); - } - //*********************NOTE************************************** - // NO SdFile calls are allowed while cache is used for raw writes - //*************************************************************** - - // clear the cache and use it as a 512 byte buffer - uint8_t* pCache = (uint8_t*)sd.vol()->cacheClear(); - - // fill cache with eight lines of 64 bytes each - memset(pCache, ' ', 512); - for (uint16_t i = 0; i < 512; i += 64) { - // put line number at end of line then CR/LF - pCache[i + 61] = '0' + (i/64); - pCache[i + 62] = '\r'; - pCache[i + 63] = '\n'; - } - - cout << F("Start raw write of ") << file.fileSize() << F(" bytes at\n"); - cout << 512000000UL/MICROS_PER_BLOCK << F(" bytes per second\n"); - cout << F("Please wait ") << (BLOCK_COUNT*MICROS_PER_BLOCK)/1000000UL; - cout << F(" seconds\n"); - - // tell card to setup for multiple block write with pre-erase - if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) { - error("writeStart failed"); - } - // init stats - uint16_t overruns = 0; - uint32_t maxWriteTime = 0; - uint32_t t = micros(); - uint32_t tNext = t; - - // write data - for (uint32_t b = 0; b < BLOCK_COUNT; b++) { - // write must be done by this time - tNext += MICROS_PER_BLOCK; - - // put block number at start of first line in block - uint32_t n = b; - for (int8_t d = 5; d >= 0; d--) { - pCache[d] = n || d == 5 ? n % 10 + '0' : ' '; - n /= 10; - } - // write a 512 byte block - uint32_t tw = micros(); - if (!sd.card()->writeData(pCache)) { - error("writeData failed"); - } - tw = micros() - tw; - - // check for max write time - if (tw > maxWriteTime) { - maxWriteTime = tw; - } - // check for overrun - if (micros() > tNext) { - if (overruns < OVER_DIM) { - over[overruns].block = b; - over[overruns].micros = tw; - } - overruns++; - // advance time to reflect overrun - tNext = micros(); - } else { - // wait for time to write next block - while(micros() < tNext); - } - } - // total write time - t = micros() - t; - - // end multiple block write mode - if (!sd.card()->writeStop()) { - error("writeStop failed"); - } - - cout << F("Done\n"); - cout << F("Elapsed time: ") << setprecision(3)<< 1.e-6*t; - cout << F(" seconds\n"); - cout << F("Max write time: ") << maxWriteTime << F(" micros\n"); - cout << F("Overruns: ") << overruns << endl; - if (overruns) { - uint8_t n = overruns > OVER_DIM ? OVER_DIM : overruns; - cout << F("fileBlock,micros") << endl; - for (uint8_t i = 0; i < n; i++) { - cout << over[i].block << ',' << over[i].micros << endl; - } - } - // close file for next pass of loop - file.close(); - Serial.println(); -} \ No newline at end of file diff --git a/SdFat/examples/ReadWriteSdFat/ReadWriteSdFat.ino b/SdFat/examples/ReadWriteSdFat/ReadWriteSdFat.ino deleted file mode 100644 index d9bf3ece..00000000 --- a/SdFat/examples/ReadWriteSdFat/ReadWriteSdFat.ino +++ /dev/null @@ -1,73 +0,0 @@ -// Ported to SdFat from the native Arduino SD library example by Bill Greiman -// On the Ethernet Shield, CS is pin 4. SdFat handles setting SS -const int chipSelect = 4; -/* - SD card read/write - - This example shows how to read and write data to and from an SD card file - The circuit: - * SD card attached to SPI bus as follows: - ** MOSI - pin 11 - ** MISO - pin 12 - ** CLK - pin 13 - ** CS - pin 4 - - created Nov 2010 - by David A. Mellis - updated 2 Dec 2010 - by Tom Igoe - modified by Bill Greiman 11 Apr 2011 - This example code is in the public domain. - - */ -#include -#include -SdFat sd; -SdFile myFile; - -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - Serial.println("Type any character to start"); - while (Serial.read() <= 0) {} - delay(400); // catch Due reset problem - - // Initialize SdFat or print a detailed error message and halt - // Use half speed like the native library. - // change to SPI_FULL_SPEED for more performance. - if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - // open the file for write at end like the Native SD library - if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)) { - sd.errorHalt("opening test.txt for write failed"); - } - // if the file opened okay, write to it: - Serial.print("Writing to test.txt..."); - myFile.println("testing 1, 2, 3."); - - // close the file: - myFile.close(); - Serial.println("done."); - - // re-open the file for reading: - if (!myFile.open("test.txt", O_READ)) { - sd.errorHalt("opening test.txt for read failed"); - } - Serial.println("test.txt:"); - - // read from the file until there's nothing else in it: - int data; - while ((data = myFile.read()) >= 0) { - Serial.write(data); - } - // close the file: - myFile.close(); -} - -void loop() { - // nothing happens after setup -} - - diff --git a/SdFat/examples/SdFormatter/SdFormatter.ino b/SdFat/examples/SdFormatter/SdFormatter.ino deleted file mode 100644 index aa493e4f..00000000 --- a/SdFat/examples/SdFormatter/SdFormatter.ino +++ /dev/null @@ -1,511 +0,0 @@ -/* - * This program will format an SD or SDHC card. - * Warning all data will be deleted! - * - * For SD/SDHC cards larger than 64 MB this - * program attempts to match the format - * generated by SDFormatter available here: - * - * http://www.sdcard.org/consumers/formatter/ - * - * For smaller cards this program uses FAT16 - * and SDFormatter uses FAT12. - */ -// Print extra info for debug if DEBUG_PRINT is nonzero -#define DEBUG_PRINT 0 -#include -#include -#if DEBUG_PRINT -#include -#endif // DEBUG_PRINT -// -// Change the value of chipSelect if your hardware does -// not use the default value, SS. Common values are: -// Arduino Ethernet shield: pin 4 -// Sparkfun SD shield: pin 8 -// Adafruit SD shields and modules: pin 10 -const uint8_t chipSelect = SS; - -// Change spiSpeed to SPI_FULL_SPEED for better performance -// Use SPI_QUARTER_SPEED for even slower SPI bus speed -const uint8_t spiSpeed = SPI_HALF_SPEED; - -// Serial output stream -ArduinoOutStream cout(Serial); - -Sd2Card card; -uint32_t cardSizeBlocks; -uint16_t cardCapacityMB; - -// cache for SD block -cache_t cache; - -// MBR information -uint8_t partType; -uint32_t relSector; -uint32_t partSize; - -// Fake disk geometry -uint8_t numberOfHeads; -uint8_t sectorsPerTrack; - -// FAT parameters -uint16_t reservedSectors; -uint8_t sectorsPerCluster; -uint32_t fatStart; -uint32_t fatSize; -uint32_t dataStart; - -// constants for file system structure -uint16_t const BU16 = 128; -uint16_t const BU32 = 8192; - -// strings needed in file system structures -char noName[] = "NO NAME "; -char fat16str[] = "FAT16 "; -char fat32str[] = "FAT32 "; -//------------------------------------------------------------------------------ -#define sdError(msg) sdError_F(F(msg)) - -void sdError_F(const __FlashStringHelper* str) { - cout << F("error: "); - cout << str << endl; - if (card.errorCode()) { - cout << F("SD error: ") << hex << int(card.errorCode()); - cout << ',' << int(card.errorData()) << dec << endl; - } - while (1); -} -//------------------------------------------------------------------------------ -#if DEBUG_PRINT -void debugPrint() { - cout << F("FreeRam: ") << FreeRam() << endl; - cout << F("partStart: ") << relSector << endl; - cout << F("partSize: ") << partSize << endl; - cout << F("reserved: ") << reservedSectors << endl; - cout << F("fatStart: ") << fatStart << endl; - cout << F("fatSize: ") << fatSize << endl; - cout << F("dataStart: ") << dataStart << endl; - cout << F("clusterCount: "); - cout << ((relSector + partSize - dataStart)/sectorsPerCluster) << endl; - cout << endl; - cout << F("Heads: ") << int(numberOfHeads) << endl; - cout << F("Sectors: ") << int(sectorsPerTrack) << endl; - cout << F("Cylinders: "); - cout << cardSizeBlocks/(numberOfHeads*sectorsPerTrack) << endl; -} -#endif // DEBUG_PRINT -//------------------------------------------------------------------------------ -// write cached block to the card -uint8_t writeCache(uint32_t lbn) { - return card.writeBlock(lbn, cache.data); -} -//------------------------------------------------------------------------------ -// initialize appropriate sizes for SD capacity -void initSizes() { - if (cardCapacityMB <= 6) { - sdError("Card is too small."); - } else if (cardCapacityMB <= 16) { - sectorsPerCluster = 2; - } else if (cardCapacityMB <= 32) { - sectorsPerCluster = 4; - } else if (cardCapacityMB <= 64) { - sectorsPerCluster = 8; - } else if (cardCapacityMB <= 128) { - sectorsPerCluster = 16; - } else if (cardCapacityMB <= 1024) { - sectorsPerCluster = 32; - } else if (cardCapacityMB <= 32768) { - sectorsPerCluster = 64; - } else { - // SDXC cards - sectorsPerCluster = 128; - } - - cout << F("Blocks/Cluster: ") << int(sectorsPerCluster) << endl; - // set fake disk geometry - sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63; - - if (cardCapacityMB <= 16) { - numberOfHeads = 2; - } else if (cardCapacityMB <= 32) { - numberOfHeads = 4; - } else if (cardCapacityMB <= 128) { - numberOfHeads = 8; - } else if (cardCapacityMB <= 504) { - numberOfHeads = 16; - } else if (cardCapacityMB <= 1008) { - numberOfHeads = 32; - } else if (cardCapacityMB <= 2016) { - numberOfHeads = 64; - } else if (cardCapacityMB <= 4032) { - numberOfHeads = 128; - } else { - numberOfHeads = 255; - } -} -//------------------------------------------------------------------------------ -// zero cache and optionally set the sector signature -void clearCache(uint8_t addSig) { - memset(&cache, 0, sizeof(cache)); - if (addSig) { - cache.mbr.mbrSig0 = BOOTSIG0; - cache.mbr.mbrSig1 = BOOTSIG1; - } -} -//------------------------------------------------------------------------------ -// zero FAT and root dir area on SD -void clearFatDir(uint32_t bgn, uint32_t count) { - clearCache(false); - if (!card.writeStart(bgn, count)) { - sdError("Clear FAT/DIR writeStart failed"); - } - for (uint32_t i = 0; i < count; i++) { - if ((i & 0XFF) == 0) { - cout << '.'; - } - if (!card.writeData(cache.data)) { - sdError("Clear FAT/DIR writeData failed"); - } - } - if (!card.writeStop()) { - sdError("Clear FAT/DIR writeStop failed"); - } - cout << endl; -} -//------------------------------------------------------------------------------ -// return cylinder number for a logical block number -uint16_t lbnToCylinder(uint32_t lbn) { - return lbn / (numberOfHeads * sectorsPerTrack); -} -//------------------------------------------------------------------------------ -// return head number for a logical block number -uint8_t lbnToHead(uint32_t lbn) { - return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack; -} -//------------------------------------------------------------------------------ -// return sector number for a logical block number -uint8_t lbnToSector(uint32_t lbn) { - return (lbn % sectorsPerTrack) + 1; -} -//------------------------------------------------------------------------------ -// format and write the Master Boot Record -void writeMbr() { - clearCache(true); - part_t* p = cache.mbr.part; - p->boot = 0; - uint16_t c = lbnToCylinder(relSector); - if (c > 1023) { - sdError("MBR CHS"); - } - p->beginCylinderHigh = c >> 8; - p->beginCylinderLow = c & 0XFF; - p->beginHead = lbnToHead(relSector); - p->beginSector = lbnToSector(relSector); - p->type = partType; - uint32_t endLbn = relSector + partSize - 1; - c = lbnToCylinder(endLbn); - if (c <= 1023) { - p->endCylinderHigh = c >> 8; - p->endCylinderLow = c & 0XFF; - p->endHead = lbnToHead(endLbn); - p->endSector = lbnToSector(endLbn); - } else { - // Too big flag, c = 1023, h = 254, s = 63 - p->endCylinderHigh = 3; - p->endCylinderLow = 255; - p->endHead = 254; - p->endSector = 63; - } - p->firstSector = relSector; - p->totalSectors = partSize; - if (!writeCache(0)) { - sdError("write MBR"); - } -} -//------------------------------------------------------------------------------ -// generate serial number from card size and micros since boot -uint32_t volSerialNumber() { - return (cardSizeBlocks << 8) + micros(); -} -//------------------------------------------------------------------------------ -// format the SD as FAT16 -void makeFat16() { - uint32_t nc; - for (dataStart = 2 * BU16;; dataStart += BU16) { - nc = (cardSizeBlocks - dataStart)/sectorsPerCluster; - fatSize = (nc + 2 + 255)/256; - uint32_t r = BU16 + 1 + 2 * fatSize + 32; - if (dataStart < r) { - continue; - } - relSector = dataStart - r + BU16; - break; - } - // check valid cluster count for FAT16 volume - if (nc < 4085 || nc >= 65525) { - sdError("Bad cluster count"); - } - reservedSectors = 1; - fatStart = relSector + reservedSectors; - partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32; - if (partSize < 32680) { - partType = 0X01; - } else if (partSize < 65536) { - partType = 0X04; - } else { - partType = 0X06; - } - // write MBR - writeMbr(); - clearCache(true); - fat_boot_t* pb = &cache.fbs; - pb->jump[0] = 0XEB; - pb->jump[1] = 0X00; - pb->jump[2] = 0X90; - for (uint8_t i = 0; i < sizeof(pb->oemId); i++) { - pb->oemId[i] = ' '; - } - pb->bytesPerSector = 512; - pb->sectorsPerCluster = sectorsPerCluster; - pb->reservedSectorCount = reservedSectors; - pb->fatCount = 2; - pb->rootDirEntryCount = 512; - pb->mediaType = 0XF8; - pb->sectorsPerFat16 = fatSize; - pb->sectorsPerTrack = sectorsPerTrack; - pb->headCount = numberOfHeads; - pb->hidddenSectors = relSector; - pb->totalSectors32 = partSize; - pb->driveNumber = 0X80; - pb->bootSignature = EXTENDED_BOOT_SIG; - pb->volumeSerialNumber = volSerialNumber(); - memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel)); - memcpy(pb->fileSystemType, fat16str, sizeof(pb->fileSystemType)); - // write partition boot sector - if (!writeCache(relSector)) { - sdError("FAT16 write PBS failed"); - } - // clear FAT and root directory - clearFatDir(fatStart, dataStart - fatStart); - clearCache(false); - cache.fat16[0] = 0XFFF8; - cache.fat16[1] = 0XFFFF; - // write first block of FAT and backup for reserved clusters - if (!writeCache(fatStart) - || !writeCache(fatStart + fatSize)) { - sdError("FAT16 reserve failed"); - } -} -//------------------------------------------------------------------------------ -// format the SD as FAT32 -void makeFat32() { - uint32_t nc; - relSector = BU32; - for (dataStart = 2 * BU32;; dataStart += BU32) { - nc = (cardSizeBlocks - dataStart)/sectorsPerCluster; - fatSize = (nc + 2 + 127)/128; - uint32_t r = relSector + 9 + 2 * fatSize; - if (dataStart >= r) { - break; - } - } - // error if too few clusters in FAT32 volume - if (nc < 65525) { - sdError("Bad cluster count"); - } - reservedSectors = dataStart - relSector - 2 * fatSize; - fatStart = relSector + reservedSectors; - partSize = nc * sectorsPerCluster + dataStart - relSector; - // type depends on address of end sector - // max CHS has lbn = 16450560 = 1024*255*63 - if ((relSector + partSize) <= 16450560) { - // FAT32 - partType = 0X0B; - } else { - // FAT32 with INT 13 - partType = 0X0C; - } - writeMbr(); - clearCache(true); - - fat32_boot_t* pb = &cache.fbs32; - pb->jump[0] = 0XEB; - pb->jump[1] = 0X00; - pb->jump[2] = 0X90; - for (uint8_t i = 0; i < sizeof(pb->oemId); i++) { - pb->oemId[i] = ' '; - } - pb->bytesPerSector = 512; - pb->sectorsPerCluster = sectorsPerCluster; - pb->reservedSectorCount = reservedSectors; - pb->fatCount = 2; - pb->mediaType = 0XF8; - pb->sectorsPerTrack = sectorsPerTrack; - pb->headCount = numberOfHeads; - pb->hidddenSectors = relSector; - pb->totalSectors32 = partSize; - pb->sectorsPerFat32 = fatSize; - pb->fat32RootCluster = 2; - pb->fat32FSInfo = 1; - pb->fat32BackBootBlock = 6; - pb->driveNumber = 0X80; - pb->bootSignature = EXTENDED_BOOT_SIG; - pb->volumeSerialNumber = volSerialNumber(); - memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel)); - memcpy(pb->fileSystemType, fat32str, sizeof(pb->fileSystemType)); - // write partition boot sector and backup - if (!writeCache(relSector) - || !writeCache(relSector + 6)) { - sdError("FAT32 write PBS failed"); - } - clearCache(true); - // write extra boot area and backup - if (!writeCache(relSector + 2) - || !writeCache(relSector + 8)) { - sdError("FAT32 PBS ext failed"); - } - fat32_fsinfo_t* pf = &cache.fsinfo; - pf->leadSignature = FSINFO_LEAD_SIG; - pf->structSignature = FSINFO_STRUCT_SIG; - pf->freeCount = 0XFFFFFFFF; - pf->nextFree = 0XFFFFFFFF; - // write FSINFO sector and backup - if (!writeCache(relSector + 1) - || !writeCache(relSector + 7)) { - sdError("FAT32 FSINFO failed"); - } - clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster); - clearCache(false); - cache.fat32[0] = 0x0FFFFFF8; - cache.fat32[1] = 0x0FFFFFFF; - cache.fat32[2] = 0x0FFFFFFF; - // write first block of FAT and backup for reserved clusters - if (!writeCache(fatStart) - || !writeCache(fatStart + fatSize)) { - sdError("FAT32 reserve failed"); - } -} -//------------------------------------------------------------------------------ -// flash erase all data -uint32_t const ERASE_SIZE = 262144L; -void eraseCard() { - cout << endl << F("Erasing\n"); - uint32_t firstBlock = 0; - uint32_t lastBlock; - uint16_t n = 0; - - do { - lastBlock = firstBlock + ERASE_SIZE - 1; - if (lastBlock >= cardSizeBlocks) { - lastBlock = cardSizeBlocks - 1; - } - if (!card.erase(firstBlock, lastBlock)) { - sdError("erase failed"); - } - cout << '.'; - if ((n++)%32 == 31) { - cout << endl; - } - firstBlock += ERASE_SIZE; - } while (firstBlock < cardSizeBlocks); - cout << endl; - - if (!card.readBlock(0, cache.data)) { - sdError("readBlock"); - } - cout << hex << showbase << setfill('0') << internal; - cout << F("All data set to ") << setw(4) << int(cache.data[0]) << endl; - cout << dec << noshowbase << setfill(' ') << right; - cout << F("Erase done\n"); -} -//------------------------------------------------------------------------------ -void formatCard() { - cout << endl; - cout << F("Formatting\n"); - initSizes(); - if (card.type() != SD_CARD_TYPE_SDHC) { - cout << F("FAT16\n"); - makeFat16(); - } else { - cout << F("FAT32\n"); - makeFat32(); - } -#if DEBUG_PRINT - debugPrint(); -#endif // DEBUG_PRINT - cout << F("Format done\n"); -} -//------------------------------------------------------------------------------ -void setup() { - char c; - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - - cout << F( - "\n" - "This program can erase and/or format SD/SDHC cards.\n" - "\n" - "Erase uses the card's fast flash erase command.\n" - "Flash erase sets all data to 0X00 for most cards\n" - "and 0XFF for a few vendor's cards.\n" - "\n" - "Cards larger than 2 GB will be formatted FAT32 and\n" - "smaller cards will be formatted FAT16.\n" - "\n" - "Warning, all data on the card will be erased.\n" - "Enter 'Y' to continue: "); - while (!Serial.available()) {} - delay(400); // catch Due restart problem - - c = Serial.read(); - cout << c << endl; - if (c != 'Y') { - cout << F("Quiting, you did not enter 'Y'.\n"); - return; - } - // read any existing Serial data - while (Serial.read() >= 0) {} - - cout << F( - "\n" - "Options are:\n" - "E - erase the card and skip formatting.\n" - "F - erase and then format the card. (recommended)\n" - "Q - quick format the card without erase.\n" - "\n" - "Enter option: "); - - while (!Serial.available()) {} - c = Serial.read(); - cout << c << endl; - if (!strchr("EFQ", c)) { - cout << F("Quiting, invalid option entered.") << endl; - return; - } - - if (!card.begin(chipSelect, spiSpeed)) { - cout << F( - "\nSD initialization failure!\n" - "Is the SD card inserted correctly?\n" - "Is chip select correct at the top of this program?\n"); - sdError("card.begin failed"); - } - cardSizeBlocks = card.cardSize(); - if (cardSizeBlocks == 0) { - sdError("cardSize"); - } - cardCapacityMB = (cardSizeBlocks + 2047)/2048; - - cout << F("Card Size: ") << cardCapacityMB; - cout << F(" MB, (MB = 1,048,576 bytes)") << endl; - - if (c == 'E' || c == 'F') { - eraseCard(); - } - if (c == 'F' || c == 'Q') { - formatCard(); - } -} -//------------------------------------------------------------------------------ -void loop() {} diff --git a/SdFat/examples/SdInfo/SdInfo.ino b/SdFat/examples/SdInfo/SdInfo.ino deleted file mode 100644 index a5315e9d..00000000 --- a/SdFat/examples/SdInfo/SdInfo.ino +++ /dev/null @@ -1,234 +0,0 @@ -/* - * This program attempts to initialize an SD card and analyze its structure. - */ -#include -#include -/* - * SD chip select pin. Common values are: - * - * Arduino Ethernet shield, pin 4. - * SparkFun SD shield, pin 8. - * Adafruit SD shields and modules, pin 10. - * Default SD chip select is the SPI SS pin. - */ -const uint8_t SD_CHIP_SELECT = SS; -/* - * Set DISABLE_CHIP_SELECT to disable a second SPI device. - * For example, with the Ethernet shield, set DISABLE_CHIP_SELECT - * to 10 to disable the Ethernet controller. - */ -const int8_t DISABLE_CHIP_SELECT = -1; -SdFat sd; - -// serial output steam -ArduinoOutStream cout(Serial); - -// global for card size -uint32_t cardSize; - -// global for card erase size -uint32_t eraseSize; -//------------------------------------------------------------------------------ -// store error strings in flash -#define sdErrorMsg(msg) sdErrorMsg_F(F(msg)); -void sdErrorMsg_F(const __FlashStringHelper* str) { - cout << str << endl; - if (sd.card()->errorCode()) { - cout << F("SD errorCode: "); - cout << hex << int(sd.card()->errorCode()) << endl; - cout << F("SD errorData: "); - cout << int(sd.card()->errorData()) << dec << endl; - } -} -//------------------------------------------------------------------------------ -uint8_t cidDmp() { - cid_t cid; - if (!sd.card()->readCID(&cid)) { - sdErrorMsg("readCID failed"); - return false; - } - cout << F("\nManufacturer ID: "); - cout << hex << int(cid.mid) << dec << endl; - cout << F("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl; - cout << F("Product: "); - for (uint8_t i = 0; i < 5; i++) { - cout << cid.pnm[i]; - } - cout << F("\nVersion: "); - cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl; - cout << F("Serial number: ") << hex << cid.psn << dec << endl; - cout << F("Manufacturing date: "); - cout << int(cid.mdt_month) << '/'; - cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl; - cout << endl; - return true; -} -//------------------------------------------------------------------------------ -uint8_t csdDmp() { - csd_t csd; - uint8_t eraseSingleBlock; - if (!sd.card()->readCSD(&csd)) { - sdErrorMsg("readCSD failed"); - return false; - } - if (csd.v1.csd_ver == 0) { - eraseSingleBlock = csd.v1.erase_blk_en; - eraseSize = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low; - } else if (csd.v2.csd_ver == 1) { - eraseSingleBlock = csd.v2.erase_blk_en; - eraseSize = (csd.v2.sector_size_high << 1) | csd.v2.sector_size_low; - } else { - cout << F("csd version error\n"); - return false; - } - eraseSize++; - cout << F("cardSize: ") << 0.000512*cardSize; - cout << F(" MB (MB = 1,000,000 bytes)\n"); - - cout << F("flashEraseSize: ") << int(eraseSize) << F(" blocks\n"); - cout << F("eraseSingleBlock: "); - if (eraseSingleBlock) { - cout << F("true\n"); - } else { - cout << F("false\n"); - } - return true; -} -//------------------------------------------------------------------------------ -// print partition table -uint8_t partDmp() { - cache_t *p = sd.vol()->cacheClear(); - if (!p) { - sdErrorMsg("cacheClear failed"); - return false; - } - if (!sd.card()->readBlock(0, p->data)) { - sdErrorMsg("read MBR failed"); - return false; - } - for (uint8_t ip = 1; ip < 5; ip++) { - part_t *pt = &p->mbr.part[ip - 1]; - if ((pt->boot & 0X7F) != 0 || pt->firstSector > cardSize) { - cout << F("\nNo MBR. Assuming Super Floppy format.\n"); - return true; - } - } - cout << F("\nSD Partition Table\n"); - cout << F("part,boot,type,start,length\n"); - for (uint8_t ip = 1; ip < 5; ip++) { - part_t *pt = &p->mbr.part[ip - 1]; - cout << int(ip) << ',' << hex << int(pt->boot) << ',' << int(pt->type); - cout << dec << ',' << pt->firstSector <<',' << pt->totalSectors << endl; - } - return true; -} -//------------------------------------------------------------------------------ -void volDmp() { - cout << F("\nVolume is FAT") << int(sd.vol()->fatType()) << endl; - cout << F("blocksPerCluster: ") << int(sd.vol()->blocksPerCluster()) << endl; - cout << F("clusterCount: ") << sd.vol()->clusterCount() << endl; - cout << F("freeClusters: "); - uint32_t volFree = sd.vol()->freeClusterCount(); - cout << volFree << endl; - float fs = 0.000512*volFree*sd.vol()->blocksPerCluster(); - cout << F("freeSpace: ") << fs << F(" MB (MB = 1,000,000 bytes)\n"); - cout << F("fatStartBlock: ") << sd.vol()->fatStartBlock() << endl; - cout << F("fatCount: ") << int(sd.vol()->fatCount()) << endl; - cout << F("blocksPerFat: ") << sd.vol()->blocksPerFat() << endl; - cout << F("rootDirStart: ") << sd.vol()->rootDirStart() << endl; - cout << F("dataStartBlock: ") << sd.vol()->dataStartBlock() << endl; - if (sd.vol()->dataStartBlock() % eraseSize) { - cout << F("Data area is not aligned on flash erase boundaries!\n"); - cout << F("Download and use formatter from www.sdsd.card()->org/consumer!\n"); - } -} -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while(!Serial) {} // wait for Leonardo - - // use uppercase in hex and use 0X base prefix - cout << uppercase << showbase << endl; - - // pstr stores strings in flash to save RAM - cout << F("SdFat version: ") << SD_FAT_VERSION << endl; - if (DISABLE_CHIP_SELECT < 0) { - cout << F( - "\nAssuming the SD is the only SPI device.\n" - "Edit DISABLE_CHIP_SELECT to disable another device.\n"); - } else { - cout << F("\nDisabling SPI device on pin "); - cout << int(DISABLE_CHIP_SELECT) << endl; - pinMode(DISABLE_CHIP_SELECT, OUTPUT); - digitalWrite(DISABLE_CHIP_SELECT, HIGH); - } - cout << F("\nAssuming the SD chip select pin is: ") <= 0) {} - - // pstr stores strings in flash to save RAM - cout << F("\ntype any character to start\n"); - while (Serial.read() <= 0) {} - delay(400); // catch Due reset problem - - uint32_t t = millis(); - // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - // breadboards. use SPI_FULL_SPEED for better performance. - if (!sd.cardBegin(SD_CHIP_SELECT, SPI_HALF_SPEED)) { - sdErrorMsg("\ncardBegin failed"); - return; - } - t = millis() - t; - - cardSize = sd.card()->cardSize(); - if (cardSize == 0) { - sdErrorMsg("cardSize failed"); - return; - } - cout << F("\ninit time: ") << t << " ms" << endl; - cout << F("\nCard type: "); - switch (sd.card()->type()) { - case SD_CARD_TYPE_SD1: - cout << F("SD1\n"); - break; - - case SD_CARD_TYPE_SD2: - cout << F("SD2\n"); - break; - - case SD_CARD_TYPE_SDHC: - if (cardSize < 70000000) { - cout << F("SDHC\n"); - } else { - cout << F("SDXC\n"); - } - break; - - default: - cout << F("Unknown\n"); - } - if (!cidDmp()) { - return; - } - if (!csdDmp()) { - return; - } - uint32_t ocr; - if (!sd.card()->readOCR(&ocr)) { - sdErrorMsg("\nreadOCR failed"); - return; - } - cout << F("OCR: ") << hex << ocr << dec << endl; - if (!partDmp()) { - return; - } - if (!sd.fsBegin()) { - sdErrorMsg("\nFile System initialization failed.\n"); - return; - } - volDmp(); -} \ No newline at end of file diff --git a/SdFat/examples/SoftwareSpi/SoftwareSpi.ino b/SdFat/examples/SoftwareSpi/SoftwareSpi.ino deleted file mode 100644 index f49263a3..00000000 --- a/SdFat/examples/SoftwareSpi/SoftwareSpi.ino +++ /dev/null @@ -1,48 +0,0 @@ -// An example of the SdFatSoftSpi template class. -// This example is for an Adafruit Data Logging Shield on a Mega. -// Software SPI is required on Mega since this shield connects to pins 10-13. -// This example will also run on an Uno and other boards using software SPI. -// -#include -#include -#if SD_SPI_CONFIGURATION >= 3 // Must be set in SdFat/SdFatConfig.h -// -// Pin numbers in templates must be constants. -const uint8_t SOFT_MISO_PIN = 12; -const uint8_t SOFT_MOSI_PIN = 11; -const uint8_t SOFT_SCK_PIN = 13; -// -// Chip select may be constant or RAM variable. -const uint8_t SD_CHIP_SELECT_PIN = 10; - -// SdFat software SPI template -SdFatSoftSpi sd; - -// Test file. -SdFile file; - -void setup() { - Serial.begin(9600); - while (!Serial) {} // Wait for Leonardo - - Serial.println("Type any character to start"); - while (Serial.read() <= 0) {} - - if (!sd.begin(SD_CHIP_SELECT_PIN)) { - sd.initErrorHalt(); - } - - if (!file.open("SoftSPI.txt", O_CREAT | O_RDWR)) { - sd.errorHalt(F("open failed")); - } - file.println(F("This line was printed using software SPI.")); - - file.close(); - - Serial.println(F("Done.")); -} -//------------------------------------------------------------------------------ -void loop() {} -#else // SD_SPI_CONFIGURATION >= 3 -#error SD_SPI_CONFIGURATION must be set to 3 in SdFat/SdFatConfig.h -#endif //SD_SPI_CONFIGURATION >= 3 \ No newline at end of file diff --git a/SdFat/examples/ThreeCards/ThreeCards.ino b/SdFat/examples/ThreeCards/ThreeCards.ino deleted file mode 100644 index 8cbe7b0c..00000000 --- a/SdFat/examples/ThreeCards/ThreeCards.ino +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Example use of three SD cards. - */ -#include -#include -#include -#if SD_SPI_CONFIGURATION >= 3 // Must be set in SdFat/SdFatConfig.h - -// SD1 is a microSD on hardware SPI pins 50-52 -// Using my fast custom SPI -SdFat sd1; -const uint8_t SD1_CS = 53; - -// SD2 is a Catalex shield on hardware SPI pins 50-52 -// Using the standard Arduino SPI library -SdFatLibSpi sd2; -const uint8_t SD2_CS = 4; - -// SD3 is a Adafruit data logging shield on pins 10-13 -// Using Software SPI -SdFatSoftSpi<12, 11, 13> sd3; -const uint8_t SD3_CS = 10; - -const uint8_t BUF_DIM = 100; -uint8_t buf[BUF_DIM]; - -const uint32_t FILE_SIZE = 1000000; -const uint16_t NWRITE = FILE_SIZE/BUF_DIM; -//------------------------------------------------------------------------------ -// print error msg, any SD error codes, and halt. -// store messages in flash -#define errorExit(msg) errorHalt(F(msg)) -#define initError(msg) initErrorHalt(F(msg)) -//------------------------------------------------------------------------------ -void list() { -// list current directory on all cards - Serial.println(F("------sd1-------")); - sd1.ls("/", LS_SIZE|LS_R); - Serial.println(F("------sd2-------")); - sd2.ls("/", LS_SIZE|LS_R); - Serial.println(F("------sd3-------")); - sd3.ls("/", LS_SIZE|LS_R); - Serial.println(F("---------------------")); -} -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - Serial.print(F("FreeRam: ")); - - Serial.println(FreeRam()); - - // fill buffer with known data - for (int i = 0; i < sizeof(buf); i++) { - buf[i] = i; - } - - Serial.println(F("type any character to start")); - while (Serial.read() <= 0) {} - - // disable sd2 while initializing sd1 - pinMode(SD2_CS, OUTPUT); - digitalWrite(SD2_CS, HIGH); - - // initialize the first card - if (!sd1.begin(SD1_CS)) { - sd1.initError("sd1:"); - } - - // initialize the second card - if (!sd2.begin(SD2_CS)) { - sd2.initError("sd2:"); - } - - // initialize the third card - if (!sd3.begin(SD3_CS)) { - sd3.initError("sd3:"); - } - - Serial.println(F("Cards OK - creating directories")); - - // create Dir1 on sd1 if it does not exist - if (!sd1.exists("/Dir1")) { - if (!sd1.mkdir("/Dir1")) { - sd1.errorExit("sd1.mkdir"); - } - } - // make /Dir1 the default directory for sd1 - if (!sd1.chdir("/Dir1")) { - sd1.errorExit("sd1.chdir"); - } - - // create Dir2 on sd2 if it does not exist - if (!sd2.exists("/Dir2")) { - if (!sd2.mkdir("/Dir2")) { - sd2.errorExit("sd2.mkdir"); - } - } - // make /Dir2 the default directory for sd2 - if (!sd2.chdir("/Dir2")) { - sd2.errorExit("sd2.chdir"); - } - - // create Dir3 on sd3 if it does not exist - if (!sd3.exists("/Dir3")) { - if (!sd3.mkdir("/Dir3")) { - sd2.errorExit("sd3.mkdir"); - } - } - // make /Dir3 the default directory for sd3 - if (!sd3.chdir("/Dir3")) { - sd3.errorExit("sd3.chdir"); - } - - Serial.println(F("Directories created - removing old files")); - - if (sd1.exists("TEST1.bin")) { - if (!sd1.remove("TEST1.bin")) { - sd1.errorExit("sd1.remove"); - } - } - if (sd2.exists("TEST2.bin")) { - if (!sd2.remove("TEST2.bin")) { - sd2.errorExit("sd2.remove"); - } - } - if (sd3.exists("TEST3.bin")) { - if (!sd3.remove("TEST3.bin")) { - sd2.errorExit("sd3.remove"); - } - } - Serial.println("Initial SD directories"); - list(); - - // create or open /Dir1/TEST1.bin and truncate it to zero length - SdFile file1; - if (!file1.open(&sd1, "TEST1.bin", O_RDWR | O_CREAT | O_TRUNC)) { - sd1.errorExit("file1"); - } - Serial.println(F("Writing SD1:/Dir1/TEST1.bin")); - - // write data to /Dir1/TEST1.bin on sd1 - for (int i = 0; i < NWRITE; i++) { - if (file1.write(buf, sizeof(buf)) != sizeof(buf)) { - sd1.errorExit("sd1.write"); - } - } - file1.sync(); - list(); - - // create or open /Dir2/TEST2.bin and truncate it to zero length - SdFile file2; - if (!file2.open(&sd2, "TEST2.bin", O_RDWR | O_CREAT | O_TRUNC)) { - sd2.errorExit("file2"); - } - Serial.println(F("Copying SD1:/Dir1/TEST1.bin to SD2::/Dir2/TEST2.bin")); - - // copy file1 to file2 - file1.rewind(); - - uint32_t t = millis(); - - while (1) { - int n = file1.read(buf, sizeof(buf)); - if (n < 0) { - sd1.errorExit("read1"); - } - if (n == 0) { - break; - } - if (file2.write(buf, n) != n) { - sd2.errorExit("write3"); - } - } - t = millis() - t; - file2.sync(); - Serial.print(F("File size: ")); - Serial.println(file2.fileSize()); - Serial.print(F("Copy time: ")); - Serial.print(t); - Serial.println(F(" millis")); - list(); - - // create or open /Dir3/TEST3.bin and truncate it to zero length - SdFile file3; - if (!file3.open(&sd3, "TEST3.bin", O_RDWR | O_CREAT | O_TRUNC)) { - sd3.errorExit("file3"); - } - file2.rewind(); - Serial.println(F("Copying SD2:/Dir2/TEST2.bin to SD3:/Dir3/TEST3.bin")); - while (1) { - int n = file2.read(buf, sizeof(buf)); - if (n == 0) { - break; - } - if (n != sizeof(buf)) { - sd2.errorExit("read2"); - } - if (file3.write(buf, n) != n) { - sd3.errorExit("write2"); - } - } - file3.sync(); - list(); - - // Verify content of file3 - file3.rewind(); - Serial.println(F("Verifying content of TEST3.bin")); - for (int i = 0; i < NWRITE; i++) { - if (file3.read(buf, sizeof(buf)) != sizeof(buf)) { - sd3.errorExit("sd3.read"); - } - for (int j = 0; j < sizeof(buf); j++) { - if (j != buf[j]) { - sd3.errorExit("Verify error"); - } - } - } - Serial.println(F("Done - Verify OK")); - file1.close(); - file2.close(); - file3.close(); -} -//------------------------------------------------------------------------------ -void loop() {} -#else // SD_SPI_CONFIGURATION >= 3 -#error SD_SPI_CONFIGURATION must be set to 3 in SdFat/SdFatConfig.h -#endif //SD_SPI_CONFIGURATION >= 3 \ No newline at end of file diff --git a/SdFat/examples/Timestamp/Timestamp.ino b/SdFat/examples/Timestamp/Timestamp.ino deleted file mode 100644 index 4a92ef38..00000000 --- a/SdFat/examples/Timestamp/Timestamp.ino +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This program tests the dateTimeCallback() function - * and the timestamp() function. - */ -#include -#include - -SdFat sd; - -SdFile file; - -// Default SD chip select is SS pin -const uint8_t chipSelect = SS; - -// create Serial stream -ArduinoOutStream cout(Serial); -//------------------------------------------------------------------------------ -// store error strings in flash to save RAM -#define error(s) sd.errorHalt(F(s)) -//------------------------------------------------------------------------------ -/* - * date/time values for debug - * normally supplied by a real-time clock or GPS - */ -// date 1-Oct-14 -uint16_t year = 2014; -uint8_t month = 10; -uint8_t day = 1; - -// time 20:30:40 -uint8_t hour = 20; -uint8_t minute = 30; -uint8_t second = 40; -//------------------------------------------------------------------------------ -/* - * User provided date time callback function. - * See SdFile::dateTimeCallback() for usage. - */ -void dateTime(uint16_t* date, uint16_t* time) { - // User gets date and time from GPS or real-time - // clock in real callback function - - // return date using FAT_DATE macro to format fields - *date = FAT_DATE(year, month, day); - - // return time using FAT_TIME macro to format fields - *time = FAT_TIME(hour, minute, second); -} -//------------------------------------------------------------------------------ -/* - * Function to print all timestamps. - */ -void printTimestamps(SdFile& f) { - dir_t d; - if (!f.dirEntry(&d)) { - error("f.dirEntry failed"); - } - - cout << F("Creation: "); - f.printFatDate(d.creationDate); - cout << ' '; - f.printFatTime(d.creationTime); - cout << endl; - - cout << F("Modify: "); - f.printFatDate(d.lastWriteDate); - cout <<' '; - f.printFatTime(d.lastWriteTime); - cout << endl; - - cout << F("Access: "); - f.printFatDate(d.lastAccessDate); - cout << endl; -} -//------------------------------------------------------------------------------ -void setup(void) { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - - cout << F("Type any character to start\n"); - while (!Serial.available()); - delay(400); // catch Due reset problem - - // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - // breadboards. use SPI_FULL_SPEED for better performance. - if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - // remove files if they exist - sd.remove("callback.txt"); - sd.remove("default.txt"); - sd.remove("stamp.txt"); - - // create a new file with default timestamps - if (!file.open("default.txt", O_CREAT | O_WRITE)) { - error("open default.txt failed"); - } - cout << F("\nOpen with default times\n"); - printTimestamps(file); - - // close file - file.close(); - /* - * Test the date time callback function. - * - * dateTimeCallback() sets the function - * that is called when a file is created - * or when a file's directory entry is - * modified by sync(). - * - * The callback can be disabled by the call - * SdFile::dateTimeCallbackCancel() - */ - // set date time callback function - SdFile::dateTimeCallback(dateTime); - - // create a new file with callback timestamps - if (!file.open("callback.txt", O_CREAT | O_WRITE)) { - error("open callback.txt failed"); - } - cout << ("\nOpen with callback times\n"); - printTimestamps(file); - - // change call back date - day += 1; - - // must add two to see change since FAT second field is 5-bits - second += 2; - - // modify file by writing a byte - file.write('t'); - - // force dir update - file.sync(); - - cout << F("\nTimes after write\n"); - printTimestamps(file); - - // close file - file.close(); - /* - * Test timestamp() function - * - * Cancel callback so sync will not - * change access/modify timestamp - */ - SdFile::dateTimeCallbackCancel(); - - // create a new file with default timestamps - if (!file.open("stamp.txt", O_CREAT | O_WRITE)) { - error("open stamp.txt failed"); - } - // set creation date time - if (!file.timestamp(T_CREATE, 2014, 11, 10, 1, 2, 3)) { - error("set create time failed"); - } - // set write/modification date time - if (!file.timestamp(T_WRITE, 2014, 11, 11, 4, 5, 6)) { - error("set write time failed"); - } - // set access date - if (!file.timestamp(T_ACCESS, 2014, 11, 12, 7, 8, 9)) { - error("set access time failed"); - } - cout << F("\nTimes after timestamp() calls\n"); - printTimestamps(file); - - file.close(); - cout << F("\nDone\n"); -} - -void loop(void) {} \ No newline at end of file diff --git a/SdFat/examples/bench/bench.ino b/SdFat/examples/bench/bench.ino deleted file mode 100644 index 24657f80..00000000 --- a/SdFat/examples/bench/bench.ino +++ /dev/null @@ -1,185 +0,0 @@ -/* - * This program is a simple binary write/read benchmark. - */ -#include -#include -#include - -// SD chip select pin -const uint8_t chipSelect = SS; - -// Size of read/write. -const size_t BUF_SIZE = 512; - -// File size in MB where MB = 1,000,000 bytes. -const uint32_t FILE_SIZE_MB = 5; - -// Write pass count. -const uint8_t WRITE_COUNT = 10; - -// Read pass count. -const uint8_t READ_COUNT = 5; -//============================================================================== -// End of configuration constants. -//------------------------------------------------------------------------------ -// File size in bytes. -const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB; - -uint8_t buf[BUF_SIZE]; - -// file system -SdFat sd; - -// test file -SdFile file; - -// Serial output stream -ArduinoOutStream cout(Serial); -//------------------------------------------------------------------------------ -// store error strings in flash to save RAM -#define error(s) sd.errorHalt(F(s)) -//------------------------------------------------------------------------------ -void cidDmp() { - cid_t cid; - if (!sd.card()->readCID(&cid)) { - error("readCID failed"); - } - cout << F("\nManufacturer ID: "); - cout << hex << int(cid.mid) << dec << endl; - cout << F("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl; - cout << F("Product: "); - for (uint8_t i = 0; i < 5; i++) { - cout << cid.pnm[i]; - } - cout << F("\nVersion: "); - cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl; - cout << F("Serial number: ") << hex << cid.psn << dec << endl; - cout << F("Manufacturing date: "); - cout << int(cid.mdt_month) << '/'; - cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl; - cout << endl; -} -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - delay(1000); - cout << F("\nUse a freshly formatted SD for best performance.\n"); - - // use uppercase in hex and use 0X base prefix - cout << uppercase << showbase << endl; -} -//------------------------------------------------------------------------------ -void loop() { - float s; - uint32_t t; - uint32_t maxLatency; - uint32_t minLatency; - uint32_t totalLatency; - - // discard any input - while (Serial.read() >= 0) {} - - // 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 - - cout << F("Free RAM: ") << FreeRam() << endl; - - // initialize the SD card at SPI_FULL_SPEED for best performance. - // try SPI_HALF_SPEED if bus errors occur. - if (!sd.begin(chipSelect, SPI_FULL_SPEED)) { - sd.initErrorHalt(); - } - - cout << F("Type is FAT") << int(sd.vol()->fatType()) << endl; - cout << F("Card size: ") << sd.card()->cardSize()*512E-9; - cout << F(" GB (GB = 1E9 bytes)") << endl; - - cidDmp(); - - // open or create file - truncate existing file. - if (!file.open("bench.dat", O_CREAT | O_TRUNC | O_RDWR)) { - error("open failed"); - } - - // fill buf with known data - for (uint16_t i = 0; i < (BUF_SIZE-2); i++) { - buf[i] = 'A' + (i % 26); - } - buf[BUF_SIZE-2] = '\r'; - buf[BUF_SIZE-1] = '\n'; - - cout << F("File size ") << FILE_SIZE_MB << F(" MB\n"); - cout << F("Buffer size ") << BUF_SIZE << F(" bytes\n"); - cout << F("Starting write test, please wait.") << endl << endl; - - // do write test - uint32_t n = FILE_SIZE/sizeof(buf); - cout < m) { - minLatency = m; - } - totalLatency += m; - } - file.sync(); - t = millis() - t; - s = file.fileSize(); - cout << s/t <<',' << maxLatency << ',' << minLatency; - cout << ',' << totalLatency/n << endl; - } - - cout << endl << F("Starting read test, please wait.") << endl; - cout << endl < m) { - minLatency = m; - } - totalLatency += m; - if (buf[BUF_SIZE-1] != '\n') { - error("data check"); - } - } - t = millis() - t; - cout << s/t <<',' << maxLatency << ',' << minLatency; - cout << ',' << totalLatency/n << endl; - } - cout << endl << F("Done") << endl; - file.close(); -} \ No newline at end of file diff --git a/SdFat/examples/directoryFunctions/directoryFunctions.ino b/SdFat/examples/directoryFunctions/directoryFunctions.ino deleted file mode 100644 index 25304ca9..00000000 --- a/SdFat/examples/directoryFunctions/directoryFunctions.ino +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Example use of chdir(), ls(), mkdir(), and rmdir(). - */ -#include -#include -// SD card chip select pin. -const uint8_t SD_CHIP_SELECT = SS; -//------------------------------------------------------------------------------ -// Permit SD to be wiped if ALLOW_WIPE is true. -const bool ALLOW_WIPE = false; - -// File system object. -SdFat sd; - -// Use for file creation in folders. -SdFile file; - -// Create a Serial output stream. -ArduinoOutStream cout(Serial); - -// Buffer for Serial input. -char cinBuf[40]; - -// Create a serial input stream. -ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf)); -//============================================================================== -// Error messages stored in flash. -#define error(msg) sd.errorHalt(F(msg)) -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - delay(1000); - - cout << F("Type any character to start\n"); - // Wait for input line and discard. - cin.readline(); - - // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - // breadboards. use SPI_FULL_SPEED for better performance. - if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - // Check for empty SD. - if (file.openNext(sd.vwd(), O_READ)) { - cout << F("Found files/folders in the root directory.\n"); - if (!ALLOW_WIPE) { - error("SD not empty, use a blank SD or set ALLOW_WIPE true."); - } else { - cout << F("Type: 'WIPE' to delete all SD files.\n"); - char buf[10]; - cin.readline(); - cin.get(buf, sizeof(buf)); - if (cin.fail() || strncmp(buf, "WIPE", 4) || buf[4] >= ' ') { - error("Invalid WIPE input"); - } - file.close(); - if (!sd.vwd()->rmRfStar()) { - error("wipe failed"); - } - cout << F("***SD wiped clean.***\n\n"); - } - } - - // Create a new folder. - if (!sd.mkdir("Folder1")) { - error("Create Folder1 failed"); - } - cout << F("Created Folder1\n"); - - // Create a file in Folder1 using a path. - if (!file.open("Folder1/file1.txt", O_CREAT | O_WRITE)) { - error("create Folder1/file1.txt failed"); - } - file.close(); - cout << F("Created Folder1/file1.txt\n"); - - // Change volume working directory to Folder1. - if (!sd.chdir("Folder1")) { - error("chdir failed for Folder1.\n"); - } - cout << F("chdir to Folder1\n"); - - // Create File2.txt in current directory. - if (!file.open("File2.txt", O_CREAT | O_WRITE)) { - error("create File2.txt failed"); - } - file.close(); - cout << F("Created File2.txt in current directory\n"); - - cout << F("List of files on the SD.\n"); - sd.ls("/", LS_R); - - // Remove files from current directory. - if (!sd.remove("file1.txt") || !sd.remove("File2.txt")) { - error("remove failed"); - } - cout << F("\nfile1.txt and File2.txt removed.\n"); - - // Change current directory to root. - if (!sd.chdir()) { - error("chdir to root failed.\n"); - } - - cout << F("List of files on the SD.\n"); - sd.ls(LS_R); - - // Remove Folder1. - if (!sd.rmdir("Folder1")) { - error("rmdir for Folder1 failed\n"); - } - - cout << F("\nFolder1 removed, SD empty.\n"); - cout << F("Done!\n"); -} -//------------------------------------------------------------------------------ -// Nothing happens in loop. -void loop() {} \ No newline at end of file diff --git a/SdFat/examples/readCSV/readCSV.ino b/SdFat/examples/readCSV/readCSV.ino deleted file mode 100644 index 07985c09..00000000 --- a/SdFat/examples/readCSV/readCSV.ino +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This example reads a simple CSV, comma-separated values, file. - * Each line of the file has a label and three values, a long and two floats. - */ -#include -#include - -// SD chip select pin -const uint8_t chipSelect = SS; - -// file system object -SdFat sd; - -// create Serial stream -ArduinoOutStream cout(Serial); - -char fileName[] = "testfile.csv"; -//------------------------------------------------------------------------------ -// store error strings in flash to save RAM -#define error(s) sd.errorHalt(F(s)) -//------------------------------------------------------------------------------ -// read and print CSV test file -void readFile() { - long lg; - float f1, f2; - char text[10]; - char c1, c2, c3; // space for commas. - - // open input file - ifstream sdin(fileName); - - // check for open error - if (!sdin.is_open()) { - error("open"); - } - - // read until input fails - while (1) { - // Get text field. - sdin.get(text, sizeof(text), ','); - - // Assume EOF if fail. - if (sdin.fail()) { - break; - } - - // Get commas and numbers. - sdin >> c1 >> lg >> c2 >> f1 >> c3 >> f2; - - // Skip CR/LF. - sdin.skipWhite(); - - if (sdin.fail()) { - error("bad input"); - } - - // error in line if not commas - if (c1 != ',' || c2 != ',' || c3 != ',') { - error("comma"); - } - - // print in six character wide columns - cout << text << setw(6) << lg << setw(6) << f1 << setw(6) << f2 << endl; - } - // Error in an input line if file is not at EOF. - if (!sdin.eof()) { - error("readFile"); - } -} -//------------------------------------------------------------------------------ -// write test file -void writeFile() { - - // create or open and truncate output file - ofstream sdout(fileName); - - // write file from string stored in flash - sdout << F( - "Line 1,1,2.3,4.5\n" - "Line 2,6,7.8,9.0\n" - "Line 3,9,8.7,6.5\n" - "Line 4,-4,-3.2,-1\n") << flush; - - // check for any errors - if (!sdout) { - error("writeFile"); - } - - sdout.close(); -} -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - cout << F("Type any character to start\n"); - while (Serial.read() <= 0) {} - delay(400); // catch Due reset problem - - // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - // breadboards. use SPI_FULL_SPEED for better performance - if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - // create test file - writeFile(); - - cout << endl; - - // read and print test - readFile(); - - cout << "\nDone!" << endl; -} -void loop() {} \ No newline at end of file diff --git a/SdFat/examples/rename/rename.ino b/SdFat/examples/rename/rename.ino deleted file mode 100644 index f29a72cf..00000000 --- a/SdFat/examples/rename/rename.ino +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This program demonstrates use of SdFile::rename() - * and SdFat::rename(). - */ -#include -#include - -// SD chip select pin -const uint8_t chipSelect = SS; - -// file system -SdFat sd; - -// Serial print stream -ArduinoOutStream cout(Serial); -//------------------------------------------------------------------------------ -// store error strings in flash to save RAM -#define error(s) sd.errorHalt(F(s)) -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - - cout << F("Insert an empty SD. Type any character to start.") << endl; - while (Serial.read() <= 0) {} - delay(400); // catch Due reset problem - - // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with - // breadboards. use SPI_FULL_SPEED for better performance. - if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { - sd.initErrorHalt(); - } - - // Remove file/dirs from previous run. - if (sd.exists("dir2/DIR3/NAME3.txt")) { - cout << F("Removing /dir2/DIR3/NAME3.txt") << endl; - if (!sd.remove("dir2/DIR3/NAME3.txt") || - !sd.rmdir("dir2/DIR3/") || - !sd.rmdir("dir2/")) { - error("remove/rmdir failed"); - } - } - // create a file and write one line to the file - SdFile file("Name1.txt", O_WRITE | O_CREAT); - if (!file.isOpen()) { - error("Name1.txt"); - } - file.println("A test line for Name1.txt"); - - // rename the file name2.txt and add a line. - // sd.vwd() is the volume working directory, root. - if (!file.rename(sd.vwd(), "name2.txt")) { - error("name2.txt"); - } - file.println("A test line for name2.txt"); - - // list files - cout << F("------") << endl; - sd.ls(LS_R); - - // make a new directory - "Dir1" - if (!sd.mkdir("Dir1")) { - error("Dir1"); - } - - // move file into Dir1, rename it NAME3.txt and add a line - if (!file.rename(sd.vwd(), "Dir1/NAME3.txt")) { - error("NAME3.txt"); - } - file.println("A line for Dir1/NAME3.txt"); - - // list files - cout << F("------") << endl; - sd.ls(LS_R); - - // make directory "dir2" - if (!sd.mkdir("dir2")) { - error("dir2"); - } - - // close file before rename(oldPath, newPath) - file.close(); - - // move Dir1 into dir2 and rename it DIR3 - if (!sd.rename("Dir1", "dir2/DIR3")) { - error("dir2/DIR3"); - } - - // open file for append in new location and add a line - if (!file.open("dir2/DIR3/NAME3.txt", O_WRITE | O_APPEND)) { - error("dir2/DIR3/NAME3.txt"); - } - file.println("A line for dir2/DIR3/NAME3.txt"); - file.close(); - - // list files - cout << F("------") << endl; - sd.ls(LS_R); - - cout << F("Done") << endl; -} -void loop() {} diff --git a/SdFat/utility/ArduinoFiles.h b/SdFat/utility/ArduinoFiles.h deleted file mode 100644 index da8e8cb0..00000000 --- a/SdFat/utility/ArduinoFiles.h +++ /dev/null @@ -1,248 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -/** - * \file - * \brief PrintFile class - */ -#ifndef ArduinoFiles_h -#define ArduinoFiles_h -#include "FatLibConfig.h" -#if ENABLE_ARDUINO_FEATURES -#include "FatFile.h" -#include -//------------------------------------------------------------------------------ -/** Arduino SD.h style flag for open for read. */ -#define FILE_READ O_READ -/** Arduino SD.h style flag for open at EOF for read/write with create. */ -#define FILE_WRITE (O_RDWR | O_CREAT | O_AT_END) -//============================================================================== -/** - * \class PrintFile - * \brief FatFile with Print. - */ -class PrintFile : public FatFile, public Print { - public: - PrintFile() {} - /** Create a file object and open it in the current working directory. - * - * \param[in] path A path for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a - * bitwise-inclusive OR of open flags. see - * FatFile::open(FatFile*, const char*, uint8_t). - */ - PrintFile(const char* path, uint8_t oflag) : FatFile(path, oflag) {} -#if DESTRUCTOR_CLOSES_FILE - ~PrintFile() {} -#endif // DESTRUCTOR_CLOSES_FILE - using FatFile::clearWriteError; - using FatFile::getWriteError; - using FatFile::read; - using FatFile::write; - /** \return number of bytes available from the current position to EOF - * or INT_MAX if more than INT_MAX bytes are available. - */ - int available() { - uint32_t n = FatFile::available(); - return n > INT_MAX ? INT_MAX : n; - } - /** Ensure that any bytes written to the file are saved to the SD card. */ - void flush() { - FatFile::sync(); - } - /** Return the next available byte without consuming it. - * - * \return The byte if no error and not at eof else -1; - */ - int peek() { - return FatFile::peek(); - } - /** Read the next byte from a file. - * - * \return For success return the next byte in the file as an int. - * If an error occurs or end of file is reached return -1. - */ -// int read() { -// return FatFile::read(); -// } - /** Write a byte to a file. Required by the Arduino Print class. - * \param[in] b the byte to be written. - * Use getWriteError to check for errors. - * \return 1 for success and 0 for failure. - */ - size_t write(uint8_t b) { - return FatFile::write(b); - } - /** Write data to an open file. Form required by Print. - * - * \note Data is moved to the cache but may not be written to the - * storage device until sync() is called. - * - * \param[in] buf Pointer to the location of the data to be written. - * - * \param[in] size Number of bytes to write. - * - * \return For success write() returns the number of bytes written, always - * \a nbyte. If an error occurs, write() returns -1. Possible errors - * include write() is called before a file has been opened, write is called - * for a read-only file, device is full, a corrupt file system or an - * I/O error. - */ - size_t write(const uint8_t *buf, size_t size) { - return FatFile::write(buf, size); - } -}; -//============================================================================== -/** - * \class File - * \brief Arduino SD.h style File API - */ -#if ARDUINO_FILE_USES_STREAM -class File : public FatFile, public Stream { -#else // ARDUINO_FILE_USES_STREAM -class File : public FatFile, public Print { -#endif // ARDUINO_FILE_USES_STREAM - public: - File() {} - /** Create a file object and open it in the current working directory. - * - * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a - * bitwise-inclusive OR of open flags. see - * FatFile::open(FatFile*, const char*, uint8_t). - */ - File(const char* path, uint8_t oflag) { - open(path, oflag); - } - using FatFile::clearWriteError; - using FatFile::getWriteError; - using FatFile::read; - using FatFile::write; - /** The parenthesis operator. - * - * \return true if a file is open. - */ - operator bool() { - return isOpen(); - } - /** \return number of bytes available from the current position to EOF - * or INT_MAX if more than INT_MAX bytes are available. - */ - int available() { - uint32_t n = FatFile::available(); - return n > INT_MAX ? INT_MAX : n; - } - /** Ensure that any bytes written to the file are saved to the SD card. */ - void flush() { - FatFile::sync(); - } - /** This function reports if the current file is a directory or not. - * \return true if the file is a directory. - */ - bool isDirectory() { - return isDir(); - } - /** No longer implemented due to Long File Names. - * - * Use getName(char* name, size_t size). - * \return a pointer to replacement suggestion. - */ - const char* name() const { - return "use getName()"; - } - /** Return the next available byte without consuming it. - * - * \return The byte if no error and not at eof else -1; - */ - int peek() { - return FatFile::peek(); - } - /** \return the current file position. */ - uint32_t position() { - return curPosition(); - } - /** Opens the next file or folder in a directory. - * - * \param[in] mode open mode flags. - * \return a File object. - */ - File openNextFile(uint8_t mode = O_READ) { - File tmpFile; - tmpFile.openNext(this, mode); - return tmpFile; - } - /** Read the next byte from a file. - * - * \return For success return the next byte in the file as an int. - * If an error occurs or end of file is reached return -1. - */ - int read() { - return FatFile::read(); - } - /** Rewind a file if it is a directory */ - void rewindDirectory() { - if (isDir()) { - rewind(); - } - } - /** - * Seek to a new position in the file, which must be between - * 0 and the size of the file (inclusive). - * - * \param[in] pos the new file position. - * \return true for success else false. - */ - bool seek(uint32_t pos) { - return seekSet(pos); - } - /** \return the file's size. */ - uint32_t size() { - return fileSize(); - } - /** Write a byte to a file. Required by the Arduino Print class. - * \param[in] b the byte to be written. - * Use getWriteError to check for errors. - * \return 1 for success and 0 for failure. - */ - size_t write(uint8_t b) { - return FatFile::write(b); - } - /** Write data to an open file. Form required by Print. - * - * \note Data is moved to the cache but may not be written to the - * storage device until sync() is called. - * - * \param[in] buf Pointer to the location of the data to be written. - * - * \param[in] size Number of bytes to write. - * - * \return For success write() returns the number of bytes written, always - * \a nbyte. If an error occurs, write() returns -1. Possible errors - * include write() is called before a file has been opened, write is called - * for a read-only file, device is full, a corrupt file system or an - * I/O error. - */ - size_t write(const uint8_t *buf, size_t size) { - return FatFile::write(buf, size); - } -}; -#endif // ENABLE_ARDUINO_FEATURES -#endif // ArduinoFiles_h diff --git a/SdFat/utility/ArduinoStream.h b/SdFat/utility/ArduinoStream.h deleted file mode 100644 index 640af61a..00000000 --- a/SdFat/utility/ArduinoStream.h +++ /dev/null @@ -1,141 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef ArduinoStream_h -#define ArduinoStream_h -/** - * \file - * \brief ArduinoInStream and ArduinoOutStream classes - */ -#include "FatLibConfig.h" -#if ENABLE_ARDUINO_FEATURES -#include -#include "bufstream.h" -//============================================================================== -/** - * \class ArduinoInStream - * \brief Input stream for Arduino Stream objects - */ -class ArduinoInStream : public ibufstream { - public: - /** - * Constructor - * \param[in] hws hardware stream - * \param[in] buf buffer for input line - * \param[in] size size of input buffer - */ - ArduinoInStream(Stream &hws, char* buf, size_t size) { - m_hw = &hws; - m_line = buf; - m_size = size; - } - /** read a line. */ - void readline() { - size_t i = 0; - uint32_t t; - m_line[0] = '\0'; - while (!m_hw->available()) {} - - while (1) { - t = millis(); - while (!m_hw->available()) { - if ((millis() - t) > 10) { - goto done; - } - } - if (i >= (m_size - 1)) { - setstate(failbit); - return; - } - m_line[i++] = m_hw->read(); - m_line[i] = '\0'; - } -done: - init(m_line); - } - - protected: - /** Internal - do not use. - * \param[in] off - * \param[in] way - * \return true/false. - */ - bool seekoff(off_type off, seekdir way) { - return false; - } - /** Internal - do not use. - * \param[in] pos - * \return true/false. - */ - bool seekpos(pos_type pos) { - return false; - } - - private: - char *m_line; - size_t m_size; - Stream* m_hw; -}; -//============================================================================== -/** - * \class ArduinoOutStream - * \brief Output stream for Arduino Print objects - */ -class ArduinoOutStream : public ostream { - public: - /** constructor - * - * \param[in] pr Print object for this ArduinoOutStream. - */ - explicit ArduinoOutStream(Print& pr) : m_pr(&pr) {} - - protected: - /// @cond SHOW_PROTECTED - /** - * Internal do not use - * \param[in] c - */ - void putch(char c) { - if (c == '\n') { - m_pr->write('\r'); - } - m_pr->write(c); - } - void putstr(const char* str) { - m_pr->write(str); - } - bool seekoff(off_type off, seekdir way) { - return false; - } - bool seekpos(pos_type pos) { - return false; - } - bool sync() { - return true; - } - pos_type tellpos() { - return 0; - } - /// @endcond - private: - ArduinoOutStream() {} - Print* m_pr; -}; -#endif // ENABLE_ARDUINO_FEATURES -#endif // ArduinoStream_h diff --git a/SdFat/utility/DigitalPin.h b/SdFat/utility/DigitalPin.h deleted file mode 100644 index b2cac38a..00000000 --- a/SdFat/utility/DigitalPin.h +++ /dev/null @@ -1,702 +0,0 @@ -/* Arduino DigitalIO Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the Arduino DigitalIO Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino DigitalIO Library. If not, see - * . - */ -/** - * @file - * @brief Fast Digital Pin functions - * - * @defgroup digitalPin Fast Pin I/O - * @details Fast Digital I/O functions and template class. - * @{ - */ -#ifndef DigitalPin_h -#define DigitalPin_h -#include -#ifdef __arm__ -#ifdef CORE_TEENSY -//------------------------------------------------------------------------------ -/** read pin value - * @param[in] pin Arduino pin number - * @return value read - */ -static inline __attribute__((always_inline)) -bool fastDigitalRead(uint8_t pin) { - return *portInputRegister(pin); -} -//------------------------------------------------------------------------------ -/** Set pin value - * @param[in] pin Arduino pin number - * @param[in] level value to write - */ -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, bool value) { - if (value) { - *portSetRegister(pin) = 1; - } else { - *portClearRegister(pin) = 1; - } -} -#else // CORE_TEENSY -//------------------------------------------------------------------------------ -/** read pin value - * @param[in] pin Arduino pin number - * @return value read - */ -static inline __attribute__((always_inline)) -bool fastDigitalRead(uint8_t pin) { - return g_APinDescription[pin].pPort->PIO_PDSR & g_APinDescription[pin].ulPin; -} -//------------------------------------------------------------------------------ -/** Set pin value - * @param[in] pin Arduino pin number - * @param[in] level value to write - */ -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, bool value) { - if (value) { - g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin; - } else { - g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin; - } -} -#endif // CORE_TEENSY -//------------------------------------------------------------------------------ -inline void fastDigitalToggle(uint8_t pin) { - fastDigitalWrite(pin, !fastDigitalRead(pin)); -} -//------------------------------------------------------------------------------ -inline void fastPinMode(uint8_t pin, bool mode) { - pinMode(pin, mode); -} -#else // __arm__ -#include -#include -//------------------------------------------------------------------------------ -/** - * @class pin_map_t - * @brief struct for mapping digital pins - */ -struct pin_map_t { - volatile uint8_t* ddr; /**< address of DDR for this pin */ - volatile uint8_t* pin; /**< address of PIN for this pin */ - volatile uint8_t* port; /**< address of PORT for this pin */ - uint8_t bit; /**< bit number for this pin */ -}; -//------------------------------------------------------------------------------ -#if defined(__AVR_ATmega168__)\ -||defined(__AVR_ATmega168P__)\ -||defined(__AVR_ATmega328P__) -// 168 and 328 Arduinos -static const pin_map_t pinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRD, &PIND, &PORTD, 5}, // D5 5 - {&DDRD, &PIND, &PORTD, 6}, // D6 6 - {&DDRD, &PIND, &PORTD, 7}, // D7 7 - {&DDRB, &PINB, &PORTB, 0}, // B0 8 - {&DDRB, &PINB, &PORTB, 1}, // B1 9 - {&DDRB, &PINB, &PORTB, 2}, // B2 10 - {&DDRB, &PINB, &PORTB, 3}, // B3 11 - {&DDRB, &PINB, &PORTB, 4}, // B4 12 - {&DDRB, &PINB, &PORTB, 5}, // B5 13 - {&DDRC, &PINC, &PORTC, 0}, // C0 14 - {&DDRC, &PINC, &PORTC, 1}, // C1 15 - {&DDRC, &PINC, &PORTC, 2}, // C2 16 - {&DDRC, &PINC, &PORTC, 3}, // C3 17 - {&DDRC, &PINC, &PORTC, 4}, // C4 18 - {&DDRC, &PINC, &PORTC, 5} // C5 19 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega1280__)\ -|| defined(__AVR_ATmega2560__) -// Mega -static const pin_map_t pinMap[] = { - {&DDRE, &PINE, &PORTE, 0}, // E0 0 - {&DDRE, &PINE, &PORTE, 1}, // E1 1 - {&DDRE, &PINE, &PORTE, 4}, // E4 2 - {&DDRE, &PINE, &PORTE, 5}, // E5 3 - {&DDRG, &PING, &PORTG, 5}, // G5 4 - {&DDRE, &PINE, &PORTE, 3}, // E3 5 - {&DDRH, &PINH, &PORTH, 3}, // H3 6 - {&DDRH, &PINH, &PORTH, 4}, // H4 7 - {&DDRH, &PINH, &PORTH, 5}, // H5 8 - {&DDRH, &PINH, &PORTH, 6}, // H6 9 - {&DDRB, &PINB, &PORTB, 4}, // B4 10 - {&DDRB, &PINB, &PORTB, 5}, // B5 11 - {&DDRB, &PINB, &PORTB, 6}, // B6 12 - {&DDRB, &PINB, &PORTB, 7}, // B7 13 - {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14 - {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15 - {&DDRH, &PINH, &PORTH, 1}, // H1 16 - {&DDRH, &PINH, &PORTH, 0}, // H0 17 - {&DDRD, &PIND, &PORTD, 3}, // D3 18 - {&DDRD, &PIND, &PORTD, 2}, // D2 19 - {&DDRD, &PIND, &PORTD, 1}, // D1 20 - {&DDRD, &PIND, &PORTD, 0}, // D0 21 - {&DDRA, &PINA, &PORTA, 0}, // A0 22 - {&DDRA, &PINA, &PORTA, 1}, // A1 23 - {&DDRA, &PINA, &PORTA, 2}, // A2 24 - {&DDRA, &PINA, &PORTA, 3}, // A3 25 - {&DDRA, &PINA, &PORTA, 4}, // A4 26 - {&DDRA, &PINA, &PORTA, 5}, // A5 27 - {&DDRA, &PINA, &PORTA, 6}, // A6 28 - {&DDRA, &PINA, &PORTA, 7}, // A7 29 - {&DDRC, &PINC, &PORTC, 7}, // C7 30 - {&DDRC, &PINC, &PORTC, 6}, // C6 31 - {&DDRC, &PINC, &PORTC, 5}, // C5 32 - {&DDRC, &PINC, &PORTC, 4}, // C4 33 - {&DDRC, &PINC, &PORTC, 3}, // C3 34 - {&DDRC, &PINC, &PORTC, 2}, // C2 35 - {&DDRC, &PINC, &PORTC, 1}, // C1 36 - {&DDRC, &PINC, &PORTC, 0}, // C0 37 - {&DDRD, &PIND, &PORTD, 7}, // D7 38 - {&DDRG, &PING, &PORTG, 2}, // G2 39 - {&DDRG, &PING, &PORTG, 1}, // G1 40 - {&DDRG, &PING, &PORTG, 0}, // G0 41 - {&DDRL, &PINL, &PORTL, 7}, // L7 42 - {&DDRL, &PINL, &PORTL, 6}, // L6 43 - {&DDRL, &PINL, &PORTL, 5}, // L5 44 - {&DDRL, &PINL, &PORTL, 4}, // L4 45 - {&DDRL, &PINL, &PORTL, 3}, // L3 46 - {&DDRL, &PINL, &PORTL, 2}, // L2 47 - {&DDRL, &PINL, &PORTL, 1}, // L1 48 - {&DDRL, &PINL, &PORTL, 0}, // L0 49 - {&DDRB, &PINB, &PORTB, 3}, // B3 50 - {&DDRB, &PINB, &PORTB, 2}, // B2 51 - {&DDRB, &PINB, &PORTB, 1}, // B1 52 - {&DDRB, &PINB, &PORTB, 0}, // B0 53 - {&DDRF, &PINF, &PORTF, 0}, // F0 54 - {&DDRF, &PINF, &PORTF, 1}, // F1 55 - {&DDRF, &PINF, &PORTF, 2}, // F2 56 - {&DDRF, &PINF, &PORTF, 3}, // F3 57 - {&DDRF, &PINF, &PORTF, 4}, // F4 58 - {&DDRF, &PINF, &PORTF, 5}, // F5 59 - {&DDRF, &PINF, &PORTF, 6}, // F6 60 - {&DDRF, &PINF, &PORTF, 7}, // F7 61 - {&DDRK, &PINK, &PORTK, 0}, // K0 62 - {&DDRK, &PINK, &PORTK, 1}, // K1 63 - {&DDRK, &PINK, &PORTK, 2}, // K2 64 - {&DDRK, &PINK, &PORTK, 3}, // K3 65 - {&DDRK, &PINK, &PORTK, 4}, // K4 66 - {&DDRK, &PINK, &PORTK, 5}, // K5 67 - {&DDRK, &PINK, &PORTK, 6}, // K6 68 - {&DDRK, &PINK, &PORTK, 7} // K7 69 -}; -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega1284P__)\ -|| defined(__AVR_ATmega1284__)\ -|| defined(__AVR_ATmega644P__)\ -|| defined(__AVR_ATmega644__)\ -|| defined(__AVR_ATmega64__)\ -|| defined(__AVR_ATmega32__)\ -|| defined(__AVR_ATmega324__)\ -|| defined(__AVR_ATmega16__) - -#ifdef PORT_D0 -// Newer version of 1284P -#define DPM(x) {PORT_TO_MODE(PORT_D##x), PORT_TO_INPUT(PORT_D##x), \ - PORT_TO_OUTPUT(PORT_D##x), BIT_D##x} - -static const pin_map_t pinMap[] = { - DPM(0), - DPM(1), - DPM(2), - DPM(3), - DPM(4), - DPM(5), - DPM(6), - DPM(7), - DPM(8), - DPM(9), - DPM(10), - DPM(11), - DPM(12), - DPM(13), - DPM(14), - DPM(15), - DPM(16), - DPM(17), - DPM(18), - DPM(19), - DPM(20), - DPM(21), - DPM(22), - DPM(23), - DPM(24), - DPM(25), - DPM(26), - DPM(27), - DPM(28), - DPM(29), - DPM(30), - DPM(31) -}; - -#undef DPM - -#elif analogInputToDigitalPin(0) == 24 -// Mighty Layout -static const pin_map_t pinMap[] = { - {&DDRB, &PINB, &PORTB, 0}, // B0 0 - {&DDRB, &PINB, &PORTB, 1}, // B1 1 - {&DDRB, &PINB, &PORTB, 2}, // B2 2 - {&DDRB, &PINB, &PORTB, 3}, // B3 3 - {&DDRB, &PINB, &PORTB, 4}, // B4 4 - {&DDRB, &PINB, &PORTB, 5}, // B5 5 - {&DDRB, &PINB, &PORTB, 6}, // B6 6 - {&DDRB, &PINB, &PORTB, 7}, // B7 7 - {&DDRD, &PIND, &PORTD, 0}, // D0 8 - {&DDRD, &PIND, &PORTD, 1}, // D1 9 - {&DDRD, &PIND, &PORTD, 2}, // D2 10 - {&DDRD, &PIND, &PORTD, 3}, // D3 11 - {&DDRD, &PIND, &PORTD, 4}, // D4 12 - {&DDRD, &PIND, &PORTD, 5}, // D5 13 - {&DDRD, &PIND, &PORTD, 6}, // D6 14 - {&DDRD, &PIND, &PORTD, 7}, // D7 15 - {&DDRC, &PINC, &PORTC, 0}, // C0 16 - {&DDRC, &PINC, &PORTC, 1}, // C1 17 - {&DDRC, &PINC, &PORTC, 2}, // C2 18 - {&DDRC, &PINC, &PORTC, 3}, // C3 19 - {&DDRC, &PINC, &PORTC, 4}, // C4 20 - {&DDRC, &PINC, &PORTC, 5}, // C5 21 - {&DDRC, &PINC, &PORTC, 6}, // C6 22 - {&DDRC, &PINC, &PORTC, 7}, // C7 23 - {&DDRA, &PINA, &PORTA, 0}, // A0 24 - {&DDRA, &PINA, &PORTA, 1}, // A1 25 - {&DDRA, &PINA, &PORTA, 2}, // A2 26 - {&DDRA, &PINA, &PORTA, 3}, // A3 27 - {&DDRA, &PINA, &PORTA, 4}, // A4 28 - {&DDRA, &PINA, &PORTA, 5}, // A5 29 - {&DDRA, &PINA, &PORTA, 6}, // A6 30 - {&DDRA, &PINA, &PORTA, 7} // A7 31 -}; -#elif analogInputToDigitalPin(0) == 21 -// Bobuino Layout -static const pin_map_t pinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRB, &PINB, &PORTB, 0}, // B0 4 - {&DDRB, &PINB, &PORTB, 1}, // B1 5 - {&DDRB, &PINB, &PORTB, 2}, // B2 6 - {&DDRB, &PINB, &PORTB, 3}, // B3 7 - {&DDRD, &PIND, &PORTD, 5}, // D5 8 - {&DDRD, &PIND, &PORTD, 6}, // D6 9 - {&DDRB, &PINB, &PORTB, 4}, // B4 10 - {&DDRB, &PINB, &PORTB, 5}, // B5 11 - {&DDRB, &PINB, &PORTB, 6}, // B6 12 - {&DDRB, &PINB, &PORTB, 7}, // B7 13 - {&DDRA, &PINA, &PORTA, 7}, // A7 14 - {&DDRA, &PINA, &PORTA, 6}, // A6 15 - {&DDRA, &PINA, &PORTA, 5}, // A5 16 - {&DDRA, &PINA, &PORTA, 4}, // A4 17 - {&DDRA, &PINA, &PORTA, 3}, // A3 18 - {&DDRA, &PINA, &PORTA, 2}, // A2 19 - {&DDRA, &PINA, &PORTA, 1}, // A1 20 - {&DDRA, &PINA, &PORTA, 0}, // A0 21 - {&DDRC, &PINC, &PORTC, 0}, // C0 22 - {&DDRC, &PINC, &PORTC, 1}, // C1 23 - {&DDRC, &PINC, &PORTC, 2}, // C2 24 - {&DDRC, &PINC, &PORTC, 3}, // C3 25 - {&DDRC, &PINC, &PORTC, 4}, // C4 26 - {&DDRC, &PINC, &PORTC, 5}, // C5 27 - {&DDRC, &PINC, &PORTC, 6}, // C6 28 - {&DDRC, &PINC, &PORTC, 7}, // C7 29 - {&DDRD, &PIND, &PORTD, 4}, // D4 30 - {&DDRD, &PIND, &PORTD, 7} // D7 31 -}; -#elif analogInputToDigitalPin(0) == 31 -// Standard Layout -static const pin_map_t pinMap[] = { - {&DDRB, &PINB, &PORTB, 0}, // B0 0 - {&DDRB, &PINB, &PORTB, 1}, // B1 1 - {&DDRB, &PINB, &PORTB, 2}, // B2 2 - {&DDRB, &PINB, &PORTB, 3}, // B3 3 - {&DDRB, &PINB, &PORTB, 4}, // B4 4 - {&DDRB, &PINB, &PORTB, 5}, // B5 5 - {&DDRB, &PINB, &PORTB, 6}, // B6 6 - {&DDRB, &PINB, &PORTB, 7}, // B7 7 - {&DDRD, &PIND, &PORTD, 0}, // D0 8 - {&DDRD, &PIND, &PORTD, 1}, // D1 9 - {&DDRD, &PIND, &PORTD, 2}, // D2 10 - {&DDRD, &PIND, &PORTD, 3}, // D3 11 - {&DDRD, &PIND, &PORTD, 4}, // D4 12 - {&DDRD, &PIND, &PORTD, 5}, // D5 13 - {&DDRD, &PIND, &PORTD, 6}, // D6 14 - {&DDRD, &PIND, &PORTD, 7}, // D7 15 - {&DDRC, &PINC, &PORTC, 0}, // C0 16 - {&DDRC, &PINC, &PORTC, 1}, // C1 17 - {&DDRC, &PINC, &PORTC, 2}, // C2 18 - {&DDRC, &PINC, &PORTC, 3}, // C3 19 - {&DDRC, &PINC, &PORTC, 4}, // C4 20 - {&DDRC, &PINC, &PORTC, 5}, // C5 21 - {&DDRC, &PINC, &PORTC, 6}, // C6 22 - {&DDRC, &PINC, &PORTC, 7}, // C7 23 - {&DDRA, &PINA, &PORTA, 7}, // A7 24 - {&DDRA, &PINA, &PORTA, 6}, // A6 25 - {&DDRA, &PINA, &PORTA, 5}, // A5 26 - {&DDRA, &PINA, &PORTA, 4}, // A4 27 - {&DDRA, &PINA, &PORTA, 3}, // A3 28 - {&DDRA, &PINA, &PORTA, 2}, // A2 29 - {&DDRA, &PINA, &PORTA, 1}, // A1 30 - {&DDRA, &PINA, &PORTA, 0} // A0 31 -}; -#else // VARIANT_MIGHTY -#error Undefined variant 1284, 644, 324, 64, 32 -#endif // VARIANT_MIGHTY -//------------------------------------------------------------------------------ -#elif defined(__AVR_ATmega32U4__) -#ifdef CORE_TEENSY -// Teensy 2.0 -static const pin_map_t pinMap[] = { - {&DDRB, &PINB, &PORTB, 0}, // B0 0 - {&DDRB, &PINB, &PORTB, 1}, // B1 1 - {&DDRB, &PINB, &PORTB, 2}, // B2 2 - {&DDRB, &PINB, &PORTB, 3}, // B3 3 - {&DDRB, &PINB, &PORTB, 7}, // B7 4 - {&DDRD, &PIND, &PORTD, 0}, // D0 5 - {&DDRD, &PIND, &PORTD, 1}, // D1 6 - {&DDRD, &PIND, &PORTD, 2}, // D2 7 - {&DDRD, &PIND, &PORTD, 3}, // D3 8 - {&DDRC, &PINC, &PORTC, 6}, // C6 9 - {&DDRC, &PINC, &PORTC, 7}, // C7 10 - {&DDRD, &PIND, &PORTD, 6}, // D6 11 - {&DDRD, &PIND, &PORTD, 7}, // D7 12 - {&DDRB, &PINB, &PORTB, 4}, // B4 13 - {&DDRB, &PINB, &PORTB, 5}, // B5 14 - {&DDRB, &PINB, &PORTB, 6}, // B6 15 - {&DDRF, &PINF, &PORTF, 7}, // F7 16 - {&DDRF, &PINF, &PORTF, 6}, // F6 17 - {&DDRF, &PINF, &PORTF, 5}, // F5 18 - {&DDRF, &PINF, &PORTF, 4}, // F4 19 - {&DDRF, &PINF, &PORTF, 1}, // F1 20 - {&DDRF, &PINF, &PORTF, 0}, // F0 21 - {&DDRD, &PIND, &PORTD, 4}, // D4 22 - {&DDRD, &PIND, &PORTD, 5}, // D5 23 - {&DDRE, &PINE, &PORTE, 6} // E6 24 -}; -//------------------------------------------------------------------------------ -#else // CORE_TEENSY -// Leonardo -static const pin_map_t pinMap[] = { - {&DDRD, &PIND, &PORTD, 2}, // D2 0 - {&DDRD, &PIND, &PORTD, 3}, // D3 1 - {&DDRD, &PIND, &PORTD, 1}, // D1 2 - {&DDRD, &PIND, &PORTD, 0}, // D0 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRC, &PINC, &PORTC, 6}, // C6 5 - {&DDRD, &PIND, &PORTD, 7}, // D7 6 - {&DDRE, &PINE, &PORTE, 6}, // E6 7 - {&DDRB, &PINB, &PORTB, 4}, // B4 8 - {&DDRB, &PINB, &PORTB, 5}, // B5 9 - {&DDRB, &PINB, &PORTB, 6}, // B6 10 - {&DDRB, &PINB, &PORTB, 7}, // B7 11 - {&DDRD, &PIND, &PORTD, 6}, // D6 12 - {&DDRC, &PINC, &PORTC, 7}, // C7 13 - {&DDRB, &PINB, &PORTB, 3}, // B3 14 - {&DDRB, &PINB, &PORTB, 1}, // B1 15 - {&DDRB, &PINB, &PORTB, 2}, // B2 16 - {&DDRB, &PINB, &PORTB, 0}, // B0 17 - {&DDRF, &PINF, &PORTF, 7}, // F7 18 - {&DDRF, &PINF, &PORTF, 6}, // F6 19 - {&DDRF, &PINF, &PORTF, 5}, // F5 20 - {&DDRF, &PINF, &PORTF, 4}, // F4 21 - {&DDRF, &PINF, &PORTF, 1}, // F1 22 - {&DDRF, &PINF, &PORTF, 0}, // F0 23 - {&DDRD, &PIND, &PORTD, 4}, // D4 24 - {&DDRD, &PIND, &PORTD, 7}, // D7 25 - {&DDRB, &PINB, &PORTB, 4}, // B4 26 - {&DDRB, &PINB, &PORTB, 5}, // B5 27 - {&DDRB, &PINB, &PORTB, 6}, // B6 28 - {&DDRD, &PIND, &PORTD, 6} // D6 29 -}; -#endif // CORE_TEENSY -//------------------------------------------------------------------------------ -#elif defined(__AVR_AT90USB646__)\ -|| defined(__AVR_AT90USB1286__) -// Teensy++ 1.0 & 2.0 -static const pin_map_t pinMap[] = { - {&DDRD, &PIND, &PORTD, 0}, // D0 0 - {&DDRD, &PIND, &PORTD, 1}, // D1 1 - {&DDRD, &PIND, &PORTD, 2}, // D2 2 - {&DDRD, &PIND, &PORTD, 3}, // D3 3 - {&DDRD, &PIND, &PORTD, 4}, // D4 4 - {&DDRD, &PIND, &PORTD, 5}, // D5 5 - {&DDRD, &PIND, &PORTD, 6}, // D6 6 - {&DDRD, &PIND, &PORTD, 7}, // D7 7 - {&DDRE, &PINE, &PORTE, 0}, // E0 8 - {&DDRE, &PINE, &PORTE, 1}, // E1 9 - {&DDRC, &PINC, &PORTC, 0}, // C0 10 - {&DDRC, &PINC, &PORTC, 1}, // C1 11 - {&DDRC, &PINC, &PORTC, 2}, // C2 12 - {&DDRC, &PINC, &PORTC, 3}, // C3 13 - {&DDRC, &PINC, &PORTC, 4}, // C4 14 - {&DDRC, &PINC, &PORTC, 5}, // C5 15 - {&DDRC, &PINC, &PORTC, 6}, // C6 16 - {&DDRC, &PINC, &PORTC, 7}, // C7 17 - {&DDRE, &PINE, &PORTE, 6}, // E6 18 - {&DDRE, &PINE, &PORTE, 7}, // E7 19 - {&DDRB, &PINB, &PORTB, 0}, // B0 20 - {&DDRB, &PINB, &PORTB, 1}, // B1 21 - {&DDRB, &PINB, &PORTB, 2}, // B2 22 - {&DDRB, &PINB, &PORTB, 3}, // B3 23 - {&DDRB, &PINB, &PORTB, 4}, // B4 24 - {&DDRB, &PINB, &PORTB, 5}, // B5 25 - {&DDRB, &PINB, &PORTB, 6}, // B6 26 - {&DDRB, &PINB, &PORTB, 7}, // B7 27 - {&DDRA, &PINA, &PORTA, 0}, // A0 28 - {&DDRA, &PINA, &PORTA, 1}, // A1 29 - {&DDRA, &PINA, &PORTA, 2}, // A2 30 - {&DDRA, &PINA, &PORTA, 3}, // A3 31 - {&DDRA, &PINA, &PORTA, 4}, // A4 32 - {&DDRA, &PINA, &PORTA, 5}, // A5 33 - {&DDRA, &PINA, &PORTA, 6}, // A6 34 - {&DDRA, &PINA, &PORTA, 7}, // A7 35 - {&DDRE, &PINE, &PORTE, 4}, // E4 36 - {&DDRE, &PINE, &PORTE, 5}, // E5 37 - {&DDRF, &PINF, &PORTF, 0}, // F0 38 - {&DDRF, &PINF, &PORTF, 1}, // F1 39 - {&DDRF, &PINF, &PORTF, 2}, // F2 40 - {&DDRF, &PINF, &PORTF, 3}, // F3 41 - {&DDRF, &PINF, &PORTF, 4}, // F4 42 - {&DDRF, &PINF, &PORTF, 5}, // F5 43 - {&DDRF, &PINF, &PORTF, 6}, // F6 44 - {&DDRF, &PINF, &PORTF, 7} // F7 45 -}; -//------------------------------------------------------------------------------ -#else // CPU type -#error unknown CPU type -#endif // CPU type -//------------------------------------------------------------------------------ -/** count of pins */ -static const uint8_t digitalPinCount = sizeof(pinMap)/sizeof(pin_map_t); -//============================================================================== -/** generate bad pin number error */ -void badPinNumber(void) -__attribute__((error("Pin number is too large or not a constant"))); -//------------------------------------------------------------------------------ -/** Check for valid pin number - * @param[in] pin Number of pin to be checked. - */ -static inline __attribute__((always_inline)) -void badPinCheck(uint8_t pin) { - if (!__builtin_constant_p(pin) || pin >= digitalPinCount) { - badPinNumber(); - } -} -//------------------------------------------------------------------------------ -/** fast write helper - * @param[in] address I/O register address - * @param[in] bit bit number to write - * @param[in] level value for bit - */ -static inline __attribute__((always_inline)) -void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) { - uint8_t oldSREG; - if (address > reinterpret_cast(0X5F)) { - oldSREG = SREG; - cli(); - } - if (level) { - *address |= 1 << bit; - } else { - *address &= ~(1 << bit); - } - if (address > reinterpret_cast(0X5F)) { - SREG = oldSREG; - } -} -//------------------------------------------------------------------------------ -/** read pin value - * @param[in] pin Arduino pin number - * @return value read - */ -static inline __attribute__((always_inline)) -bool fastDigitalRead(uint8_t pin) { - badPinCheck(pin); - return (*pinMap[pin].pin >> pinMap[pin].bit) & 1; -} -//------------------------------------------------------------------------------ -/** toggle a pin - * @param[in] pin Arduino pin number - * - * If the pin is in output mode toggle the pin level. - * If the pin is in input mode toggle the state of the 20K pull-up. - */ -static inline __attribute__((always_inline)) -void fastDigitalToggle(uint8_t pin) { - badPinCheck(pin); - if (pinMap[pin].pin > reinterpret_cast(0X5F)) { - // must write bit to high address port - *pinMap[pin].pin = 1 << pinMap[pin].bit; - } else { - // will compile to sbi and PIN register will not be read. - *pinMap[pin].pin |= 1 << pinMap[pin].bit; - } -} -//------------------------------------------------------------------------------ -/** Set pin value - * @param[in] pin Arduino pin number - * @param[in] level value to write - */ -static inline __attribute__((always_inline)) -void fastDigitalWrite(uint8_t pin, bool level) { - badPinCheck(pin); - fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level); -} -//------------------------------------------------------------------------------ -/** set pin mode - * @param[in] pin Arduino pin number - * @param[in] mode if true set output mode else input mode - * - * fastPinMode does not enable or disable the 20K pull-up for input mode. - */ -static inline __attribute__((always_inline)) -void fastPinMode(uint8_t pin, bool mode) { - badPinCheck(pin); - fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode); -} - -#endif // __arm__ -//------------------------------------------------------------------------------ -/** set pin configuration - * @param[in] pin Arduino pin number - * @param[in] mode If true set output mode else input mode - * @param[in] level If mode is output, set level high/low. - * If mode is input, enable or disable the pin's 20K pull-up. - */ -static inline __attribute__((always_inline)) -void fastPinConfig(uint8_t pin, bool mode, bool level) { - fastPinMode(pin, mode); - fastDigitalWrite(pin, level); -} -//============================================================================== -/** - * @class DigitalPin - * @brief Fast digital port I/O - */ -template -class DigitalPin { - public: - //---------------------------------------------------------------------------- - /** Constructor */ - DigitalPin() {} - //---------------------------------------------------------------------------- - /** Constructor - * @param[in] pinMode if true set output mode else input mode. - */ - explicit DigitalPin(bool pinMode) { - mode(pinMode); - } - //---------------------------------------------------------------------------- - /** Constructor - * @param[in] mode If true set output mode else input mode - * @param[in] level If mode is output, set level high/low. - * If mode is input, enable or disable the pin's 20K pull-up. - */ - DigitalPin(bool mode, bool level) { - config(mode, level); - } - //---------------------------------------------------------------------------- - /** Asignment operator - * @param[in] value If true set the pin's level high else set the - * pin's level low. - * - * @return This DigitalPin instance. - */ - inline DigitalPin & operator = (bool value) __attribute__((always_inline)) { - write(value); - return *this; - } - //---------------------------------------------------------------------------- - /** Parenthesis operator - * @return Pin's level - */ - inline operator bool() const __attribute__((always_inline)) { - return read(); - } - //---------------------------------------------------------------------------- - /** set pin configuration - * @param[in] mode If true set output mode else input mode - * @param[in] level If mode is output, set level high/low. If mode - * is input, enable or disable the pin's 20K pull-up. - */ - inline __attribute__((always_inline)) - void config(bool mode, bool level) { - fastPinConfig(PinNumber, mode, level); - } - //---------------------------------------------------------------------------- - /** - * Set pin level high if output mode or enable 20K pull-up if input mode. - */ - inline __attribute__((always_inline)) - void high() { - write(true); - } - //---------------------------------------------------------------------------- - /** - * Set pin level low if output mode or disable 20K pull-up if input mode. - */ - inline __attribute__((always_inline)) - void low() { - write(false); - } - //---------------------------------------------------------------------------- - /** - * Set pin mode - * @param[in] pinMode if true set output mode else input mode. - * - * mode() does not enable or disable the 20K pull-up for input mode. - */ - inline __attribute__((always_inline)) - void mode(bool pinMode) { - fastPinMode(PinNumber, pinMode); - } - //---------------------------------------------------------------------------- - /** @return Pin's level */ - inline __attribute__((always_inline)) - bool read() const { - return fastDigitalRead(PinNumber); - } - //---------------------------------------------------------------------------- - /** toggle a pin - * - * If the pin is in output mode toggle the pin's level. - * If the pin is in input mode toggle the state of the 20K pull-up. - */ - inline __attribute__((always_inline)) - void toggle() { - fastDigitalToggle(PinNumber); - } - //---------------------------------------------------------------------------- - /** Write the pin's level. - * @param[in] value If true set the pin's level high else set the - * pin's level low. - */ - inline __attribute__((always_inline)) - void write(bool value) { - fastDigitalWrite(PinNumber, value); - } -}; -#endif // DigitalPin_h -/** @} */ diff --git a/SdFat/utility/FatApiConstants.h b/SdFat/utility/FatApiConstants.h deleted file mode 100644 index 9bc5912f..00000000 --- a/SdFat/utility/FatApiConstants.h +++ /dev/null @@ -1,67 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef FatApiConstants_h -#define FatApiConstants_h -//------------------------------------------------------------------------------ -// use the gnu style oflag in open() -/** open() oflag for reading */ -uint8_t const O_READ = 0X01; -/** open() oflag - same as O_IN */ -uint8_t const O_RDONLY = O_READ; -/** open() oflag for write */ -uint8_t const O_WRITE = 0X02; -/** open() oflag - same as O_WRITE */ -uint8_t const O_WRONLY = O_WRITE; -/** open() oflag for reading and writing */ -uint8_t const O_RDWR = (O_READ | O_WRITE); -/** open() oflag mask for access modes */ -uint8_t const O_ACCMODE = (O_READ | O_WRITE); -/** The file offset shall be set to the end of the file prior to each write. */ -uint8_t const O_APPEND = 0X04; -/** synchronous writes - call sync() after each write */ -uint8_t const O_SYNC = 0X08; -/** truncate the file to zero length */ -uint8_t const O_TRUNC = 0X10; -/** set the initial position at the end of the file */ -uint8_t const O_AT_END = 0X20; -/** create the file if nonexistent */ -uint8_t const O_CREAT = 0X40; -/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ -uint8_t const O_EXCL = 0X80; - -// FatFile class static and const definitions -// flags for ls() -/** ls() flag for list all files including hidden. */ -uint8_t const LS_A = 1; -/** ls() flag to print modify. date */ -uint8_t const LS_DATE = 2; -/** ls() flag to print file size. */ -uint8_t const LS_SIZE = 4; -/** ls() flag for recursive list of subdirectories */ -uint8_t const LS_R = 8; - -// flags for timestamp -/** set the file's last access date */ -uint8_t const T_ACCESS = 1; -/** set the file's creation date and time */ -uint8_t const T_CREATE = 2; -/** Set the file's write date and time */ -uint8_t const T_WRITE = 4; -#endif // FatApiConstants_h diff --git a/SdFat/utility/FatFile.cpp b/SdFat/utility/FatFile.cpp deleted file mode 100644 index e013dd6b..00000000 --- a/SdFat/utility/FatFile.cpp +++ /dev/null @@ -1,1494 +0,0 @@ -/* FatLib Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#include "FatFile.h" -#include "FatFileSystem.h" -//------------------------------------------------------------------------------ -// Pointer to cwd directory. -FatFile* FatFile::m_cwd = 0; -// Callback function for date/time. -void (*FatFile::m_dateTime)(uint16_t* date, uint16_t* time) = 0; -//------------------------------------------------------------------------------ -// Add a cluster to a file. -bool FatFile::addCluster() { - m_flags |= F_FILE_DIR_DIRTY; - return m_vol->allocateCluster(m_curCluster, &m_curCluster); -} -//------------------------------------------------------------------------------ -// Add a cluster to a directory file and zero the cluster. -// Return with first block of cluster in the cache. -bool FatFile::addDirCluster() { - uint32_t block; - cache_t* pc; - - if (isRootFixed()) { - DBG_FAIL_MACRO; - goto fail; - } - // max folder size - if (m_curPosition >= 512UL*4095) { - DBG_FAIL_MACRO; - goto fail; - } - if (!addCluster()) { - DBG_FAIL_MACRO; - goto fail; - } - block = m_vol->clusterStartBlock(m_curCluster); - pc = m_vol->cacheFetchData(block, FatCache::CACHE_RESERVE_FOR_WRITE); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - memset(pc, 0, 512); - // zero rest of clusters - for (uint8_t i = 1; i < m_vol->blocksPerCluster(); i++) { - if (!m_vol->writeBlock(block + i, pc->data)) { - DBG_FAIL_MACRO; - goto fail; - } - } - // Set position to EOF to avoid inconsistent curCluster/curPosition. - m_curPosition += 512UL*m_vol->blocksPerCluster(); - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -// cache a file's directory entry -// return pointer to cached entry or null for failure -dir_t* FatFile::cacheDirEntry(uint8_t action) { - cache_t* pc; - pc = m_vol->cacheFetchData(m_dirBlock, action); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - return pc->dir + (m_dirIndex & 0XF); - -fail: - return 0; -} -//------------------------------------------------------------------------------ -bool FatFile::close() { - bool rtn = sync(); - m_attr = FILE_ATTR_CLOSED; - return rtn; -} -//------------------------------------------------------------------------------ -bool FatFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { - // error if no blocks - if (m_firstCluster == 0) { - DBG_FAIL_MACRO; - goto fail; - } - for (uint32_t c = m_firstCluster; ; c++) { - uint32_t next; - int8_t fg = m_vol->fatGet(c, &next); - if (fg < 0) { - DBG_FAIL_MACRO; - goto fail; - } - // check for contiguous - if (fg == 0 || next != (c + 1)) { - // error if not end of chain - if (fg) { - DBG_FAIL_MACRO; - goto fail; - } - *bgnBlock = m_vol->clusterStartBlock(m_firstCluster); - *endBlock = m_vol->clusterStartBlock(c) - + m_vol->blocksPerCluster() - 1; - return true; - } - } - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::createContiguous(FatFile* dirFile, - const char* path, uint32_t size) { - uint32_t count; - // don't allow zero length file - if (size == 0) { - DBG_FAIL_MACRO; - goto fail; - } - if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) { - DBG_FAIL_MACRO; - goto fail; - } - // calculate number of clusters needed - count = ((size - 1) >> (m_vol->clusterSizeShift() + 9)) + 1; - - // allocate clusters - if (!m_vol->allocContiguous(count, &m_firstCluster)) { - remove(); - DBG_FAIL_MACRO; - goto fail; - } - m_fileSize = size; - - // insure sync() will update dir entry - m_flags |= F_FILE_DIR_DIRTY; - - return sync(); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::dirEntry(dir_t* dst) { - dir_t* dir; - // Make sure fields on device are correct. - if (!sync()) { - DBG_FAIL_MACRO; - goto fail; - } - // read entry - dir = cacheDirEntry(FatCache::CACHE_FOR_READ); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // copy to caller's struct - memcpy(dst, dir, sizeof(dir_t)); - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -uint8_t FatFile::dirName(const dir_t* dir, char* name) { - uint8_t j = 0; - uint8_t lcBit = DIR_NT_LC_BASE; - for (uint8_t i = 0; i < 11; i++) { - if (dir->name[i] == ' ') { - continue; - } - if (i == 8) { - // Position bit for extension. - lcBit = DIR_NT_LC_EXT; - name[j++] = '.'; - } - char c = dir->name[i]; - if ('A' <= c && c <= 'Z' && (lcBit & dir->reservedNT)) { - c += 'a' - 'A'; - } - name[j++] = c; - } - name[j] = 0; - return j; -} - -//------------------------------------------------------------------------------ -uint32_t FatFile::dirSize() { - int8_t fg; - if (!isDir()) { - return 0; - } - if (isRootFixed()) { - return 32*m_vol->rootDirEntryCount(); - } - uint16_t n = 0; - uint32_t c = isRoot32() ? m_vol->rootDirStart() : m_firstCluster; - do { - fg = m_vol->fatGet(c, &c); - if (fg < 0 || n > 4095) { - return 0; - } - n += m_vol->blocksPerCluster(); - } while (fg); - return 512UL*n; -} -//------------------------------------------------------------------------------ -int16_t FatFile::fgets(char* str, int16_t num, char* delim) { - char ch; - int16_t n = 0; - int16_t r = -1; - while ((n + 1) < num && (r = read(&ch, 1)) == 1) { - // delete CR - if (ch == '\r') { - continue; - } - str[n++] = ch; - if (!delim) { - if (ch == '\n') { - break; - } - } else { - if (strchr(delim, ch)) { - break; - } - } - } - if (r < 0) { - // read error - return -1; - } - str[n] = '\0'; - return n; -} -//------------------------------------------------------------------------------ -void FatFile::getpos(FatPos_t* pos) { - pos->position = m_curPosition; - pos->cluster = m_curCluster; -} -//------------------------------------------------------------------------------ -bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) { - fname_t fname; - FatFile tmpDir; - - if (isOpen() || !parent->isDir()) { - DBG_FAIL_MACRO; - goto fail; - } - if (isDirSeparator(*path)) { - while (isDirSeparator(*path)) { - path++; - } - if (!tmpDir.openRoot(parent->m_vol)) { - DBG_FAIL_MACRO; - goto fail; - } - parent = &tmpDir; - } - while (1) { - if (!parsePathName(path, &fname, &path)) { - DBG_FAIL_MACRO; - goto fail; - } - if (!*path) { - break; - } - if (!open(parent, &fname, O_READ)) { - if (!pFlag || !mkdir(parent, &fname)) { - DBG_FAIL_MACRO; - goto fail; - } - } - tmpDir = *this; - parent = &tmpDir; - close(); - } - return mkdir(parent, &fname); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::mkdir(FatFile* parent, fname_t* fname) { - uint32_t block; - dir_t dot; - dir_t* dir; - cache_t* pc; - - if (!parent->isDir()) { - DBG_FAIL_MACRO; - goto fail; - } - // create a normal file - if (!open(parent, fname, O_CREAT | O_EXCL | O_RDWR)) { - DBG_FAIL_MACRO; - goto fail; - } - // convert file to directory - m_flags = O_READ; - m_attr = FILE_ATTR_SUBDIR; - - // allocate and zero first cluster - if (!addDirCluster()) { - DBG_FAIL_MACRO; - goto fail; - } - m_firstCluster = m_curCluster; - // Set to start of dir - rewind(); - // force entry to device - if (!sync()) { - DBG_FAIL_MACRO; - goto fail; - } - // cache entry - should already be in cache due to sync() call - dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // change directory entry attribute - dir->attributes = DIR_ATT_DIRECTORY; - - // make entry for '.' - memcpy(&dot, dir, sizeof(dot)); - dot.name[0] = '.'; - for (uint8_t i = 1; i < 11; i++) { - dot.name[i] = ' '; - } - - // cache block for '.' and '..' - block = m_vol->clusterStartBlock(m_firstCluster); - pc = m_vol->cacheFetchData(block, FatCache::CACHE_FOR_WRITE); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - // copy '.' to block - memcpy(&pc->dir[0], &dot, sizeof(dot)); - // make entry for '..' - dot.name[1] = '.'; - dot.firstClusterLow = parent->m_firstCluster & 0XFFFF; - dot.firstClusterHigh = parent->m_firstCluster >> 16; - // copy '..' to block - memcpy(&pc->dir[1], &dot, sizeof(dot)); - // write first block - return m_vol->cacheSync(); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::open(FatFileSystem* fs, const char* path, uint8_t oflag) { - return open(fs->vwd(), path, oflag); -} -//------------------------------------------------------------------------------ -bool FatFile::open(FatFile* dirFile, const char* path, uint8_t oflag) { - FatFile tmpDir; - fname_t fname; - - // error if already open - if (isOpen() || !dirFile->isDir()) { - DBG_FAIL_MACRO; - goto fail; - } - if (isDirSeparator(*path)) { - while (isDirSeparator(*path)) { - path++; - } - if (*path == 0) { - return openRoot(dirFile->m_vol); - } - if (!tmpDir.openRoot(dirFile->m_vol)) { - DBG_FAIL_MACRO; - goto fail; - } - dirFile = &tmpDir; - } - while (1) { - if (!parsePathName(path, &fname, &path)) { - DBG_FAIL_MACRO; - goto fail; - } - if (*path == 0) { - break; - } - if (!open(dirFile, &fname, O_READ)) { - DBG_FAIL_MACRO; - goto fail; - } - tmpDir = *this; - dirFile = &tmpDir; - close(); - } - return open(dirFile, &fname, oflag); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::open(FatFile* dirFile, uint16_t index, uint8_t oflag) { - uint8_t chksum = 0; - uint8_t lfnOrd = 0; - dir_t* dir; - ldir_t*ldir; - - // Error if already open. - if (isOpen() || !dirFile->isDir()) { - DBG_FAIL_MACRO; - goto fail; - } - // Don't open existing file if O_EXCL - user call error. - if (oflag & O_EXCL) { - DBG_FAIL_MACRO; - goto fail; - } - if (index) { - // Check for LFN. - if (!dirFile->seekSet(32UL*(index -1))) { - DBG_FAIL_MACRO; - goto fail; - } - ldir = reinterpret_cast(dirFile->readDirCache()); - if (!ldir) { - DBG_FAIL_MACRO; - goto fail; - } - if (ldir->attr == DIR_ATT_LONG_NAME) { - if (1 == (ldir->ord & 0X1F)) { - chksum = ldir->chksum; - // Use largest possible number. - lfnOrd = index > 20 ? 20 : index; - } - } - } else { - dirFile->rewind(); - } - // read entry into cache - dir = dirFile->readDirCache(); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // error if empty slot or '.' or '..' - if (dir->name[0] == DIR_NAME_DELETED || - dir->name[0] == DIR_NAME_FREE || - dir->name[0] == '.') { - DBG_FAIL_MACRO; - goto fail; - } - if (lfnOrd && chksum != lfnChecksum(dir->name)) { - DBG_FAIL_MACRO; - goto fail; - } - // open cached entry - if (!openCachedEntry(dirFile, index, oflag, lfnOrd)) { - DBG_FAIL_MACRO; - goto fail; - } - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -// open a cached directory entry. - -bool FatFile::openCachedEntry(FatFile* dirFile, uint16_t dirIndex, - uint8_t oflag, uint8_t lfnOrd) { - uint32_t firstCluster; - memset(this, 0, sizeof(FatFile)); - // location of entry in cache - m_vol = dirFile->m_vol; - m_dirIndex = dirIndex; - m_dirCluster = dirFile->m_firstCluster; - dir_t* dir = &m_vol->cacheAddress()->dir[0XF & dirIndex]; - - // Must be file or subdirectory. - if (!DIR_IS_FILE_OR_SUBDIR(dir)) { - DBG_FAIL_MACRO; - goto fail; - } - m_attr = dir->attributes & FILE_ATTR_COPY; - if (DIR_IS_FILE(dir)) { - m_attr |= FILE_ATTR_FILE; - } - m_lfnOrd = lfnOrd; - // Write, truncate, or at end is an error for a directory or read-only file. - if (oflag & (O_WRITE | O_TRUNC | O_AT_END)) { - if (isSubDir() || isReadOnly()) { - DBG_FAIL_MACRO; - goto fail; - } - } - // save open flags for read/write - m_flags = oflag & F_OFLAG; - - m_dirBlock = m_vol->cacheBlockNumber(); - - // copy first cluster number for directory fields - firstCluster = ((uint32_t)dir->firstClusterHigh << 16) - | dir->firstClusterLow; - - if (oflag & O_TRUNC) { - if (firstCluster && !m_vol->freeChain(firstCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - // need to update directory entry - m_flags |= F_FILE_DIR_DIRTY; - } else { - m_firstCluster = firstCluster; - m_fileSize = dir->fileSize; - } - if ((oflag & O_AT_END) && !seekSet(m_fileSize)) { - DBG_FAIL_MACRO; - goto fail; - } - return true; - -fail: - m_attr = FILE_ATTR_CLOSED; - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::openNext(FatFile* dirFile, uint8_t oflag) { - uint8_t chksum = 0; - ldir_t* ldir; - uint8_t lfnOrd = 0; - uint16_t index; - - // Check for not open and valid directory.. - if (isOpen() || !dirFile->isDir() || (dirFile->curPosition() & 0X1F)) { - DBG_FAIL_MACRO; - goto fail; - } - while (1) { - // read entry into cache - index = dirFile->curPosition()/32; - dir_t* dir = dirFile->readDirCache(); - if (!dir) { - if (dirFile->getError()) { - DBG_FAIL_MACRO; - } - goto fail; - } - // done if last entry - if (dir->name[0] == DIR_NAME_FREE) { - goto fail; - } - // skip empty slot or '.' or '..' - if (dir->name[0] == '.' || dir->name[0] == DIR_NAME_DELETED) { - lfnOrd = 0; - } else if (DIR_IS_FILE_OR_SUBDIR(dir)) { - if (lfnOrd && chksum != lfnChecksum(dir->name)) { - DBG_FAIL_MACRO; - goto fail; - } - if (!openCachedEntry(dirFile, index, oflag, lfnOrd)) { - DBG_FAIL_MACRO; - goto fail; - } - return true; - } else if (DIR_IS_LONG_NAME(dir)) { - ldir = reinterpret_cast(dir); - if (ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) { - lfnOrd = ldir->ord & 0X1F; - chksum = ldir->chksum; - } - } else { - lfnOrd = 0; - } - } - -fail: - return false; -} -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//------------------------------------------------------------------------------ -/** Open a file's parent directory. - * - * \param[in] file Parent of this directory will be opened. Must not be root. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ -bool FatFile::openParent(FatFile* dirFile) { - FatFile dotdot; - uint32_t lbn; - dir_t* dir; - uint32_t ddc; - cache_t* cb; - - if (isOpen() || !dirFile->isOpen()) { - goto fail; - } - if (dirFile->m_dirCluster == 0) { - return openRoot(dirFile->m_vol); - } - lbn = dirFile->m_vol->clusterStartBlock(dirFile->m_dirCluster); - cb = dirFile->m_vol->cacheFetchData(lbn, FatCache::CACHE_FOR_READ); - if (!cb) { - DBG_FAIL_MACRO; - goto fail; - } - // Point to dir entery for .. - dir = cb->dir + 1; - ddc = dir->firstClusterLow | ((uint32_t)dir->firstClusterHigh << 16); - if (ddc == 0) { - if (!dotdot.openRoot(dirFile->m_vol)) { - DBG_FAIL_MACRO; - goto fail; - } - } else { - memset(&dotdot, 0, sizeof(FatFile)); - dotdot.m_attr = FILE_ATTR_SUBDIR; - dotdot.m_flags = O_READ; - dotdot.m_vol = dirFile->m_vol; - dotdot.m_firstCluster = ddc; - } - uint32_t di; - do { - di = dotdot.curPosition()/32; - dir = dotdot.readDirCache(); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - ddc = dir->firstClusterLow | ((uint32_t)dir->firstClusterHigh << 16); - } while (ddc != dirFile->m_dirCluster); - return open(&dotdot, di, O_READ); - -fail: - return false; -} -#endif // DOXYGEN_SHOULD_SKIP_THIS -//------------------------------------------------------------------------------ -bool FatFile::openRoot(FatVolume* vol) { - // error if file is already open - if (isOpen()) { - DBG_FAIL_MACRO; - goto fail; - } - memset(this, 0, sizeof(FatFile)); - - m_vol = vol; - switch (vol->fatType()) { -#if FAT12_SUPPORT - case 12: -#endif // FAT12_SUPPORT - case 16: - m_attr = FILE_ATTR_ROOT_FIXED; - break; - - case 32: - m_attr = FILE_ATTR_ROOT32; - break; - - default: - DBG_FAIL_MACRO; - goto fail; - } - // read only - m_flags = O_READ; - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -int FatFile::peek() { - FatPos_t pos; - getpos(&pos); - int c = read(); - if (c >= 0) { - setpos(&pos); - } - return c; -} -//------------------------------------------------------------------------------ -int FatFile::read(void* buf, size_t nbyte) { - int8_t fg; - uint8_t blockOfCluster = 0; - uint8_t* dst = reinterpret_cast(buf); - uint16_t offset; - size_t toRead; - uint32_t block; // raw device block number - cache_t* pc; - - // error if not open for read - if (!isOpen() || !(m_flags & O_READ)) { - DBG_FAIL_MACRO; - goto fail; - } - - if (isFile()) { - uint32_t tmp32 = m_fileSize - m_curPosition; - if (nbyte >= tmp32) { - nbyte = tmp32; - } - } else if (isRootFixed()) { - uint16_t tmp16 = 32*m_vol->m_rootDirEntryCount - (uint16_t)m_curPosition; - if (nbyte > tmp16) { - nbyte = tmp16; - } - } - toRead = nbyte; - while (toRead) { - size_t n; - offset = m_curPosition & 0X1FF; // offset in block - if (isRootFixed()) { - block = m_vol->rootDirStart() + (m_curPosition >> 9); - } else { - blockOfCluster = m_vol->blockOfCluster(m_curPosition); - if (offset == 0 && blockOfCluster == 0) { - // start of new cluster - if (m_curPosition == 0) { - // use first cluster in file - m_curCluster = isRoot32() ? m_vol->rootDirStart() : m_firstCluster; - } else { - // get next cluster from FAT - fg = m_vol->fatGet(m_curCluster, &m_curCluster); - if (fg < 0) { - DBG_FAIL_MACRO; - goto fail; - } - if (fg == 0) { - if (isDir()) { - break; - } - DBG_FAIL_MACRO; - goto fail; - } - } - } - block = m_vol->clusterStartBlock(m_curCluster) + blockOfCluster; - } - if (offset != 0 || toRead < 512 || block == m_vol->cacheBlockNumber()) { - // amount to be read from current block - n = 512 - offset; - if (n > toRead) { - n = toRead; - } - // read block to cache and copy data to caller - pc = m_vol->cacheFetchData(block, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - uint8_t* src = pc->data + offset; - memcpy(dst, src, n); -#if USE_MULTI_BLOCK_IO - } else if (toRead >= 1024) { - uint8_t nb = toRead >> 9; - if (!isRootFixed()) { - uint8_t mb = m_vol->blocksPerCluster() - blockOfCluster; - if (mb < nb) { - nb = mb; - } - } - n = 512*nb; - if (m_vol->cacheBlockNumber() <= block - && block < (m_vol->cacheBlockNumber() + nb)) { - // flush cache if a block is in the cache - if (!m_vol->cacheSync()) { - DBG_FAIL_MACRO; - goto fail; - } - } - if (!m_vol->readBlocks(block, dst, nb)) { - DBG_FAIL_MACRO; - goto fail; - } -#endif // USE_MULTI_BLOCK_IO - } else { - // read single block - n = 512; - if (!m_vol->readBlock(block, dst)) { - DBG_FAIL_MACRO; - goto fail; - } - } - dst += n; - m_curPosition += n; - toRead -= n; - } - return nbyte - toRead; - -fail: - m_error |= READ_ERROR; - return -1; -} -//------------------------------------------------------------------------------ -int8_t FatFile::readDir(dir_t* dir) { - int16_t n; - // if not a directory file or miss-positioned return an error - if (!isDir() || (0X1F & m_curPosition)) { - return -1; - } - - while (1) { - n = read(dir, sizeof(dir_t)); - if (n != sizeof(dir_t)) { - return n == 0 ? 0 : -1; - } - // last entry if DIR_NAME_FREE - if (dir->name[0] == DIR_NAME_FREE) { - return 0; - } - // skip empty entries and entry for . and .. - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') { - continue; - } - // return if normal file or subdirectory - if (DIR_IS_FILE_OR_SUBDIR(dir)) { - return n; - } - } -} -//------------------------------------------------------------------------------ -// Read next directory entry into the cache -// Assumes file is correctly positioned -dir_t* FatFile::readDirCache(bool skipReadOk) { -// uint8_t b; - uint8_t i = (m_curPosition >> 5) & 0XF; - - if (i == 0 || !skipReadOk) { - int8_t n = read(&n, 1); - if (n != 1) { - if (n != 0) { - DBG_FAIL_MACRO; - } - goto fail; - } -// if (read(&b, 1) != 1) { -// DBG_FAIL_MACRO; -// goto fail; -// } - m_curPosition += 31; - } else { - m_curPosition += 32; - } - // return pointer to entry - return m_vol->cacheAddress()->dir + i; - -fail: - return 0; -} -//------------------------------------------------------------------------------ -bool FatFile::remove(FatFile* dirFile, const char* path) { - FatFile file; - if (!file.open(dirFile, path, O_WRITE)) { - DBG_FAIL_MACRO; - goto fail; - } - return file.remove(); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::rename(FatFile* dirFile, const char* newPath) { - dir_t entry; - uint32_t dirCluster = 0; - FatFile file; - FatFile oldFile; - cache_t* pc; - dir_t* dir; - - // Must be an open file or subdirectory. - if (!(isFile() || isSubDir())) { - DBG_FAIL_MACRO; - goto fail; - } - // Can't rename LFN in 8.3 mode. - if (!USE_LONG_FILE_NAMES && isLFN()) { - DBG_FAIL_MACRO; - goto fail; - } - // Can't move file to new volume. - if (m_vol != dirFile->m_vol) { - DBG_FAIL_MACRO; - goto fail; - } - // sync() and cache directory entry - sync(); - oldFile = *this; - dir = cacheDirEntry(FatCache::CACHE_FOR_READ); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // save directory entry - memcpy(&entry, dir, sizeof(entry)); - // make directory entry for new path - if (isFile()) { - if (!file.open(dirFile, newPath, O_CREAT | O_EXCL | O_WRITE)) { - DBG_FAIL_MACRO; - goto fail; - } - } else { - // don't create missing path prefix components - if (!file.mkdir(dirFile, newPath, false)) { - DBG_FAIL_MACRO; - goto fail; - } - // save cluster containing new dot dot - dirCluster = file.m_firstCluster; - } - // change to new directory entry - - m_dirBlock = file.m_dirBlock; - m_dirIndex = file.m_dirIndex; - m_lfnOrd = file.m_lfnOrd; - m_dirCluster = file.m_dirCluster; - // mark closed to avoid possible destructor close call - file.m_attr = FILE_ATTR_CLOSED; - - // cache new directory entry - dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // copy all but name and name flags to new directory entry - memcpy(&dir->creationTimeTenths, &entry.creationTimeTenths, - sizeof(entry) - sizeof(dir->name) - 2); - dir->attributes = entry.attributes; - - // update dot dot if directory - if (dirCluster) { - // get new dot dot - uint32_t block = m_vol->clusterStartBlock(dirCluster); - pc = m_vol->cacheFetchData(block, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - memcpy(&entry, &pc->dir[1], sizeof(entry)); - - // free unused cluster - if (!m_vol->freeChain(dirCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - // store new dot dot - block = m_vol->clusterStartBlock(m_firstCluster); - pc = m_vol->cacheFetchData(block, FatCache::CACHE_FOR_WRITE); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - memcpy(&pc->dir[1], &entry, sizeof(entry)); - } - // Remove old directory entry; - oldFile.m_firstCluster = 0; - oldFile.m_flags = O_WRITE; - oldFile.m_attr = FILE_ATTR_FILE; - if (!oldFile.remove()) { - DBG_FAIL_MACRO; - goto fail; - } - return m_vol->cacheSync(); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::rmdir() { - // must be open subdirectory - if (!isSubDir() || (!USE_LONG_FILE_NAMES && isLFN())) { - DBG_FAIL_MACRO; - goto fail; - } - rewind(); - - // make sure directory is empty - while (1) { - dir_t* dir = readDirCache(true); - if (!dir) { - // EOF if no error. - if (!getError()) { - break; - } - DBG_FAIL_MACRO; - goto fail; - } - // done if past last used entry - if (dir->name[0] == DIR_NAME_FREE) { - break; - } - // skip empty slot, '.' or '..' - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') { - continue; - } - // error not empty - if (DIR_IS_FILE_OR_SUBDIR(dir)) { - DBG_FAIL_MACRO; - goto fail; - } - } - // convert empty directory to normal file for remove - m_attr = FILE_ATTR_FILE; - m_flags |= O_WRITE; - return remove(); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::rmRfStar() { - uint16_t index; - FatFile f; - if (!isDir()) { - DBG_FAIL_MACRO; - goto fail; - } - rewind(); - while (1) { - // remember position - index = m_curPosition/32; - - dir_t* dir = readDirCache(); - if (!dir) { - // At EOF if no error. - if (!getError()) { - break; - } - DBG_FAIL_MACRO; - goto fail; - } - // done if past last entry - if (dir->name[0] == DIR_NAME_FREE) { - break; - } - - // skip empty slot or '.' or '..' - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') { - continue; - } - - // skip if part of long file name or volume label in root - if (!DIR_IS_FILE_OR_SUBDIR(dir)) { - continue; - } - - if (!f.open(this, index, O_READ)) { - DBG_FAIL_MACRO; - goto fail; - } - if (f.isSubDir()) { - // recursively delete - if (!f.rmRfStar()) { - DBG_FAIL_MACRO; - goto fail; - } - } else { - // ignore read-only - f.m_flags |= O_WRITE; - if (!f.remove()) { - DBG_FAIL_MACRO; - goto fail; - } - } - // position to next entry if required - if (m_curPosition != (32UL*(index + 1))) { - if (!seekSet(32UL*(index + 1))) { - DBG_FAIL_MACRO; - goto fail; - } - } - } - // don't try to delete root - if (!isRoot()) { - if (!rmdir()) { - DBG_FAIL_MACRO; - goto fail; - } - } - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::seekSet(uint32_t pos) { - uint32_t nCur; - uint32_t nNew; - uint32_t tmp = m_curCluster; - // error if file not open - if (!isOpen()) { - DBG_FAIL_MACRO; - goto fail; - } - if (pos == 0) { - // set position to start of file - m_curCluster = 0; - goto done; - } - if (isFile()) { - if (pos > m_fileSize) { - DBG_FAIL_MACRO; - goto fail; - } - } else if (isRootFixed()) { - if (pos <= 32*m_vol->rootDirEntryCount()) { - goto done; - } - DBG_FAIL_MACRO; - goto fail; - } - // calculate cluster index for cur and new position - nCur = (m_curPosition - 1) >> (m_vol->clusterSizeShift() + 9); - nNew = (pos - 1) >> (m_vol->clusterSizeShift() + 9); - - if (nNew < nCur || m_curPosition == 0) { - // must follow chain from first cluster - m_curCluster = isRoot32() ? m_vol->rootDirStart() : m_firstCluster; - } else { - // advance from curPosition - nNew -= nCur; - } - while (nNew--) { - if (m_vol->fatGet(m_curCluster, &m_curCluster) <= 0) { - DBG_FAIL_MACRO; - goto fail; - } - } - -done: - m_curPosition = pos; - return true; - -fail: - m_curCluster = tmp; - return false; -} -//------------------------------------------------------------------------------ -void FatFile::setpos(FatPos_t* pos) { - m_curPosition = pos->position; - m_curCluster = pos->cluster; -} -//------------------------------------------------------------------------------ -bool FatFile::sync() { - if (!isOpen()) { - return true; - } - - if (m_flags & F_FILE_DIR_DIRTY) { - dir_t* dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); - // check for deleted by another open file object - if (!dir || dir->name[0] == DIR_NAME_DELETED) { - DBG_FAIL_MACRO; - goto fail; - } - // do not set filesize for dir files - if (isFile()) { - dir->fileSize = m_fileSize; - } - - // update first cluster fields - dir->firstClusterLow = m_firstCluster & 0XFFFF; - dir->firstClusterHigh = m_firstCluster >> 16; - - // set modify time if user supplied a callback date/time function - if (m_dateTime) { - m_dateTime(&dir->lastWriteDate, &dir->lastWriteTime); - dir->lastAccessDate = dir->lastWriteDate; - } - // clear directory dirty - m_flags &= ~F_FILE_DIR_DIRTY; - } - if (m_vol->cacheSync()) { - return true; - } - DBG_FAIL_MACRO; - -fail: - m_error |= WRITE_ERROR; - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::timestamp(FatFile* file) { - dir_t* dir; - dir_t srcDir; - - // most be files get timestamps - if (!isFile() || !file->isFile() || !file->dirEntry(&srcDir)) { - DBG_FAIL_MACRO; - goto fail; - } - // update directory fields - if (!sync()) { - DBG_FAIL_MACRO; - goto fail; - } - dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // copy timestamps - dir->lastAccessDate = srcDir.lastAccessDate; - dir->creationDate = srcDir.creationDate; - dir->creationTime = srcDir.creationTime; - dir->creationTimeTenths = srcDir.creationTimeTenths; - dir->lastWriteDate = srcDir.lastWriteDate; - dir->lastWriteTime = srcDir.lastWriteTime; - - // write back entry - return m_vol->cacheSync(); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, - uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { - uint16_t dirDate; - uint16_t dirTime; - dir_t* dir; - - if (!isFile() - || year < 1980 - || year > 2107 - || month < 1 - || month > 12 - || day < 1 - || day > 31 - || hour > 23 - || minute > 59 - || second > 59) { - DBG_FAIL_MACRO; - goto fail; - } - // update directory entry - if (!sync()) { - DBG_FAIL_MACRO; - goto fail; - } - dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - dirDate = FAT_DATE(year, month, day); - dirTime = FAT_TIME(hour, minute, second); - if (flags & T_ACCESS) { - dir->lastAccessDate = dirDate; - } - if (flags & T_CREATE) { - dir->creationDate = dirDate; - dir->creationTime = dirTime; - // seems to be units of 1/100 second not 1/10 as Microsoft states - dir->creationTimeTenths = second & 1 ? 100 : 0; - } - if (flags & T_WRITE) { - dir->lastWriteDate = dirDate; - dir->lastWriteTime = dirTime; - } - return m_vol->cacheSync(); - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::truncate(uint32_t length) { - uint32_t newPos; - // error if not a normal file or read-only - if (!isFile() || !(m_flags & O_WRITE)) { - DBG_FAIL_MACRO; - goto fail; - } - // error if length is greater than current size - if (length > m_fileSize) { - DBG_FAIL_MACRO; - goto fail; - } - // fileSize and length are zero - nothing to do - if (m_fileSize == 0) { - return true; - } - - // remember position for seek after truncation - newPos = m_curPosition > length ? length : m_curPosition; - - // position to last cluster in truncated file - if (!seekSet(length)) { - DBG_FAIL_MACRO; - goto fail; - } - if (length == 0) { - // free all clusters - if (!m_vol->freeChain(m_firstCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - m_firstCluster = 0; - } else { - uint32_t toFree; - int8_t fg = m_vol->fatGet(m_curCluster, &toFree); - if (fg < 0) { - DBG_FAIL_MACRO; - goto fail; - } - if (fg) { - // free extra clusters - if (!m_vol->freeChain(toFree)) { - DBG_FAIL_MACRO; - goto fail; - } - // current cluster is end of chain - if (!m_vol->fatPutEOC(m_curCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - } - } - m_fileSize = length; - - // need to update directory entry - m_flags |= F_FILE_DIR_DIRTY; - - if (!sync()) { - DBG_FAIL_MACRO; - goto fail; - } - // set file to correct position - return seekSet(newPos); - -fail: - return false; -} -//------------------------------------------------------------------------------ -int FatFile::write(const void* buf, size_t nbyte) { - // convert void* to uint8_t* - must be before goto statements - const uint8_t* src = reinterpret_cast(buf); - cache_t* pc; - uint8_t cacheOption; - // number of bytes left to write - must be before goto statements - size_t nToWrite = nbyte; - size_t n; - // error if not a normal file or is read-only - if (!isFile() || !(m_flags & O_WRITE)) { - DBG_FAIL_MACRO; - goto fail; - } - // seek to end of file if append flag - if ((m_flags & O_APPEND)) { - if (!seekSet(m_fileSize)) { - DBG_FAIL_MACRO; - goto fail; - } - } - // Don't exceed max fileSize. - if (nbyte > (0XFFFFFFFF - m_curPosition)) { - DBG_FAIL_MACRO; - goto fail; - } - while (nToWrite) { - uint8_t blockOfCluster = m_vol->blockOfCluster(m_curPosition); - uint16_t blockOffset = m_curPosition & 0X1FF; - if (blockOfCluster == 0 && blockOffset == 0) { - // start of new cluster - if (m_curCluster != 0) { - int8_t fg = m_vol->fatGet(m_curCluster, &m_curCluster); - if (fg < 0) { - DBG_FAIL_MACRO; - goto fail; - } - if (fg == 0) { - // add cluster if at end of chain - if (!addCluster()) { - DBG_FAIL_MACRO; - goto fail; - } - } - } else { - if (m_firstCluster == 0) { - // allocate first cluster of file - if (!addCluster()) { - DBG_FAIL_MACRO; - goto fail; - } - m_firstCluster = m_curCluster; - } else { - m_curCluster = m_firstCluster; - } - } - } - // block for data write - uint32_t block = m_vol->clusterStartBlock(m_curCluster) + blockOfCluster; - - if (blockOffset != 0 || nToWrite < 512) { - // partial block - must use cache - // max space in block - n = 512 - blockOffset; - // lesser of space and amount to write - if (n > nToWrite) { - n = nToWrite; - } - - if (blockOffset == 0 && m_curPosition >= m_fileSize) { - // start of new block don't need to read into cache - cacheOption = FatCache::CACHE_RESERVE_FOR_WRITE; - } else { - // rewrite part of block - cacheOption = FatCache::CACHE_FOR_WRITE; - } - pc = m_vol->cacheFetchData(block, cacheOption); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - uint8_t* dst = pc->data + blockOffset; - memcpy(dst, src, n); - if (512 == (n + blockOffset)) { - // Force write if block is full - improves large writes. - if (!m_vol->cacheSyncData()) { - DBG_FAIL_MACRO; - goto fail; - } - } -#if USE_MULTI_BLOCK_IO - } else if (nToWrite >= 1024) { - // use multiple block write command - uint8_t maxBlocks = m_vol->blocksPerCluster() - blockOfCluster; - uint8_t nBlock = nToWrite >> 9; - if (nBlock > maxBlocks) { - nBlock = maxBlocks; - } - n = 512*nBlock; - if (m_vol->cacheBlockNumber() <= block - && block < (m_vol->cacheBlockNumber() + nBlock)) { - // invalidate cache if block is in cache - m_vol->cacheInvalidate(); - } - if (!m_vol->writeBlocks(block, src, nBlock)) { - DBG_FAIL_MACRO; - goto fail; - } -#endif // USE_MULTI_BLOCK_IO - } else { - // use single block write command - n = 512; - if (m_vol->cacheBlockNumber() == block) { - m_vol->cacheInvalidate(); - } - if (!m_vol->writeBlock(block, src)) { - DBG_FAIL_MACRO; - goto fail; - } - } - m_curPosition += n; - src += n; - nToWrite -= n; - } - if (m_curPosition > m_fileSize) { - // update fileSize and insure sync will update dir entry - m_fileSize = m_curPosition; - m_flags |= F_FILE_DIR_DIRTY; - } else if (m_dateTime) { - // insure sync will update modified date and time - m_flags |= F_FILE_DIR_DIRTY; - } - - if (m_flags & O_SYNC) { - if (!sync()) { - DBG_FAIL_MACRO; - goto fail; - } - } - return nbyte; - -fail: - // return for write error - m_error |= WRITE_ERROR; - return -1; -} diff --git a/SdFat/utility/FatFile.h b/SdFat/utility/FatFile.h deleted file mode 100644 index 1e939266..00000000 --- a/SdFat/utility/FatFile.h +++ /dev/null @@ -1,990 +0,0 @@ -/* FatLib Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef FatFile_h -#define FatFile_h -/** - * \file - * \brief FatFile class - */ -// #include -#include -#include -#include -#include "FatLibConfig.h" -#include "FatApiConstants.h" -#include "FatStructs.h" -#include "FatVolume.h" -class FatFileSystem; -//------------------------------------------------------------------------------ -// Stuff to store strings in AVR flash. -#ifdef __AVR__ -#include -#else // __AVR__ -#ifndef PGM_P -/** pointer to flash for ARM */ -#define PGM_P const char* -#endif // PGM_P -#ifndef PSTR -/** store literal string in flash for ARM */ -#define PSTR(x) (x) -#endif // PSTR -#ifndef pgm_read_byte -/** read 8-bits from flash for ARM */ -#define pgm_read_byte(addr) (*(const unsigned char*)(addr)) -#endif // pgm_read_byte -#ifndef pgm_read_word -/** read 16-bits from flash for ARM */ -#define pgm_read_word(addr) (*(const uint16_t*)(addr)) -#endif // pgm_read_word -#ifndef PROGMEM -/** store in flash for ARM */ -#define PROGMEM const -#endif // PROGMEM -#endif // __AVR__ -//------------------------------------------------------------------------------ -/** - * \struct FatPos_t - * \brief Internal type for file position - do not use in user apps. - */ -struct FatPos_t { - /** stream position */ - uint32_t position; - /** cluster for position */ - uint32_t cluster; - FatPos_t() : position(0), cluster(0) {} -}; -//------------------------------------------------------------------------------ -/** Expression for path name separator. */ -#define isDirSeparator(c) ((c) == '/') -//------------------------------------------------------------------------------ -/** - * \struct fname_t - * \brief Internal type for Short File Name - do not use in user apps. - */ -struct fname_t { - /** Flags for base and extension character case and LFN. */ - uint8_t flags; - /** length of Long File Name */ - size_t len; - /** Long File Name start. */ - const char* lfn; - /** position for sequence number */ - uint8_t seqPos; - /** Short File Name */ - uint8_t sfn[11]; -}; -/** Derived from a LFN with loss or conversion of characters. */ -const uint8_t FNAME_FLAG_LOST_CHARS = 0X01; -/** Base-name or extension has mixed case. */ -const uint8_t FNAME_FLAG_MIXED_CASE = 0X02; -/** LFN entries are required for file name. */ -const uint8_t FNAME_FLAG_NEED_LFN = - FNAME_FLAG_LOST_CHARS | FNAME_FLAG_MIXED_CASE; -/** Filename base-name is all lower case */ -const uint8_t FNAME_FLAG_LC_BASE = DIR_NT_LC_BASE; -/** Filename extension is all lower case. */ -const uint8_t FNAME_FLAG_LC_EXT = DIR_NT_LC_EXT; -//============================================================================== -/** - * \class FatFile - * \brief Basic file class. - */ -class FatFile { - public: - /** Create an instance. */ - FatFile() : m_attr(FILE_ATTR_CLOSED), m_error(0) {} - /** Create a file object and open it in the current working directory. - * - * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive - * OR of open flags. see FatFile::open(FatFile*, const char*, uint8_t). - */ - FatFile(const char* path, uint8_t oflag) { - m_attr = FILE_ATTR_CLOSED; - m_error = 0; - open(path, oflag); - } -#if DESTRUCTOR_CLOSES_FILE - ~FatFile() { - if (isOpen()) { - close(); - } - } -#endif // DESTRUCTOR_CLOSES_FILE - -#if ENABLE_ARDUINO_FEATURES - /** List directory contents. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ - void ls(uint8_t flags = 0) { - ls(&Serial, flags); - } - /** %Print a directory date field. - * - * Format is yyyy-mm-dd. - * - * \param[in] fatDate The date field from a directory entry. - */ - static void printFatDate(uint16_t fatDate) { - printFatDate(&Serial, fatDate); - } - /** %Print a directory time field. - * - * Format is hh:mm:ss. - * - * \param[in] fatTime The time field from a directory entry. - */ - static void printFatTime(uint16_t fatTime) { - printFatTime(&Serial, fatTime); - } - /** Print a file's name. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - size_t printName() { - return FatFile::printName(&Serial); - } -#endif // ENABLE_ARDUINO_FEATURES - - /** \return value of writeError */ - bool getWriteError() { - return m_error & WRITE_ERROR; - } - /** Set writeError to zero */ - void clearWriteError() { - m_error &= ~WRITE_ERROR; - } - /** Clear all error bits. */ - void clearError() { - m_error = 0; - } - /** \return All error bits. */ - uint8_t getError() { - return m_error; - } - /** get position for streams - * \param[out] pos struct to receive position - */ - void getpos(FatPos_t* pos); - /** set position for streams - * \param[out] pos struct with value for new position - */ - void setpos(FatPos_t* pos); - /** \return The number of bytes available from the current position - * to EOF for normal files. Zero is returned for directory files. - */ - uint32_t available() { - return isFile() ? fileSize() - curPosition() : 0; - } - /** Close a file and force cached data and directory information - * to be written to the storage device. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool close(); - /** Check for contiguous file and return its raw block range. - * - * \param[out] bgnBlock the first block address for the file. - * \param[out] endBlock the last block address for the file. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); - /** Create and open a new contiguous file of a specified size. - * - * \note This function only supports short DOS 8.3 names. - * See open() for more information. - * - * \param[in] dirFile The directory where the file will be created. - * \param[in] path A path with a valid DOS 8.3 file name. - * \param[in] size The desired file size. - * - * \return The value true is returned for success and - * the value false, is returned for failure. - */ - bool createContiguous(FatFile* dirFile, - const char* path, uint32_t size); - /** \return The current cluster number for a file or directory. */ - uint32_t curCluster() const { - return m_curCluster; - } - /** \return The current position for a file or directory. */ - uint32_t curPosition() const { - return m_curPosition; - } - /** \return Current working directory */ - static FatFile* cwd() { - return m_cwd; - } - /** Set the date/time callback function - * - * \param[in] dateTime The user's call back function. The callback - * function is of the form: - * - * \code - * void dateTime(uint16_t* date, uint16_t* time) { - * uint16_t year; - * uint8_t month, day, hour, minute, second; - * - * // User gets date and time from GPS or real-time clock here - * - * // return date using FAT_DATE macro to format fields - * *date = FAT_DATE(year, month, day); - * - * // return time using FAT_TIME macro to format fields - * *time = FAT_TIME(hour, minute, second); - * } - * \endcode - * - * Sets the function that is called when a file is created or when - * a file's directory entry is modified by sync(). All timestamps, - * access, creation, and modify, are set when a file is created. - * sync() maintains the last access date and last modify date/time. - * - * See the timestamp() function. - */ - static void dateTimeCallback( - void (*dateTime)(uint16_t* date, uint16_t* time)) { - m_dateTime = dateTime; - } - /** Cancel the date/time callback function. */ - static void dateTimeCallbackCancel() { - m_dateTime = 0; - } - /** Return a file's directory entry. - * - * \param[out] dir Location for return of the file's directory entry. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool dirEntry(dir_t* dir); - /** - * \return The index of this file in it's directory. - */ - uint16_t dirIndex() { - return m_dirIndex; - } - /** Format the name field of \a dir into the 13 byte array - * \a name in standard 8.3 short name format. - * - * \param[in] dir The directory structure containing the name. - * \param[out] name A 13 byte char array for the formatted name. - * \return length of the name. - */ - static uint8_t dirName(const dir_t* dir, char* name); - /** \return The number of bytes allocated to a directory or zero - * if an error occurs. - */ - uint32_t dirSize(); - /** Dump file in Hex - * \param[in] pr Print stream for list. - * \param[in] pos Start position in file. - * \param[in] n number of locations to dump. - */ - void dmpFile(print_t* pr, uint32_t pos, size_t n); - /** Test for the existence of a file in a directory - * - * \param[in] path Path of the file to be tested for. - * - * The calling instance must be an open directory file. - * - * dirFile.exists("TOFIND.TXT") searches for "TOFIND.TXT" in the directory - * dirFile. - * - * \return true if the file exists else false. - */ - bool exists(const char* path) { - FatFile file; - return file.open(this, path, O_READ); - } - /** - * Get a string from a file. - * - * fgets() reads bytes from a file into the array pointed to by \a str, until - * \a num - 1 bytes are read, or a delimiter is read and transferred to \a str, - * or end-of-file is encountered. The string is then terminated - * with a null byte. - * - * fgets() deletes CR, '\\r', from the string. This insures only a '\\n' - * terminates the string for Windows text files which use CRLF for newline. - * - * \param[out] str Pointer to the array where the string is stored. - * \param[in] num Maximum number of characters to be read - * (including the final null byte). Usually the length - * of the array \a str is used. - * \param[in] delim Optional set of delimiters. The default is "\n". - * - * \return For success fgets() returns the length of the string in \a str. - * If no data is read, fgets() returns zero for EOF or -1 if an error occurred. - */ - int16_t fgets(char* str, int16_t num, char* delim = 0); - /** \return The total number of bytes in a file. */ - uint32_t fileSize() const { - return m_fileSize; - } - /** \return The first cluster number for a file or directory. */ - uint32_t firstCluster() const { - return m_firstCluster; - } - /** - * Get a file's name followed by a zero byte. - * - * \param[out] name An array of characters for the file's name. - * \param[in] size The size of the array in bytes. The array - * must be at least 13 bytes long. The file's name will be - * truncated if the file's name is too long. - * \return The value true, is returned for success and - * the value false, is returned for failure. - */ - bool getName(char* name, size_t size); - /** - * Get a file's Short File Name followed by a zero byte. - * - * \param[out] name An array of characters for the file's name. - * The array must be at least 13 bytes long. - * \return The value true, is returned for success and - * the value false, is returned for failure. - */ - bool getSFN(char* name); - /** \return True if this is a directory else false. */ - bool isDir() const { - return m_attr & FILE_ATTR_DIR; - } - /** \return True if this is a normal file else false. */ - bool isFile() const { - return m_attr & FILE_ATTR_FILE; - } - /** \return True if this is a hidden file else false. */ - bool isHidden() const { - return m_attr & FILE_ATTR_HIDDEN; - } - /** \return true if this file has a Long File Name. */ - bool isLFN() const { - return m_lfnOrd; - } - /** \return True if this is an open file/directory else false. */ - bool isOpen() const { - return m_attr; - } - /** \return True if this is the root directory. */ - bool isRoot() const { - return m_attr & FILE_ATTR_ROOT; - } - /** \return True if this is the FAT32 root directory. */ - bool isRoot32() const { - return m_attr & FILE_ATTR_ROOT32; - } - /** \return True if this is the FAT12 of FAT16 root directory. */ - bool isRootFixed() const { - return m_attr & FILE_ATTR_ROOT_FIXED; - } - /** \return True if file is read-only */ - bool isReadOnly() const { - return m_attr & FILE_ATTR_READ_ONLY; - } - /** \return True if this is a subdirectory else false. */ - bool isSubDir() const { - return m_attr & FILE_ATTR_SUBDIR; - } - /** \return True if this is a system file else false. */ - bool isSystem() const { - return m_attr & FILE_ATTR_SYSTEM; - } - /** Check for a legal 8.3 character. - * \param[in] c Character to be checked. - * \return true for a legal 8.3 character else false. - */ - static bool legal83Char(uint8_t c) { - if (c == '"' || c == '|') { - return false; - } - // *+,./ - if (0X2A <= c && c <= 0X2F && c != 0X2D) { - return false; - } - // :;<=>? - if (0X3A <= c && c <= 0X3F) { - return false; - } - // [\] - if (0X5B <= c && c <= 0X5D) { - return false; - } - return 0X20 < c && c < 0X7F; - } - /** List directory contents. - * - * \param[in] pr Print stream for list. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - * - * \param[in] indent Amount of space before file name. Used for recursive - * list to indicate subdirectory level. - */ - void ls(print_t* pr, uint8_t flags = 0, uint8_t indent = 0); - /** Make a new directory. - * - * \param[in] dir An open FatFile instance for the directory that will - * contain the new directory. - * - * \param[in] path A path with a valid 8.3 DOS name for the new directory. - * - * \param[in] pFlag Create missing parent directories if true. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool mkdir(FatFile* dir, const char* path, bool pFlag = true); - /** Open a file in the volume working directory of a FatFileSystem. - * - * \param[in] fs File System where the file is located. - * - * \param[in] path with a valid 8.3 DOS name for a file to be opened. - * - * \param[in] oflag bitwise-inclusive OR of open mode flags. - * See see FatFile::open(FatFile*, const char*, uint8_t). - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool open(FatFileSystem* fs, const char* path, uint8_t oflag); - /** Open a file by index. - * - * \param[in] dirFile An open FatFile instance for the directory. - * - * \param[in] index The \a index of the directory entry for the file to be - * opened. The value for \a index is (directory file position)/32. - * - * \param[in] oflag bitwise-inclusive OR of open mode flags. - * See see FatFile::open(FatFile*, const char*, uint8_t). - * - * See open() by path for definition of flags. - * \return true for success or false for failure. - */ - bool open(FatFile* dirFile, uint16_t index, uint8_t oflag); - /** Open a file or directory by name. - * - * \param[in] dirFile An open FatFile instance for the directory containing - * the file to be opened. - * - * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. - * - * \param[in] oflag Values for \a oflag are constructed by a - * bitwise-inclusive OR of flags from the following list - * - * O_READ - Open for reading. - * - * O_RDONLY - Same as O_READ. - * - * O_WRITE - Open for writing. - * - * O_WRONLY - Same as O_WRITE. - * - * O_RDWR - Open for reading and writing. - * - * O_APPEND - If set, the file offset shall be set to the end of the - * file prior to each write. - * - * O_AT_END - Set the initial position at the end of the file. - * - * O_CREAT - If the file exists, this flag has no effect except as noted - * under O_EXCL below. Otherwise, the file shall be created - * - * O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. - * - * O_SYNC - Call sync() after each write. This flag should not be used with - * write(uint8_t) or any functions do character at a time writes since sync() - * will be called after each byte. - * - * O_TRUNC - If the file exists and is a regular file, and the file is - * successfully opened and is not read only, its length shall be truncated to 0. - * - * WARNING: A given file must not be opened by more than one FatFile object - * or file corruption may occur. - * - * \note Directory files must be opened read only. Write and truncation is - * not allowed for directory files. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool open(FatFile* dirFile, const char* path, uint8_t oflag); - /** Open a file in the current working directory. - * - * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. - * - * \param[in] oflag bitwise-inclusive OR of open mode flags. - * See see FatFile::open(FatFile*, const char*, uint8_t). - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool open(const char* path, uint8_t oflag = O_READ) { - return open(m_cwd, path, oflag); - } - /** Open the next file or subdirectory in a directory. - * - * \param[in] dirFile An open FatFile instance for the directory - * containing the file to be opened. - * - * \param[in] oflag bitwise-inclusive OR of open mode flags. - * See see FatFile::open(FatFile*, const char*, uint8_t). - * - * \return true for success or false for failure. - */ - bool openNext(FatFile* dirFile, uint8_t oflag = O_READ); - /** Open a volume's root directory. - * - * \param[in] vol The FAT volume containing the root directory to be opened. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool openRoot(FatVolume* vol); - /** Return the next available byte without consuming it. - * - * \return The byte if no error and not at eof else -1; - */ - int peek(); - /** Print a file's creation date and time - * - * \param[in] pr Print stream for output. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool printCreateDateTime(print_t* pr); - /** %Print a directory date field. - * - * Format is yyyy-mm-dd. - * - * \param[in] pr Print stream for output. - * \param[in] fatDate The date field from a directory entry. - */ - static void printFatDate(print_t* pr, uint16_t fatDate); - /** %Print a directory time field. - * - * Format is hh:mm:ss. - * - * \param[in] pr Print stream for output. - * \param[in] fatTime The time field from a directory entry. - */ - static void printFatTime(print_t* pr, uint16_t fatTime); - /** Print a number followed by a field terminator. - * \param[in] value The number to be printed. - * \param[in] term The field terminator. Use '\\n' for CR LF. - * \param[in] prec Number of digits after decimal point. - * \return The number of bytes written or -1 if an error occurs. - */ - int printField(float value, char term, uint8_t prec = 2); - /** Print a number followed by a field terminator. - * \param[in] value The number to be printed. - * \param[in] term The field terminator. Use '\\n' for CR LF. - * \return The number of bytes written or -1 if an error occurs. - */ - int printField(int16_t value, char term); - /** Print a number followed by a field terminator. - * \param[in] value The number to be printed. - * \param[in] term The field terminator. Use '\\n' for CR LF. - * \return The number of bytes written or -1 if an error occurs. - */ - int printField(uint16_t value, char term); - /** Print a number followed by a field terminator. - * \param[in] value The number to be printed. - * \param[in] term The field terminator. Use '\\n' for CR LF. - * \return The number of bytes written or -1 if an error occurs. - */ - int printField(int32_t value, char term); - /** Print a number followed by a field terminator. - * \param[in] value The number to be printed. - * \param[in] term The field terminator. Use '\\n' for CR LF. - * \return The number of bytes written or -1 if an error occurs. - */ - int printField(uint32_t value, char term); - /** Print a file's modify date and time - * - * \param[in] pr Print stream for output. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool printModifyDateTime(print_t* pr); - /** Print a file's name - * - * \param[in] pr Print stream for output. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - size_t printName(print_t* pr); - /** Print a file's size. - * - * \param[in] pr Print stream for output. - * - * \return The number of characters printed is returned - * for success and zero is returned for failure. - */ - size_t printFileSize(print_t* pr); - /** Print a file's Short File Name. - * - * \param[in] pr Print stream for output. - * - * \return The number of characters printed is returned - * for success and zero is returned for failure. - */ - size_t printSFN(print_t* pr); - /** Read the next byte from a file. - * - * \return For success read returns the next byte in the file as an int. - * If an error occurs or end of file is reached -1 is returned. - */ - int read() { - uint8_t b; - return read(&b, 1) == 1 ? b : -1; - } - /** Read data from a file starting at the current position. - * - * \param[out] buf Pointer to the location that will receive the data. - * - * \param[in] nbyte Maximum number of bytes to read. - * - * \return For success read() returns the number of bytes read. - * A value less than \a nbyte, including zero, will be returned - * if end of file is reached. - * If an error occurs, read() returns -1. Possible errors include - * read() called before a file has been opened, corrupt file system - * or an I/O error occurred. - */ - int read(void* buf, size_t nbyte); - /** Read the next directory entry from a directory file. - * - * \param[out] dir The dir_t struct that will receive the data. - * - * \return For success readDir() returns the number of bytes read. - * A value of zero will be returned if end of file is reached. - * If an error occurs, readDir() returns -1. Possible errors include - * readDir() called before a directory has been opened, this is not - * a directory file or an I/O error occurred. - */ - int8_t readDir(dir_t* dir); - /** Remove a file. - * - * The directory entry and all data for the file are deleted. - * - * \note This function should not be used to delete the 8.3 version of a - * file that has a long name. For example if a file has the long name - * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool remove(); - /** Remove a file. - * - * The directory entry and all data for the file are deleted. - * - * \param[in] dirFile The directory that contains the file. - * \param[in] path Path for the file to be removed. - * - * \note This function should not be used to delete the 8.3 version of a - * file that has a long name. For example if a file has the long name - * "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - static bool remove(FatFile* dirFile, const char* path); - /** Set the file's current position to zero. */ - void rewind() { - seekSet(0); - } - /** Rename a file or subdirectory. - * - * \param[in] dirFile Directory for the new path. - * \param[in] newPath New path name for the file/directory. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool rename(FatFile* dirFile, const char* newPath); - /** Remove a directory file. - * - * The directory file will be removed only if it is empty and is not the - * root directory. rmdir() follows DOS and Windows and ignores the - * read-only attribute for the directory. - * - * \note This function should not be used to delete the 8.3 version of a - * directory that has a long name. For example if a directory has the - * long name "New folder" you should not delete the 8.3 name "NEWFOL~1". - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool rmdir(); - /** Recursively delete a directory and all contained files. - * - * This is like the Unix/Linux 'rm -rf *' if called with the root directory - * hence the name. - * - * Warning - This will remove all contents of the directory including - * subdirectories. The directory will then be removed if it is not root. - * The read-only attribute for files will be ignored. - * - * \note This function should not be used to delete the 8.3 version of - * a directory that has a long name. See remove() and rmdir(). - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool rmRfStar(); - /** Set the files position to current position + \a pos. See seekSet(). - * \param[in] offset The new position in bytes from the current position. - * \return true for success or false for failure. - */ - bool seekCur(int32_t offset) { - return seekSet(m_curPosition + offset); - } - /** Set the files position to end-of-file + \a offset. See seekSet(). - * Can't be used for directory files since file size is not defined. - * \param[in] offset The new position in bytes from end-of-file. - * \return true for success or false for failure. - */ - bool seekEnd(int32_t offset = 0) { - return isFile() ? seekSet(m_fileSize + offset) : false; - } - /** Sets a file's position. - * - * \param[in] pos The new position in bytes from the beginning of the file. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool seekSet(uint32_t pos); - /** Set the current working directory. - * - * \param[in] dir New current working directory. - * - * \return true for success else false. - */ - static bool setCwd(FatFile* dir) { - if (!dir->isDir()) { - return false; - } - m_cwd = dir; - return true; - } - /** The sync() call causes all modified data and directory fields - * to be written to the storage device. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool sync(); - /** Copy a file's timestamps - * - * \param[in] file File to copy timestamps from. - * - * \note - * Modify and access timestamps may be overwritten if a date time callback - * function has been set by dateTimeCallback(). - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool timestamp(FatFile* file); - /** Set a file's timestamps in its directory entry. - * - * \param[in] flags Values for \a flags are constructed by a bitwise-inclusive - * OR of flags from the following list - * - * T_ACCESS - Set the file's last access date. - * - * T_CREATE - Set the file's creation date and time. - * - * T_WRITE - Set the file's last write/modification date and time. - * - * \param[in] year Valid range 1980 - 2107 inclusive. - * - * \param[in] month Valid range 1 - 12 inclusive. - * - * \param[in] day Valid range 1 - 31 inclusive. - * - * \param[in] hour Valid range 0 - 23 inclusive. - * - * \param[in] minute Valid range 0 - 59 inclusive. - * - * \param[in] second Valid range 0 - 59 inclusive - * - * \note It is possible to set an invalid date since there is no check for - * the number of days in a month. - * - * \note - * Modify and access timestamps may be overwritten if a date time callback - * function has been set by dateTimeCallback(). - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool timestamp(uint8_t flags, uint16_t year, uint8_t month, uint8_t day, - uint8_t hour, uint8_t minute, uint8_t second); - /** Type of file. You should use isFile() or isDir() instead of fileType() - * if possible. - * - * \return The file or directory type. - */ - uint8_t fileAttr() const { - return m_attr; - } - /** Truncate a file to a specified length. The current file position - * will be maintained if it is less than or equal to \a length otherwise - * it will be set to end of file. - * - * \param[in] length The desired length for the file. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool truncate(uint32_t length); - /** \return FatVolume that contains this file. */ - FatVolume* volume() const { - return m_vol; - } - /** Write a string to a file. Used by the Arduino Print class. - * \param[in] str Pointer to the string. - * Use getWriteError to check for errors. - * \return count of characters written for success or -1 for failure. - */ - int write(const char* str) { - return write(str, strlen(str)); - } - /** Write a single byte. - * \param[in] b The byte to be written. - * \return +1 for success or -1 for failure. - */ - int write(uint8_t b) { - return write(&b, 1); - } - /** Write data to an open file. - * - * \note Data is moved to the cache but may not be written to the - * storage device until sync() is called. - * - * \param[in] buf Pointer to the location of the data to be written. - * - * \param[in] nbyte Number of bytes to write. - * - * \return For success write() returns the number of bytes written, always - * \a nbyte. If an error occurs, write() returns -1. Possible errors - * include write() is called before a file has been opened, write is called - * for a read-only file, device is full, a corrupt file system or an I/O error. - * - */ - int write(const void* buf, size_t nbyte); -//------------------------------------------------------------------------------ - private: - /** This file has not been opened. */ - static const uint8_t FILE_ATTR_CLOSED = 0; - /** File is read-only. */ - static const uint8_t FILE_ATTR_READ_ONLY = DIR_ATT_READ_ONLY; - /** File should be hidden in directory listings. */ - static const uint8_t FILE_ATTR_HIDDEN = DIR_ATT_HIDDEN; - /** Entry is for a system file. */ - static const uint8_t FILE_ATTR_SYSTEM = DIR_ATT_SYSTEM; - /** Entry for normal data file */ - static const uint8_t FILE_ATTR_FILE = 0X08; - /** Entry is for a subdirectory */ - static const uint8_t FILE_ATTR_SUBDIR = DIR_ATT_DIRECTORY; - /** A FAT12 or FAT16 root directory */ - static const uint8_t FILE_ATTR_ROOT_FIXED = 0X20; - /** A FAT32 root directory */ - static const uint8_t FILE_ATTR_ROOT32 = 0X40; - /** Entry is for root. */ - static const uint8_t FILE_ATTR_ROOT = FILE_ATTR_ROOT_FIXED | FILE_ATTR_ROOT32; - /** Directory type bits */ - static const uint8_t FILE_ATTR_DIR = FILE_ATTR_SUBDIR | FILE_ATTR_ROOT; - /** Attributes to copy from directory entry */ - static const uint8_t FILE_ATTR_COPY = DIR_ATT_READ_ONLY | DIR_ATT_HIDDEN | - DIR_ATT_SYSTEM | DIR_ATT_DIRECTORY; - - /** experimental don't use */ - - bool openParent(FatFile* dir); - - // private functions - bool addCluster(); - bool addDirCluster(); - dir_t* cacheDirEntry(uint8_t action); - static uint8_t lfnChecksum(uint8_t* name); - bool lfnUniqueSfn(fname_t* fname); - bool openCluster(FatFile* file); - static bool parsePathName(const char* str, fname_t* fname, const char** ptr); - bool mkdir(FatFile* parent, fname_t* fname); - bool open(FatFile* dirFile, fname_t* fname, uint8_t oflag); - bool openCachedEntry(FatFile* dirFile, uint16_t cacheIndex, uint8_t oflag, - uint8_t lfnOrd); - bool readLBN(uint32_t* lbn); - dir_t* readDirCache(bool skipReadOk = false); - bool setDirSize(); - - // bits defined in m_flags - // should be 0X0F - static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); - // sync of directory entry required - static uint8_t const F_FILE_DIR_DIRTY = 0X80; - - // global pointer to cwd dir - static FatFile* m_cwd; - // data time callback function - static void (*m_dateTime)(uint16_t* date, uint16_t* time); - // private data - static const uint8_t WRITE_ERROR = 0X1; - static const uint8_t READ_ERROR = 0X2; - uint8_t m_attr; // File attributes - uint8_t m_error; // Error bits. - uint8_t m_flags; // See above for definition of m_flags bits - uint8_t m_lfnOrd; - uint16_t m_dirIndex; // index of directory entry in dir file - FatVolume* m_vol; // volume where file is located - uint32_t m_dirCluster; - uint32_t m_curCluster; // cluster for current file position - uint32_t m_curPosition; // current file position - uint32_t m_dirBlock; // block for this files directory entry - uint32_t m_fileSize; // file size in bytes - uint32_t m_firstCluster; // first cluster of file -}; -#endif // FatFile_h diff --git a/SdFat/utility/FatFileLFN.cpp b/SdFat/utility/FatFileLFN.cpp deleted file mode 100644 index 5ab9f45a..00000000 --- a/SdFat/utility/FatFileLFN.cpp +++ /dev/null @@ -1,683 +0,0 @@ -/* FatLib Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#include "FatFile.h" -//------------------------------------------------------------------------------ -// -uint8_t FatFile::lfnChecksum(uint8_t* name) { - uint8_t sum = 0; - for (uint8_t i = 0; i < 11; i++) { - sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + name[i]; - } - return sum; -} -#if USE_LONG_FILE_NAMES -//------------------------------------------------------------------------------ -// Saves about 90 bytes of flash on 328 over tolower(). -inline char lfnToLower(char c) { - return 'A' <= c && c <= 'Z' ? c + 'a' - 'A' : c; -} -//------------------------------------------------------------------------------ -// Daniel Bernstein University of Illinois at Chicago. -// Original had + instead of ^ -static uint16_t Bernstein(uint16_t hash, const char *str, size_t len) { - for (size_t i = 0; i < len; i++) { - // hash = hash * 33 ^ str[i]; - hash = ((hash << 5) + hash) ^ str[i]; - } - return hash; -} -//------------------------------------------------------------------------------ -/** - * Fetch a 16-bit long file name character. - * - * \param[in] ldir Pointer to long file name directory entry. - * \param[in] i Index of character. - * \return The 16-bit character. - */ -static uint16_t lfnGetChar(ldir_t *ldir, uint8_t i) { - if (i < LDIR_NAME1_DIM) { - return ldir->name1[i]; - } else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM)) { - return ldir->name2[i - LDIR_NAME1_DIM]; - } else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM + LDIR_NAME2_DIM)) { - return ldir->name3[i - LDIR_NAME1_DIM - LDIR_NAME2_DIM]; - } - return 0; -} -//------------------------------------------------------------------------------ -static bool lfnGetName(ldir_t *ldir, char* name, size_t n) { - uint8_t i; - size_t k = 13*((ldir->ord & 0X1F) - 1); - for (i = 0; i < 13; i++) { - uint16_t c = lfnGetChar(ldir, i); - if (c == 0 || k >= n) { - break; - } - name[k++] = c >= 0X7F ? '?' : c; - } - // Terminate with zero byte if name fits. - if (k < n && (ldir->ord & LDIR_ORD_LAST_LONG_ENTRY)) { - name[k] = 0; - } - // Truncate if name is too long. - name[n - 1] = 0; - return true; -} -//------------------------------------------------------------------------------ -inline bool lfnLegalChar(char c) { - if (c == '/' || c == '\\' || c == '"' || c == '*' || - c == ':' || c == '<' || c == '>' || c == '?' || c == '|') { - return false; - } - return 0X1F < c && c < 0X7F; -} -//------------------------------------------------------------------------------ -/** - * Store a 16-bit long file name character. - * - * \param[in] ldir Pointer to long file name directory entry. - * \param[in] i Index of character. - * \param[in] c The 16-bit character. - */ -static void lfnPutChar(ldir_t *ldir, uint8_t i, uint16_t c) { - if (i < LDIR_NAME1_DIM) { - ldir->name1[i] = c; - } else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM)) { - ldir->name2[i - LDIR_NAME1_DIM] = c; - } else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM + LDIR_NAME2_DIM)) { - ldir->name3[i - LDIR_NAME1_DIM - LDIR_NAME2_DIM] = c; - } -} -//------------------------------------------------------------------------------ -static void lfnPutName(ldir_t *ldir, const char* name, size_t n) { - size_t k = 13*((ldir->ord & 0X1F) - 1); - for (uint8_t i = 0; i < 13; i++, k++) { - uint16_t c = k < n ? name[k] : k == n ? 0 : 0XFFFF; - lfnPutChar(ldir, i, c); - } -} -//============================================================================== -bool FatFile::getName(char* name, size_t size) { - FatFile dirFile; - ldir_t* ldir; - if (!isOpen() || size < 13) { - DBG_FAIL_MACRO; - goto fail; - } - if (!isLFN()) { - return getSFN(name); - } - if (!dirFile.openCluster(this)) { - DBG_FAIL_MACRO; - goto fail; - } - for (uint8_t ord = 1; ord <= m_lfnOrd; ord++) { - if (!dirFile.seekSet(32UL*(m_dirIndex - ord))) { - DBG_FAIL_MACRO; - goto fail; - } - ldir = reinterpret_cast(dirFile.readDirCache()); - if (!ldir) { - DBG_FAIL_MACRO; - goto fail; - } - if (ldir->attr != DIR_ATT_LONG_NAME) { - DBG_FAIL_MACRO; - goto fail; - } - if (ord != (ldir->ord & 0X1F)) { - DBG_FAIL_MACRO; - goto fail; - } - if (!lfnGetName(ldir, name, size)) { - DBG_FAIL_MACRO; - goto fail; - } - if (ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) { - return true; - } - } - // Fall into fail. - DBG_FAIL_MACRO; - -fail: - name[0] = 0; - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::openCluster(FatFile* file) { - if (file->m_dirCluster == 0) { - return openRoot(file->m_vol); - } - memset(this, 0, sizeof(FatFile)); - m_attr = FILE_ATTR_SUBDIR; - m_flags = O_READ; - m_vol = file->m_vol; - m_firstCluster = file->m_dirCluster; - return true; -} -//------------------------------------------------------------------------------ -bool FatFile::parsePathName(const char* path, - fname_t* fname, const char** ptr) { - char c; - bool is83; - uint8_t bit = DIR_NT_LC_BASE; - uint8_t lc = 0; - uint8_t uc = 0; - uint8_t i = 0; - uint8_t in = 7; - int end; - int len = 0; - int si; - int dot; - - // Skip leading spaces. - while (*path == ' ') { - path++; - } - fname->lfn = path; - - for (len = 0; ; len++) { - c = path[len]; - if (c == 0 || isDirSeparator(c)) { - break; - } - if (!lfnLegalChar(c)) { - return false; - } - } - // Advance to next path component. - for (end = len; path[end] == ' ' || isDirSeparator(path[end]); end++) {} - *ptr = &path[end]; - - // Back over spaces and dots. - while (len) { - c = path[len - 1]; - if (c != '.' && c != ' ') { - break; - } - len--; - } - // Max length of LFN is 255. - if (len > 255) { - return false; - } - fname->len = len; - // Blank file short name. - for (uint8_t k = 0; k < 11; k++) { - fname->sfn[k] = ' '; - } - // skip leading spaces and dots. - for (si = 0; path[si] == '.' || path[si] == ' '; si++) {} - // Not 8.3 if leading dot or space. - is83 = !si; - - // find last dot. - for (dot = len - 1; dot >= 0 && path[dot] != '.'; dot--) {} - for (; si < len; si++) { - c = path[si]; - if (c == ' ' || (c == '.' && dot != si)) { - is83 = false; - continue; - } - if (!legal83Char(c) && si != dot) { - is83 = false; - c = '_'; - } - if (si == dot || i > in) { - if (in == 10) { - // Done - extension longer than three characters. - is83 = false; - break; - } - if (si != dot) { - is83 = false; - } - // Break if no dot and base-name is longer than eight characters. - if (si > dot) { - break; - } - si = dot; - in = 10; // Max index for full 8.3 name. - i = 8; // Place for extension. - bit = DIR_NT_LC_EXT; // bit for extension. - } else { - if ('a' <= c && c <= 'z') { - c += 'A' - 'a'; - lc |= bit; - } else if ('A' <= c && c <= 'Z') { - uc |= bit; - } - fname->sfn[i++] = c; - if (i < 7) { - fname->seqPos = i; - } - } - } - if (fname->sfn[0] == ' ') { - return false; - } - - if (is83) { - fname->flags = lc & uc ? FNAME_FLAG_MIXED_CASE : lc; - } else { - fname->flags = FNAME_FLAG_LOST_CHARS; - fname->sfn[fname->seqPos] = '~'; - fname->sfn[fname->seqPos + 1] = '1'; - } - return true; -} -//------------------------------------------------------------------------------ -bool FatFile::open(FatFile* dirFile, fname_t* fname, uint8_t oflag) { - bool fnameFound = false; - uint8_t lfnOrd = 0; - uint8_t freeNeed; - uint8_t freeFound = 0; - uint8_t ord = 0; - uint8_t chksum = 0; - uint16_t freeIndex = 0; - uint16_t curIndex; - dir_t* dir; - ldir_t* ldir; - size_t len = fname->len; - - if (!dirFile->isDir() || isOpen()) { - DBG_FAIL_MACRO; - goto fail; - } - // Number of directory entries needed. - freeNeed = fname->flags & FNAME_FLAG_NEED_LFN ? 1 + (len + 12)/13 : 1; - - dirFile->rewind(); - while (1) { - curIndex = dirFile->m_curPosition/32; - dir = dirFile->readDirCache(true); - if (!dir) { - if (dirFile->getError()) { - DBG_FAIL_MACRO; - goto fail; - } - // At EOF - goto create; - } - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == DIR_NAME_FREE) { - if (freeFound == 0) { - freeIndex = curIndex; - } - if (freeFound < freeNeed) { - freeFound++; - } - if (dir->name[0] == DIR_NAME_FREE) { - goto create; - } - } else { - if (freeFound < freeNeed) { - freeFound = 0; - } - } - // skip empty slot or '.' or '..' - if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') { - lfnOrd = 0; - } else if (DIR_IS_LONG_NAME(dir)) { - ldir_t *ldir = reinterpret_cast(dir); - if (!lfnOrd) { - if ((ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) == 0) { - continue; - } - lfnOrd = ord = ldir->ord & 0X1F; - chksum = ldir->chksum; - } else if (ldir->ord != --ord || chksum != ldir->chksum) { - lfnOrd = 0; - continue; - } - size_t k = 13*(ord - 1); - if (k >= len) { - // Not found. - lfnOrd = 0; - continue; - } - for (uint8_t i = 0; i < 13; i++) { - uint16_t u = lfnGetChar(ldir, i); - if (k == len) { - if (u != 0) { - // Not found. - lfnOrd = 0; - } - break; - } - if (u > 255 || lfnToLower(u) != lfnToLower(fname->lfn[k++])) { - // Not found. - lfnOrd = 0; - break; - } - } - } else if (DIR_IS_FILE_OR_SUBDIR(dir)) { - if (lfnOrd) { - if (1 == ord && lfnChecksum(dir->name) == chksum) { - goto found; - } - DBG_FAIL_MACRO; - goto fail; - } - if (!memcmp(dir->name, fname->sfn, sizeof(fname->sfn))) { - if (!(fname->flags & FNAME_FLAG_LOST_CHARS)) { - goto found; - } - fnameFound = true; - } - } else { - lfnOrd = 0; - } - } - -found: - // Don't open if create only. - if (oflag & O_EXCL) { - DBG_FAIL_MACRO; - goto fail; - } - goto open; - -create: - // don't create unless O_CREAT and O_WRITE - if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) { - DBG_FAIL_MACRO; - goto fail; - } - // If at EOF start in next cluster. - if (freeFound == 0) { - freeIndex = curIndex; - } - - while (freeFound < freeNeed) { - dir = dirFile->readDirCache(); - if (!dir) { - if (dirFile->getError()) { - DBG_FAIL_MACRO; - goto fail; - } - // EOF if no error. - break; - } - freeFound++; - } - while (freeFound < freeNeed) { - // Will fail if FAT16 root. - if (!dirFile->addDirCluster()) { - DBG_FAIL_MACRO; - goto fail; - } - // Done if more than one block per cluster. Max freeNeed is 21. - if (dirFile->m_vol->blocksPerCluster() > 1) { - break; - } - freeFound += 16; - } - if (fnameFound) { - if (!dirFile->lfnUniqueSfn(fname)) { - goto fail; - } - } - if (!dirFile->seekSet(32UL*freeIndex)) { - DBG_FAIL_MACRO; - goto fail; - } - lfnOrd = freeNeed - 1; - for (uint8_t ord = lfnOrd ; ord ; ord--) { - ldir = reinterpret_cast(dirFile->readDirCache()); - if (!ldir) { - DBG_FAIL_MACRO; - goto fail; - } - dirFile->m_vol->cacheDirty(); - ldir->ord = ord == lfnOrd ? LDIR_ORD_LAST_LONG_ENTRY | ord : ord; - ldir->attr = DIR_ATT_LONG_NAME; - ldir->type = 0; - ldir->chksum = lfnChecksum(fname->sfn); - ldir->mustBeZero = 0; - lfnPutName(ldir, fname->lfn, len); - } - curIndex = dirFile->m_curPosition/32; - dir = dirFile->readDirCache(); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // initialize as empty file - memset(dir, 0, sizeof(dir_t)); - memcpy(dir->name, fname->sfn, 11); - - // Set base-name and extension lower case bits. - dir->reservedNT = (DIR_NT_LC_BASE | DIR_NT_LC_EXT) & fname->flags; - - // set timestamps - if (m_dateTime) { - // call user date/time function - m_dateTime(&dir->creationDate, &dir->creationTime); - } else { - // use default date/time - dir->creationDate = FAT_DEFAULT_DATE; - dir->creationTime = FAT_DEFAULT_TIME; - } - dir->lastAccessDate = dir->creationDate; - dir->lastWriteDate = dir->creationDate; - dir->lastWriteTime = dir->creationTime; - - // Force write of entry to device. - dirFile->m_vol->cacheDirty(); - -open: - // open entry in cache. - if (!openCachedEntry(dirFile, curIndex, oflag, lfnOrd)) { - DBG_FAIL_MACRO; - goto fail; - } - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -size_t FatFile::printName(print_t* pr) { - FatFile dirFile; - uint16_t u; - size_t n = 0; - ldir_t* ldir; - - if (!isLFN()) { - return printSFN(pr); - } - if (!dirFile.openCluster(this)) { - DBG_FAIL_MACRO; - goto fail; - } - for (uint8_t ord = 1; ord <= m_lfnOrd; ord++) { - if (!dirFile.seekSet(32UL*(m_dirIndex - ord))) { - DBG_FAIL_MACRO; - goto fail; - } - ldir = reinterpret_cast(dirFile.readDirCache()); - if (!ldir) { - DBG_FAIL_MACRO; - goto fail; - } - if (ldir->attr != DIR_ATT_LONG_NAME || - ord != (ldir->ord & 0X1F)) { - DBG_FAIL_MACRO; - goto fail; - } - for (uint8_t i = 0; i < 13; i++) { - u = lfnGetChar(ldir, i); - if (u == 0) { - // End of name. - break; - } - if (u > 0X7E) { - u = '?'; - } - pr->write(static_cast(u)); - n++; - } - if (ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) { - return n; - } - } - // Fall into fail; - DBG_FAIL_MACRO; - -fail: - return 0; -} -//------------------------------------------------------------------------------ -bool FatFile::remove() { - bool last; - uint8_t chksum; - uint8_t ord; - FatFile dirFile; - dir_t* dir; - ldir_t* ldir; - - // Cant' remove not open for write. - if (!isFile() || !(m_flags & O_WRITE)) { - DBG_FAIL_MACRO; - goto fail; - } - // Free any clusters. - if (m_firstCluster && !m_vol->freeChain(m_firstCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - // Cache directory entry. - dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - chksum = lfnChecksum(dir->name); - - // Mark entry deleted. - dir->name[0] = DIR_NAME_DELETED; - - // Set this file closed. - m_attr = FILE_ATTR_CLOSED; - - // Write entry to device. - if (!m_vol->cacheSync()) { - DBG_FAIL_MACRO; - goto fail; - } - if (!isLFN()) { - // Done, no LFN entries. - return true; - } - if (!dirFile.openCluster(this)) { - DBG_FAIL_MACRO; - goto fail; - } - for (ord = 1; ord <= m_lfnOrd; ord++) { - if (!dirFile.seekSet(32UL*(m_dirIndex - ord))) { - DBG_FAIL_MACRO; - goto fail; - } - ldir = reinterpret_cast(dirFile.readDirCache()); - if (!ldir) { - DBG_FAIL_MACRO; - goto fail; - } - if (ldir->attr != DIR_ATT_LONG_NAME || - ord != (ldir->ord & 0X1F) || - chksum != ldir->chksum) { - DBG_FAIL_MACRO; - goto fail; - } - last = ldir->ord & LDIR_ORD_LAST_LONG_ENTRY; - ldir->ord = DIR_NAME_DELETED; - m_vol->cacheDirty(); - if (last) { - if (!m_vol->cacheSync()) { - DBG_FAIL_MACRO; - goto fail; - } - return true; - } - } - // Fall into fail. - DBG_FAIL_MACRO; - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatFile::lfnUniqueSfn(fname_t* fname) { - const uint8_t FIRST_HASH_SEQ = 2; // min value is 2 - uint8_t pos = fname->seqPos;; - dir_t *dir; - uint16_t hex; - - DBG_HALT_IF(!(fname->flags & FNAME_FLAG_LOST_CHARS)); - DBG_HALT_IF(fname->sfn[pos] != '~' && fname->sfn[pos + 1] != '1'); - - for (uint8_t seq = 2; seq < 100; seq++) { - if (seq < FIRST_HASH_SEQ) { - fname->sfn[pos + 1] = '0' + seq; - } else { - DBG_PRINT_IF(seq > FIRST_HASH_SEQ); - hex = Bernstein(seq + fname->len, fname->lfn, fname->len); - if (pos > 3) { - // Make space in name for ~HHHH. - pos = 3; - } - for (uint8_t i = pos + 4 ; i > pos; i--) { - uint8_t h = hex & 0XF; - fname->sfn[i] = h < 10 ? h + '0' : h + 'A' - 10; - hex >>= 4; - } - } - fname->sfn[pos] = '~'; - rewind(); - while (1) { - dir = readDirCache(true); - if (!dir) { - if (!getError()) { - // At EOF and name not found if no error. - goto done; - } - DBG_FAIL_MACRO; - goto fail; - } - if (dir->name[0] == DIR_NAME_FREE) { - goto done; - } - if (DIR_IS_FILE_OR_SUBDIR(dir) && !memcmp(fname->sfn, dir->name, 11)) { - // Name found - try another. - break; - } - } - } - // fall inti fail - too many tries. - DBG_FAIL_MACRO; - -fail: - return false; - -done: - return true; -} -#endif // #if USE_LONG_FILE_NAMES diff --git a/SdFat/utility/FatFilePrint.cpp b/SdFat/utility/FatFilePrint.cpp deleted file mode 100644 index c6a06611..00000000 --- a/SdFat/utility/FatFilePrint.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* FatLib Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#include -#include "FatFile.h" -#include "FmtNumber.h" -//------------------------------------------------------------------------------ -// print uint8_t with width 2 -static void print2u(print_t* pr, uint8_t v) { - char c0 = '?'; - char c1 = '?'; - if (v < 100) { - c1 = v/10; - c0 = v - 10*c1 + '0'; - c1 += '0'; - } - pr->write(c1); - pr->write(c0); -} -//------------------------------------------------------------------------------ -static void printU32(print_t* pr, uint32_t v) { - char buf[11]; - char* ptr = buf + sizeof(buf); - *--ptr = 0; - pr->write(fmtDec(v, ptr)); -} -//------------------------------------------------------------------------------ -static void printHex(print_t* pr, uint8_t w, uint16_t h) { - char buf[5]; - char* ptr = buf + sizeof(buf); - *--ptr = 0; - for (uint8_t i = 0; i < w; i++) { - char c = h & 0XF; - *--ptr = c < 10 ? c + '0' : c + 'A' - 10; - h >>= 4; - } - pr->write(ptr); -} -//------------------------------------------------------------------------------ -void FatFile::dmpFile(print_t* pr, uint32_t pos, size_t n) { - char text[17]; - text[16] = 0; - if (n >= 0XFFF0) { - n = 0XFFF0; - } - if (!seekSet(pos)) { - return; - } - for (size_t i = 0; i <= n; i++) { - if ((i & 15) == 0) { - if (i) { - pr->write(' '); - pr->write(text); - if (i == n) { - break; - } - } - pr->write('\r'); - pr->write('\n'); - if (i >= n) { - break; - } - printHex(pr, 4, i); - pr->write(' '); - } - int16_t h = read(); - if (h < 0) { - break; - } - pr->write(' '); - printHex(pr, 2, h); - text[i&15] = ' ' <= h && h < 0X7F ? h : '.'; - } - pr->write('\r'); - pr->write('\n'); -} -//------------------------------------------------------------------------------ -void FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) { - FatFile file; - rewind(); - while (file.openNext(this, O_READ)) { - // indent for dir level - if (!file.isHidden() || (flags & LS_A)) { - for (uint8_t i = 0; i < indent; i++) { - pr->write(' '); - } - if (flags & LS_DATE) { - file.printModifyDateTime(pr); - pr->write(' '); - } - if (flags & LS_SIZE) { - file.printFileSize(pr); - pr->write(' '); - } - file.printName(pr); - if (file.isDir()) { - pr->write('/'); - } - pr->write('\r'); - pr->write('\n'); - if ((flags & LS_R) && file.isDir()) { - file.ls(pr, flags, indent + 2); - } - } - file.close(); - } -} -//------------------------------------------------------------------------------ -bool FatFile::printCreateDateTime(print_t* pr) { - dir_t dir; - if (!dirEntry(&dir)) { - DBG_FAIL_MACRO; - goto fail; - } - printFatDate(pr, dir.creationDate); - pr->write(' '); - printFatTime(pr, dir.creationTime); - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -void FatFile::printFatDate(print_t* pr, uint16_t fatDate) { - printU32(pr, FAT_YEAR(fatDate)); - pr->write('-'); - print2u(pr, FAT_MONTH(fatDate)); - pr->write('-'); - print2u(pr, FAT_DAY(fatDate)); -} -//------------------------------------------------------------------------------ -void FatFile::printFatTime(print_t* pr, uint16_t fatTime) { - print2u(pr, FAT_HOUR(fatTime)); - pr->write(':'); - print2u(pr, FAT_MINUTE(fatTime)); - pr->write(':'); - print2u(pr, FAT_SECOND(fatTime)); -} -//------------------------------------------------------------------------------ -/** Template for FatFile::printField() */ -template -static int printFieldT(FatFile* file, char sign, Type value, char term) { - char buf[3*sizeof(Type) + 3]; - char* str = &buf[sizeof(buf)]; - - if (term) { - *--str = term; - if (term == '\n') { - *--str = '\r'; - } - } -#ifdef OLD_FMT - do { - Type m = value; - value /= 10; - *--str = '0' + m - 10*value; - } while (value); -#else // OLD_FMT - str = fmtDec(value, str); -#endif // OLD_FMT - if (sign) { - *--str = sign; - } - return file->write(str, &buf[sizeof(buf)] - str); -} -//------------------------------------------------------------------------------ - -int FatFile::printField(float value, char term, uint8_t prec) { - char buf[24]; - char* str = &buf[sizeof(buf)]; - if (term) { - *--str = term; - if (term == '\n') { - *--str = '\r'; - } - } - str = fmtFloat(value, str, prec); - return write(str, buf + sizeof(buf) - str); -} -//------------------------------------------------------------------------------ -int FatFile::printField(uint16_t value, char term) { - return printFieldT(this, 0, value, term); -} -//------------------------------------------------------------------------------ -int FatFile::printField(int16_t value, char term) { - char sign = 0; - if (value < 0) { - sign = '-'; - value = -value; - } - return printFieldT(this, sign, (uint16_t)value, term); -} -//------------------------------------------------------------------------------ -int FatFile::printField(uint32_t value, char term) { - return printFieldT(this, 0, value, term); -} -//------------------------------------------------------------------------------ -int FatFile::printField(int32_t value, char term) { - char sign = 0; - if (value < 0) { - sign = '-'; - value = -value; - } - return printFieldT(this, sign, (uint32_t)value, term); -} -//------------------------------------------------------------------------------ -bool FatFile::printModifyDateTime(print_t* pr) { - dir_t dir; - if (!dirEntry(&dir)) { - DBG_FAIL_MACRO; - goto fail; - } - printFatDate(pr, dir.lastWriteDate); - pr->write(' '); - printFatTime(pr, dir.lastWriteTime); - return true; - -fail: - return false; -} - -//------------------------------------------------------------------------------ -size_t FatFile::printFileSize(print_t* pr) { - char buf[11]; - char *ptr = buf + sizeof(buf); - *--ptr = 0; - ptr = fmtDec(fileSize(), ptr); - while (ptr > buf) { - *--ptr = ' '; - } - return pr->write(buf); -} diff --git a/SdFat/utility/FatFileSFN.cpp b/SdFat/utility/FatFileSFN.cpp deleted file mode 100644 index 4b89f09c..00000000 --- a/SdFat/utility/FatFileSFN.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* FatLib Library - * Copyright (C) 2012 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#include "FatFile.h" -#include "FatFileSystem.h" -//------------------------------------------------------------------------------ -bool FatFile::getSFN(char* name) { - dir_t* dir; - if (!isOpen()) { - DBG_FAIL_MACRO; - goto fail; - } - if (isRoot()) { - name[0] = '/'; - name[1] = '\0'; - return true; - } - // cache entry - dir = cacheDirEntry(FatCache::CACHE_FOR_READ); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // format name - dirName(dir, name); - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -size_t FatFile::printSFN(print_t* pr) { - char name[13]; - if (!getSFN(name)) { - DBG_FAIL_MACRO; - goto fail; - } - return pr->write(name); - -fail: - return 0; -} -#if !USE_LONG_FILE_NAMES -//------------------------------------------------------------------------------ -bool FatFile::getName(char* name, size_t size) { - return size < 13 ? 0 : getSFN(name); -} -//------------------------------------------------------------------------------ -// format directory name field from a 8.3 name string -bool FatFile::parsePathName(const char* path, fname_t* fname, - const char** ptr) { - uint8_t uc = 0; - uint8_t lc = 0; - uint8_t bit = FNAME_FLAG_LC_BASE; - // blank fill name and extension - for (uint8_t i = 0; i < 11; i++) { - fname->sfn[i] = ' '; - } - - for (uint8_t i = 0, n = 7;; path++) { - uint8_t c = *path; - if (c == 0 || isDirSeparator(c)) { - // Done. - break; - } - if (c == '.' && n == 7) { - n = 10; // max index for full 8.3 name - i = 8; // place for extension - - // bit for extension. - bit = FNAME_FLAG_LC_EXT; - } else { - if (!legal83Char(c) || i > n) { - DBG_FAIL_MACRO; - goto fail; - } - if ('a' <= c && c <= 'z') { - c += 'A' - 'a'; - lc |= bit; - } else if ('A' <= c && c <= 'Z') { - uc |= bit; - } - fname->sfn[i++] = c; - } - } - // must have a file name, extension is optional - if (fname->sfn[0] == ' ') { - DBG_FAIL_MACRO; - goto fail; - } - // Set base-name and extension bits. - fname->flags = lc & uc ? 0 : lc; - while (isDirSeparator(*path)) { - path++; - } - *ptr = path; - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -// open with filename in fname -#define SFN_OPEN_USES_CHKSUM 0 -bool FatFile::open(FatFile* dirFile, fname_t* fname, uint8_t oflag) { - bool emptyFound = false; -#if SFN_OPEN_USES_CHKSUM - uint8_t chksum; -#endif - uint8_t lfnOrd = 0; - uint16_t emptyIndex; - uint16_t index = 0; - dir_t* dir; - ldir_t* ldir; - - dirFile->rewind(); - while (1) { - if (!emptyFound) { - emptyIndex = index; - } - dir = dirFile->readDirCache(true); - if (!dir) { - if (dirFile->getError()) { - DBG_FAIL_MACRO; - goto fail; - } - // At EOF if no error. - break; - } - if (dir->name[0] == DIR_NAME_FREE) { - emptyFound = true; - break; - } - if (dir->name[0] == DIR_NAME_DELETED) { - lfnOrd = 0; - emptyFound = true; - } else if (DIR_IS_FILE_OR_SUBDIR(dir)) { - if (!memcmp(fname->sfn, dir->name, 11)) { - // don't open existing file if O_EXCL - if (oflag & O_EXCL) { - DBG_FAIL_MACRO; - goto fail; - } -#if SFN_OPEN_USES_CHKSUM - if (lfnOrd && chksum != lfnChecksum(dir->name)) { - DBG_FAIL_MACRO; - goto fail; - } -#endif // SFN_OPEN_USES_CHKSUM - if (!openCachedEntry(dirFile, index, oflag, lfnOrd)) { - DBG_FAIL_MACRO; - goto fail; - } - return true; - } else { - lfnOrd = 0; - } - } else if (DIR_IS_LONG_NAME(dir)) { - ldir = reinterpret_cast(dir); - if (ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) { - lfnOrd = ldir->ord & 0X1F; -#if SFN_OPEN_USES_CHKSUM - chksum = ldir->chksum; -#endif // SFN_OPEN_USES_CHKSUM - } - } else { - lfnOrd = 0; - } - index++; - } - // don't create unless O_CREAT and O_WRITE - if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) { - DBG_FAIL_MACRO; - goto fail; - } - if (emptyFound) { - index = emptyIndex; - } else { - if (!dirFile->addDirCluster()) { - DBG_FAIL_MACRO; - goto fail; - } - } - if (!dirFile->seekSet(32UL*index)) { - DBG_FAIL_MACRO; - goto fail; - } - dir = dirFile->readDirCache(); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // initialize as empty file - memset(dir, 0, sizeof(dir_t)); - memcpy(dir->name, fname->sfn, 11); - - // Set base-name and extension lower case bits. - dir->reservedNT = (DIR_NT_LC_BASE | DIR_NT_LC_EXT) & fname->flags; - - // set timestamps - if (m_dateTime) { - // call user date/time function - m_dateTime(&dir->creationDate, &dir->creationTime); - } else { - // use default date/time - dir->creationDate = FAT_DEFAULT_DATE; - dir->creationTime = FAT_DEFAULT_TIME; - } - dir->lastAccessDate = dir->creationDate; - dir->lastWriteDate = dir->creationDate; - dir->lastWriteTime = dir->creationTime; - - // Force write of entry to device. - dirFile->m_vol->cacheDirty(); - - // open entry in cache. - return openCachedEntry(dirFile, index, oflag, 0); - -fail: - return false; -} -//------------------------------------------------------------------------------ -size_t FatFile::printName(print_t* pr) { - return printSFN(pr); -} -//------------------------------------------------------------------------------ -bool FatFile::remove() { - dir_t* dir; - // Can't remove if LFN or not open for write. - if (!isFile() || isLFN() || !(m_flags & O_WRITE)) { - DBG_FAIL_MACRO; - goto fail; - } - // Free any clusters. - if (m_firstCluster && !m_vol->freeChain(m_firstCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - // Cache directory entry. - dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); - if (!dir) { - DBG_FAIL_MACRO; - goto fail; - } - // Mark entry deleted. - dir->name[0] = DIR_NAME_DELETED; - - // Set this file closed. - m_attr = FILE_ATTR_CLOSED; - - // Write entry to device. - return m_vol->cacheSync(); - -fail: - return false; -} -#endif // !USE_LONG_FILE_NAMES diff --git a/SdFat/utility/FatFileSystem.h b/SdFat/utility/FatFileSystem.h deleted file mode 100644 index 88955a42..00000000 --- a/SdFat/utility/FatFileSystem.h +++ /dev/null @@ -1,310 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef FatFileSystem_h -#define FatFileSystem_h -#include "FatVolume.h" -#include "FatFile.h" -#include "ArduinoFiles.h" -/** - * \file - * \brief FatFileSystem class - */ -//------------------------------------------------------------------------------ -/** - * \class FatFileSystem - * \brief Integration class for the FatLib library. - */ -class FatFileSystem : public FatVolume { - public: - /** - * Initialize an FatFileSystem object. - * \param[in] part partition to initialize. - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool begin(uint8_t part = 0) { - vwd()->close(); - return (part ? init(part) : init(1) || init(0)) - && vwd()->openRoot(this) && FatFile::setCwd(vwd()); - } -#if ENABLE_ARDUINO_FEATURES - /** List the directory contents of the volume working directory to Serial. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ - void ls(uint8_t flags = 0) { - ls(&Serial, flags); - } - /** List the directory contents of a directory to Serial. - * - * \param[in] path directory to list. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ - void ls(const char* path, uint8_t flags = 0) { - ls(&Serial, path, flags); - } - /** open a file - * - * \param[in] path location of file to be opened. - * \param[in] mode open mode flags. - * \return a File object. - */ - File open(const char *path, uint8_t mode = FILE_READ) { - File tmpFile; - tmpFile.open(vwd(), path, mode); - return tmpFile; - } -#endif // ENABLE_ARDUINO_FEATURES - /** Change a volume's working directory to root - * - * Changes the volume's working directory to the SD's root directory. - * Optionally set the current working directory to the volume's - * working directory. - * - * \param[in] set_cwd Set the current working directory to this volume's - * working directory if true. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool chdir(bool set_cwd = false) { - vwd()->close(); - return vwd()->openRoot(this) && (set_cwd ? FatFile::setCwd(vwd()) : true); - } - /** Change a volume's working directory - * - * Changes the volume working directory to the \a path subdirectory. - * Optionally set the current working directory to the volume's - * working directory. - * - * Example: If the volume's working directory is "/DIR", chdir("SUB") - * will change the volume's working directory from "/DIR" to "/DIR/SUB". - * - * If path is "/", the volume's working directory will be changed to the - * root directory - * - * \param[in] path The name of the subdirectory. - * - * \param[in] set_cwd Set the current working directory to this volume's - * working directory if true. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - //---------------------------------------------------------------------------- - bool chdir(const char *path, bool set_cwd = false) { - FatFile dir; - if (path[0] == '/' && path[1] == '\0') { - return chdir(set_cwd); - } - if (!dir.open(vwd(), path, O_READ)) { - goto fail; - } - if (!dir.isDir()) { - goto fail; - } -// *m_vwd = dir; - m_vwd = dir; - if (set_cwd) { - FatFile::setCwd(vwd()); - } - return true; - -fail: - return false; - } - //---------------------------------------------------------------------------- - /** Set the current working directory to a volume's working directory. - * - * This is useful with multiple SD cards. - * - * The current working directory is changed to this - * volume's working directory. - * - * This is like the Windows/DOS \: command. - */ - void chvol() { - FatFile::setCwd(vwd()); - } - //---------------------------------------------------------------------------- - /** - * Test for the existence of a file. - * - * \param[in] path Path of the file to be tested for. - * - * \return true if the file exists else false. - */ - bool exists(const char* path) { - return vwd()->exists(path); - } - //---------------------------------------------------------------------------- - /** List the directory contents of the volume working directory. - * - * \param[in] pr Print stream for list. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ - void ls(print_t* pr, uint8_t flags) { - vwd()->ls(pr, flags); - } - //---------------------------------------------------------------------------- - /** List the directory contents of a directory. - * - * \param[in] pr Print stream for list. - * - * \param[in] path directory to list. - * - * \param[in] flags The inclusive OR of - * - * LS_DATE - %Print file modification date - * - * LS_SIZE - %Print file size. - * - * LS_R - Recursive list of subdirectories. - */ - void ls(print_t* pr, const char* path, uint8_t flags) { - FatFile dir; - dir.open(vwd(), path, O_READ); - dir.ls(pr, flags); - } - //---------------------------------------------------------------------------- - /** Make a subdirectory in the volume working directory. - * - * \param[in] path A path with a valid 8.3 DOS name for the subdirectory. - * - * \param[in] pFlag Create missing parent directories if true. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool mkdir(const char* path, bool pFlag = true) { - FatFile sub; - return sub.mkdir(vwd(), path, pFlag); - } - //---------------------------------------------------------------------------- - /** Remove a file from the volume working directory. - * - * \param[in] path A path with a valid 8.3 DOS name for the file. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool remove(const char* path) { - return FatFile::remove(vwd(), path); - } - //---------------------------------------------------------------------------- - /** Rename a file or subdirectory. - * - * \param[in] oldPath Path name to the file or subdirectory to be renamed. - * - * \param[in] newPath New path name of the file or subdirectory. - * - * The \a newPath object must not exist before the rename call. - * - * The file to be renamed must not be open. The directory entry may be - * moved and file system corruption could occur if the file is accessed by - * a file object that was opened before the rename() call. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool rename(const char *oldPath, const char *newPath) { - FatFile file; - if (!file.open(vwd(), oldPath, O_READ)) { - return false; - } - return file.rename(vwd(), newPath); - } - //---------------------------------------------------------------------------- - /** Remove a subdirectory from the volume's working directory. - * - * \param[in] path A path with a valid 8.3 DOS name for the subdirectory. - * - * The subdirectory file will be removed only if it is empty. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool rmdir(const char* path) { - FatFile sub; - if (!sub.open(vwd(), path, O_READ)) { - return false; - } - return sub.rmdir(); - } - //---------------------------------------------------------------------------- - /** Truncate a file to a specified length. The current file position - * will be maintained if it is less than or equal to \a length otherwise - * it will be set to end of file. - * - * \param[in] path A path with a valid 8.3 DOS name for the file. - * \param[in] length The desired length for the file. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool truncate(const char* path, uint32_t length) { - FatFile file; - if (!file.open(vwd(), path, O_WRITE)) { - return false; - } - return file.truncate(length); - } - /** \return a pointer to the FatVolume object. */ - FatVolume* vol() { - return this; - } - /** \return a pointer to the volume working directory. */ - FatFile* vwd() { - return &m_vwd; - } - /** Wipe all data from the volume. You must reinitialize the volume before - * accessing it again. - * \param[in] pr print stream for status dots. - * \return true for success else false. - */ - bool wipe(print_t* pr = 0) { - vwd()->close(); - return FatVolume::wipe(pr); - } - - private: - FatFile m_vwd; -}; -#endif // FatFileSystem_h diff --git a/SdFat/utility/FatLib.h b/SdFat/utility/FatLib.h deleted file mode 100644 index 425a92b5..00000000 --- a/SdFat/utility/FatLib.h +++ /dev/null @@ -1,33 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef FatLib_h -#define FatLib_h -#include "ArduinoFiles.h" -#include "ArduinoStream.h" -#include "FatFileSystem.h" -#include "FatLibConfig.h" -#include "FatVolume.h" -#include "FatFile.h" -#include "StdioStream.h" -#include "fstream.h" -//------------------------------------------------------------------------------ -/** FatFileSystem version YYYYMMDD */ -#define FAT_LIB_VERSION 20150131 -#endif // FatLib_h diff --git a/SdFat/utility/FatLibConfig.h b/SdFat/utility/FatLibConfig.h deleted file mode 100644 index 923e7a07..00000000 --- a/SdFat/utility/FatLibConfig.h +++ /dev/null @@ -1,143 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -/** - * \file - * \brief configuration definitions - */ -#ifndef FatLibConfig_h -#define FatLibConfig_h -#include -// Allow this file to override defaults. -#include "../SdFatConfig.h" - -#ifdef __AVR__ -#include -#endif // __AVR__ -//------------------------------------------------------------------------------ -/** - * Set USE_LONG_FILE_NAMES nonzero to use long file names (LFN). - * Long File Name are limited to a maximum length of 255 characters. - * - * This implementation allows 7-bit characters in the range - * 0X20 to 0X7E. The following characters are not allowed: - * - * < (less than) - * > (greater than) - * : (colon) - * " (double quote) - * / (forward slash) - * \ (backslash) - * | (vertical bar or pipe) - * ? (question mark) - * * (asterisk) - * - */ -#ifndef USE_LONG_FILE_NAMES -#define USE_LONG_FILE_NAMES 1 -#endif // USE_LONG_FILE_NAMES -//------------------------------------------------------------------------------ -/** - * Set ARDUINO_FILE_USES_STREAM nonzero to use Stream as the base class - * for the Arduino File class. If ARDUINO_FILE_USES_STREAM is zero, Print - * will be used as the base class for the Arduino File class. - * - * You can save some flash if you do not use Stream input functions such as - * find(), findUntil(), readBytesUntil(), readString(), readStringUntil(), - * parseInt(), and parsefloat(). - */ -#ifndef ARDUINO_FILE_USES_STREAM -#define ARDUINO_FILE_USES_STREAM 1 -#endif // ARDUINO_FILE_USES_STREAM -//------------------------------------------------------------------------------ -/** - * Set USE_SEPARATE_FAT_CACHE non-zero to use a second 512 byte cache - * for FAT table entries. Improves performance for large writes that - * are not a multiple of 512 bytes. - */ -#ifndef USE_SEPARATE_FAT_CACHE -#ifdef __arm__ -#define USE_SEPARATE_FAT_CACHE 1 -#else // __arm__ -#define USE_SEPARATE_FAT_CACHE 0 -#endif // __arm__ -#endif // USE_SEPARATE_FAT_CACHE -//------------------------------------------------------------------------------ -/** - * Set USE_MULTI_BLOCK_IO non-zero to use multi-block SD read/write. - * - * Don't use mult-block read/write on small AVR boards. - */ -#ifndef USE_MULTI_BLOCK_IO -#if defined(RAMEND) && RAMEND < 3000 -#define USE_MULTI_BLOCK_IO 0 -#else // RAMEND -#define USE_MULTI_BLOCK_IO 1 -#endif // RAMEND -#endif // USE_MULTI_BLOCK_IO -//------------------------------------------------------------------------------ -/** - * Set DESTRUCTOR_CLOSES_FILE non-zero to close a file in its destructor. - * - * Causes use of lots of heap in ARM. - */ -#ifndef DESTRUCTOR_CLOSES_FILE -#define DESTRUCTOR_CLOSES_FILE 0 -#endif // DESTRUCTOR_CLOSES_FILE -//------------------------------------------------------------------------------ -/** - * Call flush for endl if ENDL_CALLS_FLUSH is non-zero - * - * The standard for iostreams is to call flush. This is very costly for - * SdFat. Each call to flush causes 2048 bytes of I/O to the SD. - * - * SdFat has a single 512 byte buffer for I/O so it must write the current - * data block to the SD, read the directory block from the SD, update the - * directory entry, write the directory block to the SD and read the data - * block back into the buffer. - * - * The SD flash memory controller is not designed for this many rewrites - * so performance may be reduced by more than a factor of 100. - * - * If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force - * all data to be written to the SD. - */ -#ifndef ENDL_CALLS_FLUSH -#define ENDL_CALLS_FLUSH 0 -#endif // ENDL_CALLS_FLUSH -//------------------------------------------------------------------------------ -/** - * Allow FAT12 volumes if FAT12_SUPPORT is non-zero. - * FAT12 has not been well tested. - */ -#ifndef FAT12_SUPPORT -#define FAT12_SUPPORT 0 -#endif // FAT12_SUPPORT -//------------------------------------------------------------------------------ -/** - * Enable Extra features for Arduino. - */ -#ifndef ENABLE_ARDUINO_FEATURES -#if defined(ARDUINO) || defined(DOXYGEN) -#define ENABLE_ARDUINO_FEATURES 1 -#else // #if defined(ARDUINO) || defined(DOXYGEN) -#define ENABLE_ARDUINO_FEATURES 0 -#endif // defined(ARDUINO) || defined(DOXYGEN) -#endif // ENABLE_ARDUINO_FEATURES -#endif // FatLibConfig_h diff --git a/SdFat/utility/FatStructs.h b/SdFat/utility/FatStructs.h deleted file mode 100644 index 6aae34b4..00000000 --- a/SdFat/utility/FatStructs.h +++ /dev/null @@ -1,755 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef FatStructs_h -#define FatStructs_h -/** - * \file - * \brief FAT file structures - */ -/* - * mostly from Microsoft document fatgen103.doc - * http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx - */ -//------------------------------------------------------------------------------ -/** Value for byte 510 of boot block or MBR */ -uint8_t const BOOTSIG0 = 0X55; -/** Value for byte 511 of boot block or MBR */ -uint8_t const BOOTSIG1 = 0XAA; -/** Value for bootSignature field int FAT/FAT32 boot sector */ -uint8_t const EXTENDED_BOOT_SIG = 0X29; -//------------------------------------------------------------------------------ -/** - * \struct partitionTable - * \brief MBR partition table entry - * - * A partition table entry for a MBR formatted storage device. - * The MBR partition table has four entries. - */ -struct partitionTable { - /** - * Boot Indicator . Indicates whether the volume is the active - * partition. Legal values include: 0X00. Do not use for booting. - * 0X80 Active partition. - */ - uint8_t boot; - /** - * Head part of Cylinder-head-sector address of the first block in - * the partition. Legal values are 0-255. Only used in old PC BIOS. - */ - uint8_t beginHead; - /** - * Sector part of Cylinder-head-sector address of the first block in - * the partition. Legal values are 1-63. Only used in old PC BIOS. - */ - unsigned beginSector : 6; - /** High bits cylinder for first block in partition. */ - unsigned beginCylinderHigh : 2; - /** - * Combine beginCylinderLow with beginCylinderHigh. Legal values - * are 0-1023. Only used in old PC BIOS. - */ - uint8_t beginCylinderLow; - /** - * Partition type. See defines that begin with PART_TYPE_ for - * some Microsoft partition types. - */ - uint8_t type; - /** - * head part of cylinder-head-sector address of the last sector in the - * partition. Legal values are 0-255. Only used in old PC BIOS. - */ - uint8_t endHead; - /** - * Sector part of cylinder-head-sector address of the last sector in - * the partition. Legal values are 1-63. Only used in old PC BIOS. - */ - unsigned endSector : 6; - /** High bits of end cylinder */ - unsigned endCylinderHigh : 2; - /** - * Combine endCylinderLow with endCylinderHigh. Legal values - * are 0-1023. Only used in old PC BIOS. - */ - uint8_t endCylinderLow; - /** Logical block address of the first block in the partition. */ - uint32_t firstSector; - /** Length of the partition, in blocks. */ - uint32_t totalSectors; -} __attribute__((packed)); -/** Type name for partitionTable */ -typedef struct partitionTable part_t; -//------------------------------------------------------------------------------ -/** - * \struct masterBootRecord - * - * \brief Master Boot Record - * - * The first block of a storage device that is formatted with a MBR. - */ -struct masterBootRecord { - /** Code Area for master boot program. */ - uint8_t codeArea[440]; - /** Optional Windows NT disk signature. May contain boot code. */ - uint32_t diskSignature; - /** Usually zero but may be more boot code. */ - uint16_t usuallyZero; - /** Partition tables. */ - part_t part[4]; - /** First MBR signature byte. Must be 0X55 */ - uint8_t mbrSig0; - /** Second MBR signature byte. Must be 0XAA */ - uint8_t mbrSig1; -} __attribute__((packed)); -/** Type name for masterBootRecord */ -typedef struct masterBootRecord mbr_t; -//------------------------------------------------------------------------------ -/** - * \struct fat_boot - * - * \brief Boot sector for a FAT12/FAT16 volume. - * - */ -struct fat_boot { - /** - * The first three bytes of the boot sector must be valid, - * executable x 86-based CPU instructions. This includes a - * jump instruction that skips the next non-executable bytes. - */ - uint8_t jump[3]; - /** - * This is typically a string of characters that identifies - * the operating system that formatted the volume. - */ - char oemId[8]; - /** - * The size of a hardware sector. Valid decimal values for this - * field are 512, 1024, 2048, and 4096. For most disks used in - * the United States, the value of this field is 512. - */ - uint16_t bytesPerSector; - /** - * Number of sectors per allocation unit. This value must be a - * power of 2 that is greater than 0. The legal values are - * 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided. - */ - uint8_t sectorsPerCluster; - /** - * The number of sectors preceding the start of the first FAT, - * including the boot sector. The value of this field is always 1. - */ - uint16_t reservedSectorCount; - /** - * The number of copies of the FAT on the volume. - * The value of this field is always 2. - */ - uint8_t fatCount; - /** - * For FAT12 and FAT16 volumes, this field contains the count of - * 32-byte directory entries in the root directory. For FAT32 volumes, - * this field must be set to 0. For FAT12 and FAT16 volumes, this - * value should always specify a count that when multiplied by 32 - * results in a multiple of bytesPerSector. FAT16 volumes should - * use the value 512. - */ - uint16_t rootDirEntryCount; - /** - * This field is the old 16-bit total count of sectors on the volume. - * This count includes the count of all sectors in all four regions - * of the volume. This field can be 0; if it is 0, then totalSectors32 - * must be non-zero. For FAT32 volumes, this field must be 0. For - * FAT12 and FAT16 volumes, this field contains the sector count, and - * totalSectors32 is 0 if the total sector count fits - * (is less than 0x10000). - */ - uint16_t totalSectors16; - /** - * This dates back to the old MS-DOS 1.x media determination and is - * no longer usually used for anything. 0xF8 is the standard value - * for fixed (non-removable) media. For removable media, 0xF0 is - * frequently used. Legal values are 0xF0 or 0xF8-0xFF. - */ - uint8_t mediaType; - /** - * Count of sectors occupied by one FAT on FAT12/FAT16 volumes. - * On FAT32 volumes this field must be 0, and sectorsPerFat32 - * contains the FAT size count. - */ - uint16_t sectorsPerFat16; - /** Sectors per track for interrupt 0x13. Not used otherwise. */ - uint16_t sectorsPerTrack; - /** Number of heads for interrupt 0x13. Not used otherwise. */ - uint16_t headCount; - /** - * Count of hidden sectors preceding the partition that contains this - * FAT volume. This field is generally only relevant for media - * visible on interrupt 0x13. - */ - uint32_t hidddenSectors; - /** - * This field is the new 32-bit total count of sectors on the volume. - * This count includes the count of all sectors in all four regions - * of the volume. This field can be 0; if it is 0, then - * totalSectors16 must be non-zero. - */ - uint32_t totalSectors32; - /** - * Related to the BIOS physical drive number. Floppy drives are - * identified as 0x00 and physical hard disks are identified as - * 0x80, regardless of the number of physical disk drives. - * Typically, this value is set prior to issuing an INT 13h BIOS - * call to specify the device to access. The value is only - * relevant if the device is a boot device. - */ - uint8_t driveNumber; - /** used by Windows NT - should be zero for FAT */ - uint8_t reserved1; - /** 0X29 if next three fields are valid */ - uint8_t bootSignature; - /** - * A random serial number created when formatting a disk, - * which helps to distinguish between disks. - * Usually generated by combining date and time. - */ - uint32_t volumeSerialNumber; - /** - * A field once used to store the volume label. The volume label - * is now stored as a special file in the root directory. - */ - char volumeLabel[11]; - /** - * A field with a value of either FAT, FAT12 or FAT16, - * depending on the disk format. - */ - char fileSystemType[8]; - /** X86 boot code */ - uint8_t bootCode[448]; - /** must be 0X55 */ - uint8_t bootSectorSig0; - /** must be 0XAA */ - uint8_t bootSectorSig1; -} __attribute__((packed)); -/** Type name for FAT Boot Sector */ -typedef struct fat_boot fat_boot_t; -//------------------------------------------------------------------------------ -/** - * \struct fat32_boot - * - * \brief Boot sector for a FAT32 volume. - * - */ -struct fat32_boot { - /** - * The first three bytes of the boot sector must be valid, - * executable x 86-based CPU instructions. This includes a - * jump instruction that skips the next non-executable bytes. - */ - uint8_t jump[3]; - /** - * This is typically a string of characters that identifies - * the operating system that formatted the volume. - */ - char oemId[8]; - /** - * The size of a hardware sector. Valid decimal values for this - * field are 512, 1024, 2048, and 4096. For most disks used in - * the United States, the value of this field is 512. - */ - uint16_t bytesPerSector; - /** - * Number of sectors per allocation unit. This value must be a - * power of 2 that is greater than 0. The legal values are - * 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided. - */ - uint8_t sectorsPerCluster; - /** - * The number of sectors preceding the start of the first FAT, - * including the boot sector. Must not be zero - */ - uint16_t reservedSectorCount; - /** - * The number of copies of the FAT on the volume. - * The value of this field is always 2. - */ - uint8_t fatCount; - /** - * FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0. - */ - uint16_t rootDirEntryCount; - /** - * For FAT32 volumes, this field must be 0. - */ - uint16_t totalSectors16; - /** - * This dates back to the old MS-DOS 1.x media determination and is - * no longer usually used for anything. 0xF8 is the standard value - * for fixed (non-removable) media. For removable media, 0xF0 is - * frequently used. Legal values are 0xF0 or 0xF8-0xFF. - */ - uint8_t mediaType; - /** - * On FAT32 volumes this field must be 0, and sectorsPerFat32 - * contains the FAT size count. - */ - uint16_t sectorsPerFat16; - /** Sectors per track for interrupt 0x13. Not used otherwise. */ - uint16_t sectorsPerTrack; - /** Number of heads for interrupt 0x13. Not used otherwise. */ - uint16_t headCount; - /** - * Count of hidden sectors preceding the partition that contains this - * FAT volume. This field is generally only relevant for media - * visible on interrupt 0x13. - */ - uint32_t hidddenSectors; - /** - * Contains the total number of sectors in the FAT32 volume. - */ - uint32_t totalSectors32; - /** - * Count of sectors occupied by one FAT on FAT32 volumes. - */ - uint32_t sectorsPerFat32; - /** - * This field is only defined for FAT32 media and does not exist on - * FAT12 and FAT16 media. - * Bits 0-3 -- Zero-based number of active FAT. - * Only valid if mirroring is disabled. - * Bits 4-6 -- Reserved. - * Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. - * -- 1 means only one FAT is active; it is the one referenced - * in bits 0-3. - * Bits 8-15 -- Reserved. - */ - uint16_t fat32Flags; - /** - * FAT32 version. High byte is major revision number. - * Low byte is minor revision number. Only 0.0 define. - */ - uint16_t fat32Version; - /** - * Cluster number of the first cluster of the root directory for FAT32. - * This usually 2 but not required to be 2. - */ - uint32_t fat32RootCluster; - /** - * Sector number of FSINFO structure in the reserved area of the - * FAT32 volume. Usually 1. - */ - uint16_t fat32FSInfo; - /** - * If non-zero, indicates the sector number in the reserved area - * of the volume of a copy of the boot record. Usually 6. - * No value other than 6 is recommended. - */ - uint16_t fat32BackBootBlock; - /** - * Reserved for future expansion. Code that formats FAT32 volumes - * should always set all of the bytes of this field to 0. - */ - uint8_t fat32Reserved[12]; - /** - * Related to the BIOS physical drive number. Floppy drives are - * identified as 0x00 and physical hard disks are identified as - * 0x80, regardless of the number of physical disk drives. - * Typically, this value is set prior to issuing an INT 13h BIOS - * call to specify the device to access. The value is only - * relevant if the device is a boot device. - */ - uint8_t driveNumber; - /** used by Windows NT - should be zero for FAT */ - uint8_t reserved1; - /** 0X29 if next three fields are valid */ - uint8_t bootSignature; - /** - * A random serial number created when formatting a disk, - * which helps to distinguish between disks. - * Usually generated by combining date and time. - */ - uint32_t volumeSerialNumber; - /** - * A field once used to store the volume label. The volume label - * is now stored as a special file in the root directory. - */ - char volumeLabel[11]; - /** - * A text field with a value of FAT32. - */ - char fileSystemType[8]; - /** X86 boot code */ - uint8_t bootCode[420]; - /** must be 0X55 */ - uint8_t bootSectorSig0; - /** must be 0XAA */ - uint8_t bootSectorSig1; -} __attribute__((packed)); -/** Type name for FAT32 Boot Sector */ -typedef struct fat32_boot fat32_boot_t; -//------------------------------------------------------------------------------ -/** Lead signature for a FSINFO sector */ -uint32_t const FSINFO_LEAD_SIG = 0x41615252; -/** Struct signature for a FSINFO sector */ -uint32_t const FSINFO_STRUCT_SIG = 0x61417272; -/** - * \struct fat32_fsinfo - * - * \brief FSINFO sector for a FAT32 volume. - * - */ -struct fat32_fsinfo { - /** must be 0X52, 0X52, 0X61, 0X41 */ - uint32_t leadSignature; - /** must be zero */ - uint8_t reserved1[480]; - /** must be 0X72, 0X72, 0X41, 0X61 */ - uint32_t structSignature; - /** - * Contains the last known free cluster count on the volume. - * If the value is 0xFFFFFFFF, then the free count is unknown - * and must be computed. Any other value can be used, but is - * not necessarily correct. It should be range checked at least - * to make sure it is <= volume cluster count. - */ - uint32_t freeCount; - /** - * This is a hint for the FAT driver. It indicates the cluster - * number at which the driver should start looking for free clusters. - * If the value is 0xFFFFFFFF, then there is no hint and the driver - * should start looking at cluster 2. - */ - uint32_t nextFree; - /** must be zero */ - uint8_t reserved2[12]; - /** must be 0X00, 0X00, 0X55, 0XAA */ - uint8_t tailSignature[4]; -} __attribute__((packed)); -/** Type name for FAT32 FSINFO Sector */ -typedef struct fat32_fsinfo fat32_fsinfo_t; -//------------------------------------------------------------------------------ -// End Of Chain values for FAT entries -/** FAT12 end of chain value used by Microsoft. */ -uint16_t const FAT12EOC = 0XFFF; -/** Minimum value for FAT12 EOC. Use to test for EOC. */ -uint16_t const FAT12EOC_MIN = 0XFF8; -/** FAT16 end of chain value used by Microsoft. */ -uint16_t const FAT16EOC = 0XFFFF; -/** Minimum value for FAT16 EOC. Use to test for EOC. */ -uint16_t const FAT16EOC_MIN = 0XFFF8; -/** FAT32 end of chain value used by Microsoft. */ -uint32_t const FAT32EOC = 0X0FFFFFFF; -/** Minimum value for FAT32 EOC. Use to test for EOC. */ -uint32_t const FAT32EOC_MIN = 0X0FFFFFF8; -/** Mask a for FAT32 entry. Entries are 28 bits. */ -uint32_t const FAT32MASK = 0X0FFFFFFF; -//------------------------------------------------------------------------------ -/** - * \struct directoryEntry - * \brief FAT short directory entry - * - * Short means short 8.3 name, not the entry size. - * - * Date Format. A FAT directory entry date stamp is a 16-bit field that is - * basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the - * format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the - * 16-bit word): - * - * Bits 9-15: Count of years from 1980, valid value range 0-127 - * inclusive (1980-2107). - * - * Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. - * - * Bits 0-4: Day of month, valid value range 1-31 inclusive. - * - * Time Format. A FAT directory entry time stamp is a 16-bit field that has - * a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the - * 16-bit word, bit 15 is the MSB of the 16-bit word). - * - * Bits 11-15: Hours, valid value range 0-23 inclusive. - * - * Bits 5-10: Minutes, valid value range 0-59 inclusive. - * - * Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). - * - * The valid time range is from Midnight 00:00:00 to 23:59:58. - */ -struct directoryEntry { - /** Short 8.3 name. - * - * The first eight bytes contain the file name with blank fill. - * The last three bytes contain the file extension with blank fill. - */ - uint8_t name[11]; - /** Entry attributes. - * - * The upper two bits of the attribute byte are reserved and should - * always be set to 0 when a file is created and never modified or - * looked at after that. See defines that begin with DIR_ATT_. - */ - uint8_t attributes; - /** - * Reserved for use by Windows NT. Set value to 0 when a file is - * created and never modify or look at it after that. - */ - uint8_t reservedNT; - /** - * The granularity of the seconds part of creationTime is 2 seconds - * so this field is a count of tenths of a second and its valid - * value range is 0-199 inclusive. (WHG note - seems to be hundredths) - */ - uint8_t creationTimeTenths; - /** Time file was created. */ - uint16_t creationTime; - /** Date file was created. */ - uint16_t creationDate; - /** - * Last access date. Note that there is no last access time, only - * a date. This is the date of last read or write. In the case of - * a write, this should be set to the same date as lastWriteDate. - */ - uint16_t lastAccessDate; - /** - * High word of this entry's first cluster number (always 0 for a - * FAT12 or FAT16 volume). - */ - uint16_t firstClusterHigh; - /** Time of last write. File creation is considered a write. */ - uint16_t lastWriteTime; - /** Date of last write. File creation is considered a write. */ - uint16_t lastWriteDate; - /** Low word of this entry's first cluster number. */ - uint16_t firstClusterLow; - /** 32-bit unsigned holding this file's size in bytes. */ - uint32_t fileSize; -} __attribute__((packed)); -/** Type name for directoryEntry */ -typedef struct directoryEntry dir_t; -//------------------------------------------------------------------------------ -// Definitions for directory entries -// -/** escape for name[0] = 0XE5 */ -uint8_t const DIR_NAME_0XE5 = 0X05; -/** name[0] value for entry that is free after being "deleted" */ -uint8_t const DIR_NAME_DELETED = 0XE5; -/** name[0] value for entry that is free and no allocated entries follow */ -uint8_t const DIR_NAME_FREE = 0X00; -/** file is read-only */ -uint8_t const DIR_ATT_READ_ONLY = 0X01; -/** File should e hidden in directory listings */ -uint8_t const DIR_ATT_HIDDEN = 0X02; -/** Entry is for a system file */ -uint8_t const DIR_ATT_SYSTEM = 0X04; -/** Directory entry contains the volume label */ -uint8_t const DIR_ATT_VOLUME_ID = 0X08; -/** Entry is for a directory */ -uint8_t const DIR_ATT_DIRECTORY = 0X10; -/** Old DOS archive bit for backup support */ -uint8_t const DIR_ATT_ARCHIVE = 0X20; -/** Test value for long name entry. Test is - (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */ -uint8_t const DIR_ATT_LONG_NAME = 0X0F; -/** Test mask for long name entry */ -uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; -/** defined attribute bits */ -uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; - -/** Mask for file/subdirectory tests */ -uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); - -/** Filename base-name is all lower case */ -const uint8_t DIR_NT_LC_BASE = 0X08; -/** Filename extension is all lower case.*/ -const uint8_t DIR_NT_LC_EXT = 0X10; - - -/** Directory entry is for a file - * \param[in] dir Pointer to a directory entry. - * - * \return true if the entry is for a normal file else false. - */ -static inline uint8_t DIR_IS_FILE(const dir_t* dir) { - return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; -} -/** Directory entry is for a file or subdirectory - * \param[in] dir Pointer to a directory entry. - * - * \return true if the entry is for a normal file or subdirectory else false. - */ -static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { - return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; -} -/** Directory entry is part of a long name - * \param[in] dir Pointer to a directory entry. - * - * \return true if the entry is for part of a long name else false. - */ -static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { - return dir->attributes == DIR_ATT_LONG_NAME; -} -/** Directory entry is hidden - * \param[in] dir Pointer to a directory entry. - * - * \return true if the entry is hidden else false. - */ -static inline uint8_t DIR_IS_HIDDEN(const dir_t* dir) { - return dir->attributes & DIR_ATT_HIDDEN; -} -/** Directory entry is for a subdirectory - * \param[in] dir Pointer to a directory entry. - * - * \return true if the entry is for a subdirectory else false. - */ -static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { - return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; -} -/** Directory entry is system type - * \param[in] dir Pointer to a directory entry. - * - * \return true if the entry is system else false. - */ -static inline uint8_t DIR_IS_SYSTEM(const dir_t* dir) { - return dir->attributes & DIR_ATT_SYSTEM; -} -/** date field for FAT directory entry - * \param[in] year [1980,2107] - * \param[in] month [1,12] - * \param[in] day [1,31] - * - * \return Packed date for dir_t entry. - */ -static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { - return (year - 1980) << 9 | month << 5 | day; -} -/** year part of FAT directory date field - * \param[in] fatDate Date in packed dir format. - * - * \return Extracted year [1980,2107] - */ -static inline uint16_t FAT_YEAR(uint16_t fatDate) { - return 1980 + (fatDate >> 9); -} -/** month part of FAT directory date field - * \param[in] fatDate Date in packed dir format. - * - * \return Extracted month [1,12] - */ -static inline uint8_t FAT_MONTH(uint16_t fatDate) { - return (fatDate >> 5) & 0XF; -} -/** day part of FAT directory date field - * \param[in] fatDate Date in packed dir format. - * - * \return Extracted day [1,31] - */ -static inline uint8_t FAT_DAY(uint16_t fatDate) { - return fatDate & 0X1F; -} -/** time field for FAT directory entry - * \param[in] hour [0,23] - * \param[in] minute [0,59] - * \param[in] second [0,59] - * - * \return Packed time for dir_t entry. - */ -static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { - return hour << 11 | minute << 5 | second >> 1; -} -/** hour part of FAT directory time field - * \param[in] fatTime Time in packed dir format. - * - * \return Extracted hour [0,23] - */ -static inline uint8_t FAT_HOUR(uint16_t fatTime) { - return fatTime >> 11; -} -/** minute part of FAT directory time field - * \param[in] fatTime Time in packed dir format. - * - * \return Extracted minute [0,59] - */ -static inline uint8_t FAT_MINUTE(uint16_t fatTime) { - return (fatTime >> 5) & 0X3F; -} -/** second part of FAT directory time field - * Note second/2 is stored in packed time. - * - * \param[in] fatTime Time in packed dir format. - * - * \return Extracted second [0,58] - */ -static inline uint8_t FAT_SECOND(uint16_t fatTime) { - return 2*(fatTime & 0X1F); -} -/** Default date for file timestamps is 1 Jan 2000 */ -uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; -/** Default time for file timestamp is 1 am */ -uint16_t const FAT_DEFAULT_TIME = (1 << 11); -//------------------------------------------------------------------------------ -/** Dimension of first name field in long directory entry */ -const uint8_t LDIR_NAME1_DIM = 5; -/** Dimension of first name field in long directory entry */ -const uint8_t LDIR_NAME2_DIM = 6; -/** Dimension of first name field in long directory entry */ -const uint8_t LDIR_NAME3_DIM = 2; -/** - * \struct longDirectoryEntry - * \brief FAT long directory entry - */ -struct longDirectoryEntry { - /** - * The order of this entry in the sequence of long dir entries - * associated with the short dir entry at the end of the long dir set. - * - * If masked with 0X40 (LAST_LONG_ENTRY), this indicates the - * entry is the last long dir entry in a set of long dir entries. - * All valid sets of long dir entries must begin with an entry having - * this mask. - */ - uint8_t ord; - /** Characters 1-5 of the long-name sub-component in this entry. */ - uint16_t name1[LDIR_NAME1_DIM]; - /** Attributes - must be ATTR_LONG_NAME */ - uint8_t attr; - /** - * If zero, indicates a directory entry that is a sub-component of a - * long name. NOTE: Other values reserved for future extensions. - * - * Non-zero implies other directory entry types. - */ - uint8_t type; - /** - * Checksum of name in the short dir entry at the end of the - * long dir set. - */ - uint8_t chksum; - /** Characters 6-11 of the long-name sub-component in this entry. */ - uint16_t name2[LDIR_NAME2_DIM]; - /** Must be ZERO. This is an artifact of the FAT "first cluster" */ - uint16_t mustBeZero; - /** Characters 12 and 13 of the long-name sub-component in this entry. */ - uint16_t name3[LDIR_NAME3_DIM]; -} __attribute__((packed)); -/** Type name for longDirectoryEntry */ -typedef struct longDirectoryEntry ldir_t; -/** - * Ord mast that indicates the entry is the last long dir entry in a - * set of long dir entries. All valid sets of long dir entries must - * begin with an entry having this mask. - */ -const uint8_t LDIR_ORD_LAST_LONG_ENTRY = 0X40; -#endif // FatStructs_h diff --git a/SdFat/utility/FatVolume.cpp b/SdFat/utility/FatVolume.cpp deleted file mode 100644 index dcb0a4d9..00000000 --- a/SdFat/utility/FatVolume.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#include -#include "FatVolume.h" -//------------------------------------------------------------------------------ -cache_t* FatCache::read(uint32_t lbn, uint8_t option) { - if (m_lbn != lbn) { - if (!sync()) { - DBG_FAIL_MACRO; - goto fail; - } - if (!(option & CACHE_OPTION_NO_READ)) { - if (!m_vol->readBlock(lbn, m_block.data)) { - DBG_FAIL_MACRO; - goto fail; - } - } - m_status = 0; - m_lbn = lbn; - } - m_status |= option & CACHE_STATUS_MASK; - return &m_block; - -fail: - return 0; -} -//------------------------------------------------------------------------------ -bool FatCache::sync() { - if (m_status & CACHE_STATUS_DIRTY) { - if (!m_vol->writeBlock(m_lbn, m_block.data)) { - DBG_FAIL_MACRO; - goto fail; - } - // mirror second FAT - if (m_status & CACHE_STATUS_MIRROR_FAT) { - uint32_t lbn = m_lbn + m_vol->blocksPerFat(); - if (!m_vol->writeBlock(lbn, m_block.data)) { - DBG_FAIL_MACRO; - goto fail; - } - } - m_status &= ~CACHE_STATUS_DIRTY; - } - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatVolume::allocateCluster(uint32_t current, uint32_t* next) { - uint32_t find = current ? current : m_allocSearchStart; - uint32_t start = find; - while (1) { - find++; - // If at end of FAT go to beginning of FAT. - if (find > m_lastCluster) { - find = 2; - } - uint32_t f; - int8_t fg = fatGet(find, &f); - if (fg < 0) { - DBG_FAIL_MACRO; - goto fail; - } - if (fg && f == 0) { - break; - } - if (find == start) { - // Can't find space checked all clusters. - DBG_FAIL_MACRO; - goto fail; - } - } - // mark end of chain - if (!fatPutEOC(find)) { - DBG_FAIL_MACRO; - goto fail; - } - if (current) { - // link clusters - if (!fatPut(current, find)) { - DBG_FAIL_MACRO; - goto fail; - } - } else { - // Remember place for search start. - m_allocSearchStart = find; - } - *next = find; - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -// find a contiguous group of clusters -bool FatVolume::allocContiguous(uint32_t count, uint32_t* firstCluster) { - // flag to save place to start next search - bool setStart = true; - // start of group - uint32_t bgnCluster; - // end of group - uint32_t endCluster; - // Start at cluster after last allocated cluster. - uint32_t startCluster = m_allocSearchStart; - endCluster = bgnCluster = startCluster + 1; - - // search the FAT for free clusters - while (1) { - // If past end - start from beginning of FAT. - if (endCluster > m_lastCluster) { - bgnCluster = endCluster = 2; - } - uint32_t f; - int8_t fg = fatGet(endCluster, &f); - if (fg < 0) { - DBG_FAIL_MACRO; - goto fail; - } - if (f || fg == 0) { - // cluster in use try next cluster as bgnCluster - bgnCluster = endCluster + 1; - - // don't update search start if unallocated clusters before endCluster. - if (bgnCluster != endCluster) { - setStart = false; - } - } else if ((endCluster - bgnCluster + 1) == count) { - // done - found space - break; - } - // Can't find space if all clusters checked. - if (startCluster == endCluster) { - DBG_FAIL_MACRO; - goto fail; - } - endCluster++; - } - // remember possible next free cluster - if (setStart) { - m_allocSearchStart = endCluster + 1; - } - - // mark end of chain - if (!fatPutEOC(endCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - // link clusters - while (endCluster > bgnCluster) { - if (!fatPut(endCluster - 1, endCluster)) { - DBG_FAIL_MACRO; - goto fail; - } - endCluster--; - } - // return first cluster number to caller - *firstCluster = bgnCluster; - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -uint32_t FatVolume::clusterStartBlock(uint32_t cluster) const { - return m_dataStartBlock + ((cluster - 2) << m_clusterSizeShift); -} -//------------------------------------------------------------------------------ -// Fetch a FAT entry - return -1 error, 0 EOC, else 1. -int8_t FatVolume::fatGet(uint32_t cluster, uint32_t* value) { - uint32_t lba; - uint32_t next; - cache_t* pc; - - // error if reserved cluster of beyond FAT - DBG_HALT_IF(cluster < 2 || cluster > m_lastCluster); - - if (m_fatType == 32) { - lba = m_fatStartBlock + (cluster >> 7); - pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - next = pc->fat32[cluster & 0X7F] & FAT32MASK; - goto done; - } - - if (m_fatType == 16) { - lba = m_fatStartBlock + ((cluster >> 8) & 0XFF); - pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - next = pc->fat16[cluster & 0XFF]; - goto done; - } - if (FAT12_SUPPORT && m_fatType == 12) { - uint16_t index = cluster; - index += index >> 1; - lba = m_fatStartBlock + (index >> 9); - pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - index &= 0X1FF; - uint16_t tmp = pc->data[index]; - index++; - if (index == 512) { - pc = cacheFetchFat(lba + 1, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - index = 0; - } - tmp |= pc->data[index] << 8; - next = cluster & 1 ? tmp >> 4 : tmp & 0XFFF; - goto done; - } else { - DBG_FAIL_MACRO; - goto fail; - } -done: - if (isEOC(next)) { - return 0; - } - *value = next; - return 1; - -fail: - return -1; -} -//------------------------------------------------------------------------------ -// Store a FAT entry -bool FatVolume::fatPut(uint32_t cluster, uint32_t value) { - uint32_t lba; - cache_t* pc; - - // error if reserved cluster of beyond FAT - DBG_HALT_IF(cluster < 2 || cluster > m_lastCluster); - - if (m_fatType == 32) { - lba = m_fatStartBlock + (cluster >> 7); - pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - pc->fat32[cluster & 0X7F] = value; - return true; - } - - if (m_fatType == 16) { - lba = m_fatStartBlock + ((cluster >> 8) & 0XFF); - pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - pc->fat16[cluster & 0XFF] = value; - return true; - } - - if (FAT12_SUPPORT && m_fatType == 12) { - uint16_t index = cluster; - index += index >> 1; - lba = m_fatStartBlock + (index >> 9); - pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - index &= 0X1FF; - uint8_t tmp = value; - if (cluster & 1) { - tmp = (pc->data[index] & 0XF) | tmp << 4; - } - pc->data[index] = tmp; - - index++; - if (index == 512) { - lba++; - index = 0; - pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - } - tmp = value >> 4; - if (!(cluster & 1)) { - tmp = ((pc->data[index] & 0XF0)) | tmp >> 4; - } - pc->data[index] = tmp; - return true; - } else { - DBG_FAIL_MACRO; - goto fail; - } - -fail: - return false; -} -//------------------------------------------------------------------------------ -// free a cluster chain -bool FatVolume::freeChain(uint32_t cluster) { - uint32_t next; - int8_t fg; - do { - fg = fatGet(cluster, &next); - if (fg < 0) { - DBG_FAIL_MACRO; - goto fail; - } - // free cluster - if (!fatPut(cluster, 0)) { - DBG_FAIL_MACRO; - goto fail; - } - if (cluster < m_allocSearchStart) { - m_allocSearchStart = cluster; - } - cluster = next; - } while (fg); - - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -int32_t FatVolume::freeClusterCount() { - uint32_t free = 0; - uint32_t lba; - uint32_t todo = m_lastCluster + 1; - uint16_t n; - - if (FAT12_SUPPORT && m_fatType == 12) { - for (unsigned i = 2; i < todo; i++) { - uint32_t c; - int8_t fg = fatGet(i, &c); - if (fg < 0) { - DBG_FAIL_MACRO; - goto fail; - } - if (fg && c == 0) { - free++; - } - } - } else if (m_fatType == 16 || m_fatType == 32) { - lba = m_fatStartBlock; - while (todo) { - cache_t* pc = cacheFetchFat(lba++, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - n = m_fatType == 16 ? 256 : 128; - if (todo < n) { - n = todo; - } - if (m_fatType == 16) { - for (uint16_t i = 0; i < n; i++) { - if (pc->fat16[i] == 0) { - free++; - } - } - } else { - for (uint16_t i = 0; i < n; i++) { - if (pc->fat32[i] == 0) { - free++; - } - } - } - todo -= n; - } - } else { - // invalid FAT type - DBG_FAIL_MACRO; - goto fail; - } - return free; - -fail: - return -1; -} -//------------------------------------------------------------------------------ -bool FatVolume::init(uint8_t part) { - uint32_t clusterCount; - uint32_t totalBlocks; - uint32_t volumeStartBlock = 0; - fat32_boot_t* fbs; - cache_t* pc; - uint8_t tmp; - m_fatType = 0; - m_allocSearchStart = 1; - - m_cache.init(this); -#if USE_SEPARATE_FAT_CACHE - m_fatCache.init(this); -#endif // USE_SEPARATE_FAT_CACHE - - // if part == 0 assume super floppy with FAT boot sector in block zero - // if part > 0 assume mbr volume with partition table - if (part) { - if (part > 4) { - DBG_FAIL_MACRO; - goto fail; - } - pc = cacheFetchData(0, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - part_t* p = &pc->mbr.part[part - 1]; - if ((p->boot & 0X7F) != 0 || p->firstSector == 0) { - // not a valid partition - DBG_FAIL_MACRO; - goto fail; - } - volumeStartBlock = p->firstSector; - } - pc = cacheFetchData(volumeStartBlock, FatCache::CACHE_FOR_READ); - if (!pc) { - DBG_FAIL_MACRO; - goto fail; - } - fbs = &(pc->fbs32); - if (fbs->bytesPerSector != 512 || - fbs->fatCount != 2 || - fbs->reservedSectorCount == 0) { - // not valid FAT volume - DBG_FAIL_MACRO; - goto fail; - } - m_blocksPerCluster = fbs->sectorsPerCluster; - m_clusterBlockMask = m_blocksPerCluster - 1; - - // determine shift that is same as multiply by m_blocksPerCluster - m_clusterSizeShift = 0; - for (tmp = 1; m_blocksPerCluster != tmp; tmp <<= 1, m_clusterSizeShift++) { - if (tmp == 0) { - DBG_FAIL_MACRO; - goto fail; - } - } - - m_blocksPerFat = fbs->sectorsPerFat16 ? - fbs->sectorsPerFat16 : fbs->sectorsPerFat32; - - m_fatStartBlock = volumeStartBlock + fbs->reservedSectorCount; - - // count for FAT16 zero for FAT32 - m_rootDirEntryCount = fbs->rootDirEntryCount; - - // directory start for FAT16 dataStart for FAT32 - m_rootDirStart = m_fatStartBlock + 2 * m_blocksPerFat; - // data start for FAT16 and FAT32 - m_dataStartBlock = m_rootDirStart + ((32 * fbs->rootDirEntryCount + 511)/512); - - // total blocks for FAT16 or FAT32 - totalBlocks = fbs->totalSectors16 ? - fbs->totalSectors16 : fbs->totalSectors32; - // total data blocks - clusterCount = totalBlocks - (m_dataStartBlock - volumeStartBlock); - - // divide by cluster size to get cluster count - clusterCount >>= m_clusterSizeShift; - m_lastCluster = clusterCount + 1; - - // FAT type is determined by cluster count - if (clusterCount < 4085) { - m_fatType = 12; - if (!FAT12_SUPPORT) { - DBG_FAIL_MACRO; - goto fail; - } - } else if (clusterCount < 65525) { - m_fatType = 16; - } else { - m_rootDirStart = fbs->fat32RootCluster; - m_fatType = 32; - } - return true; - -fail: - return false; -} -//------------------------------------------------------------------------------ -bool FatVolume::wipe(print_t* pr) { - cache_t* cache; - uint16_t count; - uint32_t lbn; - if (!m_fatType) { - DBG_FAIL_MACRO; - goto fail; - } - cache = cacheClear(); - if (!cache) { - DBG_FAIL_MACRO; - goto fail; - } - memset(cache->data, 0, 512); - // Zero root. - if (m_fatType == 32) { - lbn = clusterStartBlock(m_rootDirStart); - count = m_blocksPerCluster; - } else { - lbn = m_rootDirStart; - count = m_rootDirEntryCount/16; - } - for (uint32_t n = 0; n < count; n++) { - if (!writeBlock(lbn + n, cache->data)) { - DBG_FAIL_MACRO; - goto fail; - } - } - // Clear FATs. - count = 2*m_blocksPerFat; - lbn = m_fatStartBlock; - for (uint32_t nb = 0; nb < count; nb++) { - if (pr && (nb & 0XFF) == 0) { - pr->write('.'); - } - if (!writeBlock(lbn + nb, cache->data)) { - DBG_FAIL_MACRO; - goto fail; - } - } - // Reserve first two clusters. - if (m_fatType == 32) { - cache->fat32[0] = 0x0FFFFFF8; - cache->fat32[1] = 0x0FFFFFFF; - } else if (m_fatType == 16) { - cache->fat16[0] = 0XFFF8; - cache->fat16[1] = 0XFFFF; - } else if (FAT12_SUPPORT && m_fatType == 12) { - cache->fat32[0] = 0XFFFFF8; - } else { - DBG_FAIL_MACRO; - goto fail; - } - if (!writeBlock(m_fatStartBlock, cache->data) || - !writeBlock(m_fatStartBlock + m_blocksPerFat, cache->data)) { - DBG_FAIL_MACRO; - goto fail; - } - if (m_fatType == 32) { - // Reserve root cluster. - if (!fatPutEOC(m_rootDirStart) || !cacheSync()) { - DBG_FAIL_MACRO; - goto fail; - } - } - if (pr) { - pr->write('\r'); - pr->write('\n'); - } - m_fatType = 0; - return true; - -fail: - m_fatType = 0; - return false; -} diff --git a/SdFat/utility/FatVolume.h b/SdFat/utility/FatVolume.h deleted file mode 100644 index b558101d..00000000 --- a/SdFat/utility/FatVolume.h +++ /dev/null @@ -1,338 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef FatVolume_h -#define FatVolume_h -/** - * \file - * \brief FatVolume class - */ -#include -#include "FatLibConfig.h" -#include "FatStructs.h" -//------------------------------------------------------------------------------ -#ifndef DOXYGEN_SHOULD_SKIP_THIS -/** Macro for debug. */ -#define DEBUG_MODE 0 -#if DEBUG_MODE -#include -#define DBG_FAIL_MACRO Serial.print(F(__FILE__)); Serial.println(__LINE__) -#define DBG_PRINT_IF(b) if (b) {Serial.println(F(#b)); DBG_FAIL_MACRO;} -#define DBG_HALT_IF(b) if (b) {Serial.println(F(#b));\ - DBG_FAIL_MACRO; while (1);} -#else // DEBUG_MODE -#define DBG_FAIL_MACRO -#define DBG_PRINT_IF(b) -#define DBG_HALT_IF(b) -#endif // DEBUG_MODE -#endif // DOXYGEN_SHOULD_SKIP_THIS -//------------------------------------------------------------------------------ -#if ENABLE_ARDUINO_FEATURES -#include -/** Use Print on Arduino */ -typedef Print print_t; -#else // ENABLE_ARDUINO_FEATURES -// Arduino type for flash string. -class __FlashStringHelper; -/** - * \class CharWriter - * \brief Character output - often serial port. - */ -class CharWriter { - public: - virtual size_t write(char c) = 0; - virtual size_t write(const char* s) = 0; -}; -typedef CharWriter print_t; -#endif // ENABLE_ARDUINO_FEATURES -//------------------------------------------------------------------------------ -// Forward declaration of FatVolume. -class FatVolume; -//------------------------------------------------------------------------------ -/** - * \brief Cache for an raw data block. - */ -union cache_t { - /** Used to access cached file data blocks. */ - uint8_t data[512]; - /** Used to access cached FAT16 entries. */ - uint16_t fat16[256]; - /** Used to access cached FAT32 entries. */ - uint32_t fat32[128]; - /** Used to access cached directory entries. */ - dir_t dir[16]; - /** Used to access a cached Master Boot Record. */ - mbr_t mbr; - /** Used to access to a cached FAT boot sector. */ - fat_boot_t fbs; - /** Used to access to a cached FAT32 boot sector. */ - fat32_boot_t fbs32; - /** Used to access to a cached FAT32 FSINFO sector. */ - fat32_fsinfo_t fsinfo; -}; -//============================================================================== -/** - * \class FatCache - * \brief Block cache. - */ -class FatCache { - public: - /** Cached block is dirty */ - static const uint8_t CACHE_STATUS_DIRTY = 1; - /** Cashed block is FAT entry and must be mirrored in second FAT. */ - static const uint8_t CACHE_STATUS_MIRROR_FAT = 2; - /** Cache block status bits */ - static const uint8_t CACHE_STATUS_MASK - = CACHE_STATUS_DIRTY | CACHE_STATUS_MIRROR_FAT; - /** Sync existing block but do not read new block. */ - static const uint8_t CACHE_OPTION_NO_READ = 4; - /** Cache block for read. */ - static uint8_t const CACHE_FOR_READ = 0; - /** Cache block for write. */ - static uint8_t const CACHE_FOR_WRITE = CACHE_STATUS_DIRTY; - /** Reserve cache block for write - do not read from block device. */ - static uint8_t const CACHE_RESERVE_FOR_WRITE - = CACHE_STATUS_DIRTY | CACHE_OPTION_NO_READ; - /** \return Cache block address. */ - cache_t* block() { - return &m_block; - } - /** Set current block dirty. */ - void dirty() { - m_status |= CACHE_STATUS_DIRTY; - } - /** Initialize the cache. - * \param[in] vol FatVolume that owns this FatCache. - */ - void init(FatVolume *vol) { - m_vol = vol; - invalidate(); - } - /** Invalidate current cache block. */ - void invalidate() { - m_status = 0; - m_lbn = 0XFFFFFFFF; - } - /** \return Logical block number for cached block. */ - uint32_t lbn() { - return m_lbn; - } - /** Read a block into the cache. - * \param[in] lbn Block to read. - * \param[in] option mode for cached block. - * \return Address of cached block. */ - cache_t* read(uint32_t lbn, uint8_t option); - /** Write current block if dirty. - * \return true for success else false. - */ - bool sync(); - - private: - uint8_t m_status; - FatVolume* m_vol; - uint32_t m_lbn; - cache_t m_block; -}; -//============================================================================== -/** - * \class FatVolume - * \brief Access FAT16 and FAT32 volumes on raw file devices. - */ -class FatVolume { - public: - /** Create an instance of FatVolume - */ - FatVolume() : m_fatType(0) {} - - /** \return The volume's cluster size in blocks. */ - uint8_t blocksPerCluster() const { - return m_blocksPerCluster; - } - /** \return The number of blocks in one FAT. */ - uint32_t blocksPerFat() const { - return m_blocksPerFat; - } - /** Clear the cache and returns a pointer to the cache. Not for normal apps. - * \return A pointer to the cache buffer or zero if an error occurs. - */ - cache_t* cacheClear() { - if (!cacheSync()) { - return 0; - } - m_cache.invalidate(); - return m_cache.block(); - } - /** \return The total number of clusters in the volume. */ - uint32_t clusterCount() const { - return m_lastCluster - 1; - } - /** \return The shift count required to multiply by blocksPerCluster. */ - uint8_t clusterSizeShift() const { - return m_clusterSizeShift; - } - /** \return The logical block number for the start of file data. */ - uint32_t dataStartBlock() const { - return m_dataStartBlock; - } - /** \return The number of File Allocation Tables. */ - uint8_t fatCount() { - return 2; - } - /** \return The logical block number for the start of the first FAT. */ - uint32_t fatStartBlock() const { - return m_fatStartBlock; - } - /** \return The FAT type of the volume. Values are 12, 16 or 32. */ - uint8_t fatType() const { - return m_fatType; - } - /** Volume free space in clusters. - * - * \return Count of free clusters for success or -1 if an error occurs. - */ - int32_t freeClusterCount(); - /** Initialize a FAT volume. Try partition one first then try super - * floppy format. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool init() { - return init(1) || init(0); - } - /** Initialize a FAT volume. - - * \param[in] part The partition to be used. Legal values for \a part are - * 1-4 to use the corresponding partition on a device formatted with - * a MBR, Master Boot Record, or zero if the device is formatted as - * a super floppy with the FAT boot sector in block zero. - * - * \return The value true is returned for success and - * the value false is returned for failure. - */ - bool init(uint8_t part); - /** \return The number of entries in the root directory for FAT16 volumes. */ - uint16_t rootDirEntryCount() const { - return m_rootDirEntryCount; - } - /** \return The logical block number for the start of the root directory - on FAT16 volumes or the first cluster number on FAT32 volumes. */ - uint32_t rootDirStart() const { - return m_rootDirStart; - } - /** \return The number of blocks in the volume */ - uint32_t volumeBlockCount() const { - return blocksPerCluster()*clusterCount(); - } - /** Wipe all data from the volume. - * \param[in] pr print stream for status dots. - * \return true for success else false. - */ - bool wipe(print_t* pr = 0); - /** Debug access to FAT table - * - * \param[in] n cluster number. - * \param[out] v value of entry - * \return true for success or false for failure - */ - int8_t dbgFat(uint32_t n, uint32_t* v) { - return fatGet(n, v); - } -//------------------------------------------------------------------------------ - private: - // Allow FatFile and FatCache access to FatVolume private functions. - friend class FatCache; - friend class FatFile; -//------------------------------------------------------------------------------ - uint8_t m_blocksPerCluster; // Cluster size in blocks. - uint8_t m_clusterBlockMask; // Mask to extract block of cluster. - uint8_t m_clusterSizeShift; // Cluster count to block count shift. - uint8_t m_fatType; // Volume type (12, 16, OR 32). - uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir. - uint32_t m_allocSearchStart; // Start cluster for alloc search. - uint32_t m_blocksPerFat; // FAT size in blocks - uint32_t m_dataStartBlock; // First data block number. - uint32_t m_fatStartBlock; // Start block for first FAT. - uint32_t m_lastCluster; // Last cluster number in FAT. - uint32_t m_rootDirStart; // Start block for FAT16, cluster for FAT32. -//------------------------------------------------------------------------------ -// block caches - FatCache m_cache; -#if USE_SEPARATE_FAT_CACHE - FatCache m_fatCache; - cache_t* cacheFetchFat(uint32_t blockNumber, uint8_t options) { - return m_fatCache.read(blockNumber, - options | FatCache::CACHE_STATUS_MIRROR_FAT); - } - bool cacheSync() { - return m_cache.sync() && m_fatCache.sync(); - } -#else // - cache_t* cacheFetchFat(uint32_t blockNumber, uint8_t options) { - return cacheFetchData(blockNumber, - options | FatCache::CACHE_STATUS_MIRROR_FAT); - } - bool cacheSync() { - return m_cache.sync(); - } -#endif // USE_SEPARATE_FAT_CACHE - cache_t* cacheFetchData(uint32_t blockNumber, uint8_t options) { - return m_cache.read(blockNumber, options); - } - void cacheInvalidate() { - m_cache.invalidate(); - } - bool cacheSyncData() { - return m_cache.sync(); - } - cache_t *cacheAddress() { - return m_cache.block(); - } - uint32_t cacheBlockNumber() { - return m_cache.lbn(); - } - void cacheDirty() { - m_cache.dirty(); - } -//------------------------------------------------------------------------------ - bool allocateCluster(uint32_t current, uint32_t* next); - bool allocContiguous(uint32_t count, uint32_t* firstCluster); - uint8_t blockOfCluster(uint32_t position) const { - return (position >> 9) & m_clusterBlockMask; - } - uint32_t clusterStartBlock(uint32_t cluster) const; - int8_t fatGet(uint32_t cluster, uint32_t* value); - bool fatPut(uint32_t cluster, uint32_t value); - bool fatPutEOC(uint32_t cluster) { - return fatPut(cluster, 0x0FFFFFFF); - } - bool freeChain(uint32_t cluster); - bool isEOC(uint32_t cluster) const { - return cluster > m_lastCluster; - } - //---------------------------------------------------------------------------- - // Virtual block I/O functions. - virtual bool readBlock(uint32_t block, uint8_t* dst) = 0; - virtual bool writeBlock(uint32_t block, const uint8_t* src) = 0; -#if USE_MULTI_BLOCK_IO - virtual bool readBlocks(uint32_t block, uint8_t* dst, size_t nb) = 0; - virtual bool writeBlocks(uint32_t block, const uint8_t* src, size_t nb) = 0; -#endif // USE_MULTI_BLOCK_IO -}; -#endif // FatVolume diff --git a/SdFat/utility/FmtNumber.cpp b/SdFat/utility/FmtNumber.cpp deleted file mode 100644 index 3aa5bec0..00000000 --- a/SdFat/utility/FmtNumber.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#include "FmtNumber.h" -// Use Stimmer div/mod 10 on avr -#ifdef __AVR__ -#include -#define USE_STIMMER -#endif // __AVR__ -//------------------------------------------------------------------------------ -// Stimmer div/mod 10 for AVR -// this code fragment works out i/10 and i%10 by calculating -// i*(51/256)*(256/255)/2 == i*51/510 == i/10 -// by "j.k" I mean 32.8 fixed point, j is integer part, k is fractional part -// j.k = ((j+1.0)*51.0)/256.0 -// (we add 1 because we will be using the floor of the result later) -// divmod10_asm16 and divmod10_asm32 are public domain code by Stimmer. -// http://forum.arduino.cc/index.php?topic=167414.msg1293679#msg1293679 -#define divmod10_asm16(in32, mod8, tmp8) \ -asm volatile( \ - " ldi %2,51 \n\t" \ - " mul %A0,%2 \n\t" \ - " clr %A0 \n\t" \ - " add r0,%2 \n\t" \ - " adc %A0,r1 \n\t" \ - " mov %1,r0 \n\t" \ - " mul %B0,%2 \n\t" \ - " clr %B0 \n\t" \ - " add %A0,r0 \n\t" \ - " adc %B0,r1 \n\t" \ - " clr r1 \n\t" \ - " add %1,%A0 \n\t" \ - " adc %A0,%B0 \n\t" \ - " adc %B0,r1 \n\t" \ - " add %1,%B0 \n\t" \ - " adc %A0,r1 \n\t" \ - " adc %B0,r1 \n\t" \ - " lsr %B0 \n\t" \ - " ror %A0 \n\t" \ - " ror %1 \n\t" \ - " ldi %2,10 \n\t" \ - " mul %1,%2 \n\t" \ - " mov %1,r1 \n\t" \ - " clr r1 \n\t" \ - :"+r"(in32), "=d"(mod8), "=d"(tmp8) : : "r0") - -#define divmod10_asm32(in32, mod8, tmp8) \ -asm volatile( \ - " ldi %2,51 \n\t" \ - " mul %A0,%2 \n\t" \ - " clr %A0 \n\t" \ - " add r0,%2 \n\t" \ - " adc %A0,r1 \n\t" \ - " mov %1,r0 \n\t" \ - " mul %B0,%2 \n\t" \ - " clr %B0 \n\t" \ - " add %A0,r0 \n\t" \ - " adc %B0,r1 \n\t" \ - " mul %C0,%2 \n\t" \ - " clr %C0 \n\t" \ - " add %B0,r0 \n\t" \ - " adc %C0,r1 \n\t" \ - " mul %D0,%2 \n\t" \ - " clr %D0 \n\t" \ - " add %C0,r0 \n\t" \ - " adc %D0,r1 \n\t" \ - " clr r1 \n\t" \ - " add %1,%A0 \n\t" \ - " adc %A0,%B0 \n\t" \ - " adc %B0,%C0 \n\t" \ - " adc %C0,%D0 \n\t" \ - " adc %D0,r1 \n\t" \ - " add %1,%B0 \n\t" \ - " adc %A0,%C0 \n\t" \ - " adc %B0,%D0 \n\t" \ - " adc %C0,r1 \n\t" \ - " adc %D0,r1 \n\t" \ - " add %1,%D0 \n\t" \ - " adc %A0,r1 \n\t" \ - " adc %B0,r1 \n\t" \ - " adc %C0,r1 \n\t" \ - " adc %D0,r1 \n\t" \ - " lsr %D0 \n\t" \ - " ror %C0 \n\t" \ - " ror %B0 \n\t" \ - " ror %A0 \n\t" \ - " ror %1 \n\t" \ - " ldi %2,10 \n\t" \ - " mul %1,%2 \n\t" \ - " mov %1,r1 \n\t" \ - " clr r1 \n\t" \ - :"+r"(in32), "=d"(mod8), "=d"(tmp8) : : "r0") -//------------------------------------------------------------------------------ -/* -// C++ code is based on this version of divmod10 by robtillaart. -// http://forum.arduino.cc/index.php?topic=167414.msg1246851#msg1246851 -// from robtillaart post: -// The code is based upon the divu10() code from the book Hackers Delight1. -// My insight was that the error formula in divu10() was in fact modulo 10 -// but not always. Sometimes it was 10 more. -void divmod10(uint32_t in, uint32_t &div, uint32_t &mod) -{ - // q = in * 0.8; - uint32_t q = (in >> 1) + (in >> 2); - q = q + (q >> 4); - q = q + (q >> 8); - q = q + (q >> 16); // not needed for 16 bit version - - // q = q / 8; ==> q = in *0.1; - q = q >> 3; - - // determine error - uint32_t r = in - ((q << 3) + (q << 1)); // r = in - q*10; - div = q + (r > 9); - if (r > 9) mod = r - 10; - else mod = r; -} -// Hackers delight function is here: -// http://www.hackersdelight.org/hdcodetxt/divuc.c.txt -// Code below uses 8/10 = 0.1100 1100 1100 1100 1100 1100 1100 1100. -// 15 ops including the multiply, or 17 elementary ops. -unsigned divu10(unsigned n) { - unsigned q, r; - - q = (n >> 1) + (n >> 2); - q = q + (q >> 4); - q = q + (q >> 8); - q = q + (q >> 16); - q = q >> 3; - r = n - q*10; - return q + ((r + 6) >> 4); -// return q + (r > 9); -} -*/ -//------------------------------------------------------------------------------ -#ifndef DOXYGEN_SHOULD_SKIP_THIS -#ifdef __AVR__ -static const float m[] PROGMEM = {1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32}; -static const float p[] PROGMEM = {1e+1, 1e+2, 1e+4, 1e+8, 1e+16, 1e+32}; -#else // __AVR__ -static const float m[] = {1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32}; -static const float p[] = {1e+1, 1e+2, 1e+4, 1e+8, 1e+16, 1e+32}; -#endif // __AVR__ -#endif // DOXYGEN_SHOULD_SKIP_THIS -// scale float v by power of ten. return v*10^n -float scale10(float v, int8_t n) { - const float *s; - if (n < 0) { - n = -n; - s = m; - } else { - s = p; - } - n &= 63; - for (uint8_t i = 0; n; n >>= 1, i++) { -#ifdef __AVR__ - if (n & 1) { - v *= pgm_read_float(&s[i]); - } -#else // __AVR__ - if (n & 1) { - v *= s[i]; - } -#endif // __AVR__ - } - return v; -} -//------------------------------------------------------------------------------ -// Format 16-bit unsigned -char* fmtDec(uint16_t n, char* p) { - while (n > 9) { -#ifdef USE_STIMMER - uint8_t tmp8, r; - divmod10_asm16(n, r, tmp8); -#else // USE_STIMMER - uint16_t t = n; - n = (n >> 1) + (n >> 2); - n = n + (n >> 4); - n = n + (n >> 8); - // n = n + (n >> 16); // no code for 16-bit n - n = n >> 3; - uint8_t r = t - (((n << 2) + n) << 1); - if (r > 9) { - n++; - r -= 10; - } -#endif // USE_STIMMER - *--p = r + '0'; - } - *--p = n + '0'; - return p; -} -//------------------------------------------------------------------------------ -// format 32-bit unsigned -char* fmtDec(uint32_t n, char* p) { - while (n >> 16) { -#ifdef USE_STIMMER - uint8_t tmp8, r; - divmod10_asm32(n, r, tmp8); -#else // USE_STIMMER - uint32_t t = n; - n = (n >> 1) + (n >> 2); - n = n + (n >> 4); - n = n + (n >> 8); - n = n + (n >> 16); - n = n >> 3; - uint8_t r = t - (((n << 2) + n) << 1); - if (r > 9) { - n++; - r -= 10; - } -#endif // USE_STIMMER - *--p = r + '0'; - } - return fmtDec((uint16_t)n, p); -} -//------------------------------------------------------------------------------ -char* fmtFloat(float value, char* p, uint8_t prec) { - char sign = value < 0 ? '-' : 0; - if (sign) { - value = -value; - } - - if (isnan(value)) { - *--p = 'n'; - *--p = 'a'; - *--p = 'n'; - return p; - } - if (isinf(value)) { - *--p = 'f'; - *--p = 'n'; - *--p = 'i'; - return p; - } - if (value > 4294967040.0) { - *--p = 'f'; - *--p = 'v'; - *--p = 'o'; - return p; - } - if (prec > 9) { - prec = 9; - } - value += scale10(0.5, -prec); - - uint32_t whole = value; - if (prec) { - char* tmp = p - prec; - uint32_t fraction = scale10(value - whole, prec); - p = fmtDec(fraction, p); - while (p > tmp) { - *--p = '0'; - } - *--p = '.'; - } - p = fmtDec(whole, p); - if (sign) { - *--p = sign; - } - return p; -} -//------------------------------------------------------------------------------ -/** Print a number followed by a field terminator. - * \param[in] value The number to be printed. - * \param[in] ptr Pointer to last char in buffer. - * \param[in] prec Number of digits after decimal point. - * \param[in] expChar Use exp format if non zero. - * \return Pointer to first character of result. - */ -char* fmtFloat(float value, char* ptr, uint8_t prec, char expChar) { - bool neg = value < 0; - if (neg) { - value = -value; - } - - // check for nan inf ovf - if (isnan(value)) { - *--ptr = 'n'; - *--ptr = 'a'; - *--ptr = 'n'; - return ptr; - } - if (isinf(value)) { - *--ptr = 'f'; - *--ptr = 'n'; - *--ptr = 'i'; - return ptr; - } - if (!expChar && value > 4294967040.0) { - *--ptr = 'f'; - *--ptr = 'v'; - *--ptr = 'o'; - return ptr; - } - if (prec > 9) { - prec = 9; - } - float round = scale10(0.5, -prec); - if (expChar) { - int8_t exp = 0; - bool expNeg = false; - if (value) { - while (value > 10.0) { - value *= 0.1; - exp++; - } - while (value < 1.0) { - value *= 10.0; - exp--; - } - value += round; - if (value > 10.0) { - value *= 0.1; - exp++; - } - expNeg = exp < 0; - if (expNeg) { - exp = -exp; - } - } - ptr = fmtDec((uint16_t)exp, ptr); - if (exp < 10) { - *--ptr = '0'; - } - *--ptr = expNeg ? '-' : '+'; - *--ptr = expChar; - } else { - // round value - value += round; - } - uint32_t whole = value; - if (prec) { - char* tmp = ptr - prec; - uint32_t fraction = scale10(value - whole, prec); - ptr = fmtDec(fraction, ptr); - while (ptr > tmp) { - *--ptr = '0'; - } - *--ptr = '.'; - } - ptr = fmtDec(whole, ptr); - if (neg) { - *--ptr = '-'; - } - return ptr; -} -//------------------------------------------------------------------------------ -char* fmtHex(uint32_t n, char* p) { - do { - uint8_t h = n & 0XF; - *--p = h + (h < 10 ? '0' : 'A' - 10); - n >>= 4; - } while (n); - return p; -} -//------------------------------------------------------------------------------ -float scanFloat(const char* str, char** ptr) { - int16_t const EXP_LIMIT = 100; - bool digit = false; - bool dot = false; - uint32_t fract = 0; - int fracExp = 0; - uint8_t nd = 0; - bool neg; - int c; - float v; - const char* successPtr = str; - - if (ptr) { - *ptr = const_cast(str); - } - - while (isSpace((c = *str++))) {} - neg = c == '-'; - if (c == '-' || c == '+') { - c = *str++; - } - // Skip leading zeros - while (c == '0') { - c = *str++; - digit = true; - } - for (;;) { - if (isDigit(c)) { - digit = true; - if (nd < 9) { - fract = 10*fract + c - '0'; - nd++; - if (dot) { - fracExp--; - } - } else { - if (!dot) { - fracExp++; - } - } - } else if (c == '.') { - if (dot) { - goto fail; - } - dot = true; - } else { - if (!digit) { - goto fail; - } - break; - } - successPtr = str; - c = *str++; - } - if (c == 'e' || c == 'E') { - int exp = 0; - c = *str++; - bool expNeg = c == '-'; - if (c == '-' || c == '+') { - c = *str++; - } - while (isDigit(c)) { - if (exp > EXP_LIMIT) { - goto fail; - } - exp = 10*exp + c - '0'; - successPtr = str; - c = *str++; - } - fracExp += expNeg ? -exp : exp; - } - if (ptr) { - *ptr = const_cast(successPtr); - } - v = scale10(static_cast(fract), fracExp); - return neg ? -v : v; - -fail: - return 0; -} - - diff --git a/SdFat/utility/FmtNumber.h b/SdFat/utility/FmtNumber.h deleted file mode 100644 index 2bb97dc4..00000000 --- a/SdFat/utility/FmtNumber.h +++ /dev/null @@ -1,38 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef FmtNumber_h -#define FmtNumber_h -// #include -inline bool isDigit(char c) { - return '0' <= c && c <= '9'; -} -inline bool isSpace(char c) { - return c == ' ' || (0X9 <= c && c <= 0XD); -} -#include -#include -char* fmtDec(uint16_t n, char* p); -char* fmtDec(uint32_t n, char* p); -char* fmtFloat(float value, char* p, uint8_t prec); -char* fmtFloat(float value, char* ptr, uint8_t prec, char expChar); -char* fmtHex(uint32_t n, char* p); -float scale10(float v, int8_t n); -float scanFloat(const char* str, char** ptr); -#endif // FmtNumber_h diff --git a/SdFat/utility/StdioStream.cpp b/SdFat/utility/StdioStream.cpp deleted file mode 100644 index 0f61fa04..00000000 --- a/SdFat/utility/StdioStream.cpp +++ /dev/null @@ -1,606 +0,0 @@ -/* Arduino RamDisk Library - * Copyright (C) 2014 by William Greiman - * - * This file is part of the Arduino RamDisk Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino RamDisk Library. If not, see - * . - */ -#include "StdioStream.h" -#include "FmtNumber.h" -//------------------------------------------------------------------------------ -int StdioStream::fclose() { - int rtn = 0; - if (!m_flags) { - return EOF; - } - if (m_flags & F_SWR) { - if (!flushBuf()) { - rtn = EOF; - } - } - if (!FatFile::close()) { - rtn = EOF; - } - m_r = 0; - m_w = 0; - m_flags = 0; - return rtn; -} -//------------------------------------------------------------------------------ -int StdioStream::fflush() { - if ((m_flags & (F_SWR | F_SRW)) && !(m_flags & F_SRD)) { - if (flushBuf() && FatFile::sync()) { - return 0; - } - } - return EOF; -} -//------------------------------------------------------------------------------ -char* StdioStream::fgets(char* str, size_t num, size_t* len) { - char* s = str; - size_t n; - if (num-- == 0) { - return 0; - } - while (num) { - if ((n = m_r) == 0) { - if (!fillBuf()) { - if (s == str) { - return 0; - } - break; - } - n = m_r; - } - if (n > num) { - n = num; - } - uint8_t* end = reinterpret_cast(memchr(m_p, '\n', n)); - if (end != 0) { - n = ++end - m_p; - memcpy(s, m_p, n); - m_r -= n; - m_p = end; - s += n; - break; - } - memcpy(s, m_p, n); - m_r -= n; - m_p += n; - s += n; - num -= n; - } - *s = 0; - if (len) { - *len = s - str; - } - return str; -} -//------------------------------------------------------------------------------ -bool StdioStream::fopen(const char* path, const char* mode) { - uint8_t oflag; - switch (*mode++) { - case 'a': - m_flags = F_SWR; - oflag = O_WRITE | O_CREAT | O_APPEND | O_AT_END; - break; - - case 'r': - m_flags = F_SRD; - oflag = O_READ; - break; - - case 'w': - m_flags = F_SWR; - oflag = O_WRITE | O_CREAT | O_TRUNC; - break; - - default: - goto fail; - } - while (*mode) { - switch (*mode++) { - case '+': - m_flags |= F_SRW; - oflag |= O_RDWR; - break; - - case 'b': - break; - - case 'x': - oflag |= O_EXCL; - break; - - default: - goto fail; - } - } - if ((oflag & O_EXCL) && !(oflag & O_WRITE)) { - goto fail; - } - if (!FatFile::open(path, oflag)) { - goto fail; - } - m_r = 0; - m_w = 0; - m_p = m_buf; - return true; - -fail: - m_flags = 0; - return false; -} -//------------------------------------------------------------------------------ -int StdioStream::fputs(const char* str) { - size_t len = strlen(str); - return fwrite(str, 1, len) == len ? len : EOF; -} -//------------------------------------------------------------------------------ -int StdioStream::fputs_P(PGM_P str) { - PGM_P bgn = str; - for (char c; (c = pgm_read_byte(str)); str++) { - if (putc(c) < 0) { - return EOF; - } - } - return str - bgn; -} -//------------------------------------------------------------------------------ -size_t StdioStream::fread(void* ptr, size_t size, size_t count) { - uint8_t* dst = reinterpret_cast(ptr); - size_t total = size*count; - if (total == 0) { - return 0; - } - size_t need = total; - while (need > m_r) { - memcpy(dst, m_p, m_r); - dst += m_r; - m_p += m_r; - need -= m_r; - if (!fillBuf()) { - return (total - need)/size; - } - } - memcpy(dst, m_p, need); - m_r -= need; - m_p += need; - return count; -} -//------------------------------------------------------------------------------ -int StdioStream::fseek(int32_t offset, int origin) { - int32_t pos; - if (m_flags & F_SWR) { - if (!flushBuf()) { - goto fail; - } - } - switch (origin) { - case SEEK_CUR: - pos = ftell(); - if (pos < 0) { - goto fail; - } - pos += offset; - if (!FatFile::seekCur(pos)) { - goto fail; - } - break; - - case SEEK_SET: - if (!FatFile::seekSet(offset)) { - goto fail; - } - break; - - case SEEK_END: - if (!FatFile::seekEnd(offset)) { - goto fail; - } - break; - - default: - goto fail; - } - m_r = 0; - m_p = m_buf; - return 0; - -fail: - return EOF; -} -//------------------------------------------------------------------------------ -int32_t StdioStream::ftell() { - uint32_t pos = FatFile::curPosition(); - if (m_flags & F_SRD) { - if (m_r > pos) { - return -1L; - } - pos -= m_r; - } else if (m_flags & F_SWR) { - pos += m_p - m_buf; - } - return pos; -} -//------------------------------------------------------------------------------ -size_t StdioStream::fwrite(const void* ptr, size_t size, size_t count) { - return write(ptr, count*size) < 0 ? EOF : count; -#if 0 //////////////////////////////////////////////////////////////////////////////////// - const uint8_t* src = static_cast(ptr); - size_t total = count*size; - if (total == 0) { - return 0; - } - size_t todo = total; - - while (todo > m_w) { - memcpy(m_p, src, m_w); - m_p += m_w; - src += m_w; - todo -= m_w; - if (!flushBuf()) { - return (total - todo)/size; - } - } - memcpy(m_p, src, todo); - m_p += todo; - m_w -= todo; - return count; -#endif ////////////////////////////////////////////////////////////////////////////////// -} -//------------------------------------------------------------------------------ -int StdioStream::write(const void* buf, size_t count) { - const uint8_t* src = static_cast(buf); - size_t todo = count; - - while (todo > m_w) { - memcpy(m_p, src, m_w); - m_p += m_w; - src += m_w; - todo -= m_w; - if (!flushBuf()) { - return EOF; - } - } - memcpy(m_p, src, todo); - m_p += todo; - m_w -= todo; - return count; -} -//------------------------------------------------------------------------------ -size_t StdioStream::print(const __FlashStringHelper *str) { - const char *p = (const char PROGMEM *)str; - uint8_t c; - while ((c = pgm_read_byte(p))) { - if (putc(c) < 0) { - return 0; - } - p++; - } - return p - (const char PROGMEM *)str; -} -//------------------------------------------------------------------------------ -int StdioStream::printDec(float value, uint8_t prec) { -#define FLOAT_NEW_WAY -#ifdef FLOAT_NEW_WAY - char buf[24]; - char *ptr = fmtFloat(value, buf + sizeof(buf), prec); - // return fputs(ptr); - // uint8_t len = buf + sizeof(buf) - ptr; - return write(ptr, buf + sizeof(buf) - ptr); -#else - char* ptr; - uint8_t rtn = 0; - uint8_t sign = 0; - if (value < 0) { - value = -value; - sign = '-'; - } - // check for NaN INF OVF - if (isnan(value)) { - if (fputs_P(PSTR("nan")) < 0) { - return -1; - } - rtn += 3; - } else if (isinf(value)) { - if (fputs_P(PSTR("inf")) < 0) { - return -1; - } - rtn += 3; - } else if (value > 4294967040.0) { - if (fputs_P(PSTR("ovf")) < 0) { - return -1; - } - rtn += 3; - } else { - if (sign) { - if (putc(sign) < 0) { - return -1; - } - rtn++; - } - if (prec > 9) { - prec = 9; - } - - /* - uint32_t s = 1; - for (uint8_t i = 0; i < prec; i++) { - // s *= 10; - s = ((s << 2) + s) << 1; - } - // round value - value += 0.5/s; - */ - value += scale10(0.5, -prec); - uint32_t whole = value; - int np; - if ((np = printDec(whole)) < 0) { - return -1; - } - rtn += np; - if (prec) { - if (putc('.') < 0) { - return -1; - } - char* str = fmtSpace(prec); - if (!str) { - return -1; - } - char* tmp = str - prec; - - // uint32_t fraction = s*(value - whole); - uint32_t fraction = scale10(value - whole, prec); - ptr = fmtDec(fraction, str); - while (ptr > tmp) { - *--ptr = '0'; - } - rtn += prec + 1; - } - } - return rtn; -#endif -} -//------------------------------------------------------------------------------ -int StdioStream::printDec(signed char n) { - if (n < 0) { - if (fputc('-') < 0) { - return -1; - } - n = -n; - } - return printDec((unsigned char)n); -} -//------------------------------------------------------------------------------ -int StdioStream::printDec(int16_t n) { - int s; - uint8_t rtn = 0; - if (n < 0) { - if (fputc('-') < 0) { - return -1; - } - n = -n; - rtn++; - } - if ((s = printDec((uint16_t)n)) < 0) { - return s; - } - return rtn; -} -//------------------------------------------------------------------------------ -int StdioStream::printDec(uint16_t n) { -#define NEW_WAY -#ifdef NEW_WAY - char buf[5]; - char *ptr = fmtDec(n, buf + sizeof(buf)); - uint8_t len = buf + sizeof(buf) - ptr; - return write(ptr, len); -#else - uint8_t len; - if (n < 100) { - len = n < 10 ? 1 : 2; - } else { - len = n < 1000 ? 3 : n < 10000 ? 4 : 5; - } - char* str = fmtSpace(len); - if (!str) { - return -1; - } - fmtDec(n, str); - return len; -#endif -} -//------------------------------------------------------------------------------ -int StdioStream::printDec(int32_t n) { - uint8_t s = 0; - if (n < 0) { - if (fputc('-') < 0) { - return -1; - } - n = -n; - s = 1; - } - int rtn = printDec((uint32_t)n); - return rtn > 0 ? rtn + s : -1; -} -//------------------------------------------------------------------------------ -int StdioStream::printDec(uint32_t n) { -#ifdef NEW_WAY - char buf[10]; - char *ptr = fmtDec(n, buf + sizeof(buf)); - uint8_t len = buf + sizeof(buf) - ptr; - return write(ptr, len); -#else - uint8_t len; - if (n < 0X10000) { - return printDec((uint16_t)n); - } - if (n < 10000000) { - len = n < 100000 ? 5 : n < 1000000 ? 6 : 7; - } else { - len = n < 100000000 ? 8 : n < 1000000000 ? 9 : 10; - } - - char* str = fmtSpace(len); - if (!str) { - return -1; - } - fmtDec(n, str); - return len; -#endif -} -//------------------------------------------------------------------------------ -int StdioStream::printHex(uint32_t n) { -#ifdef NEW_WAY - char buf[8]; - char *ptr = fmtHex(n, buf + sizeof(buf)); - uint8_t len = buf + sizeof(buf) - ptr; - return write(ptr, len); -#else - size_t len; - if (n < 0X10000) { - len = n < 0X10 ? 1 : n < 0X100 ? 2 : n < 0X1000 ? 3 : 4; - } else { - len = n < 0X100000 ? 5 : n < 0X1000000 ? 6 : n < 0X10000000 ? 7 : 8; - } - char* str = fmtSpace(len); - if (!str) { - return -1; - } - - do { - uint8_t h = n & 0XF; - *str-- = h + (h < 10 ? '0' : 'A' - 10); - n >>= 4; - } while (n); - return len; -#endif -} -//------------------------------------------------------------------------------ -bool StdioStream::rewind() { - if (m_flags & F_SWR) { - if (!flushBuf()) { - return false; - } - } - FatFile::seekSet(0); - m_r = 0; - return true; -} -//------------------------------------------------------------------------------ -int StdioStream::ungetc(int c) { - // error if EOF. - if (c == EOF) { - return EOF; - } - // error if not reading. - if ((m_flags & F_SRD) == 0) { - return EOF; - } - // error if no space. - if (m_p == m_buf) { - return EOF; - } - m_r++; - m_flags &= ~F_EOF; - return *--m_p = (uint8_t)c; -} -//============================================================================== -// private -//------------------------------------------------------------------------------ -int StdioStream::fillGet() { - if (!fillBuf()) { - return EOF; - } - m_r--; - return *m_p++; -} -//------------------------------------------------------------------------------ -// private -bool StdioStream::fillBuf() { - if (!(m_flags & - F_SRD)) { /////////////check for F_ERR and F_EOF ??///////////////// - if (!(m_flags & F_SRW)) { - m_flags |= F_ERR; - return false; - } - if (m_flags & F_SWR) { - if (!flushBuf()) { - return false; - } - m_flags &= ~F_SWR; - m_flags |= F_SRD; - m_w = 0; - } - } - m_p = m_buf + UNGETC_BUF_SIZE; - int nr = FatFile::read(m_p, sizeof(m_buf) - UNGETC_BUF_SIZE); - if (nr <= 0) { - m_flags |= nr < 0 ? F_ERR : F_EOF; - m_r = 0; - return false; - } - m_r = nr; - return true; -} -//------------------------------------------------------------------------------ -// private -bool StdioStream::flushBuf() { - if (!(m_flags & - F_SWR)) { /////////////////check for F_ERR ??//////////////////////// - if (!(m_flags & F_SRW)) { - m_flags |= F_ERR; - return false; - } - m_flags &= ~F_SRD; - m_flags |= F_SWR; - m_r = 0; - m_w = sizeof(m_buf); - m_p = m_buf; - return true; - } - uint8_t n = m_p - m_buf; - m_p = m_buf; - m_w = sizeof(m_buf); - if (FatFile::write(m_buf, n) == n) { - return true; - } - m_flags |= F_ERR; - return false; -} -//------------------------------------------------------------------------------ -int StdioStream::flushPut(uint8_t c) { - if (!flushBuf()) { - return EOF; - } - m_w--; - return *m_p++ = c; -} -//------------------------------------------------------------------------------ -char* StdioStream::fmtSpace(uint8_t len) { - if (m_w < len) { - if (!flushBuf() || m_w < len) { - return 0; - } - } - if (len > m_w) { - return 0; - } - m_p += len; - m_w -= len; - return reinterpret_cast(m_p); -} - diff --git a/SdFat/utility/bufstream.h b/SdFat/utility/bufstream.h deleted file mode 100644 index 0253e37c..00000000 --- a/SdFat/utility/bufstream.h +++ /dev/null @@ -1,163 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef bufstream_h -#define bufstream_h -/** - * \file - * \brief \ref ibufstream and \ref obufstream classes - */ -#include -#include "iostream.h" -//============================================================================== -/** - * \class ibufstream - * \brief parse a char string - */ -class ibufstream : public istream { - public: - /** Constructor */ - ibufstream() : m_buf(0), m_len(0) {} - /** Constructor - * \param[in] str pointer to string to be parsed - * Warning: The string will not be copied so must stay in scope. - */ - explicit ibufstream(const char* str) { - init(str); - } - /** Initialize an ibufstream - * \param[in] str pointer to string to be parsed - * Warning: The string will not be copied so must stay in scope. - */ - void init(const char* str) { - m_buf = str; - m_len = strlen(m_buf); - m_pos = 0; - clear(); - } - - protected: - /// @cond SHOW_PROTECTED - int16_t getch() { - if (m_pos < m_len) { - return m_buf[m_pos++]; - } - setstate(eofbit); - return -1; - } - void getpos(FatPos_t *pos) { - pos->position = m_pos; - } - bool seekoff(off_type off, seekdir way) { - return false; - } - bool seekpos(pos_type pos) { - if (pos < m_len) { - m_pos = pos; - return true; - } - return false; - } - void setpos(FatPos_t *pos) { - m_pos = pos->position; - } - pos_type tellpos() { - return m_pos; - } - /// @endcond - private: - const char* m_buf; - size_t m_len; - size_t m_pos; -}; -//============================================================================== -/** - * \class obufstream - * \brief format a char string - */ -class obufstream : public ostream { - public: - /** constructor */ - obufstream() : m_in(0) {} - /** Constructor - * \param[in] buf buffer for formatted string - * \param[in] size buffer size - */ - obufstream(char *buf, size_t size) { - init(buf, size); - } - /** Initialize an obufstream - * \param[in] buf buffer for formatted string - * \param[in] size buffer size - */ - void init(char *buf, size_t size) { - m_buf = buf; - buf[0] = '\0'; - m_size = size; - m_in = 0; - } - /** \return a pointer to the buffer */ - char* buf() { - return m_buf; - } - /** \return the length of the formatted string */ - size_t length() { - return m_in; - } - - protected: - /// @cond SHOW_PROTECTED - void putch(char c) { - if (m_in >= (m_size - 1)) { - setstate(badbit); - return; - } - m_buf[m_in++] = c; - m_buf[m_in] = '\0'; - } - void putstr(const char *str) { - while (*str) { - putch(*str++); - } - } - bool seekoff(off_type off, seekdir way) { - return false; - } - bool seekpos(pos_type pos) { - if (pos > m_in) { - return false; - } - m_in = pos; - m_buf[m_in] = '\0'; - return true; - } - bool sync() { - return true; - } - - pos_type tellpos() { - return m_in; - } - /// @endcond - private: - char *m_buf; - size_t m_size; - size_t m_in; -}; -#endif // bufstream_h diff --git a/SdFat/utility/fstream.cpp b/SdFat/utility/fstream.cpp deleted file mode 100644 index 505f0836..00000000 --- a/SdFat/utility/fstream.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#include "fstream.h" -//============================================================================== -/// @cond SHOW_PROTECTED -int16_t FatStreamBase::getch() { - uint8_t c; - int8_t s = read(&c, 1); - if (s != 1) { - if (s < 0) { - setstate(badbit); - } else { - setstate(eofbit); - } - return -1; - } - if (c != '\r' || (getmode() & ios::binary)) { - return c; - } - s = read(&c, 1); - if (s == 1 && c == '\n') { - return c; - } - if (s == 1) { - seekCur(-1); - } - return '\r'; -} -//------------------------------------------------------------------------------ -void FatStreamBase::open(const char* path, ios::openmode mode) { - uint8_t flags; - switch (mode & (app | in | out | trunc)) { - case app | in: - case app | in | out: - flags = O_RDWR | O_APPEND | O_CREAT; - break; - - case app: - case app | out: - flags = O_WRITE | O_APPEND | O_CREAT; - break; - - case in: - flags = O_READ; - break; - - case in | out: - flags = O_RDWR; - break; - - case in | out | trunc: - flags = O_RDWR | O_TRUNC | O_CREAT; - break; - - case out: - case out | trunc: - flags = O_WRITE | O_TRUNC | O_CREAT; - break; - - default: - goto fail; - } - if (mode & ios::ate) { - flags |= O_AT_END; - } - if (!FatFile::open(path, flags)) { - goto fail; - } - setmode(mode); - clear(); - return; - -fail: - FatFile::close(); - setstate(failbit); - return; -} -//------------------------------------------------------------------------------ -void FatStreamBase::putch(char c) { - if (c == '\n' && !(getmode() & ios::binary)) { - write('\r'); - } - write(c); - if (getWriteError()) { - setstate(badbit); - } -} -//------------------------------------------------------------------------------ -void FatStreamBase::putstr(const char* str) { - size_t n = 0; - while (1) { - char c = str[n]; - if (c == '\0' || (c == '\n' && !(getmode() & ios::binary))) { - if (n > 0) { - write(str, n); - } - if (c == '\0') { - break; - } - write('\r'); - str += n; - n = 0; - } - n++; - } - if (getWriteError()) { - setstate(badbit); - } -} -//------------------------------------------------------------------------------ -/** Internal do not use - * \param[in] off - * \param[in] way - */ -bool FatStreamBase::seekoff(off_type off, seekdir way) { - pos_type pos; - switch (way) { - case beg: - pos = off; - break; - - case cur: - pos = curPosition() + off; - break; - - case end: - pos = fileSize() + off; - break; - - default: - return false; - } - return seekpos(pos); -} -//------------------------------------------------------------------------------ -/** Internal do not use - * \param[in] pos - */ -bool FatStreamBase::seekpos(pos_type pos) { - return seekSet(pos); -} -//------------------------------------------------------------------------------ -int FatStreamBase::write(const void* buf, size_t n) { - return FatFile::write(buf, n); -} -//------------------------------------------------------------------------------ -void FatStreamBase::write(char c) { - write(&c, 1); -} -/// @endcond diff --git a/SdFat/utility/fstream.h b/SdFat/utility/fstream.h deleted file mode 100644 index 5410c385..00000000 --- a/SdFat/utility/fstream.h +++ /dev/null @@ -1,315 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef fstream_h -#define fstream_h -/** - * \file - * \brief \ref fstream, \ref ifstream, and \ref ofstream classes - */ -#include "FatFile.h" -#include "iostream.h" -//============================================================================== -/** - * \class FatStreamBase - * \brief Base class for C++ style streams - */ -class FatStreamBase : protected FatFile, virtual public ios { - protected: - /// @cond SHOW_PROTECTED - int16_t getch(); - void putch(char c); - void putstr(const char *str); - void open(const char* path, ios::openmode mode); - /** Internal do not use - * \return mode - */ - ios::openmode getmode() { - return m_mode; - } - /** Internal do not use - * \param[in] mode - */ - void setmode(ios::openmode mode) { - m_mode = mode; - } - bool seekoff(off_type off, seekdir way); - bool seekpos(pos_type pos); - int write(const void* buf, size_t n); - void write(char c); - /// @endcond - private: - ios::openmode m_mode; -}; -//============================================================================== -/** - * \class fstream - * \brief file input/output stream. - */ -class fstream : public iostream, FatStreamBase { - public: - using iostream::peek; - fstream() {} - /** Constructor with open - * - * \param[in] path path to open - * \param[in] mode open mode - */ - explicit fstream(const char* path, openmode mode = in | out) { - open(path, mode); - } -#if DESTRUCTOR_CLOSES_FILE - ~fstream() {} -#endif // DESTRUCTOR_CLOSES_FILE - /** Clear state and writeError - * \param[in] state new state for stream - */ - void clear(iostate state = goodbit) { - ios::clear(state); - FatFile::clearWriteError(); - } - /** Close a file and force cached data and directory information - * to be written to the storage device. - */ - void close() { - FatFile::close(); - } - /** Open a fstream - * \param[in] path file to open - * \param[in] mode open mode - * - * Valid open modes are (at end, ios::ate, and/or ios::binary may be added): - * - * ios::in - Open file for reading. - * - * ios::out or ios::out | ios::trunc - Truncate to 0 length, if existent, - * or create a file for writing only. - * - * ios::app or ios::out | ios::app - Append; open or create file for - * writing at end-of-file. - * - * ios::in | ios::out - Open file for update (reading and writing). - * - * ios::in | ios::out | ios::trunc - Truncate to zero length, if existent, - * or create file for update. - * - * ios::in | ios::app or ios::in | ios::out | ios::app - Append; open or - * create text file for update, writing at end of file. - */ - void open(const char* path, openmode mode = in | out) { - FatStreamBase::open(path, mode); - } - /** \return True if stream is open else false. */ - bool is_open() { - return FatFile::isOpen(); - } - - protected: - /// @cond SHOW_PROTECTED - /** Internal - do not use - * \return - */ - int16_t getch() { - return FatStreamBase::getch(); - } - /** Internal - do not use - * \param[out] pos - */ - void getpos(FatPos_t* pos) { - FatFile::getpos(pos); - } - /** Internal - do not use - * \param[in] c - */ - void putch(char c) { - FatStreamBase::putch(c); - } - /** Internal - do not use - * \param[in] str - */ - void putstr(const char *str) { - FatStreamBase::putstr(str); - } - /** Internal - do not use - * \param[in] pos - */ - bool seekoff(off_type off, seekdir way) { - return FatStreamBase::seekoff(off, way); - } - bool seekpos(pos_type pos) { - return FatStreamBase::seekpos(pos); - } - void setpos(FatPos_t* pos) { - FatFile::setpos(pos); - } - bool sync() { - return FatStreamBase::sync(); - } - pos_type tellpos() { - return FatStreamBase::curPosition(); - } - /// @endcond -}; -//============================================================================== -/** - * \class ifstream - * \brief file input stream. - */ -class ifstream : public istream, FatStreamBase { - public: - using istream::peek; - ifstream() {} - /** Constructor with open - * \param[in] path file to open - * \param[in] mode open mode - */ - explicit ifstream(const char* path, openmode mode = in) { - open(path, mode); - } -#if DESTRUCTOR_CLOSES_FILE - ~ifstream() {} -#endif // DESTRUCTOR_CLOSES_FILE - /** Close a file and force cached data and directory information - * to be written to the storage device. - */ - void close() { - FatFile::close(); - } - /** \return True if stream is open else false. */ - bool is_open() { - return FatFile::isOpen(); - } - /** Open an ifstream - * \param[in] path file to open - * \param[in] mode open mode - * - * \a mode See fstream::open() for valid modes. - */ - void open(const char* path, openmode mode = in) { - FatStreamBase::open(path, mode | in); - } - - protected: - /// @cond SHOW_PROTECTED - /** Internal - do not use - * \return - */ - int16_t getch() { - return FatStreamBase::getch(); - } - /** Internal - do not use - * \param[out] pos - */ - void getpos(FatPos_t* pos) { - FatFile::getpos(pos); - } - /** Internal - do not use - * \param[in] pos - */ - bool seekoff(off_type off, seekdir way) { - return FatStreamBase::seekoff(off, way); - } - bool seekpos(pos_type pos) { - return FatStreamBase::seekpos(pos); - } - void setpos(FatPos_t* pos) { - FatFile::setpos(pos); - } - pos_type tellpos() { - return FatStreamBase::curPosition(); - } - /// @endcond -}; -//============================================================================== -/** - * \class ofstream - * \brief file output stream. - */ -class ofstream : public ostream, FatStreamBase { - public: - ofstream() {} - /** Constructor with open - * \param[in] path file to open - * \param[in] mode open mode - */ - explicit ofstream(const char* path, ios::openmode mode = out) { - open(path, mode); - } -#if DESTRUCTOR_CLOSES_FILE - ~ofstream() {} -#endif // DESTRUCTOR_CLOSES_FILE - /** Clear state and writeError - * \param[in] state new state for stream - */ - void clear(iostate state = goodbit) { - ios::clear(state); - FatFile::clearWriteError(); - } - /** Close a file and force cached data and directory information - * to be written to the storage device. - */ - void close() { - FatFile::close(); - } - /** Open an ofstream - * \param[in] path file to open - * \param[in] mode open mode - * - * \a mode See fstream::open() for valid modes. - */ - void open(const char* path, openmode mode = out) { - FatStreamBase::open(path, mode | out); - } - /** \return True if stream is open else false. */ - bool is_open() { - return FatFile::isOpen(); - } - - protected: - /// @cond SHOW_PROTECTED - /** - * Internal do not use - * \param[in] c - */ - void putch(char c) { - FatStreamBase::putch(c); - } - void putstr(const char* str) { - FatStreamBase::putstr(str); - } - bool seekoff(off_type off, seekdir way) { - return FatStreamBase::seekoff(off, way); - } - bool seekpos(pos_type pos) { - return FatStreamBase::seekpos(pos); - } - /** - * Internal do not use - * \param[in] b - */ - bool sync() { - return FatStreamBase::sync(); - } - pos_type tellpos() { - return FatStreamBase::curPosition(); - } - /// @endcond -}; -//------------------------------------------------------------------------------ -#endif // fstream_h diff --git a/SdFat/utility/ios.h b/SdFat/utility/ios.h deleted file mode 100644 index d89d96c4..00000000 --- a/SdFat/utility/ios.h +++ /dev/null @@ -1,418 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef ios_h -#define ios_h -#include "FatFile.h" -/** - * \file - * \brief \ref ios_base and \ref ios classes - */ -//============================================================================== -/** - * \class ios_base - * \brief Base class for all streams - */ -class ios_base { - public: - /** typedef for iostate bitmask */ - typedef unsigned char iostate; - // State flags. - /** iostate for no flags */ - static const iostate goodbit = 0x00; - /** iostate bad bit for a nonrecoverable error. */ - static const iostate badbit = 0X01; - /** iostate bit for end of file reached */ - static const iostate eofbit = 0x02; - /** iostate fail bit for nonfatal error */ - static const iostate failbit = 0X04; - /** - * unsigned size that can represent maximum file size. - * (violates spec - should be signed) - */ - typedef uint32_t streamsize; - /** type for absolute seek position */ - typedef uint32_t pos_type; - /** type for relative seek offset */ - typedef int32_t off_type; - - /** enumerated type for the direction of relative seeks */ - enum seekdir { - /** seek relative to the beginning of the stream */ - beg, - /** seek relative to the current stream position */ - cur, - /** seek relative to the end of the stream */ - end - }; - /** type for format flags */ - typedef unsigned int fmtflags; - /** left adjust fields */ - static const fmtflags left = 0x0001; - /** right adjust fields */ - static const fmtflags right = 0x0002; - /** fill between sign/base prefix and number */ - static const fmtflags internal = 0x0004; - /** base 10 flag*/ - static const fmtflags dec = 0x0008; - /** base 16 flag */ - static const fmtflags hex = 0x0010; - /** base 8 flag */ - static const fmtflags oct = 0x0020; - // static const fmtflags fixed = 0x0040; - // static const fmtflags scientific = 0x0080; - /** use strings true/false for bool */ - static const fmtflags boolalpha = 0x0100; - /** use prefix 0X for hex and 0 for oct */ - static const fmtflags showbase = 0x0200; - /** always show '.' for floating numbers */ - static const fmtflags showpoint = 0x0400; - /** show + sign for nonnegative numbers */ - static const fmtflags showpos = 0x0800; - /** skip initial white space */ - static const fmtflags skipws = 0x1000; - // static const fmtflags unitbuf = 0x2000; - /** use uppercase letters in number representations */ - static const fmtflags uppercase = 0x4000; - /** mask for adjustfield */ - static const fmtflags adjustfield = left | right | internal; - /** mask for basefield */ - static const fmtflags basefield = dec | hex | oct; - // static const fmtflags floatfield = scientific | fixed; - //---------------------------------------------------------------------------- - /** typedef for iostream open mode */ - typedef uint8_t openmode; - - // Openmode flags. - /** seek to end before each write */ - static const openmode app = 0X4; - /** open and seek to end immediately after opening */ - static const openmode ate = 0X8; - /** perform input and output in binary mode (as opposed to text mode) */ - static const openmode binary = 0X10; - /** open for input */ - static const openmode in = 0X20; - /** open for output */ - static const openmode out = 0X40; - /** truncate an existing stream when opening */ - static const openmode trunc = 0X80; - //---------------------------------------------------------------------------- - ios_base() : m_fill(' '), m_fmtflags(dec | right | skipws) - , m_precision(2), m_width(0) {} - /** \return fill character */ - char fill() { - return m_fill; - } - /** Set fill character - * \param[in] c new fill character - * \return old fill character - */ - char fill(char c) { - char r = m_fill; - m_fill = c; - return r; - } - /** \return format flags */ - fmtflags flags() const { - return m_fmtflags; - } - /** set format flags - * \param[in] fl new flag - * \return old flags - */ - fmtflags flags(fmtflags fl) { - fmtflags tmp = m_fmtflags; - m_fmtflags = fl; - return tmp; - } - /** \return precision */ - int precision() const { - return m_precision; - } - /** set precision - * \param[in] n new precision - * \return old precision - */ - int precision(unsigned int n) { - int r = m_precision; - m_precision = n; - return r; - } - /** set format flags - * \param[in] fl new flags to be or'ed in - * \return old flags - */ - fmtflags setf(fmtflags fl) { - fmtflags r = m_fmtflags; - m_fmtflags |= fl; - return r; - } - /** modify format flags - * \param[in] mask flags to be removed - * \param[in] fl flags to be set after mask bits have been cleared - * \return old flags - */ - fmtflags setf(fmtflags fl, fmtflags mask) { - fmtflags r = m_fmtflags; - m_fmtflags &= ~mask; - m_fmtflags |= fl; - return r; - } - /** clear format flags - * \param[in] fl flags to be cleared - * \return old flags - */ - void unsetf(fmtflags fl) { - m_fmtflags &= ~fl; - } - /** \return width */ - unsigned width() { - return m_width; - } - /** set width - * \param[in] n new width - * \return old width - */ - unsigned width(unsigned n) { - unsigned r = m_width; - m_width = n; - return r; - } - - protected: - /** \return current number base */ - uint8_t flagsToBase() { - uint8_t f = flags() & basefield; - return f == oct ? 8 : f != hex ? 10 : 16; - } - - private: - char m_fill; - fmtflags m_fmtflags; - unsigned char m_precision; - unsigned int m_width; -}; -//------------------------------------------------------------------------------ -/** function for boolalpha manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& boolalpha(ios_base& str) { - str.setf(ios_base::boolalpha); - return str; -} -/** function for dec manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& dec(ios_base& str) { - str.setf(ios_base::dec, ios_base::basefield); - return str; -} -/** function for hex manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& hex(ios_base& str) { - str.setf(ios_base::hex, ios_base::basefield); - return str; -} -/** function for internal manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& internal(ios_base& str) { - str.setf(ios_base::internal, ios_base::adjustfield); - return str; -} -/** function for left manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& left(ios_base& str) { - str.setf(ios_base::left, ios_base::adjustfield); - return str; -} -/** function for noboolalpha manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& noboolalpha(ios_base& str) { - str.unsetf(ios_base::boolalpha); - return str; -} -/** function for noshowbase manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& noshowbase(ios_base& str) { - str.unsetf(ios_base::showbase); - return str; -} -/** function for noshowpoint manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& noshowpoint(ios_base& str) { - str.unsetf(ios_base::showpoint); - return str; -} -/** function for noshowpos manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& noshowpos(ios_base& str) { - str.unsetf(ios_base::showpos); - return str; -} -/** function for noskipws manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& noskipws(ios_base& str) { - str.unsetf(ios_base::skipws); - return str; -} -/** function for nouppercase manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& nouppercase(ios_base& str) { - str.unsetf(ios_base::uppercase); - return str; -} -/** function for oct manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& oct(ios_base& str) { - str.setf(ios_base::oct, ios_base::basefield); - return str; -} -/** function for right manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& right(ios_base& str) { - str.setf(ios_base::right, ios_base::adjustfield); - return str; -} -/** function for showbase manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& showbase(ios_base& str) { - str.setf(ios_base::showbase); - return str; -} -/** function for showpos manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& showpos(ios_base& str) { - str.setf(ios_base::showpos); - return str; -} -/** function for showpoint manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& showpoint(ios_base& str) { - str.setf(ios_base::showpoint); - return str; -} -/** function for skipws manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& skipws(ios_base& str) { - str.setf(ios_base::skipws); - return str; -} -/** function for uppercase manipulator - * \param[in] str The stream - * \return The stream - */ -inline ios_base& uppercase(ios_base& str) { - str.setf(ios_base::uppercase); - return str; -} -//============================================================================== -/** - * \class ios - * \brief Error and state information for all streams - */ -class ios : public ios_base { - public: - /** Create ios with no error flags set */ - ios() : m_iostate(0) {} - - /** \return null pointer if fail() is true. */ - operator const void*() const { - return !fail() ? reinterpret_cast(this) : 0; - } - /** \return true if fail() else false. */ - bool operator!() const { - return fail(); - } - /** \return The iostate flags for this file. */ - iostate rdstate() const { - return m_iostate; - } - /** \return True if no iostate flags are set else false. */ - bool good() const { - return m_iostate == goodbit; - } - /** \return true if end of file has been reached else false. - * - * Warning: An empty file returns false before the first read. - * - * Moral: eof() is only useful in combination with fail(), to find out - * whether EOF was the cause for failure - */ - bool eof() const { - return m_iostate & eofbit; - } - /** \return true if any iostate bit other than eof are set else false. */ - bool fail() const { - return m_iostate & (failbit | badbit); - } - /** \return true if bad bit is set else false. */ - bool bad() const { - return m_iostate & badbit; - } - /** Clear iostate bits. - * - * \param[in] state The flags you want to set after clearing all flags. - **/ - void clear(iostate state = goodbit) { - m_iostate = state; - } - /** Set iostate bits. - * - * \param[in] state Bitts to set. - **/ - void setstate(iostate state) { - m_iostate |= state; - } - - private: - iostate m_iostate; -}; -#endif // ios_h diff --git a/SdFat/utility/iostream.h b/SdFat/utility/iostream.h deleted file mode 100644 index deeae6e3..00000000 --- a/SdFat/utility/iostream.h +++ /dev/null @@ -1,153 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef iostream_h -#define iostream_h -/** - * \file - * \brief \ref iostream class - */ -#include "istream.h" -#include "ostream.h" -/** Skip white space - * \param[in] is the Stream - * \return The stream - */ -inline istream& ws(istream& is) { - is.skipWhite(); - return is; -} -/** insert endline - * \param[in] os The Stream - * \return The stream - */ -inline ostream& endl(ostream& os) { - os.put('\n'); -#if ENDL_CALLS_FLUSH - os.flush(); -#endif // ENDL_CALLS_FLUSH - return os; -} -/** flush manipulator - * \param[in] os The stream - * \return The stream - */ -inline ostream& flush(ostream& os) { - os.flush(); - return os; -} -/** - * \struct setfill - * \brief type for setfill manipulator - */ -struct setfill { - /** fill character */ - char c; - /** constructor - * - * \param[in] arg new fill character - */ - explicit setfill(char arg) : c(arg) {} -}; -/** setfill manipulator - * \param[in] os the stream - * \param[in] arg set setfill object - * \return the stream - */ -inline ostream &operator<< (ostream &os, const setfill &arg) { - os.fill(arg.c); - return os; -} -/** setfill manipulator - * \param[in] obj the stream - * \param[in] arg set setfill object - * \return the stream - */ -inline istream &operator>>(istream &obj, const setfill &arg) { - obj.fill(arg.c); - return obj; -} -//------------------------------------------------------------------------------ -/** \struct setprecision - * \brief type for setprecision manipulator - */ -struct setprecision { - /** precision */ - unsigned int p; - /** constructor - * \param[in] arg new precision - */ - explicit setprecision(unsigned int arg) : p(arg) {} -}; -/** setprecision manipulator - * \param[in] os the stream - * \param[in] arg set setprecision object - * \return the stream - */ -inline ostream &operator<< (ostream &os, const setprecision &arg) { - os.precision(arg.p); - return os; -} -/** setprecision manipulator - * \param[in] is the stream - * \param[in] arg set setprecision object - * \return the stream - */ -inline istream &operator>>(istream &is, const setprecision &arg) { - is.precision(arg.p); - return is; -} -//------------------------------------------------------------------------------ -/** \struct setw - * \brief type for setw manipulator - */ -struct setw { - /** width */ - unsigned w; - /** constructor - * \param[in] arg new width - */ - explicit setw(unsigned arg) : w(arg) {} -}; -/** setw manipulator - * \param[in] os the stream - * \param[in] arg set setw object - * \return the stream - */ -inline ostream &operator<< (ostream &os, const setw &arg) { - os.width(arg.w); - return os; -} -/** setw manipulator - * \param[in] is the stream - * \param[in] arg set setw object - * \return the stream - */ -inline istream &operator>>(istream &is, const setw &arg) { - is.width(arg.w); - return is; -} -//============================================================================== -/** - * \class iostream - * \brief Input/Output stream - */ -class iostream : public istream, public ostream { -}; -#endif // iostream_h diff --git a/SdFat/utility/istream.cpp b/SdFat/utility/istream.cpp deleted file mode 100644 index 6a4e9f3f..00000000 --- a/SdFat/utility/istream.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -// #include -#include -#include -#include "istream.h" -//------------------------------------------------------------------------------ -int istream::get() { - int c; - m_gcount = 0; - c = getch(); - if (c < 0) { - setstate(failbit); - } else { - m_gcount = 1; - } - return c; -} -//------------------------------------------------------------------------------ -istream& istream::get(char& c) { - int tmp = get(); - if (tmp >= 0) { - c = tmp; - } - return *this; -} -//------------------------------------------------------------------------------ -istream& istream::get(char *str, streamsize n, char delim) { - int c; - FatPos_t pos; - m_gcount = 0; - while ((m_gcount + 1) < n) { - c = getch(&pos); - if (c < 0) { - break; - } - if (c == delim) { - setpos(&pos); - break; - } - str[m_gcount++] = c; - } - if (n > 0) { - str[m_gcount] = '\0'; - } - if (m_gcount == 0) { - setstate(failbit); - } - return *this; -} -//------------------------------------------------------------------------------ -void istream::getBool(bool *b) { - if ((flags() & boolalpha) == 0) { - getNumber(b); - return; - } - PGM_P truePtr = PSTR("true"); - PGM_P falsePtr = PSTR("false"); - const uint8_t true_len = 4; - const uint8_t false_len = 5; - bool trueOk = true; - bool falseOk = true; - uint8_t i = 0; - int c = readSkip(); - while (1) { - falseOk = falseOk && c == pgm_read_byte(falsePtr + i); - trueOk = trueOk && c == pgm_read_byte(truePtr + i); - if (trueOk == false && falseOk == false) { - break; - } - i++; - if (trueOk && i == true_len) { - *b = true; - return; - } - if (falseOk && i == false_len) { - *b = false; - return; - } - c = getch(); - } - setstate(failbit); -} -//------------------------------------------------------------------------------ -void istream::getChar(char* ch) { - int16_t c = readSkip(); - if (c < 0) { - setstate(failbit); - } else { - *ch = c; - } -} -//------------------------------------------------------------------------------ -// -// http://www.exploringbinary.com/category/numbers-in-computers/ -// -int16_t const EXP_LIMIT = 100; -static const uint32_t uint32_max = (uint32_t)-1; -bool istream::getDouble(double* value) { - bool got_digit = false; - bool got_dot = false; - bool neg; - int16_t c; - bool expNeg = false; - int16_t exp = 0; - int16_t fracExp = 0; - uint32_t frac = 0; - FatPos_t endPos; - double pow10; - double v; - - getpos(&endPos); - c = readSkip(); - neg = c == '-'; - if (c == '-' || c == '+') { - c = getch(); - } - while (1) { - if (isdigit(c)) { - got_digit = true; - if (frac < uint32_max/10) { - frac = frac * 10 + (c - '0'); - if (got_dot) { - fracExp--; - } - } else { - if (!got_dot) { - fracExp++; - } - } - } else if (!got_dot && c == '.') { - got_dot = true; - } else { - break; - } - if (fracExp < -EXP_LIMIT || fracExp > EXP_LIMIT) { - goto fail; - } - c = getch(&endPos); - } - if (!got_digit) { - goto fail; - } - if (c == 'e' || c == 'E') { - c = getch(); - expNeg = c == '-'; - if (c == '-' || c == '+') { - c = getch(); - } - while (isdigit(c)) { - if (exp > EXP_LIMIT) { - goto fail; - } - exp = exp * 10 + (c - '0'); - c = getch(&endPos); - } - } - v = static_cast(frac); - exp = expNeg ? fracExp - exp : fracExp + exp; - expNeg = exp < 0; - if (expNeg) { - exp = -exp; - } - pow10 = 10.0; - while (exp) { - if (exp & 1) { - if (expNeg) { - // check for underflow - if (v < FLT_MIN * pow10 && frac != 0) { - goto fail; - } - v /= pow10; - } else { - // check for overflow - if (v > FLT_MAX / pow10) { - goto fail; - } - v *= pow10; - } - } - pow10 *= pow10; - exp >>= 1; - } - setpos(&endPos); - *value = neg ? -v : v; - return true; - -fail: - // error restore position to last good place - setpos(&endPos); - setstate(failbit); - return false; -} -//------------------------------------------------------------------------------ - -istream& istream::getline(char *str, streamsize n, char delim) { - FatPos_t pos; - int c; - m_gcount = 0; - if (n > 0) { - str[0] = '\0'; - } - while (1) { - c = getch(&pos); - if (c < 0) { - break; - } - if (c == delim) { - m_gcount++; - break; - } - if ((m_gcount + 1) >= n) { - setpos(&pos); - setstate(failbit); - break; - } - str[m_gcount++] = c; - str[m_gcount] = '\0'; - } - if (m_gcount == 0) { - setstate(failbit); - } - return *this; -} -//------------------------------------------------------------------------------ -bool istream::getNumber(uint32_t posMax, uint32_t negMax, uint32_t* num) { - int16_t c; - int8_t any = 0; - int8_t have_zero = 0; - uint8_t neg; - uint32_t val = 0; - uint32_t cutoff; - uint8_t cutlim; - FatPos_t endPos; - uint8_t f = flags() & basefield; - uint8_t base = f == oct ? 8 : f != hex ? 10 : 16; - getpos(&endPos); - c = readSkip(); - - neg = c == '-' ? 1 : 0; - if (c == '-' || c == '+') { - c = getch(); - } - - if (base == 16 && c == '0') { // TESTSUITE - c = getch(&endPos); - if (c == 'X' || c == 'x') { - c = getch(); - // remember zero in case no hex digits follow x/X - have_zero = 1; - } else { - any = 1; - } - } - // set values for overflow test - cutoff = neg ? negMax : posMax; - cutlim = cutoff % base; - cutoff /= base; - - while (1) { - if (isdigit(c)) { - c -= '0'; - } else if (isalpha(c)) { - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - } else { - break; - } - if (c >= base) { - break; - } - if (val > cutoff || (val == cutoff && c > cutlim)) { - // indicate overflow error - any = -1; - break; - } - val = val * base + c; - c = getch(&endPos); - any = 1; - } - setpos(&endPos); - if (any > 0 || (have_zero && any >= 0)) { - *num = neg ? -val : val; - return true; - } - setstate(failbit); - return false; -} -//------------------------------------------------------------------------------ -void istream::getStr(char *str) { - FatPos_t pos; - uint16_t i = 0; - uint16_t m = width() ? width() - 1 : 0XFFFE; - if (m != 0) { - getpos(&pos); - int c = readSkip(); - - while (i < m) { - if (c < 0) { - break; - } - if (isspace(c)) { - setpos(&pos); - break; - } - str[i++] = c; - c = getch(&pos); - } - } - str[i] = '\0'; - if (i == 0) { - setstate(failbit); - } - width(0); -} -//------------------------------------------------------------------------------ -istream& istream::ignore(streamsize n, int delim) { - int c; - m_gcount = 0; - while (m_gcount < n) { - c = getch(); - if (c < 0) { - break; - } - m_gcount++; - if (c == delim) { - break; - } - } - return *this; -} -//------------------------------------------------------------------------------ -int istream::peek() { - int16_t c; - FatPos_t pos; - m_gcount = 0; - getpos(&pos); - c = getch(); - if (c < 0) { - if (!bad()) { - setstate(eofbit); - } - } else { - setpos(&pos); - } - return c; -} -//------------------------------------------------------------------------------ -int16_t istream::readSkip() { - int16_t c; - do { - c = getch(); - } while (isspace(c) && (flags() & skipws)); - return c; -} -//------------------------------------------------------------------------------ -/** used to implement ws() */ -void istream::skipWhite() { - int c; - FatPos_t pos; - do { - c = getch(&pos); - } while (isspace(c)); - setpos(&pos); -} diff --git a/SdFat/utility/ostream.cpp b/SdFat/utility/ostream.cpp deleted file mode 100644 index 230cda4a..00000000 --- a/SdFat/utility/ostream.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#include -#include "ostream.h" -#ifndef PSTR -#define PSTR(x) x -#endif -//------------------------------------------------------------------------------ -void ostream::do_fill(unsigned len) { - for (; len < width(); len++) { - putch(fill()); - } - width(0); -} -//------------------------------------------------------------------------------ -void ostream::fill_not_left(unsigned len) { - if ((flags() & adjustfield) != left) { - do_fill(len); - } -} -//------------------------------------------------------------------------------ -char* ostream::fmtNum(uint32_t n, char *ptr, uint8_t base) { - char a = flags() & uppercase ? 'A' - 10 : 'a' - 10; - do { - uint32_t m = n; - n /= base; - char c = m - base * n; - *--ptr = c < 10 ? c + '0' : c + a; - } while (n); - return ptr; -} -//------------------------------------------------------------------------------ -void ostream::putBool(bool b) { - if (flags() & boolalpha) { - if (b) { - putPgm(PSTR("true")); - } else { - putPgm(PSTR("false")); - } - } else { - putChar(b ? '1' : '0'); - } -} -//------------------------------------------------------------------------------ -void ostream::putChar(char c) { - fill_not_left(1); - putch(c); - do_fill(1); -} -//------------------------------------------------------------------------------ -void ostream::putDouble(double n) { - uint8_t nd = precision(); - double round = 0.5; - char sign; - char buf[13]; // room for sign, 10 digits, '.', and zero byte - char *end = buf + sizeof(buf) - 1; - char *str = end; - // terminate string - *end = '\0'; - - // get sign and make nonnegative - if (n < 0.0) { - sign = '-'; - n = -n; - } else { - sign = flags() & showpos ? '+' : '\0'; - } - // check for larger than uint32_t - if (n > 4.0E9) { - putPgm(PSTR("BIG FLT")); - return; - } - // round up and separate int and fraction parts - for (uint8_t i = 0; i < nd; ++i) { - round *= 0.1; - } - n += round; - uint32_t intPart = n; - double fractionPart = n - intPart; - - // format intPart and decimal point - if (nd || (flags() & showpoint)) { - *--str = '.'; - } - str = fmtNum(intPart, str, 10); - - // calculate length for fill - uint8_t len = sign ? 1 : 0; - len += nd + end - str; - - // extract adjust field - fmtflags adj = flags() & adjustfield; - if (adj == internal) { - if (sign) { - putch(sign); - } - do_fill(len); - } else { - // do fill for internal or right - fill_not_left(len); - if (sign) { - *--str = sign; - } - } - putstr(str); - // output fraction - while (nd-- > 0) { - fractionPart *= 10.0; - int digit = static_cast(fractionPart); - putch(digit + '0'); - fractionPart -= digit; - } - // do fill if not done above - do_fill(len); -} -//------------------------------------------------------------------------------ -void ostream::putNum(int32_t n) { - bool neg = n < 0 && flagsToBase() == 10; - if (neg) { - n = -n; - } - putNum(n, neg); -} -//------------------------------------------------------------------------------ -void ostream::putNum(uint32_t n, bool neg) { - char buf[13]; - char* end = buf + sizeof(buf) - 1; - char* num; - char* str; - uint8_t base = flagsToBase(); - *end = '\0'; - str = num = fmtNum(n, end, base); - if (base == 10) { - if (neg) { - *--str = '-'; - } else if (flags() & showpos) { - *--str = '+'; - } - } else if (flags() & showbase) { - if (flags() & hex) { - *--str = flags() & uppercase ? 'X' : 'x'; - } - *--str = '0'; - } - uint8_t len = end - str; - fmtflags adj = flags() & adjustfield; - if (adj == internal) { - while (str < num) { - putch(*str++); - } - } - if (adj != left) { - do_fill(len); - } - putstr(str); - do_fill(len); -} -//------------------------------------------------------------------------------ -void ostream::putPgm(const char* str) { - int n; - for (n = 0; pgm_read_byte(&str[n]); n++) {} - fill_not_left(n); - for (uint8_t c; (c = pgm_read_byte(str)); str++) { - putch(c); - } - do_fill(n); -} -//------------------------------------------------------------------------------ -void ostream::putStr(const char *str) { - unsigned n = strlen(str); - fill_not_left(n); - putstr(str); - do_fill(n); -} diff --git a/SdFat/utility/ostream.h b/SdFat/utility/ostream.h deleted file mode 100644 index 3a232dad..00000000 --- a/SdFat/utility/ostream.h +++ /dev/null @@ -1,295 +0,0 @@ -/* FatLib Library - * Copyright (C) 2013 by William Greiman - * - * This file is part of the FatLib Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the FatLib Library. If not, see - * . - */ -#ifndef ostream_h -#define ostream_h -/** - * \file - * \brief \ref ostream class - */ -#include "ios.h" -//------------------------------------------------------------------------------ -/** macro for flash inserter */ -#define pstr(str) pgm(PSTR(str)) -/** \struct pgm - * \brief type for string in flash - */ -struct pgm { - /** Pointer to flash string */ - char *ptr; - /** constructor - * \param[in] str initializer for pointer. - */ - explicit pgm(char* str) : ptr(str) {} - /** constructor - * \param[in] str initializer for pointer. - */ - explicit pgm(const char *str) : ptr(const_cast(str)) {} -}; -//============================================================================== -/** - * \class ostream - * \brief Output Stream - */ -class ostream : public virtual ios { - public: - ostream() {} - - /** call manipulator - * \param[in] pf function to call - * \return the stream - */ - ostream& operator<< (ostream& (*pf)(ostream& str)) { - return pf(*this); - } - /** call manipulator - * \param[in] pf function to call - * \return the stream - */ - ostream& operator<< (ios_base& (*pf)(ios_base& str)) { - pf(*this); - return *this; - } - /** Output bool - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (bool arg) { - putBool(arg); - return *this; - } - /** Output string - * \param[in] arg string to output - * \return the stream - */ - ostream &operator<< (const char *arg) { - putStr(arg); - return *this; - } - /** Output string - * \param[in] arg string to output - * \return the stream - */ - ostream &operator<< (const signed char *arg) { - putStr((const char*)arg); - return *this; - } - /** Output string - * \param[in] arg string to output - * \return the stream - */ - ostream &operator<< (const unsigned char *arg) { - putStr((const char*)arg); - return *this; - } - /** Output character - * \param[in] arg character to output - * \return the stream - */ - ostream &operator<< (char arg) { - putChar(arg); - return *this; - } - /** Output character - * \param[in] arg character to output - * \return the stream - */ - ostream &operator<< (signed char arg) { - putChar(static_cast(arg)); - return *this; - } - /** Output character - * \param[in] arg character to output - * \return the stream - */ - ostream &operator<< (unsigned char arg) { - putChar(static_cast(arg)); - return *this; - } - /** Output double - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (double arg) { - putDouble(arg); - return *this; - } - /** Output float - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (float arg) { - putDouble(arg); - return *this; - } - /** Output signed short - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (short arg) { // NOLINT - putNum((int32_t)arg); - return *this; - } - /** Output unsigned short - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (unsigned short arg) { // NOLINT - putNum((uint32_t)arg); - return *this; - } - /** Output signed int - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (int arg) { - putNum((int32_t)arg); - return *this; - } - /** Output unsigned int - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (unsigned int arg) { - putNum((uint32_t)arg); - return *this; - } - /** Output signed long - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (long arg) { // NOLINT - putNum((int32_t)arg); - return *this; - } - /** Output unsigned long - * \param[in] arg value to output - * \return the stream - */ - ostream &operator<< (unsigned long arg) { // NOLINT - putNum((uint32_t)arg); - return *this; - } - /** Output pointer - * \param[in] arg value to output - * \return the stream - */ - ostream& operator<< (const void* arg) { - putNum(reinterpret_cast(arg)); - return *this; - } - /** Output a string from flash using the pstr() macro - * \param[in] arg pgm struct pointing to string - * \return the stream - */ - ostream &operator<< (pgm arg) { - putPgm(arg.ptr); - return *this; - } - /** Output a string from flash using the Arduino F() macro. - * \param[in] arg pointing to flash string - * \return the stream - */ - ostream &operator<< (const __FlashStringHelper *arg) { - putPgm(reinterpret_cast(arg)); - return *this; - } - /** - * Puts a character in a stream. - * - * The unformatted output function inserts the element \a ch. - * It returns *this. - * - * \param[in] ch The character - * \return A reference to the ostream object. - */ - ostream& put(char ch) { - putch(ch); - return *this; - } -// ostream& write(char *str, streamsize count); - /** - * Flushes the buffer associated with this stream. The flush function - * calls the sync function of the associated file. - * \return A reference to the ostream object. - */ - ostream& flush() { - if (!sync()) { - setstate(badbit); - } - return *this; - } - /** - * \return the stream position - */ - pos_type tellp() { - return tellpos(); - } - /** - * Set the stream position - * \param[in] pos The absolute position in which to move the write pointer. - * \return Is always *this. Failure is indicated by the state of *this. - */ - ostream& seekp(pos_type pos) { - if (!seekpos(pos)) { - setstate(failbit); - } - return *this; - } - /** - * Set the stream position. - * - * \param[in] off An offset to move the write pointer relative to way. - * \a off is a signed 32-bit int so the offset is limited to +- 2GB. - * \param[in] way One of ios::beg, ios::cur, or ios::end. - * \return Is always *this. Failure is indicated by the state of *this. - */ - ostream& seekp(off_type off, seekdir way) { - if (!seekoff(off, way)) { - setstate(failbit); - } - return *this; - } - - protected: - /// @cond SHOW_PROTECTED - /** Put character with binary/text conversion - * \param[in] ch character to write - */ - virtual void putch(char ch) = 0; - virtual void putstr(const char *str) = 0; - virtual bool seekoff(off_type pos, seekdir way) = 0; - virtual bool seekpos(pos_type pos) = 0; - virtual bool sync() = 0; - - virtual pos_type tellpos() = 0; - /// @endcond - private: - void do_fill(unsigned len); - void fill_not_left(unsigned len); - char* fmtNum(uint32_t n, char *ptr, uint8_t base); - void putBool(bool b); - void putChar(char c); - void putDouble(double n); - void putNum(uint32_t n, bool neg = false); - void putNum(int32_t n); - void putPgm(const char* str); - void putStr(const char* str); -}; -#endif // ostream_h diff --git a/SdFatTestSuite/SdFatTestSuite.cpp b/SdFatTestSuite/SdFatTestSuite.cpp deleted file mode 100644 index f09f0997..00000000 --- a/SdFatTestSuite/SdFatTestSuite.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2011 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#include -static uint16_t failCount; -static uint16_t testCount; -static Print* testOut = &Serial; -//------------------------------------------------------------------------------ -static size_t strlenPGM(PGM_P str) { - PGM_P end = str; - while (pgm_read_byte(end++)) {} - return end - str; -} -//------------------------------------------------------------------------------ -void testBegin() { - Serial.begin(9600); - while (!Serial) {} // wait for leonardo - testOut = &Serial; - SerialPrintln_P(PSTR("Type any character to begin.")); - while (Serial.read() <= 0) {} - delay(200); // Catch Due reset problem - - testOut->print(F("FreeRam: ")); - testOut->println(FreeRam()); - testOut->println(); - failCount = 0; - testCount = 0; -} -//------------------------------------------------------------------------------ -void testEnd() { - testOut->println(); - testOut->println(F("Compiled: " __DATE__ " " __TIME__)); - testOut->print(F("FreeRam: ")); - testOut->println(FreeRam()); - testOut->print(F("Test count: ")); - testOut->println(testCount); - testOut->print(F("Fail count: ")); - testOut->println(failCount); -} -//------------------------------------------------------------------------------ -static void testResult(bool b, uint8_t n) { - while (n++ < 60) testOut->write(' '); - if (b) { - testOut->println(F("..ok")); - } else { - testOut->println(F("FAIL")); - failCount++; - } - testCount++; -} -//------------------------------------------------------------------------------ -void testVerify_P(char* result, PGM_P expect) { - testOut->write('"'); - testOut->print(result); - testOut->print("\",\""); - testOut->print((const __FlashStringHelper*)expect); - testOut->write('"'); - uint8_t n = strlen(result) + strlenPGM(expect) + 5; - testResult(!strcmp_P(result, expect), n); -} -//------------------------------------------------------------------------------ -void testVerify_P(bool b, PGM_P msg) { - testOut->print((const __FlashStringHelper*)msg); - uint8_t n = strlenPGM(msg); - testResult(b, n); -} diff --git a/SdFatTestSuite/SdFatTestSuite.h b/SdFatTestSuite/SdFatTestSuite.h deleted file mode 100644 index 736f67f7..00000000 --- a/SdFatTestSuite/SdFatTestSuite.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Arduino SdFat Library - * Copyright (C) 2011 by William Greiman - * - * This file is part of the Arduino SdFat Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino SdFat Library. If not, see - * . - */ -#ifndef SdFatTestSuite_h -#define SdFatTestSuite_h -#include -#include - -#if defined(__arm__) && !defined(strcmp_P) -#define strcmp_P(a, b) strcmp((a), (b)) -#endif // strcmp_P - -#if defined(__arm__) && !defined(strncpy_P) -#define strncpy_P(s, t, n) strncpy(s, t, n) -#endif // strncpy_P - -#if defined(__arm__) && !defined(strlen_P) -#define strlen_P(str) strlen(str) -#endif // strlen_P - -#define testVerifyBool(result) testVerify_P(result, PSTR(#result)) -#define testVerifyMsg(result, msg) testVerify_P(result, PSTR(msg)) -#define testVerifyStr(result, expect) testVerify_P(result, PSTR(expect)) - -void testBegin(); -void testEnd(); -void testVerify_P(bool b, PGM_P msg); -void testVerify_P(char* result, PGM_P expect); -#endif // SdFatTestSuite_h diff --git a/SdFatTestSuite/examples/ATS_SD_File/ATS_SD_File.ino b/SdFatTestSuite/examples/ATS_SD_File/ATS_SD_File.ino deleted file mode 100644 index 4b4fe3ad..00000000 --- a/SdFatTestSuite/examples/ATS_SD_File/ATS_SD_File.ino +++ /dev/null @@ -1,106 +0,0 @@ -// modified from ArduinoTestSuite 0022 by William Greiman -// Tests writing to and reading from a file, in particular the -// the Stream implementation (e.g. read() and peek()). - -#include -#include -#include -SdFat SD; -#define FILE_WRITE O_RDWR | O_CREAT | O_AT_END -#define ATS_PrintTestStatus(msg, b) testVerify_P(b, PSTR(msg)) -void setup() { - boolean b; - SdFile f; - uint32_t fs; - - testBegin(); - - ATS_PrintTestStatus("SD.begin()", b = SD.begin()); - if (!b) goto done; - - SD.remove("test.txt"); - - f.open("test.txt", FILE_WRITE); - ATS_PrintTestStatus("SD.open()", f.isOpen()); - if (!f.isOpen()) goto done; - - f.print("abc"); - f.print("de"); - f.close(); - - f.open("test.txt", FILE_WRITE); - ATS_PrintTestStatus("SD.open()", f.isOpen()); - if (!f.isOpen()) goto done; - - f.print("fgh"); - f.close(); - - f.open("test.txt", O_READ); - ATS_PrintTestStatus("SD.open()", f.isOpen()); - if (!f.isOpen()) goto done; - fs =f.fileSize(); - ATS_PrintTestStatus("read()", f.read() == 'a'); - ATS_PrintTestStatus("peek()", f.peek() == 'b'); - ATS_PrintTestStatus("read()", f.read() == 'b'); - ATS_PrintTestStatus("read()", f.read() == 'c'); - ATS_PrintTestStatus("peek()", f.peek() == 'd'); - ATS_PrintTestStatus("peek()", f.peek() == 'd'); - ATS_PrintTestStatus("peek()", f.peek() == 'd'); - ATS_PrintTestStatus("peek()", f.peek() == 'd'); - ATS_PrintTestStatus("read()", f.read() == 'd'); - ATS_PrintTestStatus("available()", f.curPosition() != fs); - ATS_PrintTestStatus("read()", f.read() == 'e'); - ATS_PrintTestStatus("available()", f.curPosition() != fs); - ATS_PrintTestStatus("peek()", f.peek() == 'f'); - ATS_PrintTestStatus("read()", f.read() == 'f'); - ATS_PrintTestStatus("peek()", f.peek() == 'g'); - ATS_PrintTestStatus("available()", f.curPosition() != fs); - ATS_PrintTestStatus("peek()", f.peek() == 'g'); - ATS_PrintTestStatus("read()", f.read() == 'g'); - ATS_PrintTestStatus("available()", f.curPosition() != fs); - ATS_PrintTestStatus("available()", f.curPosition() != fs); - ATS_PrintTestStatus("available()", f.curPosition() != fs); - ATS_PrintTestStatus("peek()", f.peek() == 'h'); - ATS_PrintTestStatus("read()", f.read() == 'h'); - ATS_PrintTestStatus("available()", f.curPosition() == fs); - ATS_PrintTestStatus("peek()", f.peek() == -1); - ATS_PrintTestStatus("read()", f.read() == -1); - ATS_PrintTestStatus("peek()", f.peek() == -1); - ATS_PrintTestStatus("read()", f.read() == -1); - - f.close(); - - SD.remove("test2.txt"); - - f.open("test2.txt", FILE_WRITE); - ATS_PrintTestStatus("SD.open()", f.isOpen()); - if (!f.isOpen()) goto done; - - f.print("ABC"); - f.close(); - - f.open("test.txt", O_READ); - ATS_PrintTestStatus("SD.open()", f.isOpen()); - if (!f.isOpen()) goto done; - - ATS_PrintTestStatus("peek()", f.peek() == 'a'); - - f.close(); - - f.open("test2.txt", O_READ); - ATS_PrintTestStatus("SD.open()", f.isOpen()); - if (!f.isOpen()) goto done; - - ATS_PrintTestStatus("peek()", f.peek() == 'A'); - ATS_PrintTestStatus("read()", f.read() == 'A'); - - f.close(); - -done: - testEnd(); - -} - -void loop() {} - - diff --git a/SdFatTestSuite/examples/ATS_SD_Files/ATS_SD_Files.ino b/SdFatTestSuite/examples/ATS_SD_Files/ATS_SD_Files.ino deleted file mode 100644 index 1427bb54..00000000 --- a/SdFatTestSuite/examples/ATS_SD_Files/ATS_SD_Files.ino +++ /dev/null @@ -1,76 +0,0 @@ -// modified from ArduinoTestSuite 0022 by William Greiman -#include -#include -#include -SdFat SD; -#define FILE_WRITE O_RDWR | O_CREAT | O_AT_END -#define ATS_PrintTestStatus(msg, b) testVerify_P(b, PSTR(msg)) - -void setup() { - boolean b; - SdFile f; - - testBegin(); - - ATS_PrintTestStatus("SD.begin()", b = SD.begin()); - if (!b) goto done; - - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf.txt")); - ATS_PrintTestStatus("SD.open()", f.open("asdf.txt", FILE_WRITE)); f.close(); - ATS_PrintTestStatus("SD.exists()", SD.exists("asdf.txt")); - ATS_PrintTestStatus("SD.exists()", SD.exists("/asdf.txt")); - ATS_PrintTestStatus("SD.remove()", SD.remove("asdf.txt")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf.txt")); - - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf")); - ATS_PrintTestStatus("SD.mkdir()", SD.mkdir("asdf")); - ATS_PrintTestStatus("SD.exists()", SD.exists("asdf")); - ATS_PrintTestStatus("SD.exists()", SD.exists("/asdf")); - ATS_PrintTestStatus("SD.exists()", SD.exists("asdf/")); - ATS_PrintTestStatus("SD.rmdir()", SD.rmdir("asdf")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf")); - - ATS_PrintTestStatus("SD.mkdir()", SD.mkdir("x/y/z")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x/")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x/y")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x/y/")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x/y/z")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x/y/z/")); - ATS_PrintTestStatus("SD.exists()", SD.exists("/x/y/z/")); - ATS_PrintTestStatus("SD.rmdir()", SD.rmdir("x/y/z")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x/y")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("x/y/z")); - ATS_PrintTestStatus("SD.rmdir()", SD.rmdir("x/y/")); - ATS_PrintTestStatus("SD.exists()", SD.exists("x")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("x/y")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("x/y/z")); - ATS_PrintTestStatus("SD.rmdir()", SD.rmdir("/x")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("x")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("x/y")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("x/y/z")); - - ATS_PrintTestStatus("!SD.open()", !(f.open("asdf/asdf.txt", FILE_WRITE))); f.close(); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf.txt")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf/asdf.txt")); - ATS_PrintTestStatus("SD.mkdir()", SD.mkdir("asdf")); - ATS_PrintTestStatus("SD.exists()", SD.exists("asdf")); - ATS_PrintTestStatus("SD.open()", f.open("asdf/asdf.txt", FILE_WRITE)); f.close(); - ATS_PrintTestStatus("SD.exists()", SD.exists("asdf/asdf.txt")); - ATS_PrintTestStatus("!SD.rmdir()", !SD.rmdir("asdf")); - ATS_PrintTestStatus("SD.exists()", SD.exists("asdf")); - ATS_PrintTestStatus("SD.exists()", SD.exists("asdf/asdf.txt")); - ATS_PrintTestStatus("SD.remove()", SD.remove("asdf/asdf.txt")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf/asdf.txt")); - ATS_PrintTestStatus("SD.exists()", SD.exists("asdf")); - ATS_PrintTestStatus("SD.rmdir()", SD.rmdir("asdf")); - ATS_PrintTestStatus("!SD.exists()", !SD.exists("asdf")); - -done: - - testEnd(); - -} -void loop() {} diff --git a/SdFatTestSuite/examples/ATS_SD_Seek/ATS_SD_Seek.ino b/SdFatTestSuite/examples/ATS_SD_Seek/ATS_SD_Seek.ino deleted file mode 100644 index 2d169727..00000000 --- a/SdFatTestSuite/examples/ATS_SD_Seek/ATS_SD_Seek.ino +++ /dev/null @@ -1,109 +0,0 @@ -// modified from ArduinoTestSuite 0022 by William Greiman -// Tests writing to and reading from a file, in particular the -// the Stream implementation (e.g. read() and peek()). -#include -#include -#include -SdFat SD; -#define FILE_WRITE O_RDWR | O_CREAT | O_AT_END -#define ATS_PrintTestStatus(msg, b) testVerify_P(b, PSTR(msg)) - -void setup() { - boolean b; - SdFile f; - - testBegin(); - - ATS_PrintTestStatus("SD.begin()", b = SD.begin()); - if (!b) goto done; - - SD.remove("test.txt"); - - f.open("test.txt", FILE_WRITE); - ATS_PrintTestStatus("SD.open()", f.isOpen()); - if (!f.isOpen()) goto done; - - ATS_PrintTestStatus("initial position", f.curPosition() == 0); - ATS_PrintTestStatus("initial size", f.fileSize() == 0); - - f.print("0123456789"); - - ATS_PrintTestStatus("position after writing", f.curPosition() == 10); - ATS_PrintTestStatus("size after writing", f.fileSize() == 10); - - f.seekSet(0); - - ATS_PrintTestStatus("size after seek", f.fileSize() == 10); - ATS_PrintTestStatus("position after seek", f.curPosition() == 0); - - f.seekSet(7); - - ATS_PrintTestStatus("position after seek", f.curPosition() == 7); - ATS_PrintTestStatus("reading after seek", f.read() == '7'); - ATS_PrintTestStatus("position after reading after seeking", f.curPosition() == 8); - ATS_PrintTestStatus("reading after reading after seeking", f.read() == '8'); - - f.seekSet(3); - - ATS_PrintTestStatus("position after seeking", f.curPosition() == 3); - ATS_PrintTestStatus("peeking after seeking", f.peek() == '3'); - ATS_PrintTestStatus("position after peeking after seeking", f.curPosition() == 3); - ATS_PrintTestStatus("peeking after peeking after seeking", f.peek() == '3'); - ATS_PrintTestStatus("position after peeking after seeking", f.curPosition() == 3); - ATS_PrintTestStatus("peeking after peeking after seeking", f.read() == '3'); - ATS_PrintTestStatus("position after peeking after seeking", f.curPosition() == 4); - - f.seekSet(1); - - ATS_PrintTestStatus("position after seeking", f.curPosition() == 1); - ATS_PrintTestStatus("peeking after seeking", f.peek() == '1'); - - f.seekSet(4); - - ATS_PrintTestStatus("position after seeking", f.curPosition() == 4); - ATS_PrintTestStatus("peeking after seeking", f.peek() == '4'); - - f.seekSet(7); - - ATS_PrintTestStatus("position()", f.curPosition() == 7); - ATS_PrintTestStatus("read()", f.read() == '7'); - - f.seekSet(0); - f.peek(); - f.print("AB"); - - ATS_PrintTestStatus("position()", f.curPosition() == 2); - ATS_PrintTestStatus("size()", f.fileSize() == 10); - ATS_PrintTestStatus("read()", f.read() == '2'); - - f.seekSet(0); - - ATS_PrintTestStatus("read()", f.read() == 'A'); - ATS_PrintTestStatus("read()", f.read() == 'B'); - ATS_PrintTestStatus("read()", f.read() == '2'); - - f.close(); - - f.open("test.txt", O_READ); - ATS_PrintTestStatus("SD.open()", f.isOpen()); - if (!f.isOpen()) goto done; - - ATS_PrintTestStatus("position()", f.curPosition() == 0); - ATS_PrintTestStatus("size()", f.fileSize() == 10); - ATS_PrintTestStatus("peek()", f.peek() == 'A'); - ATS_PrintTestStatus("read()", f.read() == 'A'); - - f.seekSet(4); - - ATS_PrintTestStatus("position()", f.curPosition() == 4); - ATS_PrintTestStatus("size()", f.fileSize() == 10); - ATS_PrintTestStatus("peek()", f.peek() == '4'); - ATS_PrintTestStatus("read()", f.read() == '4'); - - f.close(); - -done: - testEnd(); -} - -void loop() {} \ No newline at end of file diff --git a/SdFatTestSuite/examples/StressTest/StressTest.ino b/SdFatTestSuite/examples/StressTest/StressTest.ino deleted file mode 100644 index 11fb8040..00000000 --- a/SdFatTestSuite/examples/StressTest/StressTest.ino +++ /dev/null @@ -1,76 +0,0 @@ -// This stress test will create and write files until the SD is full. -#include -#include - -// SD chip select pin. -const uint8_t SD_CS_PIN = SS; - -// Set write buffer size. -#ifdef __arm__ -#ifndef CORE_TEENSY -// Due -const size_t BUF_SIZE = 32768; -#else // CORE_TEENSY -// Teensy 3.0 -const size_t BUF_SIZE = 8192; -#endif // CORE_TEENSY -#elif defined(RAMEND) && RAMEND > 5000 -// AVR with more than 4 KB RAM -const size_t BUF_SIZE = 4096; -#else // __arm__ -// other -const size_t BUF_SIZE = 512; -#endif // __arm__ - -const size_t FILE_SIZE_KB = 10240; -const uint16_t BUFS_PER_FILE = (1024L*FILE_SIZE_KB/BUF_SIZE); - -SdFat sd; - -SdFile file; - -uint8_t buf[BUF_SIZE]; -char name[13]; -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - Serial.print("BUF_SIZE "); - Serial.println(BUF_SIZE); - Serial.println("Type any character to start"); - while (Serial.read() < 0) {} - - if (!sd.begin(SD_CS_PIN))sd.errorHalt("sd.begin"); - - // Fill buf with known value. - for (size_t i = 0; i < BUF_SIZE; i++) buf[i] = i; - - // Wait to begin. - do {delay(10);} while (Serial.read() >= 0); - Serial.println("Type any character to stop after next file"); -} -//------------------------------------------------------------------------------ -void loop() { - // Free KB on SD. - uint32_t freeKB = sd.vol()->freeClusterCount()*sd.vol()->blocksPerCluster()/2; - - Serial.print("Free KB: "); - Serial.println(freeKB); - if (freeKB < 2*FILE_SIZE_KB) { - Serial.println(" Done!"); - while(1); - } - sprintf(name, "%lu.DAT", freeKB); - if (!file.open(name, O_WRITE | O_CREAT | O_TRUNC)) { - sd.errorHalt("Open error!"); - } - for (uint16_t i = 0; i < BUFS_PER_FILE; i++) { - if (file.write(buf, BUF_SIZE) != BUF_SIZE) { - sd.errorHalt("Write error!"); - } - } - file.close(); - if (Serial.available()) { - Serial.println("Stopped!"); - while(1); - } -} \ No newline at end of file diff --git a/SdFatTestSuite/examples/fstreamTest/fstreamTest.ino b/SdFatTestSuite/examples/fstreamTest/fstreamTest.ino deleted file mode 100644 index dc65e12a..00000000 --- a/SdFatTestSuite/examples/fstreamTest/fstreamTest.ino +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include -SdFat sd; -char *testName = "SDFAT.TST"; -//------------------------------------------------------------------------------ -void fstreamOpen() { - ios::openmode nocreate[] = {ios::in, ios::in | ios::out}; - ios::openmode create[] = - {ios::out, ios::out | ios::app, ios::app, ios::out | ios::trunc, - ios::in | ios::out | ios::trunc, ios::in | ios::out | ios::app, - ios::in | ios::app}; - ios::openmode illegal[] = - {0, ios::trunc, ios::app | ios::trunc, ios::in | ios::app | ios::trunc, - ios::in | ios::trunc, ios::out | ios::app | ios::trunc, - ios::in | ios::out | ios::app | ios::trunc}; - - sd.remove(testName); - fstream file(testName); - testVerifyMsg(!file.is_open()&& !sd.exists(testName), "fstream constructor"); - - for (uint8_t i = 0 ; i < sizeof(nocreate)/sizeof(nocreate[1]); i++) { - file.close(); - sd.remove(testName); - file.open(testName, nocreate[i]); - testVerifyMsg(!sd.exists(testName) && !file.is_open(), "fstream nocreate !exists"); - } - for (uint8_t i = 0 ; i < sizeof(create)/sizeof(create[1]); i++) { - file.close(); - sd.remove(testName); - file.open(testName, create[i]); - testVerifyMsg(sd.exists(testName) && file.is_open(), "fstream create openmode"); - } - for (uint8_t i = 0 ; i < sizeof(illegal)/sizeof(illegal[1]); i++) { - file.close(); - file.open(testName, illegal[i]); - testVerifyMsg(sd.exists(testName) && !file.is_open(), "fstream illegal openmode"); - } - for (uint8_t i = 0 ; i < sizeof(nocreate)/sizeof(nocreate[1]); i++) { - file.close(); - file.open(testName, nocreate[i]); - testVerifyMsg(sd.exists(testName) && file.is_open(), "fstream nocreate exists"); - } -} -//------------------------------------------------------------------------------ -void testPosition() { - sd.remove(testName); - ofstream ofs(testName); - testVerifyBool(ofs.good() && ofs.tellp() == 0); - ofs.seekp(0, ios::end); - testVerifyBool(ofs.good() && ofs.tellp() == 0); - ofs << "abcde"; - testVerifyBool(ofs.good() && ofs.tellp() == 5); - ofs.seekp(4); - testVerifyBool(ofs.good() && ofs.tellp() == 4); - ofs.seekp(-1, ios::cur); - testVerifyBool(ofs.good() && ofs.tellp() == 3); - ofs.close(); - ifstream ifs(testName, ios::ate); - testVerifyBool(ifs.good() && ifs.tellg() == 5); - ifs.seekg(0); - testVerifyBool(ifs.get() == 'a' && ifs.get() == 'b'); - testVerifyBool(ifs.tellg() == 2 && ifs.good()); - ifs.seekg(3, ios::cur); - testVerifyBool(ifs.tellg() == 5 && ifs.good()); - ifs.seekg(4, ios::beg); - testVerifyBool(ifs.good() && ifs.tellg() == 4); - ifs.close(); - ofs.open(testName, ios::app); - testVerifyBool(ofs.good() && ofs.tellp() == 0); - ofs << 'f'; - testVerifyBool(ofs.good() && ofs.tellp() == 6); - ofs.close(); - ofs.open(testName, ios::trunc); - ofs.seekp(0, ios::end); - testVerifyBool(ofs.good() && ofs.tellp() == 0); - ofs << "ABCDEF"; - ofs.close(); - fstream fs(testName); - testVerifyBool(fs.good() && fs.tellp() == 0 && fs.tellg() == 0); - fs.seekg(2); - testVerifyBool(fs.good() && fs.get() == 'C'); -} -//------------------------------------------------------------------------------ -void setup() { - - testBegin(); - if (!sd.begin()) sd.initErrorHalt(); - fstreamOpen(); - testPosition(); - testEnd(); -} -//------------------------------------------------------------------------------ -void loop() {} diff --git a/SdFatTestSuite/examples/istreamTest/istreamTest.ino b/SdFatTestSuite/examples/istreamTest/istreamTest.ino deleted file mode 100644 index 3cf4d6d1..00000000 --- a/SdFatTestSuite/examples/istreamTest/istreamTest.ino +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include -#include - -char buf[100]; -ibufstream ib; -#define ibInit(s) ibInit_P(PSTR(s)) - -//---------------------------------------------------------- -void ibInit_P(PGM_P p) { - if (strlen_P(p) >= sizeof(buf)) { - ib.init(""); - ib.setstate(ios::badbit); - } else { - ib.clear(); - strncpy_P(buf, p, sizeof(buf)); - ib.init(buf); - } -} -//------------------------------------------------------------------------------ -void istreamBool() { - bool b; - ibInit(" 0 1 2"); - testVerifyBool((ib >> b) && !b); - testVerifyBool((ib >> b) && b); - testVerifyBool(!(ib >> b) && !ib.good()); - - ibInit(" true false err"); - testVerifyBool((ib >> boolalpha >> b) && b && ib.good()); - testVerifyBool((ib >> b) && !b && ib.good()); - testVerifyBool(!(ib >> b) && ib.fail()); - - ibInit("1"); - testVerifyBool((ib >> noboolalpha >> b) && b && ib.eof()); -} -//------------------------------------------------------------------------------ -void istreamChar() { - char c; - signed char sc; - unsigned char uc; - - ibInit("c s u g"); - testVerifyBool((ib >> c) && ib.good() && c == 'c'); - testVerifyBool((ib >> sc) && ib.good() && sc == 's'); - testVerifyBool((ib >> uc) && ib.good() && uc == 'u'); - testVerifyBool(ib.get() == ' '); - testVerifyBool(ib.peek() == 'g' && ib.good()); - testVerifyBool(ib.get() == 'g' && ib.good()); - testVerifyBool(ib.get() == -1 && ib.eof()); -} -//------------------------------------------------------------------------------ -void istreamDouble() { - double f; - ibInit("0 .1 1. 2 3.4 .1e5 1e5 -1E6 +2.3e-3 -123.4567"); - testVerifyBool((ib >> f) && f == 0 && ib.good()); - testVerifyBool((ib >> f) && f == 0.1 && ib.good()); - testVerifyBool((ib >> f) && f == 1.0 && ib.good()); - testVerifyBool((ib >> f) && f == 2.0 && ib.good()); - testVerifyBool((ib >> f) && f == 3.4 && ib.good()); - testVerifyBool((ib >> f) && f == 10000.0 && ib.good()); - testVerifyBool((ib >> f) && f == 1e5 && ib.good()); - testVerifyBool((ib >> f) && f == -1E6 && ib.good()); - testVerifyBool((ib >> f) && f == 2.3e-3 && ib.good()); - testVerifyBool((ib >> f) && fabs(f + 123.4567) < 1e-5 && ib.eof()); - if (fabs(f + 123.4567) >= 1e-5) Serial.println(f, 8); -} -//------------------------------------------------------------------------------ -void istreamFloat() { - float f; - ibInit("0 .1 1. 2 3.4 .1e5 1e5 -1E6 +2.3e-3 -123.4567"); - testVerifyBool((ib >> f) && f == 0 && ib.good()); - testVerifyBool((ib >> f) && f == 0.1f && ib.good()); - testVerifyBool((ib >> f) && f == 1.0 && ib.good()); - testVerifyBool((ib >> f) && f == 2.0 && ib.good()); - testVerifyBool((ib >> f) && f == 3.4f && ib.good()); - testVerifyBool((ib >> f) && f == 10000.0 && ib.good()); - testVerifyBool((ib >> f) && f == 1e5 && ib.good()); - testVerifyBool((ib >> f) && f == -1E6 && ib.good()); - testVerifyBool((ib >> f) && f == 2.3e-3f && ib.good()); - testVerifyBool((ib >> f) && fabs(f + 123.4567f) < 1e-5 && ib.eof()); - if (fabs(f + 123.4567) >= 1e-5) Serial.println(f, 8); -} -//------------------------------------------------------------------------------ -void istreamGet() { - char s[4]; - ibInit("ab c"); - testVerifyBool(ib.get() == 'a' && ib.good() && ib.gcount() == 1); - testVerifyBool(ib.get() == 'b' && ib.good() && ib.gcount() == 1); - testVerifyBool(ib.get() == ' ' && ib.good() && ib.gcount() == 1); - testVerifyBool(ib.get() == 'c' && ib.good() && ib.gcount() == 1); - testVerifyBool(ib.get() == -1 && ib.eof() && ib.gcount() == 0); - - ibInit("ab\ncdef"); - ib.get(s, sizeof(s)); - testVerifyBool(ib.good() && ib.gcount() == 2); - testVerifyStr(s, "ab"); - testVerifyBool(ib.get() == '\n' && ib.good() && ib.gcount() == 1); - ib.get(s, sizeof(s)); - testVerifyBool(ib.good() && ib.gcount() == 3); - testVerifyStr(s, "cde"); - ib.get(s, sizeof(s)); - testVerifyBool(ib.eof() && ib.gcount() == 1); - testVerifyStr(s, "f"); - - ibInit( - "short line\n" - "\n" - "17 character line\n" - "too long for buffer\n" - "line with no nl" - ); - char buf[18]; - ib.getline(buf, sizeof(buf)); - testVerifyBool(ib.good() && ib.gcount() == 11); - testVerifyStr(buf, "short line"); - ib.getline(buf, sizeof(buf)); - testVerifyBool(ib.good() && ib.gcount() == 1 && buf[0] == '\0'); - ib.getline(buf, sizeof(buf)); - testVerifyBool(ib.good() && ib.gcount() == 18); - testVerifyStr(buf, "17 character line"); - ib.getline(buf, sizeof(buf)); - testVerifyBool(ib.fail() && !ib.eof() && ib.gcount() == 17); - testVerifyStr(buf, "too long for buff"); - ib.clear(); - ib.getline(buf, sizeof(buf)); - testVerifyBool(ib.good() && !ib.eof() && ib.gcount() == 3); - testVerifyStr(buf, "er"); - ib.getline(buf, sizeof(buf)); - testVerifyBool(!ib.fail() && ib.eof() && ib.gcount() == 15); - testVerifyStr(buf, "line with no nl"); -} -//------------------------------------------------------------------------------ -void istreamNumber() { - short s; - signed short ss; - unsigned short us; - int i; - signed int si; - unsigned int ui; - long l; - signed long sl; - unsigned long ul; - - ibInit("-32769"); - testVerifyBool(!(ib >> s) && ib.fail()); - ibInit("-32768 0 32767 32768"); - testVerifyBool((ib >> s) && s == -32768 && ib.good()); - testVerifyBool((ib >> s) && s == 0 && ib.good()); - testVerifyBool((ib >> s) && s == 32767 && ib.good()); - testVerifyBool(!(ib >> s) && ib.fail()); - - ibInit("-32769"); - testVerifyBool(!(ib >> ss) && ib.fail()); - ibInit("-32768 0 32767 32768"); - testVerifyBool((ib >> ss) && ss == -32768 && ib.good()); - testVerifyBool((ib >> ss) && ss == 0 && ib.good()); - testVerifyBool((ib >> ss) && ss == 32767 && ib.good()); - testVerifyBool(!(ib >> ss) && ib.fail()); - - ibInit("0 65535 65536"); - testVerifyBool((ib >> us) && us == 0 && ib.good()); - testVerifyBool((ib >> us) && us == 65535 && ib.good()); - testVerifyBool(!(ib >> us) && ib.fail()); - -if (sizeof(int) == 2) { - ibInit("-32769"); - testVerifyBool(!(ib >> i) && ib.fail()); - ibInit("-32768 0 32767 32768"); - testVerifyBool((ib >> i) && i == -32768 && ib.good()); - testVerifyBool((ib >> i) && i == 0 && ib.good()); - testVerifyBool((ib >> i) && i == 32767 && ib.good()); - testVerifyBool(!(ib >> i) && ib.fail()); - - ibInit("-32769"); - testVerifyBool(!(ib >> si) && ib.fail()); - ibInit("-32768 0 32767 32768"); - testVerifyBool((ib >> si) && si == -32768 && ib.good()); - testVerifyBool((ib >> si) && si == 0 && ib.good()); - testVerifyBool((ib >> si) && si == 32767 && ib.good()); - testVerifyBool(!(ib >> si) && ib.fail()); - - ibInit("0 65535 65536"); - testVerifyBool((ib >> ui) && ui == 0 && ib.good()); - testVerifyBool((ib >> ui) && ui == 65535 && ib.good()); - testVerifyBool(!(ib >> ui) && ib.fail()); - } else { - ibInit("-2147483649"); - testVerifyBool(!(ib >> i) && ib.fail()); - ibInit("-2147483648 0 2147483647 2147483648"); - testVerifyBool((ib >> i) && i == -2147483648 && ib.good()); - testVerifyBool((ib >> i) && i == 0 && ib.good()); - testVerifyBool((ib >> i) && i == 2147483647 && ib.good()); - testVerifyBool(!(ib >> i) && ib.fail()); - - ibInit("-2147483649"); - testVerifyBool(!(ib >> si) && ib.fail()); - ibInit("-2147483648 0 2147483647 2147483648"); - testVerifyBool((ib >> si) && si == -2147483648 && ib.good()); - testVerifyBool((ib >> si) && si == 0 && ib.good()); - testVerifyBool((ib >> si) && si == 2147483647 && ib.good()); - testVerifyBool(!(ib >> si) && ib.fail()); - - ibInit("0 4294967295 4294967296"); - testVerifyBool((ib >> ui) && ui == 0 && ib.good()); - testVerifyBool((ib >> ui) && ui == 4294967295 && ib.good()); - testVerifyBool(!(ib >> ui) && ib.fail()); - } - ibInit("-2147483649"); - testVerifyBool(!(ib >> l) && ib.fail()); - ibInit("-2147483648 0 2147483647 2147483648"); - testVerifyBool((ib >> l) && l == -2147483648 && ib.good()); - testVerifyBool((ib >> l) && l == 0 && ib.good()); - testVerifyBool((ib >> l) && l == 2147483647 && ib.good()); - testVerifyBool(!(ib >> l) && ib.fail()); - - ibInit("-2147483649"); - testVerifyBool(!(ib >> sl) && ib.fail()); - ibInit("-2147483648 0 2147483647 2147483648"); - testVerifyBool((ib >> sl) && sl == -2147483648 && ib.good()); - testVerifyBool((ib >> sl) && sl == 0 && ib.good()); - testVerifyBool((ib >> sl) && sl == 2147483647 && ib.good()); - testVerifyBool(!(ib >> sl) && ib.fail()); - - ibInit("0 4294967295 4294967296"); - testVerifyBool((ib >> ul) && ul == 0 && ib.good()); - testVerifyBool((ib >> ul) && ul == 4294967295 && ib.good()); - testVerifyBool(!(ib >> ul) && ib.fail()); - - // octal hex - ibInit("123 abc 0xdef 0XABC 567"); - testVerifyBool((ib >> oct >> i) && i == 83); - testVerifyBool((ib >> hex >> i) && i == 0xabc); - testVerifyBool((ib >> i) && i == 0xdef); - testVerifyBool((ib >> i) && i == 0xabc); - testVerifyBool((ib >> dec >> i) && i ==567); -} -//------------------------------------------------------------------------------ -void istreamStr() { - char str[20]; - ibInit("abc def\r\n hij"); - testVerifyBool((ib >> str) && ib.good()); - testVerifyStr(str, "abc"); - testVerifyBool((ib >> str) && ib.good()); - testVerifyStr(str, "def"); - testVerifyBool((ib >> str) && ib.eof()); - testVerifyStr(str, "hij"); -} -//------------------------------------------------------------------------------ -void setup() { - testBegin(); - istreamBool(); - istreamChar(); - istreamDouble(); - istreamFloat(); - istreamGet(); - istreamNumber(); - istreamStr(); - testEnd(); -} -//------------------------------------------------------------------------------ -void loop() {} \ No newline at end of file diff --git a/SdFatTestSuite/examples/lfnSize/lfnSize.ino b/SdFatTestSuite/examples/lfnSize/lfnSize.ino deleted file mode 100644 index a37e9b21..00000000 --- a/SdFatTestSuite/examples/lfnSize/lfnSize.ino +++ /dev/null @@ -1,36 +0,0 @@ -// Program to compare size of SdFat with the SD.h library. -#include -// Select the test library by commenting out one of the following two lines. -// #include -#include - -// SD chip select pin. -const uint8_t SD_CS_PIN = SS; - -#ifdef __SD_H__ -File file; -#else // __SD_H__ -SdFat SD; -SdFile file; -#endif // __SD_H__ - -void setup() { - Serial.begin(9600); - while (!Serial) {} // wait for Leonardo - - if (!SD.begin(SD_CS_PIN)) { - Serial.println("begin failed"); - return; - } - #ifdef __SD_H__ - file = SD.open("SFN_file.txt", FILE_WRITE); - #else // __SD_H__ - file.open("LFN_file.txt", O_RDWR | O_CREAT); - #endif // __SD_H__ - - file.println("Hello"); - file.close(); - Serial.println("Done"); -} -//------------------------------------------------------------------------------ -void loop() {} \ No newline at end of file diff --git a/SdFatTestSuite/examples/lfnTest/lfnTest.ino b/SdFatTestSuite/examples/lfnTest/lfnTest.ino deleted file mode 100644 index 72be3bc5..00000000 --- a/SdFatTestSuite/examples/lfnTest/lfnTest.ino +++ /dev/null @@ -1,235 +0,0 @@ -#include -#include -#include -const uint8_t SD_CS_PIN = SS; -SdFat sd; -SdFile file; -char name[260]; - -//------------------------------------------------------------------------------ -char* testName[] = { - "low.low", - "low.Mix", - "low.UP", - "Mix.low", - "Mix.Mix", - "Mix.UP", - "UP.low", - "UP.Mix", - "UP.UP", - ".dot", - ".dot.dot", - "A b c . txt", - " Leading space and no extension", - "Trailing dots and space . . .", - "Long extension.extension", - "Space after dot. txt", - "Dot.dot.test.txt", - "Dot.dot.test.seq.txt", - "LOW.LOW", - "MIX.MIX", - "Invalid character *.test" -}; -//------------------------------------------------------------------------------ -bool checkName(char first, size_t len) { - size_t i; - if (len < 5 || len > sizeof(name)) { - return false; - } - if ( name[0] != first) { - return false; - } - for (i = 1; i < (len - 4); i++) { - if (name[i] != ('0' + (i + 1) %10)) { - return false; - } - } - char* p = ".txt"; - while (*p) { - if (name[i++] != *p++) { - return false; - } - } - return name[i] == 0; -} -//------------------------------------------------------------------------------ -void makeName(char first, size_t len) { - size_t i; - if (len > sizeof(name)) { - len = 255; - } - if (len < 5) { - len = 5; - } - name[0] = first; - for (i = 1; i < (len - 4); i++) { - name[i] = '0' + (i + 1) %10; - } - char* p = ".txt"; - while (*p) name[i++] = *p++; - name[i] = 0; -} -//------------------------------------------------------------------------------ -// test open, remove, getName, and ls. -void basicTest() { - size_t i; - size_t n = sd.vol()->fatType() == 32 ? 255 : 99; - uint16_t index; - uint16_t maxIndex = 0; - - makeName('Z', 256); - if (!file.open(name, O_RDWR | O_CREAT)) { - Serial.println(F("255 limit OK")); - } else { - sd.errorHalt(F("255 limit")); - } - for (i = 5; i <= n; i++) { - makeName('A', i); - - if (!file.open(name, O_RDWR | O_CREAT)) { - sd.errorHalt(F("open A")); - } - file.println(name); - Serial.print(i); - Serial.write(' '); - Serial.print(file.dirIndex()); - Serial.write(' '); - Serial.print(file.fileSize()); - Serial.println(F(" open A")); - if (file.fileSize() != (i + 2)) { - sd.errorHalt(F("file size A")); - } - if (file.dirIndex() >= maxIndex) { - maxIndex = file.dirIndex(); - } else { - Serial.print(maxIndex); Serial.print(',');Serial.println(file.dirIndex()); - sd.errorHalt(F("dirIndex")); - } - file.close(); - if (!file.open(sd.vwd(), maxIndex, O_READ)) { - sd.errorHalt(F("open by index")); - } - memset(name, 0, sizeof(name)); - if (!file.getName(name, sizeof(name))) { - sd.errorHalt(F("getName")); - } - if (!checkName('A', i)) { - Serial.println(name); - sd.errorHalt(F("checkName")); - } - file.close(); - } - for (i = n; i >= 5; i -= 2) { - makeName('A', i); - Serial.print(i); - Serial.println(F( " rm A")); - if (!sd.remove(name)) { - sd.errorHalt(F("remove A")); - } - } - for (i = n; i >= 5; i -= 2) { - makeName('B', i); - if (!file.open(name, O_RDWR | O_CREAT)) { - sd.errorHalt(F("open B")); - } - file.println(name); - Serial.print(i); - Serial.write(' '); - Serial.print(file.dirIndex()); - Serial.write(' '); - Serial.print(file.fileSize()); - Serial.println(F(" open B")); - if (file.fileSize() != (i + 2)) { - sd.errorHalt(F("file size B")); - } - if (file.dirIndex() > maxIndex) { - sd.errorHalt(F("maxIndex")); - } - file.close(); - } - Serial.println(F("----- ls ------")); - sd.ls(); - for (i = 5; i <= n; i++) { - char fc = i & 1 ? 'B' : 'A'; - makeName(fc, i); - Serial.print(i); - Serial.print(F(" rm ")); - Serial.println(fc); - if (!sd.remove(name)) { - sd.errorHalt(F("remove A/B")); - } - } - if (file.openNext(sd.vwd())) { - sd.errorHalt(F("remove all")); - } - Serial.println(); - Serial.println(F("basicTest done")); -} -//------------------------------------------------------------------------------ -void nameTest() { - Serial.println(); - uint8_t n = sizeof(testName)/sizeof(char*); - for (uint8_t i = 0; i < n; i++) { - Serial.print(F("Name: ")); - Serial.write('"'); - Serial.print(testName[i]); - Serial.println('"'); - if(!file.open(testName[i], O_CREAT | O_RDWR)) { - Serial.println(F("Open failed")); - } else { - file.println(testName[i]); - if (!file.getName(name, sizeof(name))) { - sd.errorHalt(F("getFilemame")); - } - file.println(name); - Serial.print(F("LFN: ")); - Serial.write('"'); - Serial.print(name); - Serial.println('"'); - Serial.print(F("SFN: ")); - Serial.write('"'); - file.printSFN(&Serial); - Serial.println('"'); - Serial.print(F("Index: ")); - if (file.dirIndex() < 10) { - Serial.write(' '); - } - Serial.println(file.dirIndex()); - file.close(); - } - Serial.println(); - } - Serial.println(F("----- ls ------")); - sd.ls(); - Serial.println(); - Serial.println(F("nameTest done")); -} -//------------------------------------------------------------------------------ -void setup() { - Serial.begin(9600); - while(!Serial); - Serial.print(F("\r\nFreeRam: ")); - Serial.println(FreeRam()); - Serial.println(F("Type any character to start.")); - while (Serial.read() < 0) {} - if (!sd.begin(SD_CS_PIN)) sd.initErrorHalt(); - if (file.openNext(sd.vwd())) { - file.close(); - delay(100); - while (Serial.read() >= 0) {} - Serial.print(F("Type 'W' to wipe the card: ")); - int c; - while ((c = Serial.read()) < 0) {} - if (c != 'W') { - sd.errorHalt(F("Invalid")); - } - Serial.println((char)c); - if (!sd.wipe(&Serial) || !sd.begin(SD_CS_PIN)) { - sd.errorHalt(F("wipe failed")); - } - } - basicTest(); - nameTest(); -} -//------------------------------------------------------------------------------ -void loop() {} \ No newline at end of file diff --git a/SdFatTestSuite/examples/lfnTestCout/lfnTestCout.ino b/SdFatTestSuite/examples/lfnTestCout/lfnTestCout.ino deleted file mode 100644 index 79fd223c..00000000 --- a/SdFatTestSuite/examples/lfnTestCout/lfnTestCout.ino +++ /dev/null @@ -1,219 +0,0 @@ -#include -#include -#include -const uint8_t SD_CS_PIN = SS; -SdFat sd; -SdFile file; -char name[260]; - -// Serial output stream -ArduinoOutStream cout(Serial); - -// Serial in buffer. -char cinBuf[10]; - -// Serial input stream -ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf)); -//------------------------------------------------------------------------------ -char* testName[] = { - "low.low", - "low.Mix", - "low.UP", - "Mix.low", - "Mix.Mix", - "Mix.UP", - "UP.low", - "UP.Mix", - "UP.UP", - ".dot", - ".dot.dot", - "A b c . txt", - " Leading space and no extension", - "Trailing dots and space . . .", - "Long extension.extension", - "Space after dot. txt", - "Dot.dot.test.txt", - "Dot.dot.test.seq.txt", - "LOW.LOW", - "MIX.MIX", - "Invalid character *.test" -}; -//------------------------------------------------------------------------------ -bool checkName(char first, size_t len) { - size_t i; - if (len < 5 || len > sizeof(name)) { - return false; - } - if ( name[0] != first) { - return false; - } - for (i = 1; i < (len - 4); i++) { - if (name[i] != ('0' + (i + 1) %10)) { - return false; - } - } - char* p = ".txt"; - while (*p) { - if (name[i++] != *p++) { - return false; - } - } - return name[i] == 0; -} -//------------------------------------------------------------------------------ -void makeName(char first, size_t len) { - size_t i; - if (len > sizeof(name)) { - len = 255; - } - if (len < 5) { - len = 5; - } - name[0] = first; - for (i = 1; i < (len - 4); i++) { - name[i] = '0' + (i + 1) %10; - } - char* p = ".txt"; - while (*p) name[i++] = *p++; - name[i] = 0; -} -//------------------------------------------------------------------------------ -// test open, remove, getName, and ls. -void basicTest() { - size_t i; - size_t n = sd.vol()->fatType() == 32 ? 255 : 99; - uint16_t index; - uint16_t maxIndex = 0; - - makeName('Z', 256); - if (!file.open(name, O_RDWR | O_CREAT)) { - cout << F("255 limit OK") << endl; - } else { - sd.errorHalt(F("255 limit")); - } - for (i = 5; i <= n; i++) { - makeName('A', i); - - if (!file.open(name, O_RDWR | O_CREAT)) { - sd.errorHalt(F("open A")); - } - file.println(name); - cout << setw(3) << i << setw(5) << file.dirIndex() << F(" open A") << endl; - - if (file.fileSize() != (i + 2)) { - sd.errorHalt(F("file size A")); - } - if (file.dirIndex() >= maxIndex) { - maxIndex = file.dirIndex(); - } else { - sd.errorHalt(F("dirIndex")); - } - file.close(); - if (!file.open(sd.vwd(), maxIndex, O_READ)) { - sd.errorHalt(F("open by index")); - } - memset(name, 0, sizeof(name)); - if (!file.getName(name, sizeof(name))) { - sd.errorHalt(F("getName")); - } - if (!checkName('A', i)) { - cout << name << endl; - sd.errorHalt(F("checkName")); - } - file.close(); - } - for (i = n; i >= 5; i -= 2) { - makeName('A', i); - cout << setw(3) << i << F( " rm A") << endl; - if (!sd.remove(name)) { - sd.errorHalt(F("remove A")); - } - } - for (i = n; i >= 5; i -= 2) { - makeName('B', i); - if (!file.open(name, O_RDWR | O_CREAT)) { - sd.errorHalt(F("open B")); - } - file.println(name); - - cout << setw(3) << i << setw(5) << file.dirIndex() << F(" open B") << endl; - - if (file.fileSize() != (i + 2)) { - sd.errorHalt(F("file size B")); - } - if (file.dirIndex() > maxIndex) { - sd.errorHalt(F("maxIndex")); - } - file.close(); - } - cout << endl << F("----- ls ------") << endl; - sd.ls(); - for (i = 5; i <= n; i++) { - char fc = i & 1 ? 'B' : 'A'; - makeName(fc, i); - cout << setw(3) << i << F(" rm ") << fc << endl; - if (!sd.remove(name)) { - sd.errorHalt(F("remove A/B")); - } - } - if (file.openNext(sd.vwd())) { - sd.errorHalt(F("remove all")); - } - cout << endl << F("basicTest done") << endl; -} -//------------------------------------------------------------------------------ -void nameTest() { - cout << endl; - uint8_t n = sizeof(testName)/sizeof(char*); - for (uint8_t i = 0; i < n; i++) { - cout << F("Name: \"") << testName[i] << '"' << endl; - if(!file.open(testName[i], O_CREAT | O_RDWR)) { - cout < -#include -#include -//------------------------------------------------------------------------------ -void ostreamBool() { - char buf[40]; - obufstream ob(buf, sizeof(buf)); - bool f = false; - bool t = true; - ob << t << ',' << f << ',' << setw(2) << t << ',' << left << setw(2) << f; - testVerifyStr(buf, "1,0, 1,0 "); - - ob.init(buf, sizeof(buf)); - ob << boolalpha << t << ',' << f << ',' << setw(5) << t; - ob << ',' << right << setw(6) << f; - testVerifyStr(buf, "true,false,true , false"); -} -//------------------------------------------------------------------------------ -void ostreamChar() { - char buf[40]; - obufstream ob(buf, sizeof(buf)); - char c = 'c'; - signed char sc = 's'; - unsigned char uc = 'u'; - ob <<'l' << c << sc << uc; - ob.put('p'); - testVerifyStr(buf, "lcsup"); - - ob.init(buf, sizeof(buf)); - ob << 's' << setw(2) << 'r' << 'n' << left << setw(2) << 'l'; - ob << 'm' << right << setw(2) << 'e'; - testVerifyStr(buf, "s rnl m e"); - - ob.init(buf, sizeof(buf)); - ob << setfill('f') << setw(5) << 'r'; - testVerifyStr(buf, "ffffr"); -} -//------------------------------------------------------------------------------ -void ostreamFloat() { - char buf[50]; - obufstream ob(buf, sizeof(buf)); - float f = 9.87654; - double d = -123.4567; - ob << f <<','; - ob << internal << setw(10) << d << ','; - ob << setfill('0') << setw(10) << d; - testVerifyStr(buf, "9.88,- 123.46,-000123.46"); - - ob.init(buf, sizeof(buf)); - ob << setw(10) << left << d << ',' << showpos << -d << ','; - ob << setprecision(0) << d; - testVerifyStr(buf, "-123.46000,+123.46,-123"); - - ob.init(buf, sizeof(buf)); - ob << showpoint << d << noshowpoint << ',' << d << ','; - ob << setprecision(4) << f << ',' << setprecision(2) << noshowpos << f; - testVerifyStr(buf, "-123.,-123,+9.8765,9.88"); -} -//------------------------------------------------------------------------------ -void ostreamNumber() { - char buf[50]; - obufstream ob(buf, sizeof(buf)); - - short s = 1; - short signed ss = 2; - short unsigned su = 3; - int i = 4; - int signed is = 5; - int unsigned iu = 6; - long l = 7; - long signed ls = 8; - long unsigned lu = 9; - - - ob << s << ss << su << i << is << iu << l <