From a93a61d1163833d9bdee2026ba5a89a8863bf802 Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Sun, 20 Mar 2011 18:31:35 -0400 Subject: [PATCH] Add FAT16 library --- FAT16/byteordering.c | 62 + FAT16/byteordering.h | 137 + .../FAT16_ReadExample/FAT16_ReadExample.pde | 195 ++ .../applet/FAT16/byteordering.c.o | Bin 0 -> 1604 bytes .../FAT16_ReadExample/applet/FAT16/fat.c.o | Bin 0 -> 68660 bytes .../applet/FAT16/partition.c.o | Bin 0 -> 7552 bytes .../FAT16_ReadExample/applet/FAT16/sd_raw.c.o | Bin 0 -> 29332 bytes .../applet/FAT16_ReadExample.cpp | 215 ++ .../applet/FAT16_ReadExample.cpp.eep | 1 + .../applet/FAT16_ReadExample.cpp.elf | Bin 0 -> 74473 bytes .../applet/FAT16_ReadExample.cpp.hex | 509 ++++ .../applet/FAT16_ReadExample.cpp.o | Bin 0 -> 13216 bytes .../applet/HardwareSerial.cpp.o | Bin 0 -> 16184 bytes .../FAT16_ReadExample/applet/Print.cpp.o | Bin 0 -> 25172 bytes .../FAT16_ReadExample/applet/WInterrupts.c.o | Bin 0 -> 5628 bytes .../FAT16_ReadExample/applet/WMath.cpp.o | Bin 0 -> 7012 bytes .../examples/FAT16_ReadExample/applet/core.a | Bin 0 -> 93558 bytes .../FAT16_ReadExample/applet/pins_arduino.c.o | Bin 0 -> 3056 bytes .../FAT16_ReadExample/applet/wiring.c.o | Bin 0 -> 8772 bytes .../applet/wiring_analog.c.o | Bin 0 -> 6564 bytes .../applet/wiring_digital.c.o | Bin 0 -> 8276 bytes .../FAT16_ReadExample/applet/wiring_pulse.c.o | Bin 0 -> 6452 bytes .../FAT16_ReadExample/applet/wiring_shift.c.o | Bin 0 -> 4084 bytes .../FAT16_WriteExample/FAT16_WriteExample.pde | 205 ++ .../applet/FAT16/byteordering.c.o | Bin 0 -> 1604 bytes .../FAT16_WriteExample/applet/FAT16/fat.c.o | Bin 0 -> 68660 bytes .../applet/FAT16/partition.c.o | Bin 0 -> 7552 bytes .../applet/FAT16/sd_raw.c.o | Bin 0 -> 29332 bytes .../applet/FAT16_WriteExample.cpp | 225 ++ .../applet/FAT16_WriteExample.cpp.eep | 1 + .../applet/FAT16_WriteExample.cpp.elf | Bin 0 -> 81422 bytes .../applet/FAT16_WriteExample.cpp.hex | 883 +++++++ .../applet/FAT16_WriteExample.cpp.o | Bin 0 -> 14604 bytes .../applet/HardwareSerial.cpp.o | Bin 0 -> 16184 bytes .../FAT16_WriteExample/applet/Print.cpp.o | Bin 0 -> 25172 bytes .../FAT16_WriteExample/applet/WInterrupts.c.o | Bin 0 -> 5628 bytes .../FAT16_WriteExample/applet/WMath.cpp.o | Bin 0 -> 7012 bytes .../examples/FAT16_WriteExample/applet/core.a | Bin 0 -> 93558 bytes .../applet/pins_arduino.c.o | Bin 0 -> 3056 bytes .../FAT16_WriteExample/applet/wiring.c.o | Bin 0 -> 8772 bytes .../applet/wiring_analog.c.o | Bin 0 -> 6564 bytes .../applet/wiring_digital.c.o | Bin 0 -> 8276 bytes .../applet/wiring_pulse.c.o | Bin 0 -> 6452 bytes .../applet/wiring_shift.c.o | Bin 0 -> 4084 bytes FAT16/fat.c | 2326 +++++++++++++++++ FAT16/fat.h | 129 + FAT16/fat_config.h | 111 + FAT16/partition.c | 160 ++ FAT16/partition.h | 212 ++ FAT16/partition_config.h | 44 + FAT16/sd-reader_config.h | 53 + FAT16/sd_raw.c | 1011 +++++++ FAT16/sd_raw.h | 148 ++ FAT16/sd_raw_config.h | 146 ++ 54 files changed, 6773 insertions(+) create mode 100644 FAT16/byteordering.c create mode 100644 FAT16/byteordering.h create mode 100644 FAT16/examples/FAT16_ReadExample/FAT16_ReadExample.pde create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16/byteordering.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16/fat.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16/partition.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16/sd_raw.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.eep create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.elf create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.hex create mode 100644 FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/HardwareSerial.cpp.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/Print.cpp.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/WInterrupts.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/WMath.cpp.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/core.a create mode 100644 FAT16/examples/FAT16_ReadExample/applet/pins_arduino.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/wiring.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/wiring_analog.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/wiring_digital.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/wiring_pulse.c.o create mode 100644 FAT16/examples/FAT16_ReadExample/applet/wiring_shift.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/FAT16_WriteExample.pde create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16/byteordering.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16/fat.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16/partition.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16/sd_raw.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.eep create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.elf create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.hex create mode 100644 FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/HardwareSerial.cpp.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/Print.cpp.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/WInterrupts.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/WMath.cpp.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/core.a create mode 100644 FAT16/examples/FAT16_WriteExample/applet/pins_arduino.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/wiring.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/wiring_analog.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/wiring_digital.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/wiring_pulse.c.o create mode 100644 FAT16/examples/FAT16_WriteExample/applet/wiring_shift.c.o create mode 100644 FAT16/fat.c create mode 100644 FAT16/fat.h create mode 100644 FAT16/fat_config.h create mode 100644 FAT16/partition.c create mode 100644 FAT16/partition.h create mode 100644 FAT16/partition_config.h create mode 100644 FAT16/sd-reader_config.h create mode 100644 FAT16/sd_raw.c create mode 100644 FAT16/sd_raw.h create mode 100644 FAT16/sd_raw_config.h diff --git a/FAT16/byteordering.c b/FAT16/byteordering.c new file mode 100644 index 0000000..69330c9 --- /dev/null +++ b/FAT16/byteordering.c @@ -0,0 +1,62 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include "byteordering.h" + +/** + * \addtogroup byteordering + * + * Architecture-dependent handling of byte-ordering. + * + * @{ + */ +/** + * \file + * Byte-order handling implementation (license: GPLv2 or LGPLv2.1) + * + * \author Roland Riegel + */ + +#if !(__AVR__) +/** + * Converts a 16-bit integer to little-endian byte order. + * + * Use this function on variable values instead of the + * macro HTOL16(). This saves code size. + * + * \param[in] h A 16-bit integer in host byte order. + * \returns The given 16-bit integer converted to little-endian byte order. + */ +uint16_t htol16(uint16_t h) +{ + return HTOL16(h); +} +#endif + +#if !(__AVR__) +/** + * Converts a 32-bit integer to little-endian byte order. + * + * Use this function on variable values instead of the + * macro HTOL32(). This saves code size. + * + * \param[in] h A 32-bit integer in host byte order. + * \returns The given 32-bit integer converted to little-endian byte order. + */ +uint32_t htol32(uint32_t h) +{ + return HTOL32(h); +} +#endif + +/** + * @} + */ + diff --git a/FAT16/byteordering.h b/FAT16/byteordering.h new file mode 100644 index 0000000..48ddffe --- /dev/null +++ b/FAT16/byteordering.h @@ -0,0 +1,137 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef BYTEORDERING_H +#define BYTEORDERING_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup byteordering + * + * @{ + */ +/** + * \file + * Byte-order handling header (license: GPLv2 or LGPLv2.1) + * + * \author Roland Riegel + */ + +/** + * \def HTOL16(val) + * + * Converts a 16-bit integer to little-endian byte order. + * + * Use this macro for compile time constants only. For variable values + * use the function htol16() instead. This saves code size. + * + * \param[in] val A 16-bit integer in host byte order. + * \returns The given 16-bit integer converted to little-endian byte order. + */ +/** + * \def HTOL32(val) + * + * Converts a 32-bit integer to little-endian byte order. + * + * Use this macro for compile time constants only. For variable values + * use the function htol32() instead. This saves code size. + * + * \param[in] val A 32-bit integer in host byte order. + * \returns The given 32-bit integer converted to little-endian byte order. + */ + +#if __AVR__ +#define HTOL16(val) (val) +#define HTOL32(val) (val) +#elif defined(BIG_ENDIAN) +#define HTOL16(val) ((((uint16_t) (val)) << 8) | \ + (((uint16_t) (val)) >> 8) \ + ) +#define HTOL32(val) (((((uint32_t) (val)) & 0x000000ff) << 24) | \ + ((((uint32_t) (val)) & 0x0000ff00) << 8) | \ + ((((uint32_t) (val)) & 0x00ff0000) >> 8) | \ + ((((uint32_t) (val)) & 0xff000000) >> 24) \ + ) +#else +#error "Endianess undefined! Please define LITTLE_ENDIAN=1 or BIG_ENDIAN=1." +#endif + +uint16_t htol16(uint16_t h); +uint32_t htol32(uint32_t h); + +/** + * Converts a 16-bit integer to host byte order. + * + * Use this macro for compile time constants only. For variable values + * use the function ltoh16() instead. This saves code size. + * + * \param[in] val A 16-bit integer in little-endian byte order. + * \returns The given 16-bit integer converted to host byte order. + */ +#define LTOH16(val) HTOL16(val) + +/** + * Converts a 32-bit integer to host byte order. + * + * Use this macro for compile time constants only. For variable values + * use the function ltoh32() instead. This saves code size. + * + * \param[in] val A 32-bit integer in little-endian byte order. + * \returns The given 32-bit integer converted to host byte order. + */ +#define LTOH32(val) HTOL32(val) + +/** + * Converts a 16-bit integer to host byte order. + * + * Use this function on variable values instead of the + * macro LTOH16(). This saves code size. + * + * \param[in] l A 16-bit integer in little-endian byte order. + * \returns The given 16-bit integer converted to host byte order. + */ +#define ltoh16(l) htol16(l) + +/** + * Converts a 32-bit integer to host byte order. + * + * Use this function on variable values instead of the + * macro LTOH32(). This saves code size. + * + * \param[in] l A 32-bit integer in little-endian byte order. + * \returns The given 32-bit integer converted to host byte order. + */ +#define ltoh32(l) htol32(l) + + +/** + * @} + */ + +#if __AVR__ +#define htol16(h) (h) +#define htol32(h) (h) +#else +uint16_t htol16(uint16_t h); +uint32_t htol32(uint32_t h); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/FAT16/examples/FAT16_ReadExample/FAT16_ReadExample.pde b/FAT16/examples/FAT16_ReadExample/FAT16_ReadExample.pde new file mode 100644 index 0000000..5bae1dc --- /dev/null +++ b/FAT16/examples/FAT16_ReadExample/FAT16_ReadExample.pde @@ -0,0 +1,195 @@ +/* +FAT16 ReadFile Example +SparkFun Electronics +Written by Ryan Owens +3/16/2010 + +Code Description: Uses an Arduino Duemillanove or Arduino Pro to read the file contents of each file on an SD card. + +Circuit Description: Uses the SparkFun microSD shield. (http://www.sparkfun.com/commerce/product_info.php?products_id=9520) + +Attributions: Special thanks to Roland Riegel for providing an open source FAT library +for AVR microcontrollers. See more of his projects here: +http://www.roland-riegel.de/ + +This code is provided under the Creative Commons Attribution License. More information can be found here: +http://creativecommons.org/licenses/by/3.0/ + +(Use our code freely! Please just remember to give us credit where it's due. Thanks!) +*/ + +//Add libraries to support FAT16 on the SD Card. +//(Note: If you already have these libraries installed in the directory, they'll have to remove in order to compile this.) +#include +#include +#include +#include +#include +#include +#include +#include + +//Define the pin numbers +#define CS 8 +#define MOSI 11 +#define MISO 12 +#define SCK 13 + +//This is the amount of data to be fetched from the SD card for each read. +#define BUFFERSIZE 256 + +unsigned char buffer[BUFFERSIZE]; +char file_name[30]; + +struct fat_dir_struct* dd; //FAT16 directory +struct fat_dir_entry_struct dir_entry; //FAT16 directory entry (A.K.A. a file) + +struct fat_fs_struct* fs; //FAT16 File System +struct partition_struct* partition; //FAT16 Partition + +struct fat_file_struct * file_handle; //FAT16 File Handle + +void setup() +{ + //Set up the pins for the Serial communication + pinMode(0, INPUT); + pinMode(1, OUTPUT); + Serial.begin(9600); + + //Set up the pins for the microSD shield + pinMode(CS, OUTPUT); + pinMode(MOSI, OUTPUT); + pinMode(MISO, INPUT); + pinMode(SCK, OUTPUT); + pinMode(10, OUTPUT); +} + +void loop() +{ + int bytes_read=0; //Keeps track of how many bytes are read when accessing a file on the SD card. + + init_filesystem(); //Initialize the FAT16 file system on the SD card. + + //Get the next file in the directory + while(get_next_filename(dd, file_name)){ + //Open the file + file_handle=open_file_in_dir(fs, dd, file_name); + //Read up to 512 bytes from the file + bytes_read = fat_read_file(file_handle, buffer, BUFFERSIZE); + //Print whatever we just got from the file + Serial.println((const char *)buffer); + //Keep reading from the file until we reach the end (nothing more is read from the file) + while(bytes_read > 0){ + //If there's more to be read from the file, go get it. + bytes_read = fat_read_file(file_handle, buffer, BUFFERSIZE); + //Print the contents that have been read + Serial.println((const char *)buffer); + } + //Close the file before moving on to the next one. + fat_close_file(file_handle); + delay(1000); + Serial.println("Next File..."); + } + while(1); +} + +uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry) +{ + fat_reset_dir(dd); //Make sure to start from the beginning of the directory! + while(fat_read_dir(dd, dir_entry)) + { + if(strcmp(dir_entry->long_name, name) == 0) + { + //fat_reset_dir(dd); + return 1; + } + } + + return 0; +} + +struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name) +{ + struct fat_dir_entry_struct file_entry; + if(!find_file_in_dir(fs, dd, name, &file_entry)) + return 0; + + return fat_open_file(fs, &file_entry); +} + +char init_filesystem(void) +{ + //setup sd card slot + if(!sd_raw_init()) + { + return 0; + } + + //open first partition + partition = partition_open(sd_raw_read, + sd_raw_read_interval, +#if SD_RAW_WRITE_SUPPORT + sd_raw_write, + sd_raw_write_interval, +#else + 0, + 0, +#endif + 0 + ); + + if(!partition) + { + //If the partition did not open, assume the storage device + //is a "superfloppy", i.e. has no MBR. + partition = partition_open(sd_raw_read, + sd_raw_read_interval, +#if SD_RAW_WRITE_SUPPORT + sd_raw_write, + sd_raw_write_interval, +#else + 0, + 0, +#endif + -1 + ); + if(!partition) + { + return 0; + } + } + + //Open file system + fs = fat_open(partition); + if(!fs) + { + return 0; + } + + //Open root directory + fat_get_dir_entry_of_path(fs, "/", &dir_entry); + dd=fat_open_dir(fs, &dir_entry); + + if(!dd) + { + return 0; + } + return 1; +} + +char get_next_filename(struct fat_dir_struct* cur_dir, char * new_file) +{ + //'dir_entry' is a global variable of type directory_entry_struct + + //Get the next file from the root directory + if(fat_read_dir(cur_dir, &dir_entry)) + { + sprintf(new_file, "%s", dir_entry.long_name); + Serial.println((const char *)new_file); + return 1; + } + //If another file isn't found, return 0 + return 0; +} + + diff --git a/FAT16/examples/FAT16_ReadExample/applet/FAT16/byteordering.c.o b/FAT16/examples/FAT16_ReadExample/applet/FAT16/byteordering.c.o new file mode 100644 index 0000000000000000000000000000000000000000..07d283e1caaf5af14618100063c66a33b260ec11 GIT binary patch literal 1604 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 literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/FAT16/partition.c.o b/FAT16/examples/FAT16_ReadExample/applet/FAT16/partition.c.o new file mode 100644 index 0000000000000000000000000000000000000000..f5741e114c89962978b54c883352050a43e0f674 GIT binary patch literal 7552 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 +#include +#include +#include +#include +#include +#include +#include + +//Define the pin numbers +#define CS 8 +#define MOSI 11 +#define MISO 12 +#define SCK 13 + +//This is the amount of data to be fetched from the SD card for each read. +#define BUFFERSIZE 256 + +#include "WProgram.h" +void setup(); +void loop(); +uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry); +struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name); +char init_filesystem(void); +char get_next_filename(struct fat_dir_struct* cur_dir, char * new_file); +unsigned char buffer[BUFFERSIZE]; +char file_name[30]; + +struct fat_dir_struct* dd; //FAT16 directory +struct fat_dir_entry_struct dir_entry; //FAT16 directory entry (A.K.A. a file) + +struct fat_fs_struct* fs; //FAT16 File System +struct partition_struct* partition; //FAT16 Partition + +struct fat_file_struct * file_handle; //FAT16 File Handle + +void setup() +{ + //Set up the pins for the Serial communication + pinMode(0, INPUT); + pinMode(1, OUTPUT); + Serial.begin(9600); + + //Set up the pins for the microSD shield + pinMode(CS, OUTPUT); + pinMode(MOSI, OUTPUT); + pinMode(MISO, INPUT); + pinMode(SCK, OUTPUT); + pinMode(10, OUTPUT); +} + +void loop() +{ + int bytes_read=0; //Keeps track of how many bytes are read when accessing a file on the SD card. + + init_filesystem(); //Initialize the FAT16 file system on the SD card. + + //Get the next file in the directory + while(get_next_filename(dd, file_name)){ + //Open the file + file_handle=open_file_in_dir(fs, dd, file_name); + //Read up to 512 bytes from the file + bytes_read = fat_read_file(file_handle, buffer, BUFFERSIZE); + //Print whatever we just got from the file + Serial.println((const char *)buffer); + //Keep reading from the file until we reach the end (nothing more is read from the file) + while(bytes_read > 0){ + //If there's more to be read from the file, go get it. + bytes_read = fat_read_file(file_handle, buffer, BUFFERSIZE); + //Print the contents that have been read + Serial.println((const char *)buffer); + } + //Close the file before moving on to the next one. + fat_close_file(file_handle); + delay(1000); + Serial.println("Next File..."); + } + while(1); +} + +uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry) +{ + fat_reset_dir(dd); //Make sure to start from the beginning of the directory! + while(fat_read_dir(dd, dir_entry)) + { + if(strcmp(dir_entry->long_name, name) == 0) + { + //fat_reset_dir(dd); + return 1; + } + } + + return 0; +} + +struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name) +{ + struct fat_dir_entry_struct file_entry; + if(!find_file_in_dir(fs, dd, name, &file_entry)) + return 0; + + return fat_open_file(fs, &file_entry); +} + +char init_filesystem(void) +{ + //setup sd card slot + if(!sd_raw_init()) + { + return 0; + } + + //open first partition + partition = partition_open(sd_raw_read, + sd_raw_read_interval, +#if SD_RAW_WRITE_SUPPORT + sd_raw_write, + sd_raw_write_interval, +#else + 0, + 0, +#endif + 0 + ); + + if(!partition) + { + //If the partition did not open, assume the storage device + //is a "superfloppy", i.e. has no MBR. + partition = partition_open(sd_raw_read, + sd_raw_read_interval, +#if SD_RAW_WRITE_SUPPORT + sd_raw_write, + sd_raw_write_interval, +#else + 0, + 0, +#endif + -1 + ); + if(!partition) + { + return 0; + } + } + + //Open file system + fs = fat_open(partition); + if(!fs) + { + return 0; + } + + //Open root directory + fat_get_dir_entry_of_path(fs, "/", &dir_entry); + dd=fat_open_dir(fs, &dir_entry); + + if(!dd) + { + return 0; + } + return 1; +} + +char get_next_filename(struct fat_dir_struct* cur_dir, char * new_file) +{ + //'dir_entry' is a global variable of type directory_entry_struct + + //Get the next file from the root directory + if(fat_read_dir(cur_dir, &dir_entry)) + { + sprintf(new_file, "%s", dir_entry.long_name); + Serial.println((const char *)new_file); + return 1; + } + //If another file isn't found, return 0 + return 0; +} + + + +int main(void) +{ + init(); + + setup(); + + for (;;) + loop(); + + return 0; +} + diff --git a/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.eep b/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.eep new file mode 100644 index 0000000..1996e8f --- /dev/null +++ b/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.eep @@ -0,0 +1 @@ +:00000001FF diff --git a/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.elf b/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.elf new file mode 100644 index 0000000000000000000000000000000000000000..3a694d3e548b0b6c02dfb4ab4c89638a3e5959e1 GIT binary patch literal 74473 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

Hg_&KcHUZ$Ma zz#jzKLBP8Jm!?4%;0J&c0FUj0r#b+i1w0!ts;gxs0Gflc4l6y!=<5i6gJz~{cnRPd z(8q_+_XDrhIKcq?99B(VqvslUViXxTRw^Lv(@ANY!&)-X$Ugx28#Hrb2+ZzoS>I|u z=W6;m4N)a4wTF7zG2oQS?%rv7q|hbf{a3hi^&?YYU3X zD{D%u$D%{9f>Lx~Yo{hvmlPH&$|hJF$Wl;TR&9NuDb*!4CAE_BevFbSE-5dmEm8SS zk5#nEkSVPxs42Ul#HtRbl~$LOSbb1?>X#)_{Xz5)5-O`oDy;Nmg%p7e&E&5NCrPtA zq8BJ7EJqpev!>OQlw7MQ1?VG`no(V5tXz^3EKF+uER-O1pU_!}up%hGproRmX-Vz0Dk}%6sfA?~Rv{9Trj?eKR9mx=WYZPMB3pnJ7hCHHO!HY!Q>4b)1Q2K? zYX^zUH>I$m7+&WwUsj6a+@&ymDX@Zq=_N(AmDL4Tn+>f8b8afK|F?><&$>5+SXNOrtyWSu zhEOY~)f(~_AnP7dfNn%ZQXv%`I-EBNgVxl-nro%Xv|x8Ld1XJAOyspL!4EwUN0gX} zvluFo;K?CeIlvsk-5bDmI2lN+ajwmOh1t1y|mgR600f?6CuWC#slRC`;^XN%_+) zl5zy2>}4!xG1o`-QYO9QnA`!&?D|?JZ^6hNb&(HAr{fizU4jcgKYq~<@Z{%d6;9xj zW3NYvQ4{t_!U3FBhGh6X+7DFaB8t(}uBC8g1~8{18)qea9)-iT%OavbrvjPR9tYn> z&A3eFygHEc`an*Z(suE(AVwO;rj4p!EOYT<#U&`Rp1J%;gcxUcWdY64NYRZ_lp6j` z(FoIKlP0Z-O+bB;qgGysV&eV!Z{h;}^8dOEVA;&!m8 zCuxNv%M~{loh|Bl7Usxu$MqrhBAddI6%%&>vA-*B`fsU-6aU+Obs`O>W{Y30?*3OZYW5xdsLO%RD@RVsK zIHD1qTq?(23_=&NU^rqUZgwm>$?YnW755yfDHbU#D(-wJ6pNL5cbpI6qJh>rvf|_J zM|DM`!V=;xrKDHoONz^(WQ)R5tXN(qb#slH#NsZ+2qx}il6A|YlDl4mIq)iCh|Lq* z3|&KAqaTD!B9;nbEmM?E1{8N+rKA(9FyV`PR3QW7UWO~hI^~za(8RjMzJl5ecAc`{ zX!=W-rU$jAxHF+qJf!jtlwK6;RmJkG*qx}aQ#?8lMkxaxW0L0VX12!}fDDO6H0}x2 zOi?g^%43&;7$u&Wz|8d&e^!-Z#WmB>&*{uo(i_a(!xpTLxE12bta-Z4WXF}PTe{7x zP|Sg(6J5$GCJmt;r|Nei9)Z|VdMV09D?9EcH_FA%l)|VIF)qq<{s_#J%{Yl97i(&D z{sBm88H#bS3Tdg=SYn7wB2uOzi%53;g7vu5P84;tg2B~Q+)Dj_cgitE42D=T7JTAm zCzB9*lonpZs=et@GB;9&ReQq`tlAq6RxRZT8u+$Mr={dl^Cu2zoYhV07FRm4Lu(4T zLKV_oOrw5J@Er+9gJ&az(pgHTV2jJ6$7-s7ObC|6%@1yHKsE&hN!drG-#NZ#NQXZv zC98mEHbJxvzb?|MH-roh+@P|0)Y8oBROM7TQmNM{t&-JT9#C2(tLFpmkzH+?gDsv5 zRhfYDP=)+iR^72s1n3^=pEZ(x1~TC2@i&~XKPN4f6r50}2?!Wjr!QrlIKHYneJLex zB|e|-Q1}bLyKuM@dxRYC7RGo!B73jk5cfIR(%Lo|pN@r2&oy-VKB?_jusx3v|5oC> zWa@GNEr8p2GTIl~p05~c?b2^2gYB75_94k$0Nm=anx!Y&aySpE2rrZ~9>-3MNU;5& zuYqt+4ynNDxcFkPDDjF?ubAu=y{bs&K<=946-8cQbr(0VptZJOV{<19&e<-VgD_oV zGx;pbcRHq^0$HMf;?LNk88nJ>vkO^xDV|=6EKkcUJHb&_JuR(@Mc$0L$O1ll^x42Y za(sN*W~gif-bKdL-(@Fuz`xx=6R$||Hj1xj_J2t6E+{nnbChu`7`LP7-g2nhW^*7e z1rzVT;7Hj*6<YDhcggJAA(6uoXB_yel}zqT;JFpdYgv8S3C)4paa*C^0?_)A z-nS#ptT#9Kz;(jg{d$9TA-O%ez%KDm)#E9_Z9Pc+6H>}0Z#(^vTM6L|*-&pg*-$S5 zPe=Q_?PUAx2iCi=da@1R0> zze$5O!g%qkgIVD{*_-GK9^z+5Xm64Y%&j!(oST1s^=x}AGpnh%mrDW2NjWU}WWtyCf2`8dR);b?Tx6&C)ouReH zfY}LFb>c#jtGA>+42q#bP4YXzl9T)pIsK-{HQ#Z9i@p@uKSm0Qq>N;AkCr_lWiSgl zUCt0G%c<-Pm41@xGo{{??o5wS>3f*>EG1Jw`q?UdHT9gM(!5=Or^r~Ll<%3ItkO3z zU8&O2$2W>^VUG%Rres@oK_ywYK_Z6wcgec2F&U<4&{uI)m?x|D1#4CUm*uko53>E{ z0~?Ix)DHuoHzyrB-$2gukyE%u?jYcOc){6!I8sAS#|e!z-~zx$ka56ONPNab84^xp z8ZZrslbEPS;$KWGLLwV+H(&)43z)bEiIP zEF>1V3R@!~?r}wg?Q4+f#OngCO`VSSiSpWu%k>`7potIFV%n%cODALFTYBaL>6s?v zQJ(lfuCl38t(W$=xL!IX$<%GHtjiU|e?)VNHWyW0Py7^CX`if;k2r6ciEkzT18~)0 zzjLV$D?G#K*&pQMeF#)|I#PT@^Z;1-Eb-Imx{(s!20Y-R*QomwR_kY}dq0>#?k;e9 zS4^9Vg|f_=iJkkP+dUg-3jTzg>AaaB_Dj9%fGc0_mvd?cHeTc~=ybCiEd}b~<-c&d8Aj`Y=Wu~y4q>@- ze?rfq31ca@i$a;OSeo!TbYyUYUM!X-B%~M<7E2RKflCus%US;gpy5USIXX}z zcO=F8QIT^Y?|{hl;@<0} z#224P`73}A%?D#S^s38%uVls>zzDYHOW>x+tIVGz*K;<)T>K)_Ybcp>T&U;LoVnwH z=bnXApD|z$n1~c_PxhHYj8}c%G8>L8yx{;{YYwaF<#48~X{)ShN8H3z%f8kqvPKYZ zfg;fw#aL|u?zx0vwNBP-18~IABw0iyYn&D(7vCVr1HF%TiewR~vWO`dH`O{LHHz1@ z3yIH#ut<&Ks$~~&<;)D}%+qk+Q#m_RdSU``x%&1<`C8)ZnZKu$zXN!n`*cOwYF->J z?cGgbc^x)FD$BsVBWq|KPS-u=N|GHD7AoL#^*HJo0UhI(=~OSKDrL#l0AKpXD%9 zR$#Qv5oJGUo-NFChRky^?*Dog5Uh#}Uk>}$luC)J!Vsk&@u#rQ~N>FK# zm})DkUJ7u-LoNm4tr%Jw&m9+bPD!+^V@~71`l16Ar=2V6tax5U4h<3D4zhSDOA4Gq z0nR$(jexL@vDroccA6BJ27zPYv==xA2&XN-y)Y0N9P;j+-gW*FRWk<{N)MvfJEkEN z95XpY*m`?gZ9tzQDRKi^?>akzyUw=Wb=I5SYOA@HIn@5QP3wWF{clHbf7zk-m&?F( zsQqO|ywkA(XO}n*=hyIyZstj*<|73@Iga&c$EXP(O2Q7DRfeCCQnE4^QCxsK)c&#? z)pR;|vt0=vhg5|2XciH@g(sQUF%Gsz%{WEo923YnDUeg9v|Up`jgiK|)mBtJhZU!T z(~e6}gl>*B&Y|{~*Gf^2-O98#DH>k!=&7VhtIYl~?@{ahWe!=~OjP^JzevpNFSDM( z{bgDa++UXF2KJZBWInUMtgsGNyx_%-SR$JQ67oQ=n}Xsy$d&72CePvs<8;vUc<~i` z&S*h8y9A$tL5`o9L+%ibqQQ;G(Sa6=QM7myQMq9>iY5>C0Og*z7)6_B5H zM}Q_=MD!FE@)OWRc~NjG3&Aot30>d{R?kZ2IUXILBTtD|Cr5NLt;{qe5Z|Z0eG@@( z+V6=vj9^ghu(;&W9i|WjbBsX|cc(x=-|tbKMc=LAT@-y=DEt-;%?`gIBRzbiyF~gf z%(=*+@4{S-q_aybc1xp%p9SMxm&L%elZH}fmK9xz`|wet$#7%|*IAH@I(>q~qFi@S z@*E`@>*`0|SgLbm#kqL5FzRB(OLYB{*yRdKa{Zh6u9`0;lU?(euSoGayMCeMH4000 z4JPk8g{8UvNo=OVx>#-|E{7>GJUOgbN3@cLD{U>Jl9G*EH_t2V|BFGRvR9;HE-k7JauOkvl|UzL2U#(n~NBuXqY^5LuEZ zS$NQ$nyrqam7F3i*HP?+ZK6V>ohWS%1azlpM1nbhr!%RT9iToy&fUTv&UqA6A3663UgU=4A@wbC)`=9@9>UoM>Zjy9AO?kV zNNpqMAu%SLL#hQ&hz;`UU1^i`iwCt2IZtt$^>6f0k*!)nyA|FWiLt)(TjWi$nfAgv zX^+xdD{VH~bHLM+q~|3rD$;Hyca=@wUeinaQY*wpyN$_S9kEcCf!42;8Rs1)T5GFz zF!ExZ&0$U+%y+-c_ayRp*j!KJ2O8s)qjz_40quCeA#21~;A4NN(N!4MI?L_h!S8uxgJkHJrT;fRA7iX-KBQT}U3&j3{h-D1ez zLHRbv2?365SW+J(=R1eQHz4gJ-i|0*GDgO`R(syqN`tCF0=hByN zO8l%GF0)~!^4l*`>H8qc7M2^=Z9>+G*JtrC3b!C6ehShT5|37OW_l8Fw?pR5hf*wA1c%P0hdAE)n-GL5|_qz zwb@X25tqhywO4_^A2^NgYSZ}h`=dp8k3sa3eePD^nY^T3j$c|+EEv6Qw&w~ku+Pg&^?p2U*2Q34^2H_DBRxzW~-b2Dn67E)ny&&|*lXBuO zEClQ7UC?2*q5t5a7PLr|xCs|eQK>kY<32QXJcf&-KFtxnJ{X65W z9sH1Gf_xqzYBH%#`8vd-LQi?r)q7AZ|~ zCcvS|u9a&c<>G4C)fx{b8-vyxc8ySNl~JxR;3e0R-_0cIW# zad9efy?8aMj>kh>>{G74E35QxTO^$)I=?O`W%`P#X;tq90LJnBbg7RgT+hQPTbd? zT!GX~a657LU@}W=1ePRsHYa1gwVoj=w}>b6vTz4ACG$xI7(g|#jvH`JVA-*bRb=u} z50NM?j|Z6kBuw}e0xXzM!J}}Zvhe9FoSW&g@aZhP=Ri~VbQV4wXv$L7;(Dsag#-$j z3r1&g4b`7bm3*ikYEw{bihO+I+>;^eD))-1xLuqoDwzKSO7XFKNT!KH9H8Ey7)gBE z9^@{cliGC;&e6k9W+g=QaS$m)Qg*LHRyR3d=3hXj({95cBs(AYT+gk2M{QsLJ`;RD?fM>oB2cZ!ec_)+2_ zC=p9>a$%==G_mMk$TZ_11L1rMUx1d4DTSwKOeGL2wh||E zK)emJ(2pQKkvbiM5$uqM|eokDFQ|gS_~3(leQi zt1iLA3NmvCD!U%P6ljVsVgVU+b3!Ld%Z#GT>OhG){N#itr7|g%D5a#%dr-8MGzT)x z_$5f0-jva|z?DKpQLT>9aa@N|JJKY#C}-Kc>7fo(t_h8$DtA6b{)Q4d@vQNY+!%5vraSN-7@HwZuhq5|pch&-bW$jtka6>Uftm2*_ola3yy^&>yk@`om~D zJ0NvoP)e39ima46BL*lgFM@36MIvqUpdVz$=)6$50Rg$NOMn&c%8^7p@9HeY^`6**QeEOx#FR64D69~UB*$FP#4|X_ ztz+SS7fE*wPF74*#u9*7A@d5w$3P&n#5uNuCm;Rj@Gw-(5!v0)OA_Ri-KacZy&a^ zBP+p9IfmREg(li5-;s5%I0-km46v$_ z^lEW_kipuyX~Pju)aX9K$x0J{p-*T3!t=F3b(bOo9%#M~?i2UD2_`d(+X4dMZRa}p zq0y)STR^N0^3p^l)jhL>=jVd-t}<4{KOQ07kz@@-GYMTW>Sr+QkmoOvsT)ag4hnU5 za8E9t$#n4za}TlmA=G;mA;nhD$c9_R5IP|fo880YDCO~ivn`-r2DxQTTu;OxyeOEHM^b*UVywfX)rMEFo= zP-HwrhC=5*XtyY}hINI>f}(sK8RC4wE%$x+m$dcxiFbPM1=^d}S-A|d5XOI_1EBb0 zcy%e>k;9JDe#=>B9V5q$ejIeLBtIJzYZNZ>9P(i=J-G@_X~^AGoB` zlPUwiT-|YEbVT*M0i+vHkZU4vUT<^4iWZw-hiJVAG+R6i5qAq%B8Ha`@>L!yTC4<9 zJeem&J_?Hb8G=eAR*t|?ea@#KMqm~tS z$}#i46uKZN^bpIOLUnOs3`-mG6xH#nN~@8J0?jLz21ZJ2FoWG8u@bDqcR7CME`% zK@Y_%C#+b)?7C3t9jgNkW4tF=i4MLro#faEHS7wB4#t-wD#{B&qT@c0lIfj92Vav& zW_3F{&3BZ8 z#tuQzUD5V<-5t+l0Fj!FxVSd;AgjF>r{D00mDYeVShZ^WPzGw?4InfXVHyo;+C@!>*Vc=`O*#e<^Da7$ zXrP~3~B zOe@O~oyKw49H4^`}GRK_ERswTjuP-$85YZk(WrvyM5S ziBFdVHGQBpopCNi_!L*TAJ6&?k6URRt<3?=e5F08`B*5Ujki(r)pT@s4rAtkJl}Xv z=d*t|ft!9D63rA#pxVD`wKtv&kxzm22-PZXPTd2osh{BlO`JB(0Zn|H zBB&|;cxB*t8aN(^3eE9Ud>7DgPh9%PA}WpZkU3B!U(XK~`K~U~%OZab6zOG=>BDhK zd)DLyM0UQ%AIv@sBHcE#|2)ZwY64N-!xv8ufcRg5X5UNHNA3qit2wv*gTa?D0xQ{a z=6#jicy&pnHlD+K+H=cM=x?-pA7kQUkYkU1k)@vk{Z@`)Wq-(${>ge>3`Texy%X9- zRvMQt=0KJCrGj9UZ$@rL(bY7%g=OS&GB*e0gR+ll*%g%ikh0bQ#JKxaIH6UP_ zKLsG>CY;>duyfoXSJR-Ar0CqXb5x7Bm3+0KyK<5G0zav`ljY_Po@18yQOVs(x%Y5# zb05#KLdaJNoc789ox6FC4T9TKC~v)?<5ghMJE2pYosf(?NthEH*;ZWK$sk~{uaoRr zA#xXri(QeDsg|8EBJPB^vpS*T!EDY%C?n0)S>(i@)kz>3?X*a7lLf2$NG!IKuoL3q zsDd(ac%NSDJ039?FNDh5p(mvCkS#%#fn^vZ-Ku0tCJllfpiY+Nk-C!cXd5M*EETUC zC_a%+eSk2LGAxAJIZn`oRL}z1(&FH^ET zG$T)2k4Ry*e4S0BgM%nG3#4u+8%hId_^?nDNjL`bI(F!bV}sd8#*=WwP!5e>6ZYr< z|1X5{(VWmB+zAOGwSZ3&Lr~NqDOf37gP7jY(e#c^rgt2%uDW}&gNIf-w65X3(G}hs zqrUQAMF09C%asN>i&s?bl|G~8rFf2)O`n8;e8IBco3pZ#S%L5 zk$X|+knRCzriOG6plRB-7$6vaU3zGRD(1UJ##cAh3BtN{Xf&sXs6$ir2==iI-DJz1VY7|p%Z_?Q)5aZ_J(V0P2qM+>Sx+7{iFazd(xK{PjL4?4AMJ#_MZ zA$edwI<*;Kf205Ww`0l#k=q1Oj0vJx6GU;H^(=s|UND3($#VutP##JQ`rx)v7}bNr zOHz2xO74V^J24(}LBOYRAvq9HIy|(~%;Z26{^%SmCs;&kP?c$#v>?eCgV=KDvbzSI zJTjifbPFZ0obLZqeh=CkoD*F^<(QCzMPphH6%ST0CYXVJBsP2oh%+O8d}wY{ZH94& zU>VGx5bom0(JiFQsVUq{dmYsb(QwxY&$WYcEGKAh-a@nH}1UH z9-S0NE*yuUui#ZC_Wu~S#f4uNBoU9yG)#7-;H;x;>JUDgC4|priKbpjX5>jWE!>e- zsYPiIxpeK6j)ISm9fDCOB~%LudR(9htVW0*6(KFGUW(QwjCPi;XK-N|>H!Q9sv)~4 z={0qFFt-Z89>L(kW=b%$ux<>M4pxrV)r@iDZ^$>=L-*QP%}M!owpY6s2HDw6fKBt)nmTsI{l* zu)R!&%`zP}I~W9%ft9?Yx3|V(rINCl>_th2OpO=MSqtxueP$X9K7k(dF5r3@+KD*cZ+W@Xr`M9^Z2P&$3Oxo$12bK}D#P zRa0AxuQ(2xLU-ip&*kEaucc*^K?6T8@Tpmi^JBze0#qeML)@tyYp=pB66NF08g>i% z9I2a7s{N=Vj>ubpseo;O>3}~2q8*R|wD9b&NtzPUH0vY{sf40b z5(5vCB&acz6LeBy+AK%g=QLYi9{CjspjtiWHCQ$JPLQ_*r@zgR}a8$fRy)Wm=9<# zxRLgpj3l%2OI`N&ax!T`lBF#LWUf~MsfAz4Af2}$Y5FceW^DtsFQl@ANM!+9*u!V_ zV*#n5BOr73(l|ebr7F$TPv9)noJRrkf%^cNLw@=SaHr`h!| zYMdpKZaTP;Gl6HIku!XQ8~p|vzWwX<#uPe%Mc8xY1Q}YI$z?>0R)ZV9u`Z;lA9OJK zO{P8(RWkHQ7+EF5H>Mlhj4;L+!#A!ot~7FnZ}J=1QQKws1{%K6Z*Zg6;D&FUVdw^O zUJ7-pkx1S0`hN)xEh$174u%8MHf}P-Mw(&hA%!k=8%vC^fu<0X$yC?yBVnYx2{>b%(PN;=Z}1M< zy*A!nR`EF6P`2D`NTv{bec&?J*kz#6XY`vak@TbC#)&5X;R`xbl97n4p=oVXf^s*f zR(pe7Y^_0(Ouj?ROUZ43bl10)8V^HYv5LR zGB8P+K4KzWMGw6_9+F!C$@vtJp|eZFZnz^)dM`j;!VUt=0UQR%FmKZQZvkZqc*u$J zeE`*{FbpYbJQ0vNPSfyQ4aWmAwD?V=-)r|Xu`b5l%KtC5yV^|rgS(7c_-OlxI|BnO z9m>X6jm(7o%~6>2yS-9&J$_P3P3RMmVq=wRSPn>?{NNOupC6mD@%a>70%^_-fXu;9 zPz?v9{0NnO33c$jN0$Grmf%OI zIDWjO>91-!KTLHJ==>CwJ)SwYYl%+*xj5XVaXx`gyj|lz0@8l&fO9L6pPy1?cSMSu zE*fS4(iVQ4ie>T5HrjFqAQwUWm{W+~cLp{UrF!tp>}DD%61VR>Y=nPC>x)1xQ>GaW%;;d~W_~odfq~Kj+Z3mw$}+%q2UcH3$iRTr%L1z{`?G+weQ%KZ zet>H78W_-VM?l(;jL08_W|PO%$v~6;KgEqb_9+ZJ`s4}?jYbs~3=sQ%xf8?>aoJnt zQi&gJwr9%*`V*5+s>^*OX;-s`>j2qSK0s>a=a<=r+W=Yq9!>vMLpPqpCA|wE<@sM1 ziDv_{jr(XgO!N7fFMEYF=tLwbdI}&-;Mc$OD8g5vNSZ*>5-EK(l9VncX|Eh>N||hu z+$tv32vo;pgQU(vl6mF#l7XT^kqsT5P{gNiVqD9`(a2p`KwH?rYOg6-BBuhc!cgR#TGG)IadpDC* zovz`D8lD13J^V(Q%EXktNw#tYlcO0bwMa2k>Hz77CJomBvXNc@WFx-{$c5}{n!XK? z>OTh5yS#oRsp4}DzXqgbdjO{a^222IpJk1H)gn>2pT{h*fE49-%jN)f1mwO#FHIk! zA-`p2&zCArLy}p~)^MB_xe$=oP2)BF3JoV}K0kfd0Ddu`T_;tQYLRll+rg?LYk_1< zN0Nr!0Js8h0U%3V3`n;$X?!)H{kY8X0FuRE@dIkg@l4rI%dsOiMdi;2Wd36T>DDoT zEawW%zZx(ecpYE`AU}zwlri-WP#yfRF%4>kk zu?3Kt-UXzlJ%E&J*DyX+mB{bIDfcpEuaG@!6q0P4a{;N0pLHXg0!XFhfKBa1YF3VHAPj|Jmz{qDuTPUUQrKKfICsJK1Wk zEvYS?!R+X1bD6GP{7XL7ZH_}5ngNmxE@H#=*o$<&Um7-P|NGD*-6?0gy@mGUKi+0UYzJh^e-6k<;Fsh{=SRm>7%|lZ%8!7I znW!{%v#b{&bM^t`HO*;&)G!8+p+7<669E}hukhl+!8u_((YI<7Z zK0q!q-vH#sDnC4?axyg^l!Jh@EeX%Z5OxEk27XISNiua6C?f#beMSMYo)ZB%hExEu z>{);ubLRoF7W`~IH7(chZa}+|(+$5qrgSrPzNWDBm$d9_8h!vs`c94S*6>>mf7H-{ z-o&z^*sJ7I2TXmUDYVWFoG>1c8u=+MNb>B!EW`9+50vmL5Dx1;$^75c3#}Pt_;0b3 z55Hy$zX)d)N1>{@y2{4`(n%)*(iNv@{0t4x*6>^nF9f8kF41_Yh6^?1*TR&u0j-N5 zNl49v3>89_7z(M8crfQgO))tQG&xNU2G!9u(VFRy;HSsz0*2WJq-e#XfYkMphA#sq z0DndEU)A(&8uHs@L%{zUkhbs}VnJ)`L7^2M4cS478!OENB$3t|Ii-m@|EhH}=Rx3< z_!W>jqq?b16bnc^36T75fSfI}HN77oZ5*cgCu=wckoTf41Z4ipG`t#+DAt zArv31aoP|{585y-f)lC1;;gkDkagr&gh;;(ka&fL%K_<|yEMKUkbP~P z#vj!DS2ga}aKDE9+E1|V&mkwh9_j6%gilMDvBkj1b}$-(Ip5GZ&Fxo{LrKt%4;4mup^&;KEkl0h74YM{nlu6)PaRV8g?b9P@|=xA%y%8xkrV)OI!~ z9<6-7ej4DE7G=(D=oZa{>9ek)S0vfkL(R8D`MCKvTkPVy;=>Oai3U zrGS(u*N`7D32L3Eb=c3!uEGL%Nk$m1mXyae$E*wVUKv@7G|NonCNr-Q$v0WdfMEYD z_k74|iO3o>&a7aL?)=p{Z={4NKB$Yg0$Ez5WKg16O9VH$FV>X9wOt;eP2Fpze)C+? z(aTvGk=JN9Flf=(qeuoN7HbLnR1*}Yo`-9j9HC9!<)Y0eX^zQbY!8;RE+VgyG%zT+ zNlOMAdVipyTQ$q{5cW?NZ$u3=#T(odlBng)gItDge-$X=FIvQink&1Yeb;FTQ;1O# zlz8wc5+RbmIn=*^Dmkq6IREcjVTP^Y!Y)DNeR)e)8&>~j^|1Gf|1E(-;CuMl@g9kT zBoFfV z)+rJ4Pe<_O*HS5ngOBvw0BH2{X`J#9ybgFTU0!7S`9SA^duuX3aXvu7|LsG4k@9>Q zhX-6N`A5Qe`+ZLY{{~$j%JXKSX&>Ue)if+bo;Q>h=<>xy?FA^NDj4^{x<{Tb`$d;M~ZZ5Q1~Na!v@&EylA$aBd9ZS&<|9%Y(S!u33ZT z6X$_twv;#cB_TNXoyLdYNQTLCr>9o)BkS7${oF+urTN5pti+G)X>e2j$oyL%&ucXk zPsDjl#E%%AWF>@BaXnCy`!yeMb|v1t`GWs@sPiajI;kRrUR_&c{{j`lX= zgh?}NODe02OY|P}nde{ZIn^V#CoFu%uC%1OpuD6)-gv1gDY>?Q?_5f3a!GALX-z>* z*$u$Us%!9qV)?Y1TF6(Hme$}V5AW6Beosk7vEkHMg|)TSWs|1WmefdgHEs=I%dWbh zsIa_zQen}x*r1zi&8RM`En%sXYo|!DN+_|4rj!(2TZ8}otnL9-;eE`Yjww)7Qf-x& zRuq&})K<^L%aYUJAR1RtQ8Gj2L21w{D^OEXR9lH+DOG@1I;m3?E7{T{RU64-J!`9{ z71dg}eO6LEy`;E6X{fPGrKKMM3Mqy(h}Y8&9OJY{!fX+c#Xs$E<% zy{xE2+Z6DQa%xao`pQitwCTR>3gP&4UJ%F;HFt zZ8EaTD{D%Og;EvhWff&LQ%Z`Zz_gme$;d8q8Q06OHIYDV zCAcrDgHxGNQW%V(z}-#LZbn_eY}tsaZ=!>$UK!{O(r#&r$#+9Zb*1U2Z1$l;*zPLk zWTinvoEMgZOg@5ExrapY*F4Ybt|*%Q!_p4775n zuq@NGVpzuru`5qt-hc%BBlFpMU zsi&$M{W9RlfJ#)L02Rf5k~yqbR+N+!>*$s|U1u}CVlbE0(bGXlOozm1_@EZj9chUk zJVOG^GQne27tT=4|DR4^@G@@qs9}Tyuj+bgG?Y`9nw&UA(g#(QHM)1!$Z;CkrSH(m zi*?jtn5qu(pqhyg=TKc0^e3hw6C5E!Zb8ws>S~Mq%R)(}-&-})CaHlv7@4MBgA_T> z{lWWR5g#R(5YPf&1kxy;qZw*ea=og2VRda;ZCPc-f9mYO^TksOE2fne7S&GUx}jhu zBEiznYlH=;j$Td~;W?&OR$!XL;s8T48l<>@aZp}abS(q1yl}Ff`f#JA7IU>#1c@R! ztQAb1R$gmOqNo`pm{k&to-h+IXJeJ2mlHuFuw2lk*2pDFH7_OVrH7!guO)3&djsGcg>?L1f(Ep_~T-OUQA9hY=4Bi{s8Il6_N7MRF99 zMXKCVWhC*Bs2n#W-xMPaHe+z4dAPQytilKpRuh(b++prN-0~u;wrpxib$&tR^pfh* z@=DAwTo+-}3*(G6wXCQbgKa^o&y%tx_{K?bjfJ`O zq6<$y^N)^E;g13Yo~F@dl~!Yv!dP5g%Ml#^FRW@>ZNa!R&x2j;&~nispBcE6mmOGv zNTdL30m{pKl#Za|zmXM8Ev&g#YKq|fKiypmj2+c^p1XFIl&-)*E+NPQLxB)dt?b3- znSgPyYYcT9n|CPJ`?7cGzPjFZ9g5HfA(tXVkk+bDVnqlMglOatnnr{~lp=~yODJs# zO=(44+N7vO)Q*tVq7?W0{(rtXk2}})8nUfA*75xB|GdwcnZ5rp$HtJ?(eZ&nBN(fI z?cV@JHaBr#OLTZl`J+;S`E~5`Teoh!f%(M%<=jWn4^lVid-@}Z>Ft9}o|Ll{PY6Rr zbGmPG61S?sF7mz36#B!4wtQTtW)Mvtxe{Cg$8YPJ?7Dt*;WqT;Qz8d)!XiYjv@Z2-@oc%Efz z*pNaCR(;S7VK2ri-Y`Adhy6y*jq0nk*y=Z`D`l?5&S;=4UuF*1j*RzCtr-|{_kmrO z8IE`0Ilg-%GlzAb%PrrZnC^%T=Byb}BLm~pT<3%RV0QU(qk1vdjKX|##}xJf_O5`N zD7+D11@!e|cQG~YZV$hhV=@@{9lUk8C7s=~PbhfPW>;t7LEi&DHrp7-5xM2X&mwz} zBuDrK!~N{Rw*m7ts`!NYDWtQ|*@SM0cD`eD4>iv?S+3VN+vpGew=%0 zAN2hEvUYf&Z<=jv4)y{)*PmPYI*R+yj(+7WcC@^p->!wzI<($}4feY2nFYLi9-K$` z4kYEB@PkNQd_f*CN z+ZEx`Uj@0Rkva=+4Z=JtF3lk+Zq21=?OwB%w&7OfhQZOgN^9<$6oy9YDsG)^G-n%I zW*fb;4N~Yml_h0ki!6Q9Un;9Iu&i$)brx=!@IkZTJ;`g76fc8QS%y2U46Y?>x~t6s zp7uAk$Rnoj_6R>}xXTfKJmM4PN8h~PlJ-U#^`b9;`<9(^(hTchaXjiJ&SML#tu4N!u*w>C<iBT z?$R#PP7YJY+2ZNmRZd&=3rJVt6L*?x>E@F`pr=!7zGw%zw7Ud)uAdH_*7E246c2Xu z);c^cy>uuXp2`mOQzYe)@CJMU&6fwtJ!5j72f_^WhBi8fcLr@!?;*_aYUJ_G0BhnA z=HFb9r<^fR+*wvFE($vBbYa1h6a<4*n z2K26SVe>_tvDauZrAmik=NP9A{?3#nVewA_zYj^inGgCGE*;_0WB9sfkzngA-k(Fl zl*QW%ND?RfGE!GL+xlGh1H{gF2I)8`+t!!Jvq;txu@xr#s_^0226M$yR0_&gMNqyN zPHzCIQ4H`lgrvL>9zja;BGXWiQGhbXsC=iwF^YLM@24Tj9$_|Jt36gAHF#&Xu}e97 zw!_OVC*;cuWBxH`S_hRU;nEQ(A88V%CcN27Cs&sVMWEAjp0toap_iB~EPbcgn@q=Ev9&7zRT7HmA z_t>J>@7L<7L8q?9(kV-_y4SZ%Jyklbb)POybLZ!aV~(fx+vg+KYqyEW`$TGA3sLZs z^N)n5_Jf_dv~|!zt42@K`RMNCvq8d7aoK4UO@Vm>MXU&vbfdUIU|us3D*}Ub-X8f_ zOWUV)?B)F2Ud~T(<)cyDS_1}BRWG%LuO|5heiTw((bOMELp7jC?e>d}Vpt-LA~H}> z#m$?n{d<(O?`Z=R?0mTVU^kx+)90Ml`SFACgI}NXgzKI^1Gd&*I);N@-pAU><@K26 zBOfU?O7R3A{G|GU{^8bRu-oo&FE4L8N9CJ**=zRz;oIrd*Dp#|d1-Cyye-l;Y;B9V z@q^!dKARgZJJ{pl4U1nfELv;dP1|hla_K`5E>OL1q%Hn`K~_1;YZWz*7d+{e*GSwt$I6q3e5Qu&s&^hM zFW7FkOHbP)$fu9z`DzyA(jHyko_RmdaapT>BUn$BPTp!CHZDKf&8Odt@)_-DrF&p5a<5gyxJYIM&h;d2c4 z{1J9P&L_Mo;uEHAZ7_qMbT1t8=W7)6=6dOxH3RySX3xt>csG79q_M)VxBLN-aFv64 zkC~q5lkgLU`uU6rfum5KWUQ(Ki>nINT)0gOS*UkavF=_~^0R3tnUFU5_4YNO|4NvQ_}Je@2=Zxp=(I}3Dn zyebwxpRCsGrg>4G(l^DT>R!*Snn+^hy?!S&7iymCdfljX>ILel>;a4&+g1LtiI03z zW{m1R+s6edkF>~=(t%%;rr-5Q;qOjUyQ&*`)uw~~PC~R)J?s)*Y`Bk5hMqkh*2E`F z>(Xzv>*IrVJ5A1CiW7Fdbo@~6Abe=smd=~x-a|`;_in<^Bc(M;%KMQNVTRD{Dz$vu zL<&nITZEUjNRjeRB&G5xC)x_TP3FgI%jdzR(0s|X9Vh%2Qkq{<7@<}VgM{BRDc4Fj zrS!}aYOPS|gsU9FuZ1Og5Kik}^XayTzeQ#&+q9pM@&bO9oW2Gpg}+r!WmPw_q&`6# zmq1$OV|3WNBAoCp!@ZB)5BTYbPnh0huhozDA^Q1qlk*ohgk3M~W0d|CNO>lbQqJk)t`?i5&|BJ1Nx95yc%NtOd2Kn)+IleJ z6Mh^i%`Yi?jp|xypE?L1tHD(tQ9fCFi|`xtw4F(L$f)t0L<)bep326S7^+uoNca)M zeLf&eZSiA0`qQLN_+%tLiu3L^y?qHY46w$eZ(~W>jpTp$+7C+FltZ!Q#_?&Yp z_{)&=O6_*QcSiUO;0Gc+&hcAj$9;7|#!KKh;WJIodnsWrh4TqN7V%@d|6+E1R$w4x zx9d3JvP{*IZt;Z?sTWH-Lkpi~;1F+&EDS1d7dVwS#s>zKw>?hfjWL2jMDe3fat`h;IGyj9=j ze1#$Ws>yk7V?PWBtS%%v<79Lqkc0daUS@czALKkgt@`d?bVilkft1#zxQsQ+__FvD zHr^gIuzHq|RQ)Dc+-Nf@(%}{Avm#wQG6`ht4n~7b2Qew{8r3_o*AFR-<&nzD5@XFW zer!!%RpAoN7bpe*nLvtEXMo=4q{nb$h>wUXL$#!;Zlg!G51>$exr{z-%3NMBMu|Kb z(M6)S_df&aRFLw{*v>>=H$g7#q?!)I*FAqpkmEtlXYqEp=nWi;P+k!jNH^AiBIVWd z|DkLQ9&^35r%%6x-$OJMJ%Fg}l-q@rz78PeB!quSH{#M^kjp2{R=RfmHMCwsY82PK zj@x1w04S|%ps^7NgJBbHTO4FS&8Hlcpze9I9En~tj&c(WiE|o~=!7paJbgT2C>%yU zlpNtV4ENqmnBj56SJr}_Ps!AK-Q?0Gg1U^CD1E}GARLZH3t@)S5nuL$p4+G15|i@@ zkg)5eOG41|C4qX2P0#a1*!9vSLw@soh#t+*A{~V&Juz-$E*j`*?ionv%1EB@&4#CQ zO}i|pR>jvn$~|KdF|ebuM0ldcMUYFgD3j6;czqTl*FiLY{aXLcE*+`TP9H-8)!Q@8 zY&%(>X}u@Og6`4aia>GGmq4QGo>z+K^(7HE*J{^_bF&hx=XFw7Q$ad!oBC$eD{AS@ zEpPeUe0VGMFBGIRzqOY?9nCctdA%LIy>#oZuW`YD$``%9UFJfSrF_41Bs}OHU5~2I zQ?Qb*z=57yPuCyG)myLcS@nMdTThk!XsT!wH;Jly{j)(mHR!}!{linmt=SOjO`1e< zJkZmM6urLU#Qk7{k3SB(5q%rm<6W@_A@!bRyV|+3(wkH!~dNMI~ zXMT~!=luL4jnDJC2=h@qzewW)_>nHk@UbVqNaF)SyNf)=&}8C9Kfg%hMw^LS+595S zVq)UXeWWhJ7DQZx|E+uX_AiZ2_4XCr2xQ^+Awi5ASaeS@{9Sh+;v{ts4E9ZLLu|a> zv2BADIx*eHSUweQp^PNj*N5OrQXCl`8x)KvE(m8>iou~kgn<%Rx;graVe@hdvcI5f z%oIzO;@f|uuIcHFQcly&Zs7Nv9t1H(*~K4&aq6YLb6{`v(xUi&GcG&_aig7ci`U`?%ZE6PB!s-fuD%>;WCf->%|`2&jrq9q=6d$L)@o<_m%kf zabFFbLx%j9aMv{-<@rZAQygdJ|6Mu9eLnnSI2QXVpB=@=f&W8f!2*q+}5{%;FrY-V77 z{(?C22bSgUN5J0!A2-AQ6~KQ)_1%EG` zrW)=jE(ZQog!AORcO(23;BQCxDDa;}_?^Jds`eWl#r?pKkMM_pZ;kM81HV4Pp94M+ z;eP{sSA@R_T-SWG#{u|TT=v1G=(PV0d=qdixj5dm!$PfGf&Rjk?_=oSr(#Lu^A@%% z#y=N0pXYcE1m#x(9|Dgn*~fsdrF>-n3&0g;p7K17_l~msi-2zjz9#bbW#D|ybY`=P!ZB`TKj|I_H4?_GSFH zfh$fw`5#5zq)+>&06)d*!t;ANa6WhP90|&I1Lt!K162{{JA=Jd`41er891NYzKi^k z&p7z9&-VFU;BR4mQT`cTCNA#-nf%v)FG6{-4Yl%q12~_1xc{U5?*Zp?*s2o$Q{a4_ zi58*1s}n8U&!)eeVhpVpWxr|1;rg7(h@ z&gao?2oS#-cx?ZM4DScNf8h*{-1YK|0+&D5&lK>_!e3QCz}Ex6yOh5N_~j9QH*h}p z-ctJiA@JD$-(~nuGW-B=z8}Gmu>9kLggq;wNQR#bJhpcR@R#AATWoTTZIUybgF=Uz>sNtj0%2(FdIG6Q)Xk+kih;8l?Sc;CvUvb6%Lg zuK<4~;(r}@$lrqEao~Kvq51Axz+?YU1Lu1H)(!2w41AT@cKk=cbuGpIcweUf@4)#! z1LylE`MU&oY>(kQ_&$!$C)D2z{Ge%5AB|Lhx_Yz8pt{W_f-`R3 z*jy(7p;STn+~+pheQI<9VP>}(Y=;Cmf>6SUE6#wzRaD?I_PG(OX!9NcT1NnQ*#9!H zes|BZWfys*_4G^zDk~N`JwySQw`UQeJrrwQ1lTMtWcR>0LJ=d{zMW;^;fPb3g*`UX z2x6Bv@xF>-TM_;=rB!0vM#lSa90HFGi6s-V30J|_lR)e$phv$3OJT6%*yACFcok|~ zQN`QG7w@kkmDfi;ZaEm)qHlUlB2?_~4#XKA8eY*vX!~Z2TVa}r6)b_V!EMVSk`Q_l z!r)E>La&T$&x{gJjFONTEeXM>nQ)_s5j=r#x#QdLBG6)yM`zYl0gHQj5KDNnAJNLo z;LllHYId(G0Jil-i&%~xSjAtiLN!-LQD{YVts>JRjBFEcKSu^{o5p}?%3T@Pnr;xQ zxjZ(Zsu0w2FjYmLMUZ0HLa8Rk`NC73tBK=4@FI0<6hFIXg$L^nIYUjghWQOKUJ*NZ zz{9&wPEQ~n_uwe2rs|+p6}1+sV9P#!5KI;!h(mCEi?8g4aYP8RUk3QTpcrP`#f70( z#Xlcma?68mYAOP;a?7~b<=9}`C`NWmJnqV9&-rj*!`!mzgBTPWsP3MFn~<6x&W|#@ zdGN9_6l3}FC{n#ggASEigs9ZfL`ILt78$4Y;ESzXcG80%S<>2FEqJk% zFDyKOH=>&~Z@%{WJgzru6O*TAMWBO&7^(lY#)wl6lZJqGPXK|G~od*tD9|K zjrJZ4cPl^25-kSoTU;Bf9*)B)ns$_v*QXXEma^Bd!MB+vhCmjKLP=Hjmo4FdX;&_U`npmE*{}v z(a!sSt8x(H*Ea|4gHW2~i`cxa2Pb6RCPdKpB?YeGs9da=1C3->cY!mnY~4|5QIA#0 km)U|a1fhy_0pMs`5E#gtgnFRoN0QiFM~(4jyw(^012jV*)&Kwi literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.hex b/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.hex new file mode 100644 index 0000000..6d9a1c7 --- /dev/null +++ b/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.hex @@ -0,0 +1,509 @@ +:100000000C9462000C948A000C948A000C948A0070 +:100010000C948A000C948A000C948A000C948A0038 +:100020000C948A000C948A000C948A000C948A0028 +:100030000C948A000C948A000C948A000C948A0018 +:100040000C94890C0C948A000C94550D0C948A0025 +:100050000C948A000C948A000C948A000C948A00F8 +:100060000C948A000C948A000000000024002700F1 +:100070002A0000000000250028002B0000000000DE +:1000800023002600290004040404040404040202DA +:100090000202020203030303030301020408102007 +:1000A0004080010204081020010204081020000012 +:1000B0000007000201000003040600000000000029 +:1000C00000009E0E11241FBECFEFD8E0DEBFCDBFD3 +:1000D00011E0A0E0B1E0E8E8FFE102C005900D9278 +:1000E000A632B107D9F715E0A6E2B1E001C01D9232 +:1000F000A13EB107E1F710E0C4ECD0E004C02297C4 +:10010000FE010E94BE0FC23CD107C9F70E94820CBB +:100110000C94C20F0C940000FB01DC0102C00190A2 +:100120000D9241505040D8F70895FC0181918617F7 +:1001300021F08823D9F7992708953197CF010895A1 +:10014000FB01DC018D91019080190110D9F3990B0D +:100150000895FB01DC0101900D920020E1F7089564 +:10016000FB01DC014150504030F08D91019080192D +:1001700019F40020B9F7881B990B0895DF93CF93EA +:1001800000D0CDB7DEB7DC01009781F16230710598 +:1001900068F1ED91FC911197660F771F80E090E078 +:1001A00016962D913D914D915C911997620F731F99 +:1001B000841F951F0190F081E02DAE014F5F5F4FCE +:1001C00022E030E00995882389F029813A812115C0 +:1001D000310571F08FEF273F380741F0C901409694 +:1001E000079720F08FEF283F380710F020E030E02D +:1001F000C9010F900F90CF91DF910895FC010097F6 +:1002000011F01182108208952F923F924F925F92C7 +:100210006F927F928F929F92AF92BF92CF92DF9216 +:10022000EF92FF920F931F93DF93CF93CDB7DEB77B +:100230002A970FB6F894DEBF0FBECDBF2C017A838C +:1002400069835C834B83009709F409C1672B09F428 +:1002500006C1452B09F403C1DC019D96AD90BD900C +:10026000CD90DC90D09795962D913D914D915C91DC +:100270009897EB81FC81CF01A0E0B0E08A0D9B1D37 +:10028000AC1DBD1D281739074A075B0740F4B901AB +:100290006A197B097C836B83672B09F4E3C0D20165 +:1002A000ED91FC91119720883188D196ED91FC91C8 +:1002B000D297FA87E987EF2BF1F593962D913C9130 +:1002C00094973A872987232B39F4A114B104C104E8 +:1002D000D10409F4C7C0C3C0A114B104C104D1043E +:1002E00051F1860175013101882499246627772709 +:1002F000CB0166197709880999096D837E838F83FD +:10030000988714C0D2018D919C9169857A850E944D +:10031000BE009A878987892B09F4A1C06D817E81EF +:100320008F819885E60EF71E081F191FE614F70443 +:100330000805190538F7089421083108A220B320D0 +:100340000894211C311CCB80DC80D201ED90FC9004 +:10035000E114F10409F1E985FA85E230F105E0F0F4 +:100360003297BF0180E090E03296FA87E987D701A3 +:1003700050962D913C91519740E050E00E94390FEA +:100380009B01AC01F70182899389A489B589280F63 +:10039000391F4A1F5B1F04C020E030E040E050E0FE +:1003A00081010A191B09C016D10608F48601D7017C +:1003B000ED91FC91C501A0E0B0E0280F391F4A1F64 +:1003C0005B1F0190F081E02DCA01B90149815A817A +:1003D00098010995882341F1C01AD10AC801A0E00B +:1003E000B0E0F20125A536A547A550A9280F391F71 +:1003F0004A1F5B1FD2019D962D933D934D935C93B5 +:10040000D097C8018A0D9B1D82159305A0F08D9190 +:100410009C9169857A850E94BE009A878987892B7D +:1004200041F4F20112AA11AA4B815C814C195D09B9 +:100430001BC0AA24BB24E985FA85D201D296FC937D +:10044000EE93D197C114D10439F029813A81200F5C +:10045000311F3A83298379CF4B815C8105C04FEFEF +:100460005FEF02C040E050E0CA012A960FB6F89450 +:10047000DEBF0FBECDBFCF91DF911F910F91FF90D7 +:10048000EF90DF90CF90BF90AF909F908F907F9034 +:100490006F905F904F903F902F900895FC010097D0 +:1004A00011F480E0089583A194A196A785A710AACE +:1004B00017A681E00895CF92DF92EF92FF920F93FB +:1004C0001F93CF93DF938C016A017B01A901D901AE +:1004D000CD91DC91119712968D919C9113978096F6 +:1004E00013969C938E931297F8018081853E09F4B0 +:1004F000BAC0882309F4B7C08FA198A5A9A5BAA549 +:100500000097A105B10521F4CFA2D8A6E9A6FAA6C5 +:10051000209709F4AAC00115110509F4A6C0D80155 +:100520009C91992309F4A1C01B968C918F30A1F561 +:10053000892F90E08F7390702DE030E0829FA001B2 +:10054000839F500D929F500D11244D50504010929A +:1005500027011092260111C0AC0FBD1FF901E15F08 +:10056000FE4F8081F801E80FF11D80818C932F5F91 +:100570003F4F30932701209326012091260130918F +:1005800027012D30310508F06EC0DA01A20FB31F2C +:10059000AF31B10508F367C08881882309F04FC0E7 +:1005A000B801DE01780120E0F70190819032A1F0DE +:1005B0009C93F801848583FF08C0F7018081813412 +:1005C00020F08B3510F4905E9C932F5F0894E11C13 +:1005D000F11C1196283041F78881853011F485EEA1 +:1005E0008883D80118968C91803211F4322F23C061 +:1005F000FE01E20FF11D8EE28083322F3F5F2C5F00 +:10060000FB0190859032B9F0FE01E30FF11D90835C +:10061000D8011C968C9184FF09C0DB0118968C913F +:10062000813420F08B3510F4905E90833F5F6F5FD4 +:100630007F4F321729F7FE01E30FF11D1082F801F9 +:10064000838588A3828D938D9AA389A3848D958DAC +:10065000A68DB78D8BA39CA3ADA3BEA381E0DA01C9 +:1006600014968C9302C081E001C080E0DF91CF91AD +:100670001F910F91FF90EF90DF90CF9008952F92F0 +:100680003F924F925F926F927F928F929F92AF9222 +:10069000BF92CF92DF92EF92FF920F931F93DF935F +:1006A000CF93CDB7DEB7A7970FB6F894DEBF0FBED6 +:1006B000CDBF2C017FA36EA3009709F4B1C06115D3 +:1006C000710509F4ADC0DC018D909C901197F40187 +:1006D000208831889D96AD90BC909E979F966D9096 +:1006E0007C90D0978BE2DB011D928A95E9F7FE01A1 +:1006F000319685E0DF011D928A95E9F7A114B104D6 +:1007000009F076C0F4012288338886899789281AEF +:10071000390A6EC0730100E010E0A114B10441F485 +:10072000D40156966D917D918D919C9159972DC0D4 +:100730008114910421F1B2E0AB16B10400F1EEEFA7 +:10074000FFEFAE0EBF1EB50180E090E022E030E08A +:10075000A20EB31ED40150962D913C91519740E0CA +:1007600050E00E94390F9B01AC01F401828993890A +:10077000A489B589280F391F4A1F5B1F04C020E0D8 +:1007800030E040E050E0CA01B9016E0D7F1D801FCE +:10079000911F1C821B82D401ED91FC9181010619ED +:1007A00017090280F381E02DAE014A5F5F4F20E21E +:1007B00030E0ABE5EA2EA2E0FA2E6E010894C11CEF +:1007C000D11C0995882361F18B819C81680E791E6B +:1007D0006214730488F0C401B5010E94BE005C017C +:1007E00066247724009741F4F201A3A0B4A008C0C6 +:1007F0002EA13FA13A8329838D81882309F48ACFD2 +:10080000D2019E96BC92AE929D97D0967C926E92AB +:100810009F97EEA1FFA18081882319F081E001C09C +:1008200080E0A7960FB6F894DEBF0FBECDBFCF9184 +:10083000DF911F910F91FF90EF90DF90CF90BF90CD +:10084000AF909F908F907F906F905F904F903F9070 +:100850002F9008952F923F924F925F926F927F92C6 +:100860008F929F92AF92BF92CF92DF92EF92FF92C0 +:100870000F931F93DF93CF93CDB7DEB7A8970FB633 +:10088000F894DEBF0FBECDBF98A78FA3009709F4E1 +:100890005CC1DC0114968D919C911597892B09F40C +:1008A00054C116968D919C911797892B09F44DC1CF +:1008B00068C1E8E2F1E08AE1DF011D928A95E9F77B +:1008C000EFA1F8A5F0932901E09328012184328457 +:1008D0004384548459E0220C331C441C551C5A9503 +:1008E000D1F7C201B101655F7F4F8F4F9F4F0190DC +:1008F000F081E02DAE014F5F5F4F29E130E00995B7 +:10090000882309F445C1E981FA81FBA3EAA32C817C +:100910003D81FB81FCA34E818F8198859EA38DA391 +:10092000E985FA856C857D856E887F88888C998CB1 +:10093000611471048104910431F4309709F428C1E1 +:100940003F01882499246115710509F421C1C90169 +:10095000A0E0B0E08E8F9F8FA8A3B9A380E090E0C5 +:10096000242F30E040E050E00E94390F6A8F7B8FE7 +:100970008C8F9D8F840173012E8D3F8D48A159A1CD +:10098000E21AF30A040B150BE61AF70A080B190B07 +:100990008AA19BA101972DA13EA145E0220F331F03 +:1009A0004A95E1F7820F931F6AA17BA10E94580F1D +:1009B00080E090E0E61AF70A080B190B8CA1282FAB +:1009C00030E040E050E0C801B7010E947F0F79019C +:1009D0008A0195EFE9169FE0F90690E0090790E09B +:1009E000190708F4D5C0A5EFEA16AFEFFA06A0E0A4 +:1009F0000A07A0E01A0728F486E0EFA1F8A580878F +:100A000005C08BE0AFA1B8A518968C9388E1EAE207 +:100A1000F1E0DF011D928A95E9F7EAA1FBA15F01F0 +:100A2000CC24DD24C401B301A60195010E94390F35 +:100A300060932A0170932B0180932C0190932D01D8 +:100A4000C601B5012E8D3F8D48A159A10E94390FD5 +:100A5000260E371E481E591E20922E0130922F015D +:100A60004092300150923101AFA1B8A518968C91F7 +:100A7000863029F064E070E080E090E004C062E03D +:100A800070E080E090E022E030E040E050E0E20EF4 +:100A9000F31E041F151FA80197010E94390F6093D0 +:100AA00032017093330180933401909335014AA150 +:100AB0005BA150933701409336015CA1852F90E0F4 +:100AC000DC01EAA1FBA1AE9FC001AF9F900DBE9FCC +:100AD000900D112490933901809338016A8D7B8D9C +:100AE0008C8D9D8DA60195010E94390F20912E01BC +:100AF00030912F014091300150913101620F731FED +:100B0000841F951F60933E0170933F0180934001C5 +:100B100090934101ADA1BEA19D0140E050E0B5E040 +:100B2000220F331F441F551FBA95D1F7620F731F51 +:100B3000841F951F60933A0170933B0180933C01A1 +:100B400090933D0128E231E002C020E030E0C9018D +:100B5000A8960FB6F894DEBF0FBECDBFCF91DF9140 +:100B60001F910F91FF90EF90DF90CF90BF90AF90CB +:100B70009F908F907F906F905F904F903F902F90BD +:100B800008958091280190912901892BF1F691CE49 +:100B90001092290110922801D8CFCF93DF93AC0196 +:100BA000DB01009789F16115710571F190968C91C7 +:100BB000909784FF29C08091750190917601892BCF +:100BC00019F4E5E7F1E008C08091A6019091A70132 +:100BD000892BD1F4E6EAF1E09F012E5F3F4FBD0182 +:100BE0008BE2EB010990BE01E90109929E0181505F +:100BF000C1F75183408391968D919C91929796A7CE +:100C000085A710AA17A602C0E0E0F0E0CF01DF91AF +:100C1000CF910895CF93DF939C01FB01009731F0B2 +:100C20006115710519F080A184FF23C020E030E038 +:100C3000C901DF91CF910895C4E4D1E0DF018BE2D7 +:100C40000D9009928150E1F73093430120934201C6 +:100C500010926F0110927001109271011092720146 +:100C600081A192A1909374018093730122E431E0F9 +:100C7000DFCF8091420190914301892BB9F6DCCFFF +:100C80006F927F928F929F92AF92BF92CF92DF929C +:100C9000EF92FF920F931F93CF93DF934C01EB01E1 +:100CA0007A01009709F467C06115710509F463C002 +:100CB0008881882309F45FC04115510509F45BC0A0 +:100CC0008F3209F421968BE2F70111928A95E9F7A8 +:100CD00080E1F70180A3370101C0E5018881882305 +:100CE00009F44BC0C401B7010E94CD056C01009707 +:100CF00009F441C0CE016FE270E00E9495000097B8 +:100D000039F0482F4C1B5C010894A11CB11C2AC06F +:100D1000FE0101900020E9F731974E2F4C1B5E0138 +:100D2000A40EB11C1FC0F30101900020E9F7319718 +:100D3000E619F709E017F107B9F4CE01B301A801EC +:100D40000E94B000009781F4F601118210820C0F0E +:100D50001D1FF8018081882381F0F70180A184FDA7 +:100D6000BCCF09C0042F10E0C601B7010E943F03A9 +:100D70008823C9F612C080E001C081E0DF91CF91E5 +:100D80001F910F91FF90EF90DF90CF90BF90AF90A9 +:100D90009F908F907F906F900895F601118210823E +:100DA0009DCF8F929F92AF92BF92CF92DF92EF92A0 +:100DB000FF920F93DF93CF93CDB7DEB760970FB657 +:100DC000F894DEBF0FBECDBF7C016B015A01490113 +:100DD000009709F493C06115710509F48FC00430C0 +:100DE0000CF08CC007FD1DC0602F772767FD709544 +:100DF000E4E0660F771FEA95E1F762547E4F88279B +:100E000077FD8095982FAE014F5F5F4F20E130E076 +:100E1000F7010995882309F471C08D81882309F4AD +:100E20006DC08091DF01882309F068C07CC08D818E +:100E30008093DF012A8530E040E050E0542F432FBB +:100E4000322F22278B8590E0A0E0B0E0DC019927CB +:100E50008827282B392B4A2B5B2B898590E0A0E033 +:100E6000B0E0282B392B4A2B5B2B8C8590E0A0E03F +:100E7000B0E0B82FAA2799278827282B392B4A2B8F +:100E80005B2B2093E0013093E1014093E20150930A +:100E9000E3012E8530E040E050E0542F432F322F05 +:100EA00022278F8590E0A0E0B0E0DC019927882719 +:100EB000282B392B4A2B5B2B8D8590E0A0E0B0E0EE +:100EC000282B392B4A2B5B2B888990E0A0E0B0E0DF +:100ED000B82FAA2799278827282B392B4A2B5B2B39 +:100EE0002093E4013093E5014093E6015093E7013C +:100EF00003C08FEF8093DF019F0102C020E030E04C +:100F0000C90160960FB6F894DEBF0FBECDBFCF917A +:100F1000DF910F91FF90EF90DF90CF90BF90AF9057 +:100F20009F908F900895E7EDF1E081E1DF011D9240 +:100F30008A95E9F7F092D801E092D701D092DA01D0 +:100F4000C092D901B092DC01A092DB019092DE0147 +:100F50008092DD0107FF6BCFCCCF282F8FEF8EBDA6 +:100F60000DB407FEFDCF8DB58F778DBD8EB5822F69 +:100F700080648EBD0DB407FEFDCF8DB58F778DBD1E +:100F8000872F9927AA27BB278EBD0DB407FEFDCF5B +:100F90008DB58F778DBDCB01AA27BB278EBD0DB434 +:100FA00007FEFDCF8DB58F778DBDBB27A72F962F61 +:100FB000852F8EBD0DB407FEFDCF8DB58F778DBD0E +:100FC0004EBD0DB407FEFDCF8DB58F778DBD2223AD +:100FD00019F0283069F406C085E98EBD0DB407FE0E +:100FE000FDCF0BC087E88EBD0DB407FEFDCF05C059 +:100FF0008FEF8EBD0DB407FEFDCF8DB58F778DBD04 +:101000001092E9011092E80120E030E09FEF13C058 +:101010009EBD0DB407FEFDCF8DB58F778DBD8EB50E +:10102000A9014F5F5F4F8F3F29F03093E901209373 +:10103000E80108959A012A30310550F33093E9010F +:101040002093E8018FEF08952F923F924F925F9285 +:101050006F927F928F929F92AF92BF92CF92DF92C8 +:10106000EF92FF920F931F93CF93DF934B015C019D +:101070002A01390133243A9422242394AFC0E40195 +:10108000D170CE01A0E0B0E085017401E81AF90A40 +:101090000A0B1B0BC12CB2E0DB2ECC1ADD0A6C1440 +:1010A0007D0408F463018091EA039091EB03A09121 +:1010B000EC03B091ED03E816F9060A071B07F9F0F7 +:1010C0000E940809882309F48FC0209729F480E042 +:1010D000C81682E0D80658F4C801B7014AEE51E0BC +:1010E00020E032E00E942209882309F47DC0E092CA +:1010F000EA03F092EB030093EC031093ED038AEE06 +:10110000481681E0580671F09E0126513E4FC901F4 +:10111000B201A6010E948C001092EE036C147D04B3 +:1011200009F460C0289888E1B801A7010E94AD07C2 +:10113000882311F0289A58C08EEF8EBD0DB407FE9B +:10114000FDCF8DB58F778DBD1092E9011092E8012A +:10115000EAEEF1E020E030E00BC080818EBD0DB4FE +:1011600007FEFDCF31968DB58F778DBD2F5F3F4F39 +:1011700082E02030380788F33093E9012093E801BA +:101180003EBC0DB407FEFDCF8DB58F778DBD3EBC47 +:101190000DB407FEFDCF8DB58F778DBD3EBC0DB470 +:1011A00007FEFDCF8DB58F778DBD8EB58F3FB1F723 +:1011B0008EBD0DB407FEFDCF8DB58F778DBD8EB57D +:1011C000289A4C0C5D1CC601A0E0B0E0880E991E68 +:1011D000AA1EBB1E6C187D082092EE0361147104D8 +:1011E00009F04DCF81E001C080E0DF91CF911F91E8 +:1011F0000F91FF90EF90DF90CF90BF90AF909F90B6 +:101200008F907F906F905F904F903F902F900895B8 +:101210008091EE03882311F081E008956091EA0344 +:101220007091EB038091EC039091ED034AEE51E055 +:1012300020E032E00E942408882319F081E08093A6 +:10124000EE0308953F924F925F926F927F928F923A +:101250009F92AF92BF92CF92DF92EF92FF920F9345 +:101260001F93CF93DF933B014C016A012901332483 +:101270003A9496C01FEFA12E11E0B12EA620B72000 +:10128000C501A0E0B0E084017301E81AF90A0A0B75 +:101290001B0BC0E0D2E0CA19DB094C165D0608F44E +:1012A000E2018091EA039091EB03A091EC03B091ED +:1012B000ED03E816F9060A071B0709F45EC00E9451 +:1012C0000809882309F471C0289881E1B801A701B1 +:1012D0000E94AD07882319F0289A80E066C03EBCC2 +:1012E0000DB407FEFDCF8DB58F778DBD8EB58E3FCA +:1012F000B1F7EAEEF1E020E030E00BC03EBC0DB407 +:1013000007FEFDCF8DB58F778DBD8EB581932F5F95 +:101310003F4F82E02030380788F33093E901209373 +:10132000E801E092EA03F092EB030093EC031093E0 +:10133000ED03950126513E4FC601B901AE010E9451 +:101340008C003EBC0DB407FEFDCF8DB58F778DBDF3 +:101350008EB53EBC0DB407FEFDCF8DB58F778DBD2C +:101360008EB5289A3EBC0DB407FEFDCFCC0EDD1E17 +:101370008DB58F778DBD8EB50AC0950126513E4F34 +:10138000C601B901AE010E948C00CC0EDD1E4C1AC4 +:101390005D0ACE01A0E0B0E0680E791E8A1E9B1E99 +:1013A0004114510409F066CF81E0DF91CF911F9184 +:1013B0000F91FF90EF90DF90CF90BF90AF909F90F4 +:1013C0008F907F906F905F904F903F9008952F92F5 +:1013D0003F924F925F926F927F928F929F92AF92C5 +:1013E000BF92CF92DF92EF92FF920F931F93DF9302 +:1013F000CF9300D000D0CDB7DEB74B015C013A01EE +:101400003C832B832701DA82C98241155105A9F15A +:101410002115310591F10217130778F1E114F10458 +:1014200061F119013094219431083394021B130B9C +:101430006901EE24FF24C501B401A3012B813C8185 +:101440000E9422098823C9F0C301B501A4012981A2 +:101450003A81F2010995882391F0020D131D8B81C9 +:101460009C81800F911F2B813C818217930738F05C +:101470008C0C9D1CAE1CBF1CDECF80E001C081E047 +:101480000F900F900F900F90CF91DF911F910F91C0 +:10149000FF90EF90DF90CF90BF90AF909F908F9094 +:1014A0007F906F905F904F903F902F9008951F9383 +:1014B000CF93DF93239A259A209A24982C9A289ADE +:1014C00083E58CBD8DB58E7F8DBD1092EF0320E03E +:1014D00030E09FEF0AC09EBD0DB407FEFDCF8DB575 +:1014E0008F778DBD8EB52F5F3F4F2A30310598F332 +:1014F0003093E9012093E80128981092E9011092B5 +:10150000E80180E040E050E060E070E00E94AD075C +:10151000182F813079F08091E8019091E90121E064 +:101520008F3F920709F44DC001969093E901809393 +:10153000E801E7CF87E340E050E060E070E00E9420 +:10154000AD0789E240E050E060E070E00E94AD0746 +:1015500082FD02C01093EF031092E9011092E8019E +:101560008091EF03C82FD0E0C370D070209749F06E +:1015700087E340E050E060E070E00E94AD0789E260 +:1015800001C081E040E050E060E070E00E94AD0703 +:1015900080FF0EC08091E8019091E9012FE78F3F15 +:1015A000920779F001969093E9018093E801DECFEC +:1015B00080E140E052E060E070E00E94AD078823E7 +:1015C00019F0289A80E022C0289A8CB58C7F8CBDB7 +:1015D0008DB581608DBD8FEF9FEFAFEFBFEF809333 +:1015E000EA039093EB03A093EC03B093ED0381E047 +:1015F0008093EE0360E070E080E090E04AEE51E01E +:1016000020E032E00E942209811181E0DF91CF9138 +:101610001F9108954F925F926F927F928F929F9247 +:10162000AF92BF92CF92DF92EF92FF920F931F93F0 +:10163000CF93DF935B016C014A01E9013801270177 +:101640004115510571F10115110559F1FF242115BD +:10165000310511F5FF24F3941FC0C401B601A501A3 +:101660009201F30109958C010097E9F0FF2019F42C +:10167000C817D907B0F0C601B501A40198010E94AE +:101680002408882371F0C801A0E0B0E0A80EB91EBC +:10169000CA1EDB1EC01BD10BFF20F9F62097E9F60E +:1016A00002C080E001C081E0DF91CF911F910F91D6 +:1016B000FF90EF90DF90CF90BF90AF909F908F9072 +:1016C0007F906F905F904F900895CF93DF93EB01E1 +:1016D00060E175E00E943F03882359F0CE0160E18C +:1016E00075E00E94A9008EEC95E0BE010E942E0FCD +:1016F00081E0DF91CF9108950F930E94570A8823CC +:1017000009F445C082E299E067EE79E044E258E0EE +:101710002AE03BE000E00E94D10690933E058093D2 +:101720003D05892B89F482E299E067EE79E044E295 +:1017300058E02AE03BE00FEF0E94D10690933E056F +:1017400080933D05892B19F180913D0590913E05CF +:101750000E942A0490933C0580933B050097B9F0C2 +:1017600060E071E040E155E00E94400680913B0559 +:1017700090913C0560E175E00E94CD0590930F05C6 +:1017800080930E0520E0892B19F021E001C020E0B4 +:10179000822F0F910895EF92FF920F931F93CF9393 +:1017A000DF93EB018A017901CB010E944E0208C050 +:1017B000C701B8010E94A000009711F481E006C0A3 +:1017C000CE01B7010E943F03882391F7DF91CF91AB +:1017D0001F910F91FF90EF900895EF92FF920F935A +:1017E0001F93DF93CF93CDB7DEB7AB970FB6F894C7 +:1017F000DEBF0FBECDBF8C017E010894E11CF11C41 +:1018000097010E94CB0B882319F420E030E005C03B +:10181000C801B7010E940A069C01C901AB960FB628 +:10182000F894DEBF0FBECDBFCF91DF911F910F9116 +:10183000FF90EF900895CF93DF930E947C0B32C00E +:1018400060910E0570910F0580913B0590913C05CC +:1018500040EF54E00E94ED0B9093400580933F05CC +:1018600060EF73E040E051E00E940401EC018EEC77 +:1018700095E060EF73E00E942E0F80913F059091FC +:1018800040051C161D0664F30E94FE0068EE73E01E +:1018900080E090E00E94D10C8EEC95E062E071E077 +:1018A0000E942E0F80910E0590910F0560EF74E05D +:1018B0000E94650B882321F6FFCF80E060E00E9444 +:1018C000350D81E061E00E94350D8EEC95E040E839 +:1018D00055E260E070E00E94920D88E061E00E94B5 +:1018E000350D8BE061E00E94350D8CE060E00E94D8 +:1018F000350D8DE061E00E94350D8AE061E00E94C7 +:10190000350D08950E94FB0C0E945D0C0E941B0C7B +:10191000FDCF1F920F920FB60F9211242F933F937A +:101920008F939F93AF93BF93809145059091460508 +:10193000A0914705B0914805309149050196A11D38 +:10194000B11D232F2D5F2D3720F02D570196A11D9E +:10195000B11D209349058093450590934605A093BA +:101960004705B09348058091410590914205A091AB +:101970004305B09144050196A11DB11D8093410519 +:1019800090934205A0934305B0934405BF91AF9156 +:101990009F918F913F912F910F900FBE0F901F90AD +:1019A0001895EF92FF920F931F937B018C018FB7D5 +:1019B000F894409145055091460560914705709116 +:1019C00048058FBF2FB7F894809145059091460543 +:1019D000A0914705B09148052FBF841B950BA60B1E +:1019E000B70BE816F9060A071B0760F71F910F915E +:1019F000FF90EF900895789484B5826084BD84B59B +:101A0000816084BD85B5826085BD85B5816085BDF9 +:101A1000EEE6F0E0808181608083E1E8F0E08081A3 +:101A200082608083808181608083E0E8F0E0808153 +:101A300081608083E1EBF0E0808184608083E0EB73 +:101A4000F0E0808181608083EAE7F0E0808184605B +:101A500080838081826080838081816080838081B7 +:101A6000806880831092C1000895282F30E0C9015A +:101A700086569F4FFC0194912A573F4FF90184915C +:101A8000882391F0E82FF0E0EE0FFF1FE859FF4F99 +:101A9000A591B491662329F48C91909589238C9318 +:101AA00008958C91892B8C9308951F920F920FB6F5 +:101AB0000F9211242F933F934F935F936F937F93D4 +:101AC0008F939F93AF93BF93EF93FF934091C60083 +:101AD000E091CA05F091CB05CF01019660E870E076 +:101AE0000E946C0F9C018091CC059091CD05281728 +:101AF000390739F0E65BFA4F40833093CB052093EA +:101B0000CA05FF91EF91BF91AF919F918F917F9106 +:101B10006F915F914F913F912F910F900FBE0F905A +:101B20001F9018955F926F927F928F929F92AF92C3 +:101B3000BF92CF92DF92EF92FF920F931F93CF93BA +:101B4000DF93EC013A014B01413482E458078FE006 +:101B5000680780E078070CF07FC060E874E88EE1E9 +:101B600090E0A40193010E94A10F21503040404019 +:101B70005040CA01B90122E030E040E050E00E944C +:101B8000A10F59016A01A601950120953095409554 +:101B9000509594E0220F331F441F551F9A95D1F79B +:101BA00060E074E284EF90E00E94A10FCA01B901E5 +:101BB0002FEF30E040E050E00E94390FA401930184 +:101BC0000E94A10FC90181509F4F181619061CF4DD +:101BD000522E5A9403C055245394521A60E079E06F +:101BE0008DE390E0A40193010E94A10F21503040A9 +:101BF00040405040CA01B90122E030E040E050E0EE +:101C00000E94A10F209530954095509583E0220FBA +:101C1000331F441F551F8A95D1F760E074E284EFAB +:101C200090E00E94A10FCA01B9012FEF30E040E01F +:101C300050E00E94390FA40193010E94A10FC90135 +:101C400081509F4F181619061CF4822F815002C034 +:101C500081E0821B851500F5E885F98581E090E03B +:101C60000A8802C0880F991F0A94E2F7808360E017 +:101C700079E08DE390E0A40193010E94A10F21502F +:101C8000304040405040CA01B90122E030E040E01D +:101C900050E00E94A10F04C0E885F98510829501EB +:101CA000EC81FD813083EE81FF812083EA85FB8515 +:101CB000208141E050E0CA010E8402C0880F991FC4 +:101CC0000A94E2F7282B2083EA85FB852081CA014C +:101CD0000F8402C0880F991F0A94E2F7282B2083F3 +:101CE000EA85FB858081088802C0440F551F0A944D +:101CF000E2F7842B8083DF91CF911F910F91FF90AA +:101D0000EF90DF90CF90BF90AF909F908F907F909B +:101D10006F905F900895FC01A085B18521898C9119 +:101D200090E0022E02C0959587950A94E2F780FF15 +:101D3000F6CF0484F585E02D6083089580E291E07C +:101D40009093CF058093CE058AE495E09093D105DA +:101D50008093D00585EC90E09093D3058093D205D5 +:101D600084EC90E09093D5058093D40580EC90E0CE +:101D70009093D7058093D60581EC90E09093D90598 +:101D80008093D80586EC90E09093DB058093DA058C +:101D900084E08093DC0583E08093DD0587E0809319 +:101DA000DE0585E08093DF0581E08093E0050895FE +:101DB0000F931F93CF93DF938C01EB0109C0219602 +:101DC000D801ED91FC910190F081E02DC8010995B9 +:101DD00068816623A1F7DF91CF911F910F9108953C +:101DE000EF92FF920F931F93CF93DF938C017B01B0 +:101DF000EA010CC0D7016D917D01D801ED91FC91F4 +:101E00000190F081E02DC80109952197209791F765 +:101E1000DF91CF911F910F91FF90EF900895DC011A +:101E2000ED91FC910280F381E02D099508950F93C7 +:101E30001F938C01DC01ED91FC910190F081E02D6C +:101E40006DE00995D801ED91FC910190F081E02DB4 +:101E5000C8016AE009951F910F9108950F931F9390 +:101E60008C010E940F0FC8010E94170F1F910F9144 +:101E70000895629FD001739FF001829FE00DF11DD4 +:101E8000649FE00DF11D929FF00D839FF00D749FF4 +:101E9000F00D659FF00D9927729FB00DE11DF91FA0 +:101EA000639FB00DE11DF91FBD01CF0111240895FD +:101EB000AA1BBB1B51E107C0AA1FBB1FA617B70770 +:101EC00010F0A61BB70B881F991F5A95A9F780958C +:101ED0009095BC01CD01089597FB092E07260AD0E5 +:101EE00077FD04D0E5DF06D000201AF470956195E7 +:101EF0007F4F0895F6F7909581959F4F0895A1E241 +:101F00001A2EAA1BBB1BFD010DC0AA1FBB1FEE1F73 +:101F1000FF1FA217B307E407F50720F0A21BB30BBE +:101F2000E40BF50B661F771F881F991F1A9469F73A +:101F300060957095809590959B01AC01BD01CF0196 +:101F4000089597FB092E05260ED057FD04D0D7DF44 +:101F50000AD0001C38F450954095309521953F4F9C +:101F60004F4F5F4F0895F6F7909580957095619566 +:101F70007F4F8F4F9F4F0895EE0FFF1F0590F491F5 +:081F8000E02D0994F894FFCF55 +:101F88002F004E6578742046696C652E2E2E000150 +:101F9800030507090E10121416181C1E0000000075 +:061FA8008B0ED80EF00EB6 +:00000001FF diff --git a/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.o b/FAT16/examples/FAT16_ReadExample/applet/FAT16_ReadExample.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..5d241a8af8b54cf266ee621e946606f8aaa764fd GIT binary patch literal 13216 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 J92hQ{{{@TQ=12el literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/HardwareSerial.cpp.o b/FAT16/examples/FAT16_ReadExample/applet/HardwareSerial.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..d5af08330172ca95dbd3c2941a9a9ad01415a023 GIT binary patch literal 16184 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 literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/WInterrupts.c.o b/FAT16/examples/FAT16_ReadExample/applet/WInterrupts.c.o new file mode 100644 index 0000000000000000000000000000000000000000..52801e41ca39ea2fa8995912d6f46f4594003e65 GIT binary patch literal 5628 zcmcIoZD^a<6+Tz8Y{zyiJ6Y1SO=czal5}Y$$8(q9Wp;^ECt;y6O|x~wLzN}j7TA*W zT6UT;u#>c-8G~BU!oof%qk|2)k-^4bKh~B)VQdWgV;lVw$o4B`bah5n#v1UR=f3Ak z*IKsH!VbRgea^Y(Jonts_m!6(J27gE5hq4YNnI1U(<<^j8V9VyUP;IfG2P}Ceogi#vqXnV~%fT?8cpPd~>Q@q;sH7f~fc-uwx|0 zFvN%*QIj34KVoa)U@IH4W`-CdjACrP2)A7K7AG zVInn^&8Ct`{?Sq>W@i?1c^MfTA5*GPQjPmm|6t9jYH}u;0_5V-D4F zuAya{>U~OFio5 zReAlLt3GS@g{}*&S9&hTFUNlwzueuMst#9AR@2o|b*cJd^`+{y>TA{as%zEdipUDe zrF~}g2I^Im4OiAG?^Rx_T&uiPd9kuoDOJ*yla=90suEv`zZzfZS=sh~WER|UvIa3? zmU=r9R)@*TD4uM0vKzqHzj7Dd`5Kx2-|$H^hgWjJ@0U)5*3^Eqg)f7Ux5?^!a3B;8fWpKnt`4=2_H4|oG5e2mFO080;ESa~ zZgioT9V-WdV@@aw#reWiF`r9haka=ysW_FWncyQwA3vQKNem=ElkAs;`FyZGh#ofP zKLc_7l@F%NGF!r>R`+3q?W#7-`~4ZWj`Z=ff*#&dk1x!MBSt%m{$W?l8w_J2HU2_mGYXr zLEX*TZ_`R*Ja!uWgeLLsa0!H2&y=$3GMrnOD8dJ$^2U(~GR3I|n=^$pn46EX5$}gH z4uLdlQ1~rWXJ8v;CknBBIimh=etXcy4~Y-+v#)IUIU(O0PC@PZ9riGr-$&trcjDk6 z4D|ym^208Xt7!Zr?EGqB8}FVm6c+<1hjG?Tc;2bj+P(nn^BvkGazy#~`Q!L98sp|~ z1P$)GKvRtmZ{Kx%%Xr}&gN^y|i^%bP4Vd{kzDsD>4c&>${VWWOaq=7RJqd+;_%^KZ zeH+;4yM`eD+H!oCH3pTH?Vk`i1Vp}#C@#OB0{eXUlD#Y6k2MCBm8U$uI4q9uRbYR= zWWnc;%jNeL{2V4>4t`uqCobl9FgVP%Z=v6(QF9zv!dkz70rvTR0lo)ebK=^r!{GDX z2A^9uz#8A*fn5wau7mF>0u|TxE_9#o(3WstGQX|b#(mm?02c#Q9>InK8fc@h=gKy`^? zR(M}g7-{URTh%_I_D1k^PHtVo(fK-8tu9e}a(taTzb;X`bA6q&QvD>Jg_>)?*uSD)RGdZq4aHn1u7k0^o<*)G=9>M07_q!}ULnRk zLirgA?JuK#L-E_F|D+g|Fb_j=$e&S&x$f^0E9V`>tEi*s!*IeN_TB{MzUZPI{vQC} zL(CTd#NLI#^!cp%lz=_Ri6tk~0ikZea#T?ps#mwQ7V$K`>fl`~F?<(E}`^$=%&nt=# z0{>hw=jYeNI&b{P3Nd4Uub8oaRLt1xiW$r4iy+A(sJXW{=-e{zHpP7B(Z{`Cod0&% z`5(6=+gUIty{MZNTMoq>FZrYJVXB-yV%o{$`eh%kUvf2R4m?N1NL?O6iD3V5EPZN6 zW$$w5<6@bYi{(4X#v%bfmOcY0jHM5AGJHU`p}2iTPG`60nuCBa*4fGH_W2RdZqK-` z5zIBtCdIo@^NL|#oKL>Xi2G4<{)x$VpJMJq&a>g9LVV1$=uffvYn}<{E;pOMpARPi pV)Iel3f=Lr8)Eir`IXbo74UA@ZC`rExu)!kdn`e$ef27){ohUPtK|Ry literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/WMath.cpp.o b/FAT16/examples/FAT16_ReadExample/applet/WMath.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..d8792d0391c6e8f516c46ed92a0d602d3fa07516 GIT binary patch literal 7012 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 AhX4Qo literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/pins_arduino.c.o b/FAT16/examples/FAT16_ReadExample/applet/pins_arduino.c.o new file mode 100644 index 0000000000000000000000000000000000000000..c1fa9f5a6f20782b5e4861539495c483cb7d0663 GIT binary patch literal 3056 zcmbVO&ub(_6n@n+lT3DYW8(OeMVZxXOjhm5X2Yrxvua3UBx-QcgGSq)>E222&UBAG zJ*$ZeE26Lm(eK`B;M9`ZEf?gDIa1VNj->a_b?sOCvA5;Cl_r0q3 zs=8iR&Dn*OMIi)f5pd48lEXI9u@46?&0Vm+*4s~lV9*ovc-#6U@u z2kt_*7tsd!QKXVFC?gvu#oHi6NhTdS103_4;!!&+W<0;y?mI5c&#tYiP>URDEgNc0hgxd} zVd^95MGm&ZT<6N_dVbGRqs(T!zomGWg}7R-fcIXAzlKq1Y6Y;tLB{9?Iwa9SnxGpc zx}L^ql8QX}!W0}Y!|DcMWJQ712^`m2 zUAm9n$&jAk?MIURGQ$S_NYlKzj@R-cyKP~;97qP_K-;^04KK1fcJGu7c_n6$8yk5Y zHE@Zp39{?(QSD_#JWPm>wCZCg>Ee_6|679PUw#Mvw z9gROKEgJHCikgHzhjV`wPFx|xhcf&2qTP$8#{kmTFn(m9MEe$CXXE{Vi-pH?JU-oZ zyoZ5#O#HbMy$|pRY%MyT2SQ`^@p=D&?v(L4z}dV%XYyi6N!|@LW(u0+W5nb2YGKH2 z6ix31`wYB{=NTx`Ls;uIu&azsJP+~`V2;6a8bKRE%f@>Z#BboV=y=-JI?ESni%+dY z3On8m$Is4$?SjmGEE%!2%_sX@#=Z{tj*QJmd0L}e+kBa)vbD{z(mCbllidN%FR%4v zctKV`V#3dFC6xm4PNh;n<*cNpT+5?5`=qjYU6EpZArZ8hCyODfz=GU8o(X(AEd1RH6z?n0T+58#fWDlu zDmAVrjjv(64-d!~8uy<@u}msl0zRtnlhAi7Tm%1r!aqUFvjJl#!9S+>v(S#h`@o-4 z_;+YNw>j5-@aGkN0{TtHeDFZtMdLnm=<^9<@LU&PDISWxVGN#Y=U2w)&;NlgD4y$v ii=TP^PKFtyKiAJyieCaAS3K9z=Vkc$SbjdN-^$ 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 A=l}o! literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/wiring_digital.c.o b/FAT16/examples/FAT16_ReadExample/applet/wiring_digital.c.o new file mode 100644 index 0000000000000000000000000000000000000000..02809cee965fb2c44e4dab53cce05b8900f7235f GIT binary patch literal 8276 zcmb`Le{h^d8OL|;k~F_)o3u^S(jV70K+*P+l+boUTdtOt@~b@(5U9cHUG9<`z1+pi zC4~;qf)VK$u_5h9(LskFjx*{E%)lr!=#&wisp5Y{N1Tz&pp1?TP^>7z5WnBuXW#eD zwOD1?$-ev9XPcX=dbeF!lYHpQMp%ztFw*?}l!c8hXyR+_!x@+bsRUz_fr7A5dRTb4%;gb4Dorcn^ z%0Q3msJ^n^wKwQS9jm2I4Rorl)ey$3^}B>>m8$FTT9v9t#dF|-I(XZtX=1i7XP-HN zDlE>mib^%i!BpsbFQyuirlHh-yZpGT9o*4<{jUr?#qq1F`i`x>KRJzuExHS;)r z^9sapkw5B{^_%LIT70n?MKxC-iYCYvCjP-iFk(JJ8lED=h7W8o5`-3U4pnCJC26=j z&W6w|HiRlFZDDKGwpMLx)>@^ms?^oSu

|NylT64{4J%}_S4 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 literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/wiring_pulse.c.o b/FAT16/examples/FAT16_ReadExample/applet/wiring_pulse.c.o new file mode 100644 index 0000000000000000000000000000000000000000..354b096cd4d801ccb3545b3351de996ac06532a0 GIT binary patch literal 6452 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 Z&xKBZTkP58u5HA#RO7KeOhL>x{0C_-2KN8} literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_ReadExample/applet/wiring_shift.c.o b/FAT16/examples/FAT16_ReadExample/applet/wiring_shift.c.o new file mode 100644 index 0000000000000000000000000000000000000000..2f318d06c30fdab697c1313d36a079948805eedb GIT binary patch literal 4084 zcmbVPTWnNC82)FsEtQr+K~PeV#h{?V*{VcHRU~q&N}z$DL@LYKOSeas-RATZXvIiC z#RnrxOT9#6d@#`mNK7nytwsbT--1Ni(kvgMq6sdRAW6hyuWpk^VuQtvWX{fI`Cy-_q#Ktg|V&mFrqWpkC zB=kV)^cdp<)oOkc3XvFw#zX702Hj&UiF&UbNFp&yo9gOA7D|nw)EG*!6v>{|@T(8| zTT<&WQBCP?R2$8t{}yK*c1xn#Dxt45dZLzYFoMWFwymDntd;9(C(!G$5xPBoWR4OId4*ThnmrWOQxwPZ(j~cI>D-Gle zvZqMPm$j7+%@Fin z)`vTa35O_cxRu+C+-mqj!xzoqRzJt+ml}@6T#SWH2+9%okCr*L<%KMAarnycwc+c- zQ^RvdmW^B)xi<2PbHn+}85{q0JdvI^ero)(b9MEFl$!ifH9ImkFj^d)eKs*EW1p*1 z+lx(?m5hy!o*I3AG%@*=a{Jy`({fhi^cr_OF#+Khosft0A1Ry3!CvZWIifGg>>l9K%vTCSugf*A`fSCWt5J_{{ZlC`iw z4vZ*wq*mxk4p@`r4N@9Wha#6Y7{X2b8E6Pi@BGezKu0X8nd`L7PkdT6p8u_v`Dwbpsic|h`R z;7*I7gAVz79L{F2J`+UqkNg-F^+qW^1abNY4+U-(Jn%!_Yf(@*8i>PTh?DK_2P|X< ziWxVX^$Ul^@e3u_sJwDdWtyVol?z6}EKY4-;!!=gUaVJ`8p|{-P2WJa3?FnI>&*4t za&d;vs=_pwz>F>Zcab&3n$x!^c=+B#{M8$W%$|A*g7*m&#zpC4~;n;TH~J4j&2 z+8%>!F-_;uSnZaqtpkdv%tiL%Ft3O4Ht6}p(8lxKg=S*_~$M!pn*Av>l%$QIM| zHuBvL&U{U1c6_IRBz7L?YWNjRCJl`kC_ZxJ~hpE@{y#;Jz0A(|RmJt}TwqeNe zd>_mW*Pre4(o z)R*xKMU96Fex)YlE16uSZ!n`Dp-hHiso?qQu!JmTjZl#`U(P{8$@SO(#2>!Ie9{6(xUjok? z{2us0gTDjsGZ;*c8O$?zk{EXnN#9+-Tx<5nF;MpoF*gJBJ{tAAz&|F2{toc-M*jr( z7e@aG_}2zM3;w;quYvzbY>q=C4v`(hJcD^YZ#OsvoHF=s;8h0S3*2rn*NpEE^Kfl8 z8oVF4)8HQ9E`!U!dkyA%xfcnp1%;%mM)-?wIqtJ10 ztpCQC&$bwT%HZSRoQw76ni8kL3o*=Eq&@)G@2bIrMt>NbdrzMw;IA9(gEtWK0D +#include +#include +#include +#include +#include +#include +#include + +//Define the pin numbers +#define CS 8 +#define MOSI 11 +#define MISO 12 +#define SCK 13 + +//This is the amount of data to be fetched from the SD card for each read. +#define BUFFERSIZE 256 + +char buffer[BUFFERSIZE]="Testing\n"; +char file_name[30]; + +struct fat_dir_struct* dd; //FAT16 directory +struct fat_dir_entry_struct dir_entry; //FAT16 directory entry (A.K.A. a file) + +struct fat_fs_struct* fs; //FAT16 File System +struct partition_struct* partition; //FAT16 Partition + +struct fat_file_struct * file_handle; //FAT16 File Handle + +void setup() +{ + //Set up the pins for the Serial communication + pinMode(0, INPUT); + pinMode(1, OUTPUT); + Serial.begin(9600); + + //Set up the pins for the microSD shield + pinMode(CS, OUTPUT); + pinMode(MOSI, OUTPUT); + pinMode(MISO, INPUT); + pinMode(SCK, OUTPUT); + pinMode(10, OUTPUT); +} + +void loop() +{ + int bytes_read=0; //Keeps track of how many bytes are read when accessing a file on the SD card. + int count=0; + + init_filesystem(); //Initialize the FAT16 file system on the SD card. + + //Create a file named Test.txt. If the file already exists, delete it and create a new one. + if(!fat_create_file(dd, "Test.txt", &dir_entry)){ + fat_delete_file(fs, &dir_entry); + fat_create_file(dd, "Test.txt", &dir_entry); + } + //Open the file that's just been created + file_handle=open_file_in_dir(fs, dd, "Test.txt"); + //Write some initial data to the file + fat_write_file(file_handle, (const uint8_t*)buffer, strlen(buffer)); + sd_raw_sync(); //An SD sync must be performed after each write operation + fat_close_file(file_handle); //Close the file. + while(1){ + //Open the file (now we're at the beginning of the file again. + open_file_in_dir(fs, dd, "Test.txt"); + //Read the contents of the file (up to 512 bytes) + bytes_read = fat_read_file(file_handle, (uint8_t*)buffer, BUFFERSIZE); + //Print the contents of the file + Serial.println((const char*)buffer); + //Now go to the end of the file to write some data. + fat_seek_file(file_handle, 0, FAT_SEEK_END); + sprintf(buffer, "%d", count++); + //Write the new 'buffer' string to the end of the file + fat_write_file(file_handle, (const uint8_t*)buffer, strlen(buffer)); + sd_raw_sync(); + //Close the file, we're finished! + fat_close_file(file_handle); + delay(1000); + } + + while(1); +} + +uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry) +{ + fat_reset_dir(dd); //Make sure to start from the beginning of the directory! + while(fat_read_dir(dd, dir_entry)) + { + if(strcmp(dir_entry->long_name, name) == 0) + { + //fat_reset_dir(dd); + return 1; + } + } + + return 0; +} + +struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name) +{ + struct fat_dir_entry_struct file_entry; + if(!find_file_in_dir(fs, dd, name, &file_entry)) + return 0; + + return fat_open_file(fs, &file_entry); +} + +char init_filesystem(void) +{ + //setup sd card slot + if(!sd_raw_init()) + { + return 0; + } + + //open first partition + partition = partition_open(sd_raw_read, + sd_raw_read_interval, +#if SD_RAW_WRITE_SUPPORT + sd_raw_write, + sd_raw_write_interval, +#else + 0, + 0, +#endif + 0 + ); + + if(!partition) + { + //If the partition did not open, assume the storage device + //is a "superfloppy", i.e. has no MBR. + partition = partition_open(sd_raw_read, + sd_raw_read_interval, +#if SD_RAW_WRITE_SUPPORT + sd_raw_write, + sd_raw_write_interval, +#else + 0, + 0, +#endif + -1 + ); + if(!partition) + { + return 0; + } + } + + //Open file system + fs = fat_open(partition); + if(!fs) + { + return 0; + } + + //Open root directory + fat_get_dir_entry_of_path(fs, "/", &dir_entry); + dd=fat_open_dir(fs, &dir_entry); + + if(!dd) + { + return 0; + } + return 1; +} + +char get_next_filename(struct fat_dir_struct* cur_dir, char * new_file) +{ + //'dir_entry' is a global variable of type directory_entry_struct + + //Get the next file from the root directory + if(fat_read_dir(cur_dir, &dir_entry)) + { + sprintf(new_file, "%s", dir_entry.long_name); + Serial.println((const char *)new_file); + return 1; + } + //If another file isn't found, return 0 + return 0; +} + + diff --git a/FAT16/examples/FAT16_WriteExample/applet/FAT16/byteordering.c.o b/FAT16/examples/FAT16_WriteExample/applet/FAT16/byteordering.c.o new file mode 100644 index 0000000000000000000000000000000000000000..07d283e1caaf5af14618100063c66a33b260ec11 GIT binary patch literal 1604 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 literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/FAT16/partition.c.o b/FAT16/examples/FAT16_WriteExample/applet/FAT16/partition.c.o new file mode 100644 index 0000000000000000000000000000000000000000..f5741e114c89962978b54c883352050a43e0f674 GIT binary patch literal 7552 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 +#include +#include +#include +#include +#include +#include +#include + +//Define the pin numbers +#define CS 8 +#define MOSI 11 +#define MISO 12 +#define SCK 13 + +//This is the amount of data to be fetched from the SD card for each read. +#define BUFFERSIZE 256 + +#include "WProgram.h" +void setup(); +void loop(); +uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry); +struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name); +char init_filesystem(void); +char get_next_filename(struct fat_dir_struct* cur_dir, char * new_file); +char buffer[BUFFERSIZE]="Testing\n"; +char file_name[30]; + +struct fat_dir_struct* dd; //FAT16 directory +struct fat_dir_entry_struct dir_entry; //FAT16 directory entry (A.K.A. a file) + +struct fat_fs_struct* fs; //FAT16 File System +struct partition_struct* partition; //FAT16 Partition + +struct fat_file_struct * file_handle; //FAT16 File Handle + +void setup() +{ + //Set up the pins for the Serial communication + pinMode(0, INPUT); + pinMode(1, OUTPUT); + Serial.begin(9600); + + //Set up the pins for the microSD shield + pinMode(CS, OUTPUT); + pinMode(MOSI, OUTPUT); + pinMode(MISO, INPUT); + pinMode(SCK, OUTPUT); + pinMode(10, OUTPUT); +} + +void loop() +{ + int bytes_read=0; //Keeps track of how many bytes are read when accessing a file on the SD card. + int count=0; + + init_filesystem(); //Initialize the FAT16 file system on the SD card. + + //Create a file named Test.txt. If the file already exists, delete it and create a new one. + if(!fat_create_file(dd, "Test.txt", &dir_entry)){ + fat_delete_file(fs, &dir_entry); + fat_create_file(dd, "Test.txt", &dir_entry); + } + //Open the file that's just been created + file_handle=open_file_in_dir(fs, dd, "Test.txt"); + //Write some initial data to the file + fat_write_file(file_handle, (const uint8_t*)buffer, strlen(buffer)); + sd_raw_sync(); //An SD sync must be performed after each write operation + fat_close_file(file_handle); //Close the file. + while(1){ + //Open the file (now we're at the beginning of the file again. + open_file_in_dir(fs, dd, "Test.txt"); + //Read the contents of the file (up to 512 bytes) + bytes_read = fat_read_file(file_handle, (uint8_t*)buffer, BUFFERSIZE); + //Print the contents of the file + Serial.println((const char*)buffer); + //Now go to the end of the file to write some data. + fat_seek_file(file_handle, 0, FAT_SEEK_END); + sprintf(buffer, "%d", count++); + //Write the new 'buffer' string to the end of the file + fat_write_file(file_handle, (const uint8_t*)buffer, strlen(buffer)); + sd_raw_sync(); + //Close the file, we're finished! + fat_close_file(file_handle); + delay(1000); + } + + while(1); +} + +uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry) +{ + fat_reset_dir(dd); //Make sure to start from the beginning of the directory! + while(fat_read_dir(dd, dir_entry)) + { + if(strcmp(dir_entry->long_name, name) == 0) + { + //fat_reset_dir(dd); + return 1; + } + } + + return 0; +} + +struct fat_file_struct* open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name) +{ + struct fat_dir_entry_struct file_entry; + if(!find_file_in_dir(fs, dd, name, &file_entry)) + return 0; + + return fat_open_file(fs, &file_entry); +} + +char init_filesystem(void) +{ + //setup sd card slot + if(!sd_raw_init()) + { + return 0; + } + + //open first partition + partition = partition_open(sd_raw_read, + sd_raw_read_interval, +#if SD_RAW_WRITE_SUPPORT + sd_raw_write, + sd_raw_write_interval, +#else + 0, + 0, +#endif + 0 + ); + + if(!partition) + { + //If the partition did not open, assume the storage device + //is a "superfloppy", i.e. has no MBR. + partition = partition_open(sd_raw_read, + sd_raw_read_interval, +#if SD_RAW_WRITE_SUPPORT + sd_raw_write, + sd_raw_write_interval, +#else + 0, + 0, +#endif + -1 + ); + if(!partition) + { + return 0; + } + } + + //Open file system + fs = fat_open(partition); + if(!fs) + { + return 0; + } + + //Open root directory + fat_get_dir_entry_of_path(fs, "/", &dir_entry); + dd=fat_open_dir(fs, &dir_entry); + + if(!dd) + { + return 0; + } + return 1; +} + +char get_next_filename(struct fat_dir_struct* cur_dir, char * new_file) +{ + //'dir_entry' is a global variable of type directory_entry_struct + + //Get the next file from the root directory + if(fat_read_dir(cur_dir, &dir_entry)) + { + sprintf(new_file, "%s", dir_entry.long_name); + Serial.println((const char *)new_file); + return 1; + } + //If another file isn't found, return 0 + return 0; +} + + + +int main(void) +{ + init(); + + setup(); + + for (;;) + loop(); + + return 0; +} + diff --git a/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.eep b/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.eep new file mode 100644 index 0000000..1996e8f --- /dev/null +++ b/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.eep @@ -0,0 +1 @@ +:00000001FF diff --git a/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.elf b/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.elf new file mode 100644 index 0000000000000000000000000000000000000000..a82c1fa3854a0127abc05c088c4f7df033b3ae7c GIT binary patch literal 81422 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 literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.hex b/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.hex new file mode 100644 index 0000000..8e576ae --- /dev/null +++ b/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.hex @@ -0,0 +1,883 @@ +:100000000C9462000C948A000C948A000C948A0070 +:100010000C948A000C948A000C948A000C948A0038 +:100020000C948A000C948A000C948A000C948A0028 +:100030000C948A000C948A000C948A000C948A0018 +:100040000C9480170C948A000C944C180C948A0021 +:100050000C948A000C948A000C948A000C948A00F8 +:100060000C948A000C948A000000000024002700F1 +:100070002A0000000000250028002B0000000000DE +:1000800023002600290004040404040404040202DA +:100090000202020203030303030301020408102007 +:1000A0004080010204081020010204081020000012 +:1000B0000007000201000003040600000000000029 +:1000C0000000951911241FBECFEFD8E0DEBFCDBFD1 +:1000D00012E0A0E0B1E0E4EEF5E302C005900D927D +:1000E000A632B107D9F715E0A6E2B2E001C01D9231 +:1000F000A33CB107E1F710E0C4ECD0E004C02297C4 +:10010000FE010E94B51AC23CD107C9F70E947917B7 +:100110000C94F01A0C940000FB01DC0102C0019069 +:100120000D9241505040D8F70895DC0101C06D9305 +:1001300041505040E0F70895FC018191861721F06D +:100140008823D9F7992708953197CF010895FB01A6 +:10015000DC018D91019080190110D9F3990B08955C +:10016000FB01DC014150504030F08D91019080192D +:1001700019F40020B9F7881B990B0895FB01DC01E5 +:100180004150504048F001900D920020C9F701C045 +:100190001D9241505040E0F70895FC0181E090E04D +:1001A0000190061609F4CF010020D1F701970895B8 +:1001B000AEE0B0E0EEEDF0E00C94C71A0D891E89B8 +:1001C00086E08C831A8309838FEF9FE79E838D835C +:1001D0009E01275E3F4FCE0101966F89788DA90160 +:1001E0000E94FC002F813885020F131FF801108236 +:1001F0002E96E4E00C94E31AABE0B0E0E2E0F1E02C +:100200000C94B91A3C012B015A01FC011782168289 +:10021000838181FD03C06FEF7FEFC6C19AE0892E15 +:100220001E010894211C311CF3012381F20123FDDE +:10023000859123FF81912F01882309F4B2C1853272 +:1002400039F423FD859123FF81912F01853229F413 +:1002500090E0B3010E94EF02E7CF982FFF24EE2435 +:100260009924FFE1FF15D0F09B3269F09C3228F40D +:10027000903259F0933291F40EC09D3249F0903390 +:1002800069F441E024C052E0F52A84E0F82A28C04D +:1002900098E0F92A25C0E0E1FE2A22C0F7FC29C037 +:1002A000892F80538A3070F4F6FE05C0989C902CFC +:1002B0001124980E15C0E89CE02C1124E80EF0E201 +:1002C000FF2A0EC09E3229F4F6FC6BC140E4F42AEA +:1002D00007C09C3619F450E8F52A02C0983649F454 +:1002E000F20123FD959123FF91912F01992309F0AC +:1002F000B8CF892F8554833018F08052833038F47A +:1003000044E050E0A40EB51E5FE359830FC093365E +:1003100031F0933779F0933509F056C020C0F501DC +:100320008081898342E050E0A40EB51E610101E0A6 +:1003300010E012C0F501C080D180F6FC03C06FEF61 +:100340007FEF02C0692D70E042E050E0A40EB51EC0 +:10035000C6010E94E4028C015FE7F52214C0F5019A +:10036000C080D180F6FC03C06FEF7FEF02C0692D23 +:1003700070E042E050E0A40EB51EC6010E94D90212 +:100380008C0150E8F52AF3FE07C01AC080E290E025 +:10039000B3010E94EF02EA948E2D90E0081719072E +:1003A000A8F30EC0F601F7FC8591F7FE81916F016D +:1003B00090E0B3010E94EF02E110EA940150104076 +:1003C0000115110579F7EAC0943611F0993669F5EF +:1003D000F7FE08C0F501208131814281538184E01C +:1003E00090E00AC0F501808191819C01442737FD8E +:1003F0004095542F82E090E0A80EB91E9FE6F922A6 +:1004000057FF09C050954095309521953F4F4F4F6C +:100410005F4FE0E8FE2ACA01B901A1012AE030E0FD +:100420000E941B03D82ED21840C0953729F41F2DE7 +:100430001F7E2AE030E01DC01F2D197F9F3661F01E +:10044000903720F4983509F0ACC00FC0903739F0E0 +:10045000983709F0A6C004C028E030E00AC0106157 +:1004600014FD146020E130E004C014FD166020E1AA +:1004700032E017FF08C0F5016081718182819381AC +:1004800044E050E008C0F50180819181BC0180E02A +:1004900090E042E050E0A40EB51EA1010E941B03B3 +:1004A000D82ED2188FE7F82EF122F6FE0BC05EEFA1 +:1004B000F522D91438F4F4FE07C0F2FC05C08FEE23 +:1004C000F82202C01D2D01C0192DF4FE0DC0FE0141 +:1004D000ED0DF11D8081803319F499EEF92208C0E9 +:1004E0001F5FF2FE05C003C08F2D867809F01F5FE5 +:1004F0000F2DF3FC14C0F0FE0FC01E1510F09D2C44 +:100500000BC09D2C9E0C911A1E2D06C080E290E01F +:10051000B3010E94EF021F5F1E15C0F304C01E1539 +:1005200010F4E11A01C0EE2404FF0FC080E390E054 +:10053000B3010E94EF0202FF1DC001FD03C088E766 +:1005400090E00EC088E590E00BC0802F867891F097 +:1005500001FF02C08BE201C080E2F7FC8DE290E077 +:10056000B3010E94EF0206C080E390E0B3010E9455 +:10057000EF029A94D914C0F3DA94F101ED0DF11D54 +:10058000808190E0B3010E94EF02DD20A9F706C050 +:1005900080E290E0B3010E94EF02EA94EE20C1F7FE +:1005A00043CEF30166817781CB012B96E2E10C9477 +:1005B000D51AFC010590615070400110D8F7809564 +:1005C00090958E0F9F1F0895FC016150704001901F +:1005D0000110D8F7809590958E0F9F1F08950F9367 +:1005E0001F93CF93DF938C01EB018B8181FF1BC0A5 +:1005F00082FF0DC02E813F818C819D812817390794 +:1006000064F4E881F9810193F983E88306C0E88501 +:10061000F985802F0995892B31F48E819F81019670 +:100620009F838E8302C00FEF1FEFC801DF91CF9130 +:100630001F910F910895FA01AA27283051F1203116 +:1006400081F1E8946F936E7F6E5F7F4F8F4F9F4F66 +:10065000AF4FB1E03ED0B4E03CD0670F781F891FA8 +:100660009A1FA11D680F791F8A1F911DA11D6A0F76 +:10067000711D811D911DA11D20D009F468943F9129 +:100680002AE0269F11243019305D3193DEF6CF0128 +:100690000895462F4770405D4193B3E00FD0C9F7EE +:1006A000F6CF462F4F70405D4A3318F0495D31FD5B +:1006B0004052419302D0A9F7EACFB4E0A6959795AE +:1006C000879577956795BA95C9F700976105710584 +:1006D00008959B01AC010A2E0694579547953795CE +:1006E0002795BA95C9F7620F731F841F951FA01D28 +:1006F0000895DF93CF9300D0CDB7DEB7DC0100972C +:1007000081F16230710568F1ED91FC911197660FEE +:10071000771F80E090E016962D913D914D915C9170 +:100720001997620F731F841F951F0190F081E02DB0 +:10073000AE014F5F5F4F22E030E00995882389F0DA +:1007400029813A812115310571F08FEF273F380754 +:1007500041F0C9014096079720F08FEF283F3807F6 +:1007600010F020E030E0C9010F900F90CF91DF91A1 +:1007700008954F925F926F927F928F929F92AF9265 +:10078000BF92CF92DF92EF92FF920F931F93DF936E +:10079000CF9300D0CDB7DEB75C01009709F449C014 +:1007A0006230710508F445C0DC0116966D907D90AD +:1007B0008D909C9019972E010894411C511C660F36 +:1007C000771F7B0100E010E0E60CF71C081D191DE7 +:1007D000D501ED91FC910190F081E02DC801B701A8 +:1007E000A20122E030E00995882319F1C980DA805E +:1007F000C114D10401F1C60140960897D0F0B8EFBA +:10080000CB16BFEFDB0610F0CC24DD241A82198250 +:10081000D501ED91FC910480F581E02DC801B7016F +:10082000A20122E030E00995B601C114D10439F6E5 +:1008300002C080E001C081E00F900F90CF91DF9166 +:100840001F910F91FF90EF90DF90CF90BF90AF90EE +:100850009F908F907F906F905F904F9008952F9210 +:100860003F924F925F926F927F928F929F92AF9240 +:10087000BF92CF92DF92EF92FF920F931F93DF937D +:10088000CF93CDB7DEB72A970FB6F894DEBF0FBE71 +:10089000CDBF3C012B01009709F48FC0DC01ED9125 +:1008A000FC911197208131813A87298724803580F6 +:1008B00016968D919D910D90BC91A02D8D839E8358 +:1008C000AF83B887F30182859385A485B585B695F6 +:1008D000A795979587959C838B834A01CC24DD242B +:1008E00042E0A42EB12C41C0C501880F991F7C01A4 +:1008F00000E010E02D813E814F815885E20EF31E0D +:10090000041F151FC801B701AE014F5F5F4F22E002 +:1009100030E0A985BA85FD010995882309F44DC009 +:1009200089819A81892BF1F4C114D10429F4EFEF64 +:10093000FFEFFA83E98302C0DA82C982C801B701F6 +:10094000AE014F5F5F4F22E030E0F101099588234F +:1009500091F00894810891088114910411F46501C3 +:100960000CC065010894A11CB11C2B813C81A2160E +:10097000B30608F4B9CF8928E1F432E043165104F4 +:10098000F0F0DA82C982440C551CB20180E090E09C +:100990002D813E814F815885620F731F841F951FE3 +:1009A000AE014F5F5F4F22E030E0F10109958823EF +:1009B00031F4C301B6010E94B903CC24DD24C60181 +:1009C0002A960FB6F894DEBF0FBECDBFCF91DF9150 +:1009D0001F910F91FF90EF90DF90CF90BF90AF905D +:1009E0009F908F907F906F905F904F903F902F904F +:1009F000089580E190E00895FC01009711F01182C4 +:100A0000108208952F923F924F925F926F927F9241 +:100A10008F929F92AF92BF92CF92DF92EF92FF920E +:100A20000F931F93DF93CF93CDB7DEB72A970FB6FF +:100A3000F894DEBF0FBECDBF2C017A8369835C833F +:100A40004B83009709F409C1672B09F406C1452BB4 +:100A500009F403C1DC019D96AD90BD90CD90DC9072 +:100A6000D09795962D913D914D915C919897EB8102 +:100A7000FC81CF01A0E0B0E08A0D9B1DAC1DBD1D27 +:100A8000281739074A075B0740F4B9016A197B093F +:100A90007C836B83672B09F4E3C0D201ED91FC9159 +:100AA000119720883188D196ED91FC91D297FA87E1 +:100AB000E987EF2BF1F593962D913C9194973A8726 +:100AC0002987232B39F4A114B104C104D10409F4FA +:100AD000C7C0C3C0A114B104C104D10451F186013F +:100AE000750131018824992466277727CB0166197F +:100AF0007709880999096D837E838F83988714C04D +:100B0000D2018D919C9169857A850E9479039A879B +:100B10008987892B09F4A1C06D817E818F81988599 +:100B2000E60EF71E081F191FE614F704080519053D +:100B300038F7089421083108A220B3200894211C1A +:100B4000311CCB80DC80D201ED90FC90E114F104EB +:100B500009F1E985FA85E230F105E0F03297BF014D +:100B600080E090E03296FA87E987D70150962D9180 +:100B70003C91519740E050E00E94301A9B01AC013B +:100B8000F70182899389A489B589280F391F4A1FE3 +:100B90005B1F04C020E030E040E050E081010A1912 +:100BA0001B09C016D10608F48601D701ED91FC910E +:100BB000C501A0E0B0E0280F391F4A1F5B1F01905C +:100BC000F081E02DCA01B90149815A819801099546 +:100BD000882341F1C01AD10AC801A0E0B0E0F201B7 +:100BE00025A536A547A550A9280F391F4A1F5B1F09 +:100BF000D2019D962D933D934D935C93D097C80160 +:100C00008A0D9B1D82159305A0F08D919C9169859D +:100C10007A850E9479039A878987892B41F4F201AA +:100C200012AA11AA4B815C814C195D091BC0AA2430 +:100C3000BB24E985FA85D201D296FC93EE93D19735 +:100C4000C114D10439F029813A81200F311F3A8330 +:100C5000298379CF4B815C8105C04FEF5FEF02C0E4 +:100C600040E050E0CA012A960FB6F894DEBF0FBEEE +:100C7000CDBFCF91DF911F910F91FF90EF90DF904B +:100C8000CF90BF90AF909F908F907F906F905F902C +:100C90004F903F902F900895FC01009711F480E051 +:100CA000089583A194A196A785A710AA17A681E00D +:100CB0000895CF92DF92EF92FF920F931F93CF93FD +:100CC000DF938C016A017B01A901D901CD91DC91EF +:100CD000119712968D919C911397809613969C93E1 +:100CE0008E931297F8018081853E09F4BAC088235B +:100CF00009F4B7C08FA198A5A9A5BAA50097A10529 +:100D0000B10521F4CFA2D8A6E9A6FAA6209709F446 +:100D1000AAC00115110509F4A6C0D8019C91992318 +:100D200009F4A1C01B968C918F30A1F5892F90E01A +:100D30008F7390702DE030E0829FA001839F500D53 +:100D4000929F500D11244D50504010922702109246 +:100D5000260211C0AC0FBD1FF901E25FFD4F80817B +:100D6000F801E80FF11D80818C932F5F3F4F309386 +:100D700027022093260220912602309127022D304F +:100D8000310508F06EC0DA01A20FB31FAF31B10513 +:100D900008F367C08881882309F04FC0B801DE01DD +:100DA000780120E0F70190819032A1F09C93F80146 +:100DB000848583FF08C0F7018081813420F08B3562 +:100DC00010F4905E9C932F5F0894E11CF11C119627 +:100DD000283041F78881853011F485EE8883D80169 +:100DE00018968C91803211F4322F23C0FE01E20F4D +:100DF000F11D8EE28083322F3F5F2C5FFB019085D7 +:100E00009032B9F0FE01E30FF11D9083D8011C96DA +:100E10008C9184FF09C0DB0118968C91813420F0FD +:100E20008B3510F4905E90833F5F6F5F7F4F32177A +:100E300029F7FE01E30FF11D1082F801838588A3D5 +:100E4000828D938D9AA389A3848D958DA68DB78D60 +:100E50008BA39CA3ADA3BEA381E0DA0114968C936F +:100E600002C081E001C080E0DF91CF911F910F911E +:100E7000FF90EF90DF90CF9008957F928F929F9296 +:100E8000AF92BF92CF92DF92EF92FF920F931F9398 +:100E9000DF93CF93CDB7DEB72C970FB6F894DEBFB4 +:100EA0000FBECDBF6C015B01009709F453C0611503 +:100EB000710509F44FC0DB019796ED90FD900D91FF +:100EC0001C919A97E114F1040105110509F442C03F +:100ED0004E010894811C911C75EE772ED601ED9180 +:100EE000FC910190F081E02DC801B701A4012CE034 +:100EF00030E00995882371F17982D601ED91FC915A +:100F00000480F581E02DC801B701A4012CE030E098 +:100F100009958823F9F08C858F3049F480E290E0C0 +:100F2000A0E0B0E0E80EF91E0A1F1B1FD7CFD501C5 +:100F300091966D917C9192976115710539F0C6017A +:100F40000E94B90320E030E0882311F021E030E076 +:100F5000822F01C080E02C960FB6F894DEBF0FBE42 +:100F6000CDBFCF91DF911F910F91FF90EF90DF9058 +:100F7000CF90BF90AF909F908F907F900895CF9229 +:100F8000DF92EF92FF920F931F93DF93CF93CDB732 +:100F9000DEB760970FB6F894DEBF0FBECDBF8C01F1 +:100FA0006230710510F480E035C0009729F440E00C +:100FB00050E060E070E016C06250704080E090E069 +:100FC000F8012089318940E050E00E94301AAB01DD +:100FD000BC01F80182899389A489B589480F591FFA +:100FE0006A1F7B1FDE01119680E1FD0111928A9537 +:100FF000E9F7F8018081918120893189FC01C6805F +:10100000D780CB01BA01AD0109EF14E0EE24FF2433 +:10101000F601099560960FB6F894DEBF0FBECDBFFE +:10102000CF91DF911F910F91FF90EF90DF90CF90C4 +:1010300008952F923F924F925F926F927F928F927C +:101040009F92AF92BF92CF92DF92EF92FF920F9357 +:101050001F93DF93CF93CDB7DEB7A7970FB6F89462 +:10106000DEBF0FBECDBF2C017FA36EA3009709F496 +:10107000B1C06115710509F4ADC0DC018D909C9083 +:101080001197F401208831889D96AD90BC909E9771 +:101090009F966D907C90D0978BE2DB011D928A9594 +:1010A000E9F7FE01319685E0DF011D928A95E9F7A7 +:1010B000A114B10409F076C0F4012288338886892E +:1010C0009789281A390A6EC0730100E010E0A11454 +:1010D000B10441F4D40156966D917D918D919C910E +:1010E00059972DC08114910421F1B2E0AB16B104DF +:1010F00000F1EEEFFFEFAE0EBF1EB50180E090E015 +:1011000022E030E0A20EB31ED40150962D913C9106 +:10111000519740E050E00E94301A9B01AC01F4016D +:1011200082899389A489B589280F391F4A1F5B1FBB +:1011300004C020E030E040E050E0CA01B9016E0D8B +:101140007F1D801F911F1C821B82D401ED91FC9199 +:101150008101061917090280F381E02DAE014A5F73 +:101160005F4F20E230E0A9E5EA2EA6E0FA2E6E01FC +:101170000894C11CD11C0995882361F18B819C8145 +:10118000680E791E6214730488F0C401B5010E94D0 +:1011900079035C0166247724009741F4F201A3A04F +:1011A000B4A008C02EA13FA13A8329838D81882352 +:1011B00009F48ACFD2019E96BC92AE929D97D096AA +:1011C0007C926E929F97EEA1FFA18081882319F0F7 +:1011D00081E001C080E0A7960FB6F894DEBF0FBE95 +:1011E000CDBFCF91DF911F910F91FF90EF90DF90D6 +:1011F000CF90BF90AF909F908F907F906F905F90B7 +:101200004F903F902F9008952F923F924F925F9270 +:101210006F927F928F929F92AF92BF92CF92DF9206 +:10122000EF92FF920F931F93DF93CF93CDB7DEB76B +:10123000A8970FB6F894DEBF0FBECDBF98A78FA3B7 +:10124000009709F45CC1DC0114968D919C9115976F +:10125000892B09F454C116968D919C911797892B6F +:1012600009F44DC168C1E8E2F2E08AE1DF011D92B4 +:101270008A95E9F7EFA1F8A5F0932902E0932802F7 +:10128000218432844384548459E0220C331C441C4E +:10129000551C5A95D1F7C201B101655F7F4F8F4F41 +:1012A0009F4F0190F081E02DAE014F5F5F4F29E12C +:1012B00030E00995882309F445C1E981FA81FBA34F +:1012C000EAA32C813D81FB81FCA34E818F8198850F +:1012D0009EA38DA3E985FA856C857D856E887F88C0 +:1012E000888C998C611471048104910431F43097D5 +:1012F00009F428C13F01882499246115710509F476 +:1013000021C1C901A0E0B0E08E8F9F8FA8A3B9A32F +:1013100080E090E0242F30E040E050E00E94301A5E +:101320006A8F7B8F8C8F9D8F840173012E8D3F8DF3 +:1013300048A159A1E21AF30A040B150BE61AF70AA1 +:10134000080B190B8AA19BA101972DA13EA145E095 +:10135000220F331F4A95E1F7820F931F6AA17BA1E9 +:101360000E944F1A80E090E0E61AF70A080B190B6A +:101370008CA1282F30E040E050E0C801B7010E9466 +:10138000761A79018A0195EFE9169FE0F90690E057 +:10139000090790E0190708F4D5C0A5EFEA16AFEFEA +:1013A000FA06A0E00A07A0E01A0728F486E0EFA1F9 +:1013B000F8A5808705C08BE0AFA1B8A518968C93DF +:1013C00088E1EAE2F2E0DF011D928A95E9F7EAA1FD +:1013D000FBA15F01CC24DD24C401B301A60195016A +:1013E0000E94301A60932A0270932B0280932C0281 +:1013F00090932D02C601B5012E8D3F8D48A159A1B4 +:101400000E94301A260E371E481E591E20922E02A8 +:1014100030922F024092300250923102AFA1B8A513 +:1014200018968C91863029F064E070E080E090E0BE +:1014300004C062E070E080E090E022E030E040E054 +:1014400050E0E20EF31E041F151FA80197010E9431 +:10145000301A609332027093330280933402909377 +:1014600035024AA15BA150933702409336025CA13A +:10147000852F90E0DC01EAA1FBA1AE9FC001AF9FE8 +:10148000900DBE9F900D11249093390280933802E5 +:101490006A8D7B8D8C8D9D8DA60195010E94301AE1 +:1014A00020912E0230912F02409130025091310252 +:1014B000620F731F841F951F60933E0270933F025B +:1014C0008093400290934102ADA1BEA19D0140E0F6 +:1014D00050E0B5E0220F331F441F551FBA95D1F7D6 +:1014E000620F731F841F951F60933A0270933B0233 +:1014F00080933C0290933D0228E232E002C020E05B +:1015000030E0C901A8960FB6F894DEBF0FBECDBF7C +:10151000CF91DF911F910F91FF90EF90DF90CF90CF +:10152000BF90AF909F908F907F906F905F904F9003 +:101530003F902F9008958091280290912902892B45 +:10154000F1F691CE1092290210922802D8CF2F9254 +:101550003F924F925F926F927F928F929F92AF9243 +:10156000BF92CF92DF92EF92FF920F931F93DF9380 +:10157000CF9300D00F92CDB7DEB71C019B0100972F +:1015800009F4D2C04115510509F4CEC0FA01019009 +:101590000020E9F7E41BF50BCF010B966DE070E03E +:1015A0000E944F1A862F8F5F8B83D90193964D909F +:1015B0005C9094974114510451F0AA24BB24650116 +:1015C000EE24FF2487016624772443010BC0F10138 +:1015D000E688F788008D118D6288738884889588E5 +:1015E000570168011A82E614F7040805190509F085 +:1015F0006EC04114510409F497C0E114F1040105CF +:10160000110589F1C101B2010E947903009751F5DA +:10161000C101B20141E050E00E942F048C0100970B +:1016200009F482C002501040B80180E090E00E5FE3 +:101630001F4FD10150962D913C91519740E050E0C1 +:101640000E94301A5B016C01F10182899389A4899F +:10165000B589A80EB91ECA1EDB1EC101B8010E94C1 +:10166000BF0765C02C01F2E04F16510420F4EE24B0 +:10167000FF2487011DC02EEF3FEF420E531EB20123 +:1016800080E090E0A2E0B0E04A0E5B1EF10120890C +:10169000318940E050E00E94301A7B018C01F10159 +:1016A00082899389A489B589E80EF91E0A1F1B1F38 +:1016B000D10150968D919C9151973C018824992499 +:1016C0006E0C7F1C801E911E570168011A82D10189 +:1016D000ED91FC910190F081E02DC801B701AE01C0 +:1016E0004F5F5F4F21E030E009958823E9F0898161 +:1016F000853E11F0882379F4BA81BF5FBA83EB810C +:10170000BE17A8F480E290E0A0E0B0E0E80EF91E79 +:101710000A1F1B1F68CF80E290E0A0E0B0E0E80E57 +:10172000F91E0A1F1B1F5CCFAA24BB246501B5014B +:10173000C6010F900F900F90CF91DF911F910F91E5 +:10174000FF90EF90DF90CF90BF90AF909F908F90E1 +:101750007F906F905F904F903F902F9008953F92B1 +:101760004F925F926F927F928F929F92AF92BF92B1 +:10177000CF92DF92EF92FF920F931F93DF93CF935D +:10178000CDB7DEB7A0970FB6F894DEBF0FBECDBFC2 +:10179000FC018B01009709F424C16115710509F45E +:1017A00020C10190F081E02D44805580DB019796A7 +:1017B000AD90BD90CD90DC909A97E62E912EFB01D6 +:1017C00001900020E9F73197FE2EF61A8F2D90E058 +:1017D0000C966DE070E00E94631A762ECE010196A1 +:1017E00060E270E04BE050E00E949500C8016EE2BC +:1017F00070E00E94CD00FC010097E1F09C012F5F9A +:101800003F4F81818823B1F0D9010D900020E9F785 +:101810001197A21BB30B8A2F8095F80EBE01675F4C +:101820007F4F4A2FA43008F043E0CB01B90150E0CC +:101830000E948C00CE010196B8E0BF1588F06E2D95 +:10184000792D4F2D50E00E948C00F80180818E325E +:1018500031F581818E3209F482818823F9F01FC02D +:10186000DC018E2D992D9C01F90188E001900D92EB +:101870008150E1F7D80191968C91982F92959F70A5 +:10188000803A10F4905D01C09F598F708A3010F437 +:10189000805D01C08F599F83888701C0772489812B +:1018A000853E11F485E0898385E1FE013C96DF01E8 +:1018B0001D928A95E9F7F80180A18C8781A192A1F8 +:1018C0009C8F8B8F83A194A1A5A1B6A18D8F9E8F94 +:1018D000AF8FB8A3672D70E0E5E0660F771FEA953C +:1018E000E1F780E090E06A0D7B1D8C1D9D1DAE012F +:1018F0004F5F5F4F20E230E0F2010995882309F441 +:1019000070C0E98081E090E09093270280932602E6 +:10191000FE01329621E030E00AC08E2D8695E794D4 +:10192000EE24E794E82A8191E80E2F5F3F4F2B3099 +:10193000310598F33093270220932602F72C4E01AD +:101940000894811C911C7DE0372E6FE0662E44C008 +:10195000C4016FEF70E040E250E00E949500F39CFC +:10196000D00111241D97A00FB11F91E0F401E90FE0 +:10197000F11D8C918083892F8F5FF401E80FF11D99 +:1019800010829E5F9B3019F09A3121F402C09EE0D4 +:1019900001C09CE18C91882321F09F3110F41196B5 +:1019A000E5CFF982F71419F48F2D806489836C8652 +:1019B000EE861D861B8E1C8EC601B501A40120E299 +:1019C00030E0F201099580E290E0A0E0B0E0A80EDE +:1019D000B91ECA1EDB1EFA94FF2009F0B9CF81E0C0 +:1019E00001C080E0A0960FB6F894DEBF0FBECDBF59 +:1019F000CF91DF911F910F91FF90EF90DF90CF90EB +:101A0000BF90AF909F908F907F906F905F904F901E +:101A10003F900895AF92BF92CF92DF92EF92FF92E4 +:101A20000F931F93CF93DF938C017B01EA01009703 +:101A300009F448C06115710509F444C0FB018081B7 +:101A4000882309F43FC041155105E1F1B42EAD2EB4 +:101A5000C801BE010E941908882379F0C7016B2DC7 +:101A60007A2D0E94A700009799F7F80183A194A10D +:101A700096A785A710AA17A625C0F801C080D18017 +:101A80008BE2FE0111928A95E9F78B2D9A2DB70111 +:101A90004FE150E00E94BE00C601B801AE010E94B5 +:101AA000A70A6FA378A789A79AA761157105810571 +:101AB000910541F0C601BE010E94AF0B882319F0C9 +:101AC00081E001C080E0DF91CF911F910F91FF90E5 +:101AD000EF90DF90CF90BF90AF9008954F925F92BC +:101AE0006F927F928F929F92AF92BF92CF92DF922E +:101AF000EF92FF920F931F93DF93CF93CDB7DEB793 +:101B00002A970FB6F894DEBF0FBECDBF2C015A0145 +:101B10006B01009709F4E5C0DC0193960D911C91CF +:101B20009497ED91FC91208931890115110599F067 +:101B3000AB82BC82CD82DE8239018824992422279F +:101B40003327A90126193709480959092F833887EE +:101B500049875A8720C0411551056105710509F46F +:101B6000A9C0E6CFD2018D919C91B8010E94790362 +:101B70000097D9F0EB80FC800D811E812F81388584 +:101B800049855A85E20EF31E041F151FEB82FC8265 +:101B90000D831E838C018B819C81AD81BE81681673 +:101BA00079068A069B06F0F2B4C078016B817C81CD +:101BB0008D819E81660D771D881D991D6150704035 +:101BC00080409040A40193010E94761AD2018D9129 +:101BD0009C91B801A9010E942F04009709F481C0CB +:101BE000012B21F4F20194A383A37C01D2019596E9 +:101BF000AD92BD92CD92DC929897A114B104C1042C +:101C0000D10421F494961C921E929397F201819133 +:101C10009191BF010E94AF0B882309F462C0A11407 +:101C2000B104C104D10429F4F20180819181B7018A +:101C30003FC00B811C812D813E816016710682069A +:101C40009306C0F1D2010D911C910115110591F17E +:101C5000B2E0EB16F10470F1C801B7010E947903FC +:101C60004C018FEF9FEF9A838983D801ED91FC910E +:101C70001197EE0CFF1CB70180E090E016962D91B5 +:101C80003D914D915C911997620F731F841F951FB1 +:101C90000480F581E02DAE014F5F5F4F22E030E020 +:101CA0000995882339F08114910421F0C801B40109 +:101CB0000E94B903F20185A596A5A7A5B0A9A8160B +:101CC000B906CA06DB0658F4D2019D96AD92BD92C4 +:101CD000CD92DC92D097D2961C921E92D19781E041 +:101CE00001C080E02A960FB6F894DEBF0FBECDBFCC +:101CF000CF91DF911F910F91FF90EF90DF90CF90E8 +:101D0000BF90AF909F908F907F906F905F904F901B +:101D1000089578010115110509F448CF67CFCF92D6 +:101D2000DF92EF92FF920F931F93CF93DF93EC011B +:101D30006B01009709F445C06115710509F441C0B4 +:101D40008DA59EA5AFA5B8A9413059F0413018F036 +:101D50004230B9F50CC0FB01E080F18002811381B3 +:101D600013C0FB01E080F1800281138109C0FB01F7 +:101D7000E080F180028113818DA19EA1AFA1B8A561 +:101D8000E80EF91E0A1F1B1F8DA19EA1AFA1B8A5C9 +:101D90008E159F05A007B10738F4CE01B801A70141 +:101DA0000E946E0D882369F0EDA6FEA60FA718AB62 +:101DB0001AAA19AAF601E082F1820283138381E054 +:101DC00001C080E0DF91CF911F910F91FF90EF90C4 +:101DD000DF90CF9008952F923F924F925F926F9233 +:101DE0007F928F929F92AF92BF92CF92DF92EF92AB +:101DF000FF920F931F93DF93CF9300D000D000D0BA +:101E0000CDB7DEB79E838D837A8369835C834B83F2 +:101E1000009709F441C1672B09F43EC1452B09F431 +:101E20003BC1DC019D968D909D90AD90BC90D0976C +:101E3000FC0185A196A1A7A1B0A588159905AA05C1 +:101E4000BB0508F429C10190F081E02D208831887C +:101E5000AD81BE81D1960D911C91D29701151105CE +:101E600009F055C093960D911C9194970115110599 +:101E7000A9F481149104A104B10409F00DC1CF01AA +:101E800060E070E041E050E00E942F048C01ED81A1 +:101E9000FE8194A383A3009709F4FEC0AD81BE81A7 +:101EA0009D96CD90DD90ED90FC90D097C114D1041B +:101EB000E104F10421F52BC0C418D508E608F708A1 +:101EC000ED81FE8180819181B8010E9479030097A4 +:101ED00011F08C0117C0C114D104E104F10409F020 +:101EE000DBC0AD81BE818D919C91B80141E050E095 +:101EF0000E942F04009709F4CFC08C0103C0210178 +:101F000066247724C414D504E604F704A8F60894DC +:101F100021083108822093200894211C311CAB80B9 +:101F2000BC80ED81FE81C080D180C114D104F9F064 +:101F300002301105E0F002501040B80180E090E05E +:101F40000E5F1F4FD60150962D913C91519740E066 +:101F500050E00E94301A9B01AC01F60182899389FE +:101F6000A489B589280F391F4A1F5B1F04C020E0D0 +:101F700030E040E050E07101E818F908AE14BF0409 +:101F800008F47501D601ED91FC91C401A0E0B0E028 +:101F9000280F391F4A1F5B1F0480F581E02DCA01FD +:101FA000B90149815A8197010995882309F448C0EC +:101FB000AE18BF08C701A0E0B0E0ED81FE8125A505 +:101FC00036A547A550A9280F391F4A1F5B1F25A713 +:101FD00036A747A750ABC701880D991D82159305F9 +:101FE00008F180819181B8010E947903009711F076 +:101FF0008C0116C0A114B10459F0ED81FE818081DD +:102000009181B80141E050E00E942F04009739F41B +:10201000AD81BE81D2961C921E92D19711C08C01C7 +:1020200088249924ED81FE8112AB01ABA114B10487 +:1020300039F089819A818E0D9F1D9A83898371CF92 +:10204000ED81FE8185A596A5A7A5B0A9E5A0F6A07E +:1020500007A110A5E816F9060A071B07C0F485A317 +:1020600096A3A7A3B0A781919191BF010E94AF0B46 +:10207000882369F4AD81BE819D96AD90BC909E97FA +:10208000AE18BF08FD01E5A6F6A607A710AB4B8169 +:102090005C814A195B0902C04FEF5FEFCA012696C7 +:1020A0000FB6F894DEBF0FBECDBFCF91DF911F9169 +:1020B0000F91FF90EF90DF90CF90BF90AF909F90E7 +:1020C0008F907F906F905F904F903F902F900895EA +:1020D000CF93DF93AC01DB01009789F161157105A6 +:1020E00071F190968C91909784FF29C08091750230 +:1020F00090917602892B19F4E5E7F2E008C080910F +:10210000A6029091A702892BD1F4E6EAF2E09F01A2 +:102110002E5F3F4FBD018BE2EB010990BE01E9014B +:1021200009929E018150C1F75183408391968D9110 +:102130009C91929796A785A710AA17A602C0E0E0E7 +:10214000F0E0CF01DF91CF910895CF93DF939C0111 +:10215000FB01009731F06115710519F080A184FF32 +:1021600023C020E030E0C901DF91CF910895C4E49D +:10217000D2E0DF018BE20D9009928150E1F73093BC +:1021800043022093420210926F021092700210924A +:1021900071021092720281A192A1909374028093B5 +:1021A000730222E432E0DFCF809142029091430239 +:1021B000892BB9F6DCCF6F927F928F929F92AF926C +:1021C000BF92CF92DF92EF92FF920F931F93CF9324 +:1021D000DF934C01EB017A01009709F467C06115A8 +:1021E000710509F463C08881882309F45FC0411533 +:1021F000510509F45BC08F3209F421968BE2F70197 +:1022000011928A95E9F780E1F70180A3370101C0B7 +:10221000E5018881882309F44BC0C401B7010E94FD +:1022200068106C01009709F441C0CE016FE270E0C4 +:102230000E949C00009739F0482F4C1B5C010894C9 +:10224000A11CB11C2AC0FE0101900020E9F73197C2 +:102250004E2F4C1B5E01A40EB11C1FC0F301019058 +:102260000020E9F73197E619F709E017F107B9F40B +:10227000CE01B301A8010E94B000009781F4F601DD +:10228000118210820C0F1D1FF8018081882381F0BC +:10229000F70180A184FDBCCF09C0042F10E0C60166 +:1022A000B7010E9419088823C9F612C080E001C056 +:1022B00081E0DF91CF911F910F91FF90EF90DF9020 +:1022C000CF90BF90AF909F908F907F906F90089528 +:1022D000F601118210829DCF8F929F92AF92BF9292 +:1022E000CF92DF92EF92FF920F93DF93CF93CDB710 +:1022F000DEB760970FB6F894DEBF0FBECDBF7C018E +:102300006B015A014901009709F493C061157105E9 +:1023100009F48FC004300CF08CC007FD1DC0602F85 +:10232000772767FD7095E4E0660F771FEA95E1F780 +:1023300062547E4F882777FD8095982FAE014F5FBE +:102340005F4F20E130E0F7010995882309F471C05F +:102350008D81882309F46DC08091DF02882309F004 +:1023600068C07CC08D818093DF022A8530E040E028 +:1023700050E0542F432F322F22278B8590E0A0E08E +:10238000B0E0DC0199278827282B392B4A2B5B2BBF +:10239000898590E0A0E0B0E0282B392B4A2B5B2BFD +:1023A0008C8590E0A0E0B0E0B82FAA279927882775 +:1023B000282B392B4A2B5B2B2093E0023093E10230 +:1023C0004093E2025093E3022E8530E040E050E07B +:1023D000542F432F322F22278F8590E0A0E0B0E0CA +:1023E000DC0199278827282B392B4A2B5B2B8D85DD +:1023F00090E0A0E0B0E0282B392B4A2B5B2B88899A +:1024000090E0A0E0B0E0B82FAA2799278827282BD2 +:10241000392B4A2B5B2B2093E4023093E502409347 +:10242000E6025093E70203C08FEF8093DF029F0123 +:1024300002C020E030E0C90160960FB6F894DEBF1C +:102440000FBECDBFCF91DF910F91FF90EF90DF9046 +:10245000CF90BF90AF909F908F900895E7EDF2E0FE +:1024600081E1DF011D928A95E9F7F092D802E092AE +:10247000D702D092DA02C092D902B092DC02A092C6 +:10248000DB029092DE028092DD0207FF6BCFCCCFA1 +:10249000282F8FEF8EBD0DB407FEFDCF8DB58F7742 +:1024A0008DBD8EB5822F80648EBD0DB407FEFDCF2D +:1024B0008DB58F778DBD872F9927AA27BB278EBD16 +:1024C0000DB407FEFDCF8DB58F778DBDCB01AA274B +:1024D000BB278EBD0DB407FEFDCF8DB58F778DBDAB +:1024E000BB27A72F962F852F8EBD0DB407FEFDCFDE +:1024F0008DB58F778DBD4EBD0DB407FEFDCF8DB56B +:102500008F778DBD222319F0283069F406C085E944 +:102510008EBD0DB407FEFDCF0BC087E88EBD0DB498 +:1025200007FEFDCF05C08FEF8EBD0DB407FEFDCFBA +:102530008DB58F778DBD1092E9021092E80220E0F0 +:1025400030E09FEF13C09EBD0DB407FEFDCF8DB5EB +:102550008F778DBD8EB5A9014F5F5F4F8F3F29F0FB +:102560003093E9022093E80208959A012A30310558 +:1025700050F33093E9022093E8028FEF08952F92F1 +:102580003F924F925F926F927F928F929F92AF9203 +:10259000BF92CF92DF92EF92FF920F931F93CF9350 +:1025A000DF934B015C012A01390133243A94222440 +:1025B0002394AFC0E401D170CE01A0E0B0E085016A +:1025C0007401E81AF90A0A0B1B0BC12CB2E0DB2ECE +:1025D000CC1ADD0A6C147D0408F463018091EA04CE +:1025E0009091EB04A091EC04B091ED04E816F9068B +:1025F0000A071B07F9F00E94A313882309F48FC070 +:10260000209729F480E0C81682E0D80658F4C80163 +:10261000B7014AEE52E020E032E00E94BD13882369 +:1026200009F47DC0E092EA04F092EB040093EC041C +:102630001093ED048AEE481682E0580671F09E0170 +:1026400026513D4FC901B201A6010E948C00109293 +:10265000EE046C147D0409F460C0289888E1B80188 +:10266000A7010E944812882311F0289A58C08EEFC3 +:102670008EBD0DB407FEFDCF8DB58F778DBD109249 +:10268000E9021092E802EAEEF2E020E030E00BC04E +:1026900080818EBD0DB407FEFDCF31968DB58F774D +:1026A0008DBD2F5F3F4F82E02030380788F3309395 +:1026B000E9022093E8023EBC0DB407FEFDCF8DB5C4 +:1026C0008F778DBD3EBC0DB407FEFDCF8DB58F77E6 +:1026D0008DBD3EBC0DB407FEFDCF8DB58F778DBD92 +:1026E0008EB58F3FB1F78EBD0DB407FEFDCF8DB512 +:1026F0008F778DBD8EB5289A4C0C5D1CC601A0E06D +:10270000B0E0880E991EAA1EBB1E6C187D08209290 +:10271000EE046114710409F04DCF81E001C080E046 +:10272000DF91CF911F910F91FF90EF90DF90CF90AD +:10273000BF90AF909F908F907F906F905F904F90E1 +:102740003F902F9008958091EE04882311F081E04E +:1027500008956091EA047091EB048091EC049091EB +:10276000ED044AEE52E020E032E00E94BF128823DE +:1027700019F081E08093EE0408953F924F925F92AA +:102780006F927F928F929F92AF92BF92CF92DF9281 +:10279000EF92FF920F931F93CF93DF933B014C0176 +:1027A0006A01290133243A9496C01FEFA12E11E04B +:1027B000B12EA620B720C501A0E0B0E084017301CE +:1027C000E81AF90A0A0B1B0BC0E0D2E0CA19DB09B0 +:1027D0004C165D0608F4E2018091EA049091EB0446 +:1027E000A091EC04B091ED04E816F9060A071B0766 +:1027F00009F45EC00E94A313882309F471C02898CD +:1028000081E1B801A7010E944812882319F0289A93 +:1028100080E066C03EBC0DB407FEFDCF8DB58F775E +:102820008DBD8EB58E3FB1F7EAEEF2E020E030E0EC +:102830000BC03EBC0DB407FEFDCF8DB58F778DBDAF +:102840008EB581932F5F3F4F82E02030380788F3A9 +:102850003093E9022093E802E092EA04F092EB045C +:102860000093EC041093ED04950126513D4FC601F1 +:10287000B901AE010E948C003EBC0DB407FEFDCF35 +:102880008DB58F778DBD8EB53EBC0DB407FEFDCFE7 +:102890008DB58F778DBD8EB5289A3EBC0DB407FEE1 +:1028A000FDCFCC0EDD1E8DB58F778DBD8EB50AC0E8 +:1028B000950126513D4FC601B901AE010E948C0021 +:1028C000CC0EDD1E4C1A5D0ACE01A0E0B0E0680E11 +:1028D000791E8A1E9B1E4114510409F066CF81E0C7 +:1028E000DF91CF911F910F91FF90EF90DF90CF90EC +:1028F000BF90AF909F908F907F906F905F904F9020 +:102900003F9008952F923F924F925F926F927F92E5 +:102910008F929F92AF92BF92CF92DF92EF92FF92EF +:102920000F931F93DF93CF9300D000D0CDB7DEB7C6 +:102930004B015C013A013C832B832701DA82C98277 +:1029400041155105A9F12115310591F10217130720 +:1029500078F1E114F10461F1190130942194310806 +:102960003394021B130B6901EE24FF24C501B4014B +:10297000A3012B813C810E94BD138823C9F0C301B0 +:10298000B501A40129813A81F2010995882391F0CA +:10299000020D131D8B819C81800F911F2B813C8127 +:1029A0008217930738F08C0C9D1CAE1CBF1CDECF29 +:1029B00080E001C081E00F900F900F900F90CF91B9 +:1029C000DF911F910F91FF90EF90DF90CF90BF901C +:1029D000AF909F908F907F906F905F904F903F90BF +:1029E0002F9008951F93CF93DF93239A259A209ACF +:1029F00024982C9A289A83E58CBD8DB58E7F8DBD49 +:102A00001092EF0420E030E09FEF0AC09EBD0DB4AD +:102A100007FEFDCF8DB58F778DBD8EB52F5F3F4FF4 +:102A20002A30310598F33093E9022093E802289880 +:102A30001092E9021092E80280E040E050E060E08D +:102A400070E00E944812182F813079F08091E802DE +:102A50009091E90221E08F3F920709F44DC0019661 +:102A60009093E9028093E802E7CF87E340E050E0EB +:102A700060E070E00E94481289E240E050E060E0CF +:102A800070E00E94481282FD02C01093EF04109281 +:102A9000E9021092E8028091EF04C82FD0E0C370E1 +:102AA000D070209749F087E340E050E060E070E0AC +:102AB0000E94481289E201C081E040E050E060E0FD +:102AC00070E00E94481280FF0EC08091E802909151 +:102AD000E9022FE78F3F920779F001969093E90280 +:102AE0008093E802DECF80E140E052E060E070E0F9 +:102AF0000E944812882319F0289A80E022C0289A60 +:102B00008CB58C7F8CBD8DB581608DBD8FEF9FEFB7 +:102B1000AFEFBFEF8093EA049093EB04A093EC0433 +:102B2000B093ED0481E08093EE0460E070E080E01B +:102B300090E04AEE52E020E032E00E94BD138111A5 +:102B400081E0DF91CF911F9108954F925F926F9234 +:102B50007F928F929F92AF92BF92CF92DF92EF922D +:102B6000FF920F931F93CF93DF935B016C014A0198 +:102B7000E901380127014115510571F101151105D0 +:102B800059F1FF242115310511F5FF24F3941FC0DD +:102B9000C401B601A5019201F30109958C010097CA +:102BA000E9F0FF2019F4C817D907B0F0C601B50144 +:102BB000A40198010E94BF12882371F0C801A0E00F +:102BC000B0E0A80EB91ECA1EDB1EC01BD10BFF2031 +:102BD000F9F62097E9F602C080E001C081E0DF91BC +:102BE000CF911F910F91FF90EF90DF90CF90BF900A +:102BF000AF909F908F907F906F905F904F900895CF +:102C00000F930E94F214882309F445C08DEB93E1E1 +:102C100062E874E14FEB52E125EA35E100E00E9401 +:102C20006C119093200580931F05892B89F48DEBFF +:102C300093E162E874E14FEB52E125EA35E10FEFF1 +:102C40000E946C119093200580931F05892B19F128 +:102C500080911F05909120050E94040990931E0504 +:102C600080931D050097B9F060E071E042EF54E0F9 +:102C70000E94DB1080911D0590911E0562EF74E0AB +:102C80000E9468109093F1048093F00420E0892B57 +:102C900019F021E001C020E0822F0F910895EF92FA +:102CA000FF920F931F93CF93DF93EB018A0179017A +:102CB000CB010E944C0608C0C701B8010E94A700C2 +:102CC000009711F481E006C0CE01B7010E941908F7 +:102CD000882391F7DF91CF911F910F91FF90EF9093 +:102CE0000895EF92FF920F931F93DF93CF93CDB789 +:102CF000DEB7AB970FB6F894DEBF0FBECDBF8C0129 +:102D00007E010894E11CF11C97010E944F16882354 +:102D100019F420E030E005C0C801B7010E94A510F9 +:102D20009C01C901AB960FB6F894DEBF0FBECDBFB4 +:102D3000CF91DF911F910F91FF90EF900895CF9267 +:102D4000DF92EF92FF920F931F93CF93DF930E9436 +:102D500000168091F0049091F10462E071E042EF7E +:102D600054E00E940A0D882391F480911D059091F2 +:102D70001E0562EF74E00E943D078091F00490917F +:102D8000F10462E071E042EF54E00E940A0D6091AC +:102D9000F0047091F10480911D0590911E0542E0B0 +:102DA00051E00E94711690932205809321050EE058 +:102DB00011E0F80101900020E9F73197E01BF10BD9 +:102DC000B801AF010E94EB0E0E94A3138091210570 +:102DD000909122050E94FC04C0E0D0E078018BE0D5 +:102DE000C82E81E0D82E6091F0047091F10480919A +:102DF0001D0590911E0542E051E00E9471168091E0 +:102E00002105909122056EE071E040E051E00E94C2 +:102E1000020580EB95E06EE071E00E94251A80913A +:102E200021059091220560E070E042E00E948F0E43 +:102E30008E010F5F1F4F00D000D000D0EDB7FEB75E +:102E40003196ADB7BEB71296FC92EE921197D3822F +:102E5000C282D583C4830E94D800F701019000206C +:102E6000E9F73197EE50F1408DB79EB706960FB651 +:102E7000F8949EBF0FBE8DBF8091210590912205D1 +:102E8000B701AF010E94EB0E0E94A31380912105B0 +:102E9000909122050E94FC0468EE73E080E090E0CF +:102EA0000E94C817E8019FCF80E060E00E942C18C4 +:102EB00081E061E00E942C1880EB95E040E855E24B +:102EC00060E070E00E94891888E061E00E942C18A0 +:102ED0008BE061E00E942C188CE060E00E942C18CE +:102EE0008DE061E00E942C188AE061E00E942C18BD +:102EF00008950E94F2170E9454170E949F16FDCF5A +:102F00001F920F920FB60F9211242F933F938F931E +:102F10009F93AF93BF938091270590912805A0912F +:102F20002905B0912A0530912B050196A11DB11DEF +:102F3000232F2D5F2D3720F02D570196A11DB11D98 +:102F400020932B058093270590932805A0932905AE +:102F5000B0932A058091230590912405A091250521 +:102F6000B09126050196A11DB11D80932305909374 +:102F70002405A0932505B0932605BF91AF919F919D +:102F80008F913F912F910F900FBE0F901F9018952A +:102F9000EF92FF920F931F937B018C018FB7F894F0 +:102FA00040912705509128056091290570912A05C7 +:102FB0008FBF2FB7F8948091270590912805A09195 +:102FC0002905B0912A052FBF841B950BA60BB70BC3 +:102FD000E816F9060A071B0760F71F910F91FF908B +:102FE000EF900895789484B5826084BD84B5816043 +:102FF00084BD85B5826085BD85B5816085BDEEE601 +:10300000F0E0808181608083E1E8F0E0808182608F +:103010008083808181608083E0E8F0E0808181604E +:103020008083E1EBF0E0808184608083E0EBF0E07E +:10303000808181608083EAE7F0E080818460808322 +:1030400080818260808380818160808380818068CC +:1030500080831092C1000895282F30E0C901865660 +:103060009F4FFC0194912A573F4FF9018491882387 +:1030700091F0E82FF0E0EE0FFF1FE859FF4FA59108 +:10308000B491662329F48C91909589238C930895AB +:103090008C91892B8C9308951F920F920FB60F92EB +:1030A00011242F933F934F935F936F937F938F934D +:1030B0009F93AF93BF93EF93FF934091C600E0912E +:1030C000AC05F091AD05CF01019660E870E00E947B +:1030D000631A9C018091AE059091AF0528173907BE +:1030E00039F0E45DFA4F40833093AD052093AC0591 +:1030F000FF91EF91BF91AF919F918F917F916F91D0 +:103100005F914F913F912F910F900FBE0F901F90A5 +:1031100018955F926F927F928F929F92AF92BF921B +:10312000CF92DF92EF92FF920F931F93CF93DF9393 +:10313000EC013A014B01413482E458078FE0680703 +:1031400080E078070CF07FC060E874E88EE190E0E2 +:10315000A40193010E94981A2150304040405040F1 +:10316000CA01B90122E030E040E050E00E94981A24 +:1031700059016A01A6019501209530954095509519 +:1031800094E0220F331F441F551F9A95D1F760E03A +:1031900074E284EF90E00E94981ACA01B9012FEFFF +:1031A00030E040E050E00E94301AA40193010E94F8 +:1031B000981AC90181509F4F181619061CF4522EF7 +:1031C0005A9403C055245394521A60E079E08DE379 +:1031D00090E0A40193010E94981A21503040404091 +:1031E0005040CA01B90122E030E040E050E00E94C6 +:1031F000981A209530954095509583E0220F331F03 +:10320000441F551F8A95D1F760E074E284EF90E087 +:103210000E94981ACA01B9012FEF30E040E050E057 +:103220000E94301AA40193010E94981AC90181508A +:103230009F4F181619061CF4822F815002C081E09E +:10324000821B851500F5E885F98581E090E00A8804 +:1032500002C0880F991F0A94E2F7808360E079E04A +:103260008DE390E0A40193010E94981A2150304010 +:1032700040405040CA01B90122E030E040E050E057 +:103280000E94981A04C0E885F98510829501EC81A6 +:10329000FD813083EE81FF812083EA85FB852081DB +:1032A00041E050E0CA010E8402C0880F991F0A94C1 +:1032B000E2F7282B2083EA85FB852081CA010F8451 +:1032C00002C0880F991F0A94E2F7282B2083EA8511 +:1032D000FB858081088802C0440F551F0A94E2F7DD +:1032E000842B8083DF91CF911F910F91FF90EF90FE +:1032F000DF90CF90BF90AF909F908F907F906F9016 +:103300005F900895FC01A085B18521898C9190E0A2 +:10331000022E02C0959587950A94E2F780FFF6CFBA +:103320000484F585E02D608308958FE192E0909309 +:10333000B1058093B0058CE295E09093B30580933E +:10334000B20585EC90E09093B5058093B40584ECCC +:1033500090E09093B7058093B60580EC90E0909351 +:10336000B9058093B80581EC90E09093BB058093FC +:10337000BA0586EC90E09093BD058093BC0584E08F +:103380008093BE0583E08093BF0587E08093C005EE +:1033900085E08093C10581E08093C20508950F9375 +:1033A0001F93CF93DF938C01EB0109C02196D801C5 +:1033B000ED91FC910190F081E02DC80109956881A3 +:1033C0006623A1F7DF91CF911F910F910895EF929E +:1033D000FF920F931F93CF93DF938C017B01EA0140 +:1033E0000CC0D7016D917D01D801ED91FC91019048 +:1033F000F081E02DC80109952197209791F7DF9181 +:10340000CF911F910F91FF90EF900895DC01ED9106 +:10341000FC910280F381E02D099508950F931F938D +:103420008C01DC01ED91FC910190F081E02D6DE0CB +:103430000995D801ED91FC910190F081E02DC80132 +:103440006AE009951F910F9108950F931F938C01C6 +:103450000E94061AC8010E940E1A1F910F9108952A +:10346000629FD001739FF001829FE00DF11D649F68 +:10347000E00DF11D929FF00D839FF00D749FF00DF4 +:10348000659FF00D9927729FB00DE11DF91F639F95 +:10349000B00DE11DF91FBD01CF0111240895AA1B34 +:1034A000BB1B51E107C0AA1FBB1FA617B70710F02F +:1034B000A61BB70B881F991F5A95A9F78095909561 +:1034C000BC01CD01089597FB092E07260AD077FD90 +:1034D00004D0E5DF06D000201AF4709561957F4F87 +:1034E0000895F6F7909581959F4F0895A1E21A2EC1 +:1034F000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1F98 +:10350000A217B307E407F50720F0A21BB30BE40BE7 +:10351000F50B661F771F881F991F1A9469F760952E +:103520007095809590959B01AC01BD01CF010895E8 +:1035300097FB092E05260ED057FD04D0D7DF0AD001 +:10354000001C38F450954095309521953F4F4F4FD2 +:103550005F4F0895F6F790958095709561957F4F30 +:103560008F4F9F4F0895EE0FFF1F0590F491E02DB0 +:1035700009942F923F924F925F926F927F928F9217 +:103580009F92AF92BF92CF92DF92EF92FF920F93F2 +:103590001F93CF93DF93CDB7DEB7CA1BDB0B0FB6FC +:1035A000F894DEBF0FBECDBF09942A8839884888B9 +:1035B0005F846E847D848C849B84AA84B984C8844F +:1035C000DF80EE80FD800C811B81AA81B981CE0F46 +:1035D000D11D0FB6F894DEBF0FBECDBFED0108952B +:0435E000F894FFCF8D +:1035E4002F00546573742E74787400256400546538 +:1035F4007374696E670A0000000000000000000098 +:1036040000000000000000000000000000000000B6 +:1036140000000000000000000000000000000000A6 +:103624000000000000000000000000000000000096 +:103634000000000000000000000000000000000086 +:103644000000000000000000000000000000000076 +:103654000000000000000000000000000000000066 +:103664000000000000000000000000000000000056 +:103674000000000000000000000000000000000046 +:103684000000000000000000000000000000000036 +:103694000000000000000000000000000000000026 +:1036A4000000000000000000000000000000000016 +:1036B4000000000000000000000000000000000006 +:1036C40000000000000000000000000000000000F6 +:1036D40000000000000000000000000000000000E6 +:1036E40000000000000000000000000000000103D2 +:1036F4000507090E10121416181C1E000000008283 +:0637040019CF19E71900BE +:00000001FF diff --git a/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.o b/FAT16/examples/FAT16_WriteExample/applet/FAT16_WriteExample.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..70062d7ec46e40e17f91bccd56bb8437c8162105 GIT binary patch literal 14604 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 brk^|mTc5?xcFKXd#H|0~^BI%_!zJ_IX#K3p literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/HardwareSerial.cpp.o b/FAT16/examples/FAT16_WriteExample/applet/HardwareSerial.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..d5af08330172ca95dbd3c2941a9a9ad01415a023 GIT binary patch literal 16184 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 literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/WInterrupts.c.o b/FAT16/examples/FAT16_WriteExample/applet/WInterrupts.c.o new file mode 100644 index 0000000000000000000000000000000000000000..52801e41ca39ea2fa8995912d6f46f4594003e65 GIT binary patch literal 5628 zcmcIoZD^a<6+Tz8Y{zyiJ6Y1SO=czal5}Y$$8(q9Wp;^ECt;y6O|x~wLzN}j7TA*W zT6UT;u#>c-8G~BU!oof%qk|2)k-^4bKh~B)VQdWgV;lVw$o4B`bah5n#v1UR=f3Ak z*IKsH!VbRgea^Y(Jonts_m!6(J27gE5hq4YNnI1U(<<^j8V9VyUP;IfG2P}Ceogi#vqXnV~%fT?8cpPd~>Q@q;sH7f~fc-uwx|0 zFvN%*QIj34KVoa)U@IH4W`-CdjACrP2)A7K7AG zVInn^&8Ct`{?Sq>W@i?1c^MfTA5*GPQjPmm|6t9jYH}u;0_5V-D4F zuAya{>U~OFio5 zReAlLt3GS@g{}*&S9&hTFUNlwzueuMst#9AR@2o|b*cJd^`+{y>TA{as%zEdipUDe zrF~}g2I^Im4OiAG?^Rx_T&uiPd9kuoDOJ*yla=90suEv`zZzfZS=sh~WER|UvIa3? zmU=r9R)@*TD4uM0vKzqHzj7Dd`5Kx2-|$H^hgWjJ@0U)5*3^Eqg)f7Ux5?^!a3B;8fWpKnt`4=2_H4|oG5e2mFO080;ESa~ zZgioT9V-WdV@@aw#reWiF`r9haka=ysW_FWncyQwA3vQKNem=ElkAs;`FyZGh#ofP zKLc_7l@F%NGF!r>R`+3q?W#7-`~4ZWj`Z=ff*#&dk1x!MBSt%m{$W?l8w_J2HU2_mGYXr zLEX*TZ_`R*Ja!uWgeLLsa0!H2&y=$3GMrnOD8dJ$^2U(~GR3I|n=^$pn46EX5$}gH z4uLdlQ1~rWXJ8v;CknBBIimh=etXcy4~Y-+v#)IUIU(O0PC@PZ9riGr-$&trcjDk6 z4D|ym^208Xt7!Zr?EGqB8}FVm6c+<1hjG?Tc;2bj+P(nn^BvkGazy#~`Q!L98sp|~ z1P$)GKvRtmZ{Kx%%Xr}&gN^y|i^%bP4Vd{kzDsD>4c&>${VWWOaq=7RJqd+;_%^KZ zeH+;4yM`eD+H!oCH3pTH?Vk`i1Vp}#C@#OB0{eXUlD#Y6k2MCBm8U$uI4q9uRbYR= zWWnc;%jNeL{2V4>4t`uqCobl9FgVP%Z=v6(QF9zv!dkz70rvTR0lo)ebK=^r!{GDX z2A^9uz#8A*fn5wau7mF>0u|TxE_9#o(3WstGQX|b#(mm?02c#Q9>InK8fc@h=gKy`^? zR(M}g7-{URTh%_I_D1k^PHtVo(fK-8tu9e}a(taTzb;X`bA6q&QvD>Jg_>)?*uSD)RGdZq4aHn1u7k0^o<*)G=9>M07_q!}ULnRk zLirgA?JuK#L-E_F|D+g|Fb_j=$e&S&x$f^0E9V`>tEi*s!*IeN_TB{MzUZPI{vQC} zL(CTd#NLI#^!cp%lz=_Ri6tk~0ikZea#T?ps#mwQ7V$K`>fl`~F?<(E}`^$=%&nt=# z0{>hw=jYeNI&b{P3Nd4Uub8oaRLt1xiW$r4iy+A(sJXW{=-e{zHpP7B(Z{`Cod0&% z`5(6=+gUIty{MZNTMoq>FZrYJVXB-yV%o{$`eh%kUvf2R4m?N1NL?O6iD3V5EPZN6 zW$$w5<6@bYi{(4X#v%bfmOcY0jHM5AGJHU`p}2iTPG`60nuCBa*4fGH_W2RdZqK-` z5zIBtCdIo@^NL|#oKL>Xi2G4<{)x$VpJMJq&a>g9LVV1$=uffvYn}<{E;pOMpARPi pV)Iel3f=Lr8)Eir`IXbo74UA@ZC`rExu)!kdn`e$ef27){ohUPtK|Ry literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/WMath.cpp.o b/FAT16/examples/FAT16_WriteExample/applet/WMath.cpp.o new file mode 100644 index 0000000000000000000000000000000000000000..d8792d0391c6e8f516c46ed92a0d602d3fa07516 GIT binary patch literal 7012 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 N4!h0?_lOv`{|P8`R;~a5 literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/pins_arduino.c.o b/FAT16/examples/FAT16_WriteExample/applet/pins_arduino.c.o new file mode 100644 index 0000000000000000000000000000000000000000..c1fa9f5a6f20782b5e4861539495c483cb7d0663 GIT binary patch literal 3056 zcmbVO&ub(_6n@n+lT3DYW8(OeMVZxXOjhm5X2Yrxvua3UBx-QcgGSq)>E222&UBAG zJ*$ZeE26Lm(eK`B;M9`ZEf?gDIa1VNj->a_b?sOCvA5;Cl_r0q3 zs=8iR&Dn*OMIi)f5pd48lEXI9u@46?&0Vm+*4s~lV9*ovc-#6U@u z2kt_*7tsd!QKXVFC?gvu#oHi6NhTdS103_4;!!&+W<0;y?mI5c&#tYiP>URDEgNc0hgxd} zVd^95MGm&ZT<6N_dVbGRqs(T!zomGWg}7R-fcIXAzlKq1Y6Y;tLB{9?Iwa9SnxGpc zx}L^ql8QX}!W0}Y!|DcMWJQ712^`m2 zUAm9n$&jAk?MIURGQ$S_NYlKzj@R-cyKP~;97qP_K-;^04KK1fcJGu7c_n6$8yk5Y zHE@Zp39{?(QSD_#JWPm>wCZCg>Ee_6|679PUw#Mvw z9gROKEgJHCikgHzhjV`wPFx|xhcf&2qTP$8#{kmTFn(m9MEe$CXXE{Vi-pH?JU-oZ zyoZ5#O#HbMy$|pRY%MyT2SQ`^@p=D&?v(L4z}dV%XYyi6N!|@LW(u0+W5nb2YGKH2 z6ix31`wYB{=NTx`Ls;uIu&azsJP+~`V2;6a8bKRE%f@>Z#BboV=y=-JI?ESni%+dY z3On8m$Is4$?SjmGEE%!2%_sX@#=Z{tj*QJmd0L}e+kBa)vbD{z(mCbllidN%FR%4v zctKV`V#3dFC6xm4PNh;n<*cNpT+5?5`=qjYU6EpZArZ8hCyODfz=GU8o(X(AEd1RH6z?n0T+58#fWDlu zDmAVrjjv(64-d!~8uy<@u}msl0zRtnlhAi7Tm%1r!aqUFvjJl#!9S+>v(S#h`@o-4 z_;+YNw>j5-@aGkN0{TtHeDFZtMdLnm=<^9<@LU&PDISWxVGN#Y=U2w)&;NlgD4y$v ii=TP^PKFtyKiAJyieCaAS3K9z=Vkc$SbjdN-^$ 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 A=l}o! literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/wiring_digital.c.o b/FAT16/examples/FAT16_WriteExample/applet/wiring_digital.c.o new file mode 100644 index 0000000000000000000000000000000000000000..02809cee965fb2c44e4dab53cce05b8900f7235f GIT binary patch literal 8276 zcmb`Le{h^d8OL|;k~F_)o3u^S(jV70K+*P+l+boUTdtOt@~b@(5U9cHUG9<`z1+pi zC4~;qf)VK$u_5h9(LskFjx*{E%)lr!=#&wisp5Y{N1Tz&pp1?TP^>7z5WnBuXW#eD zwOD1?$-ev9XPcX=dbeF!lYHpQMp%ztFw*?}l!c8hXyR+_!x@+bsRUz_fr7A5dRTb4%;gb4Dorcn^ z%0Q3msJ^n^wKwQS9jm2I4Rorl)ey$3^}B>>m8$FTT9v9t#dF|-I(XZtX=1i7XP-HN zDlE>mib^%i!BpsbFQyuirlHh-yZpGT9o*4<{jUr?#qq1F`i`x>KRJzuExHS;)r z^9sapkw5B{^_%LIT70n?MKxC-iYCYvCjP-iFk(JJ8lED=h7W8o5`-3U4pnCJC26=j z&W6w|HiRlFZDDKGwpMLx)>@^ms?^oSu

|NylT64{4J%}_S4 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 literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/wiring_pulse.c.o b/FAT16/examples/FAT16_WriteExample/applet/wiring_pulse.c.o new file mode 100644 index 0000000000000000000000000000000000000000..354b096cd4d801ccb3545b3351de996ac06532a0 GIT binary patch literal 6452 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 Z&xKBZTkP58u5HA#RO7KeOhL>x{0C_-2KN8} literal 0 HcmV?d00001 diff --git a/FAT16/examples/FAT16_WriteExample/applet/wiring_shift.c.o b/FAT16/examples/FAT16_WriteExample/applet/wiring_shift.c.o new file mode 100644 index 0000000000000000000000000000000000000000..2f318d06c30fdab697c1313d36a079948805eedb GIT binary patch literal 4084 zcmbVPTWnNC82)FsEtQr+K~PeV#h{?V*{VcHRU~q&N}z$DL@LYKOSeas-RATZXvIiC z#RnrxOT9#6d@#`mNK7nytwsbT--1Ni(kvgMq6sdRAW6hyuWpk^VuQtvWX{fI`Cy-_q#Ktg|V&mFrqWpkC zB=kV)^cdp<)oOkc3XvFw#zX702Hj&UiF&UbNFp&yo9gOA7D|nw)EG*!6v>{|@T(8| zTT<&WQBCP?R2$8t{}yK*c1xn#Dxt45dZLzYFoMWFwymDntd;9(C(!G$5xPBoWR4OId4*ThnmrWOQxwPZ(j~cI>D-Gle zvZqMPm$j7+%@Fin z)`vTa35O_cxRu+C+-mqj!xzoqRzJt+ml}@6T#SWH2+9%okCr*L<%KMAarnycwc+c- zQ^RvdmW^B)xi<2PbHn+}85{q0JdvI^ero)(b9MEFl$!ifH9ImkFj^d)eKs*EW1p*1 z+lx(?m5hy!o*I3AG%@*=a{Jy`({fhi^cr_OF#+Khosft0A1Ry3!CvZWIifGg>>l9K%vTCSugf*A`fSCWt5J_{{ZlC`iw z4vZ*wq*mxk4p@`r4N@9Wha#6Y7{X2b8E6Pi@BGezKu0X8nd`L7PkdT6p8u_v`Dwbpsic|h`R z;7*I7gAVz79L{F2J`+UqkNg-F^+qW^1abNY4+U-(Jn%!_Yf(@*8i>PTh?DK_2P|X< ziWxVX^$Ul^@e3u_sJwDdWtyVol?z6}EKY4-;!!=gUaVJ`8p|{-P2WJa3?FnI>&*4t za&d;vs=_pwz>F>Zcab&3n$x!^c=+B#{M8$W%$|A*g7*m&#zpC4~;n;TH~J4j&2 z+8%>!F-_;uSnZaqtpkdv%tiL%Ft3O4Ht6}p(8lxKg=S*_~$M!pn*Av>l%$QIM| zHuBvL&U{U1c6_IRBz7L?YWNjRCJl`kC_ZxJ~hpE@{y#;Jz0A(|RmJt}TwqeNe zd>_mW*Pre4(o z)R*xKMU96Fex)YlE16uSZ!n`Dp-hHiso?qQu!JmTjZl#`U(P{8$@SO(#2>!Ie9{6(xUjok? z{2us0gTDjsGZ;*c8O$?zk{EXnN#9+-Tx<5nF;MpoF*gJBJ{tAAz&|F2{toc-M*jr( z7e@aG_}2zM3;w;quYvzbY>q=C4v`(hJcD^YZ#OsvoHF=s;8h0S3*2rn*NpEE^Kfl8 z8oVF4)8HQ9E`!U!dkyA%xfcnp1%;%mM)-?wIqtJ10 ztpCQC&$bwT%HZSRoQw76ni8kL3o*=Eq&@)G@2bIrMt>NbdrzMw;IA9(gEtWK0D + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include "byteordering.h" +#include "partition.h" +#include "fat.h" +#include "fat_config.h" +#include "sd-reader_config.h" + +#include + +#include + +#if USE_DYNAMIC_MEMORY + #include +#endif + +/** + * \addtogroup fat FAT support + * + * This module implements FAT16/FAT32 read and write access. + * + * The following features are supported: + * - File names up to 31 characters long. + * - Unlimited depth of subdirectories. + * - Short 8.3 and long filenames. + * - Creating and deleting files. + * - Reading and writing from and to files. + * - File resizing. + * - File sizes of up to 4 gigabytes. + * + * @{ + */ +/** + * \file + * FAT implementation (license: GPLv2 or LGPLv2.1) + * + * \author Roland Riegel + */ + +/** + * \addtogroup fat_config FAT configuration + * Preprocessor defines to configure the FAT implementation. + */ + +/** + * \addtogroup fat_fs FAT access + * Basic functions for handling a FAT filesystem. + */ + +/** + * \addtogroup fat_file FAT file functions + * Functions for managing files. + */ + +/** + * \addtogroup fat_dir FAT directory functions + * Functions for managing directories. + */ + +/** + * @} + */ + +#define FAT16_CLUSTER_FREE 0x0000 +#define FAT16_CLUSTER_RESERVED_MIN 0xfff0 +#define FAT16_CLUSTER_RESERVED_MAX 0xfff6 +#define FAT16_CLUSTER_BAD 0xfff7 +#define FAT16_CLUSTER_LAST_MIN 0xfff8 +#define FAT16_CLUSTER_LAST_MAX 0xffff + +#define FAT32_CLUSTER_FREE 0x00000000 +#define FAT32_CLUSTER_RESERVED_MIN 0x0ffffff0 +#define FAT32_CLUSTER_RESERVED_MAX 0x0ffffff6 +#define FAT32_CLUSTER_BAD 0x0ffffff7 +#define FAT32_CLUSTER_LAST_MIN 0x0ffffff8 +#define FAT32_CLUSTER_LAST_MAX 0x0fffffff + +#define FAT_DIRENTRY_DELETED 0xe5 +#define FAT_DIRENTRY_LFNLAST (1 << 6) +#define FAT_DIRENTRY_LFNSEQMASK ((1 << 6) - 1) + +/* Each entry within the directory table has a size of 32 bytes + * and either contains a 8.3 DOS-style file name or a part of a + * long file name, which may consist of several directory table + * entries at once. + * + * multi-byte integer values are stored little-endian! + * + * 8.3 file name entry: + * ==================== + * offset length description + * 0 8 name (space padded) + * 8 3 extension (space padded) + * 11 1 attributes (FAT_ATTRIB_*) + * + * long file name (lfn) entry ordering for a single file name: + * =========================================================== + * LFN entry n + * ... + * LFN entry 2 + * LFN entry 1 + * 8.3 entry (see above) + * + * lfn entry: + * ========== + * offset length description + * 0 1 ordinal field + * 1 2 unicode character 1 + * 3 3 unicode character 2 + * 5 3 unicode character 3 + * 7 3 unicode character 4 + * 9 3 unicode character 5 + * 11 1 attribute (always 0x0f) + * 12 1 type (reserved, always 0) + * 13 1 checksum + * 14 2 unicode character 6 + * 16 2 unicode character 7 + * 18 2 unicode character 8 + * 20 2 unicode character 9 + * 22 2 unicode character 10 + * 24 2 unicode character 11 + * 26 2 cluster (unused, always 0) + * 28 2 unicode character 12 + * 30 2 unicode character 13 + * + * The ordinal field contains a descending number, from n to 1. + * For the n'th lfn entry the ordinal field is or'ed with 0x40. + * For deleted lfn entries, the ordinal field is set to 0xe5. + */ + +struct fat_header_struct +{ + offset_t size; + + offset_t fat_offset; + uint32_t fat_size; + + uint16_t sector_size; + uint16_t cluster_size; + + offset_t cluster_zero_offset; + + offset_t root_dir_offset; +#if FAT_FAT32_SUPPORT + cluster_t root_dir_cluster; +#endif +}; + +struct fat_fs_struct +{ + struct partition_struct* partition; + struct fat_header_struct header; +}; + +struct fat_file_struct +{ + struct fat_fs_struct* fs; + struct fat_dir_entry_struct dir_entry; + offset_t pos; + cluster_t pos_cluster; +}; + +struct fat_dir_struct +{ + struct fat_fs_struct* fs; + struct fat_dir_entry_struct dir_entry; + cluster_t entry_cluster; + uint16_t entry_offset; +}; + +struct fat_read_dir_callback_arg +{ + struct fat_dir_entry_struct* dir_entry; + uintptr_t bytes_read; + uint8_t finished; +}; + +struct fat_usage_count_callback_arg +{ + cluster_t cluster_count; + uintptr_t buffer_size; +}; + +uint16_t i=0; + +#if !USE_DYNAMIC_MEMORY +static struct fat_fs_struct fat_fs_handles[FAT_FS_COUNT]; +static struct fat_file_struct fat_file_handles[FAT_FILE_COUNT]; +static struct fat_dir_struct fat_dir_handles[FAT_DIR_COUNT]; +#endif + +static uint8_t fat_read_header(struct fat_fs_struct* fs); +static cluster_t fat_get_next_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num); +static offset_t fat_cluster_offset(const struct fat_fs_struct* fs, cluster_t cluster_num); +static uint8_t fat_dir_entry_read_callback(uint8_t* buffer, offset_t offset, void* p); +static uint8_t fat_interpret_dir_entry(struct fat_dir_entry_struct* dir_entry, const uint8_t* raw_entry); + +static uint8_t fat_get_fs_free_16_callback(uint8_t* buffer, offset_t offset, void* p); +#if FAT_FAT32_SUPPORT +static uint8_t fat_get_fs_free_32_callback(uint8_t* buffer, offset_t offset, void* p); +#endif + +#if FAT_WRITE_SUPPORT +static cluster_t fat_append_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num, cluster_t count); +static uint8_t fat_free_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num); +static uint8_t fat_terminate_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num); +static uint8_t fat_clear_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num); +static uintptr_t fat_clear_cluster_callback(uint8_t* buffer, offset_t offset, void* p); +static offset_t fat_find_offset_for_dir_entry(const struct fat_fs_struct* fs, const struct fat_dir_struct* parent, const struct fat_dir_entry_struct* dir_entry); +static uint8_t fat_write_dir_entry(const struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry); +#if FAT_DATETIME_SUPPORT +static void fat_set_file_modification_date(struct fat_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day); +static void fat_set_file_modification_time(struct fat_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec); +#endif +#endif + +/** + * \ingroup fat_fs + * Opens a FAT filesystem. + * + * \param[in] partition Discriptor of partition on which the filesystem resides. + * \returns 0 on error, a FAT filesystem descriptor on success. + * \see fat_close + */ +struct fat_fs_struct* fat_open(struct partition_struct* partition) +{ + if(!partition || +#if FAT_WRITE_SUPPORT + !partition->device_write || + !partition->device_write_interval +#else + 0 +#endif + ) + return 0; + +#if USE_DYNAMIC_MEMORY + struct fat_fs_struct* fs = malloc(sizeof(*fs)); + if(!fs) + return 0; +#else + struct fat_fs_struct* fs = fat_fs_handles; + uint8_t i; + for(i = 0; i < FAT_FS_COUNT; ++i) + { + if(!fs->partition) + break; + + ++fs; + } + if(i >= FAT_FS_COUNT) + return 0; +#endif + + memset(fs, 0, sizeof(*fs)); + + fs->partition = partition; + if(!fat_read_header(fs)) + { +#if USE_DYNAMIC_MEMORY + free(fs); +#else + fs->partition = 0; +#endif + return 0; + } + + return fs; +} + +/** + * \ingroup fat_fs + * Closes a FAT filesystem. + * + * When this function returns, the given filesystem descriptor + * will be invalid. + * + * \param[in] fs The filesystem to close. + * \see fat_open + */ +void fat_close(struct fat_fs_struct* fs) +{ + if(!fs) + return; + +#if USE_DYNAMIC_MEMORY + free(fs); +#else + fs->partition = 0; +#endif +} + +/** + * \ingroup fat_fs + * Reads and parses the header of a FAT filesystem. + * + * \param[inout] fs The filesystem for which to parse the header. + * \returns 0 on failure, 1 on success. + */ +uint8_t fat_read_header(struct fat_fs_struct* fs) +{ + if(!fs) + return 0; + + struct partition_struct* partition = fs->partition; + if(!partition) + return 0; + + /* read fat parameters */ +#if FAT_FAT32_SUPPORT + uint8_t buffer[37]; +#else + uint8_t buffer[25]; +#endif + offset_t partition_offset = (offset_t) partition->offset * 512; + if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer))) + return 0; + + uint16_t bytes_per_sector = ltoh16(*((uint16_t*) &buffer[0x00])); + uint16_t reserved_sectors = ltoh16(*((uint16_t*) &buffer[0x03])); + uint8_t sectors_per_cluster = buffer[0x02]; + uint8_t fat_copies = buffer[0x05]; + uint16_t max_root_entries = ltoh16(*((uint16_t*) &buffer[0x06])); + uint16_t sector_count_16 = ltoh16(*((uint16_t*) &buffer[0x08])); + uint16_t sectors_per_fat = ltoh16(*((uint16_t*) &buffer[0x0b])); + uint32_t sector_count = ltoh32(*((uint32_t*) &buffer[0x15])); +#if FAT_FAT32_SUPPORT + uint32_t sectors_per_fat32 = ltoh32(*((uint32_t*) &buffer[0x19])); + uint32_t cluster_root_dir = ltoh32(*((uint32_t*) &buffer[0x21])); +#endif + + if(sector_count == 0) + { + if(sector_count_16 == 0) + /* illegal volume size */ + return 0; + else + sector_count = sector_count_16; + } +#if FAT_FAT32_SUPPORT + if(sectors_per_fat != 0) + sectors_per_fat32 = sectors_per_fat; + else if(sectors_per_fat32 == 0) + /* this is neither FAT16 nor FAT32 */ + return 0; +#else + if(sectors_per_fat == 0) + /* this is not a FAT16 */ + return 0; +#endif + + /* determine the type of FAT we have here */ + uint32_t data_sector_count = sector_count + - reserved_sectors +#if FAT_FAT32_SUPPORT + - sectors_per_fat32 * fat_copies +#else + - (uint32_t) sectors_per_fat * fat_copies +#endif + - ((max_root_entries * 32 + bytes_per_sector - 1) / bytes_per_sector); + uint32_t data_cluster_count = data_sector_count / sectors_per_cluster; + if(data_cluster_count < 4085) + /* this is a FAT12, not supported */ + return 0; + else if(data_cluster_count < 65525) + /* this is a FAT16 */ + partition->type = PARTITION_TYPE_FAT16; + else + /* this is a FAT32 */ + partition->type = PARTITION_TYPE_FAT32; + + /* fill header information */ + struct fat_header_struct* header = &fs->header; + memset(header, 0, sizeof(*header)); + + header->size = (offset_t) sector_count * bytes_per_sector; + + header->fat_offset = /* jump to partition */ + partition_offset + + /* jump to fat */ + (offset_t) reserved_sectors * bytes_per_sector; + header->fat_size = (data_cluster_count + 2) * (partition->type == PARTITION_TYPE_FAT16 ? 2 : 4); + + header->sector_size = bytes_per_sector; + header->cluster_size = (uint16_t) bytes_per_sector * sectors_per_cluster; + +#if FAT_FAT32_SUPPORT + if(partition->type == PARTITION_TYPE_FAT16) +#endif + { + header->root_dir_offset = /* jump to fats */ + header->fat_offset + + /* jump to root directory entries */ + (offset_t) fat_copies * sectors_per_fat * bytes_per_sector; + + header->cluster_zero_offset = /* jump to root directory entries */ + header->root_dir_offset + + /* skip root directory entries */ + (offset_t) max_root_entries * 32; + } +#if FAT_FAT32_SUPPORT + else + { + header->cluster_zero_offset = /* jump to fats */ + header->fat_offset + + /* skip fats */ + (offset_t) fat_copies * sectors_per_fat32 * bytes_per_sector; + + header->root_dir_cluster = cluster_root_dir; + } +#endif + + return 1; +} + +/** + * \ingroup fat_fs + * Retrieves the next following cluster of a given cluster. + * + * Using the filesystem file allocation table, this function returns + * the number of the cluster containing the data directly following + * the data within the cluster with the given number. + * + * \param[in] fs The filesystem for which to determine the next cluster. + * \param[in] cluster_num The number of the cluster for which to determine its successor. + * \returns The wanted cluster number, or 0 on error. + */ +cluster_t fat_get_next_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num) +{ + if(!fs || cluster_num < 2) + return 0; + +#if FAT_FAT32_SUPPORT + if(fs->partition->type == PARTITION_TYPE_FAT32) + { + /* read appropriate fat entry */ + uint32_t fat_entry; + if(!fs->partition->device_read(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry))) + return 0; + + /* determine next cluster from fat */ + cluster_num = ltoh32(fat_entry); + + if(cluster_num == FAT32_CLUSTER_FREE || + cluster_num == FAT32_CLUSTER_BAD || + (cluster_num >= FAT32_CLUSTER_RESERVED_MIN && cluster_num <= FAT32_CLUSTER_RESERVED_MAX) || + (cluster_num >= FAT32_CLUSTER_LAST_MIN && cluster_num <= FAT32_CLUSTER_LAST_MAX)) + return 0; + } + else +#endif + { + /* read appropriate fat entry */ + uint16_t fat_entry; + if(!fs->partition->device_read(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry))) + return 0; + + /* determine next cluster from fat */ + cluster_num = ltoh16(fat_entry); + + if(cluster_num == FAT16_CLUSTER_FREE || + cluster_num == FAT16_CLUSTER_BAD || + (cluster_num >= FAT16_CLUSTER_RESERVED_MIN && cluster_num <= FAT16_CLUSTER_RESERVED_MAX) || + (cluster_num >= FAT16_CLUSTER_LAST_MIN && cluster_num <= FAT16_CLUSTER_LAST_MAX)) + return 0; + } + + return cluster_num; +} + +#if FAT_WRITE_SUPPORT +/** + * \ingroup fat_fs + * Appends a new cluster chain to an existing one. + * + * Set cluster_num to zero to create a completely new one. + * + * \param[in] fs The file system on which to operate. + * \param[in] cluster_num The cluster to which to append the new chain. + * \param[in] count The number of clusters to allocate. + * \returns 0 on failure, the number of the first new cluster on success. + */ +cluster_t fat_append_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num, cluster_t count) +{ + if(!fs) + return 0; + + device_read_t device_read = fs->partition->device_read; + device_write_t device_write = fs->partition->device_write; + offset_t fat_offset = fs->header.fat_offset; + cluster_t count_left = count; + cluster_t cluster_next = 0; + cluster_t cluster_max; + uint16_t fat_entry16; +#if FAT_FAT32_SUPPORT + uint32_t fat_entry32; + uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32); + + if(is_fat32) + cluster_max = fs->header.fat_size / sizeof(fat_entry32); + else +#endif + cluster_max = fs->header.fat_size / sizeof(fat_entry16); + + cluster_t cluster_new=0; + for(cluster_new = 2; cluster_new < cluster_max; ++cluster_new) + { +#if FAT_FAT32_SUPPORT + if(is_fat32) + { + if(!device_read(fat_offset + cluster_new * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32))) + return 0; + } + else +#endif + { + if(!device_read(fat_offset + cluster_new * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16))) + return 0; + } + +#if FAT_FAT32_SUPPORT + if(is_fat32) + { + /* check if this is a free cluster */ + if(fat_entry32 != HTOL32(FAT32_CLUSTER_FREE)) + continue; + + /* allocate cluster */ + if(cluster_next == 0) + fat_entry32 = HTOL32(FAT32_CLUSTER_LAST_MAX); + else + fat_entry32 = htol32(cluster_next); + + if(!device_write(fat_offset + cluster_new * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32))) + break; + } + else +#endif + { + /* check if this is a free cluster */ + if(fat_entry16 != HTOL16(FAT16_CLUSTER_FREE)) + continue; + + /* allocate cluster */ + if(cluster_next == 0) + fat_entry16 = HTOL16(FAT16_CLUSTER_LAST_MAX); + else + fat_entry16 = htol16((uint16_t) cluster_next); + + if(!device_write(fat_offset + cluster_new * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16))) + break; + } + + cluster_next = cluster_new; + if(--count_left == 0) + break; + } + + do + { + if(count_left > 0) + break; + + /* We allocated a new cluster chain. Now join + * it with the existing one (if any). + */ + if(cluster_num >= 2) + { +#if FAT_FAT32_SUPPORT + if(is_fat32) + { + fat_entry32 = htol32(cluster_next); + + if(!device_write(fat_offset + cluster_num * sizeof(fat_entry32), (uint8_t*) &fat_entry32, sizeof(fat_entry32))) + break; + } + else +#endif + { + fat_entry16 = htol16((uint16_t) cluster_next); + + if(!device_write(fat_offset + cluster_num * sizeof(fat_entry16), (uint8_t*) &fat_entry16, sizeof(fat_entry16))) + break; + } + } + + return cluster_next; + + } while(0); + + /* No space left on device or writing error. + * Free up all clusters already allocated. + */ + fat_free_clusters(fs, cluster_next); + + return 0; +} +#endif + +#if FAT_WRITE_SUPPORT +/** + * \ingroup fat_fs + * Frees a cluster chain, or a part thereof. + * + * Marks the specified cluster and all clusters which are sequentially + * referenced by it as free. They may then be used again for future + * file allocations. + * + * \note If this function is used for freeing just a part of a cluster + * chain, the new end of the chain is not correctly terminated + * within the FAT. Use fat_terminate_clusters() instead. + * + * \param[in] fs The filesystem on which to operate. + * \param[in] cluster_num The starting cluster of the chain which to free. + * \returns 0 on failure, 1 on success. + * \see fat_terminate_clusters + */ +uint8_t fat_free_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num) +{ + if(!fs || cluster_num < 2) + return 0; + + offset_t fat_offset = fs->header.fat_offset; +#if FAT_FAT32_SUPPORT + if(fs->partition->type == PARTITION_TYPE_FAT32) + { + uint32_t fat_entry; + while(cluster_num) + { + if(!fs->partition->device_read(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry))) + return 0; + + /* get next cluster of current cluster before freeing current cluster */ + uint32_t cluster_num_next = ltoh32(fat_entry); + + if(cluster_num_next == FAT32_CLUSTER_FREE) + return 1; + if(cluster_num_next == FAT32_CLUSTER_BAD || + (cluster_num_next >= FAT32_CLUSTER_RESERVED_MIN && + cluster_num_next <= FAT32_CLUSTER_RESERVED_MAX + ) + ) + return 0; + if(cluster_num_next >= FAT32_CLUSTER_LAST_MIN && cluster_num_next <= FAT32_CLUSTER_LAST_MAX) + cluster_num_next = 0; + + /* free cluster */ + fat_entry = HTOL32(FAT32_CLUSTER_FREE); + fs->partition->device_write(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)); + + /* We continue in any case here, even if freeing the cluster failed. + * The cluster is lost, but maybe we can still free up some later ones. + */ + + cluster_num = cluster_num_next; + } + } + else +#endif + { + uint16_t fat_entry; + while(cluster_num) + { + if(!fs->partition->device_read(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry))) + return 0; + + /* get next cluster of current cluster before freeing current cluster */ + uint16_t cluster_num_next = ltoh16(fat_entry); + + if(cluster_num_next == FAT16_CLUSTER_FREE) + return 1; + if(cluster_num_next == FAT16_CLUSTER_BAD || + (cluster_num_next >= FAT16_CLUSTER_RESERVED_MIN && + cluster_num_next <= FAT16_CLUSTER_RESERVED_MAX + ) + ) + return 0; + if(cluster_num_next >= FAT16_CLUSTER_LAST_MIN && cluster_num_next <= FAT16_CLUSTER_LAST_MAX) + cluster_num_next = 0; + + /* free cluster */ + fat_entry = HTOL16(FAT16_CLUSTER_FREE); + fs->partition->device_write(fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry)); + + /* We continue in any case here, even if freeing the cluster failed. + * The cluster is lost, but maybe we can still free up some later ones. + */ + + cluster_num = cluster_num_next; + } + } + + return 1; +} +#endif + +#if FAT_WRITE_SUPPORT +/** + * \ingroup fat_fs + * Frees a part of a cluster chain and correctly terminates the rest. + * + * Marks the specified cluster as the new end of a cluster chain and + * frees all following clusters. + * + * \param[in] fs The filesystem on which to operate. + * \param[in] cluster_num The new end of the cluster chain. + * \returns 0 on failure, 1 on success. + * \see fat_free_clusters + */ +uint8_t fat_terminate_clusters(const struct fat_fs_struct* fs, cluster_t cluster_num) +{ + if(!fs || cluster_num < 2) + return 0; + + /* fetch next cluster before overwriting the cluster entry */ + cluster_t cluster_num_next = fat_get_next_cluster(fs, cluster_num); + + /* mark cluster as the last one */ +#if FAT_FAT32_SUPPORT + if(fs->partition->type == PARTITION_TYPE_FAT32) + { + uint32_t fat_entry = HTOL32(FAT32_CLUSTER_LAST_MAX); + if(!fs->partition->device_write(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry))) + return 0; + } + else +#endif + { + uint16_t fat_entry = HTOL16(FAT16_CLUSTER_LAST_MAX); + if(!fs->partition->device_write(fs->header.fat_offset + cluster_num * sizeof(fat_entry), (uint8_t*) &fat_entry, sizeof(fat_entry))) + return 0; + } + + /* free remaining clusters */ + if(cluster_num_next) + return fat_free_clusters(fs, cluster_num_next); + else + return 1; +} +#endif + +#if FAT_WRITE_SUPPORT +/** + * \ingroup fat_fs + * Clears a single cluster. + * + * The complete cluster is filled with zeros. + * + * \param[in] fs The filesystem on which to operate. + * \param[in] cluster_num The cluster to clear. + * \returns 0 on failure, 1 on success. + */ +uint8_t fat_clear_cluster(const struct fat_fs_struct* fs, cluster_t cluster_num) +{ + if(cluster_num < 2) + return 0; + + offset_t cluster_offset = fat_cluster_offset(fs, cluster_num); + + uint8_t zero[16]; + memset(zero, 0, sizeof(zero)); + return fs->partition->device_write_interval(cluster_offset, + zero, + fs->header.cluster_size, + fat_clear_cluster_callback, + 0 + ); +} +#endif + +#if FAT_WRITE_SUPPORT +/** + * \ingroup fat_fs + * Callback function for clearing a cluster. + */ +uintptr_t fat_clear_cluster_callback(uint8_t* buffer, offset_t offset, void* p) +{ + return 16; +} +#endif + +/** + * \ingroup fat_fs + * Calculates the offset of the specified cluster. + * + * \param[in] fs The filesystem on which to operate. + * \param[in] cluster_num The cluster whose offset to calculate. + * \returns The cluster offset. + */ +offset_t fat_cluster_offset(const struct fat_fs_struct* fs, cluster_t cluster_num) +{ + if(!fs || cluster_num < 2) + return 0; + + return fs->header.cluster_zero_offset + (offset_t) (cluster_num - 2) * fs->header.cluster_size; +} + +/** + * \ingroup fat_file + * Retrieves the directory entry of a path. + * + * The given path may both describe a file or a directory. + * + * \param[in] fs The FAT filesystem on which to search. + * \param[in] path The path of which to read the directory entry. + * \param[out] dir_entry The directory entry to fill. + * \returns 0 on failure, 1 on success. + * \see fat_read_dir + */ +uint8_t fat_get_dir_entry_of_path(struct fat_fs_struct* fs, const char* path, struct fat_dir_entry_struct* dir_entry) +{ + if(!fs || !path || path[0] == '\0' || !dir_entry) + return 0; + + if(path[0] == '/') + ++path; + + /* begin with the root directory */ + memset(dir_entry, 0, sizeof(*dir_entry)); + dir_entry->attributes = FAT_ATTRIB_DIR; + + while(1) + { + if(path[0] == '\0') + return 1; + + struct fat_dir_struct* dd = fat_open_dir(fs, dir_entry); + if(!dd) + break; + + /* extract the next hierarchy we will search for */ + const char* sub_path = strchr(path, '/'); + uint8_t length_to_sep; + if(sub_path) + { + length_to_sep = sub_path - path; + ++sub_path; + } + else + { + length_to_sep = strlen(path); + sub_path = path + length_to_sep; + } + + /* read directory entries */ + while(fat_read_dir(dd, dir_entry)) + { + /* check if we have found the next hierarchy */ + if((strlen(dir_entry->long_name) != length_to_sep || + strncmp(path, dir_entry->long_name, length_to_sep) != 0)) + continue; + + fat_close_dir(dd); + dd = 0; + + if(path[length_to_sep] == '\0') + /* we iterated through the whole path and have found the file */ + return 1; + + if(dir_entry->attributes & FAT_ATTRIB_DIR) + { + /* we found a parent directory of the file we are searching for */ + path = sub_path; + break; + } + + /* a parent of the file exists, but not the file itself */ + return 0; + } + + fat_close_dir(dd); + } + + return 0; +} + +/** + * \ingroup fat_file + * Opens a file on a FAT filesystem. + * + * \param[in] fs The filesystem on which the file to open lies. + * \param[in] dir_entry The directory entry of the file to open. + * \returns The file handle, or 0 on failure. + * \see fat_close_file + */ +struct fat_file_struct* fat_open_file(struct fat_fs_struct* fs, const struct fat_dir_entry_struct* dir_entry) +{ + if(!fs || !dir_entry || (dir_entry->attributes & FAT_ATTRIB_DIR)) + return 0; + +#if USE_DYNAMIC_MEMORY + struct fat_file_struct* fd = malloc(sizeof(*fd)); + if(!fd) + return 0; +#else + struct fat_file_struct* fd = fat_file_handles; + uint8_t i; + for(i = 0; i < FAT_FILE_COUNT; ++i) + { + if(!fd->fs) + break; + + ++fd; + } + if(i >= FAT_FILE_COUNT) + return 0; +#endif + + memcpy(&fd->dir_entry, dir_entry, sizeof(*dir_entry)); + fd->fs = fs; + fd->pos = 0; + fd->pos_cluster = dir_entry->cluster; + + return fd; +} + +/** + * \ingroup fat_file + * Closes a file. + * + * \param[in] fd The file handle of the file to close. + * \see fat_open_file + */ +void fat_close_file(struct fat_file_struct* fd) +{ + if(fd) +#if USE_DYNAMIC_MEMORY + free(fd); +#else + fd->fs = 0; +#endif +} + +/** + * \ingroup fat_file + * Reads data from a file. + * + * The data requested is read from the current file location. + * + * \param[in] fd The file handle of the file from which to read. + * \param[out] buffer The buffer into which to write. + * \param[in] buffer_len The amount of data to read. + * \returns The number of bytes read, 0 on end of file, or -1 on failure. + * \see fat_write_file + */ +intptr_t fat_read_file(struct fat_file_struct* fd, uint8_t* buffer, uintptr_t buffer_len) +{ + /* check arguments */ + if(!fd || !buffer || buffer_len < 1) + return -1; + + /* determine number of bytes to read */ + if(fd->pos + buffer_len > fd->dir_entry.file_size) + buffer_len = fd->dir_entry.file_size - fd->pos; + if(buffer_len == 0) + return 0; + + uint16_t cluster_size = fd->fs->header.cluster_size; + cluster_t cluster_num = fd->pos_cluster; + uintptr_t buffer_left = buffer_len; + uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1)); + + /* find cluster in which to start reading */ + if(!cluster_num) + { + cluster_num = fd->dir_entry.cluster; + + if(!cluster_num) + { + if(!fd->pos) + return 0; + else + return -1; + } + + if(fd->pos) + { + uint32_t pos = fd->pos; + while(pos >= cluster_size) + { + pos -= cluster_size; + cluster_num = fat_get_next_cluster(fd->fs, cluster_num); + if(!cluster_num) + return -1; + } + } + } + + /* read data */ + do + { + /* calculate data size to copy from cluster */ + offset_t cluster_offset = fat_cluster_offset(fd->fs, cluster_num) + first_cluster_offset; + uint16_t copy_length = cluster_size - first_cluster_offset; + if(copy_length > buffer_left) + copy_length = buffer_left; + + /* read data */ + if(!fd->fs->partition->device_read(cluster_offset, buffer, copy_length)) + return buffer_len - buffer_left; + + /* calculate new file position */ + buffer += copy_length; + buffer_left -= copy_length; + fd->pos += copy_length; + + if(first_cluster_offset + copy_length >= cluster_size) + { + /* we are on a cluster boundary, so get the next cluster */ + if((cluster_num = fat_get_next_cluster(fd->fs, cluster_num))) + { + first_cluster_offset = 0; + } + else + { + fd->pos_cluster = 0; + return buffer_len - buffer_left; + } + } + + fd->pos_cluster = cluster_num; + + } while(buffer_left > 0); /* check if we are done */ + + return buffer_len; +} + +/** + * \ingroup fat_file + * Writes data to a file. + * + * The data is written to the current file location. + * + * \param[in] fd The file handle of the file to which to write. + * \param[in] buffer The buffer from which to read the data to be written. + * \param[in] buffer_len The amount of data to write. + * \returns The number of bytes written, 0 on disk full, or -1 on failure. + * \see fat_read_file + */ +intptr_t fat_write_file(struct fat_file_struct* fd, const uint8_t* buffer, uintptr_t buffer_len) +{ + /* check arguments */ + if(!fd || !buffer || buffer_len < 1) + return -1; + if(fd->pos > fd->dir_entry.file_size) + return -1; + + uint16_t cluster_size = fd->fs->header.cluster_size; + cluster_t cluster_num = fd->pos_cluster; + uintptr_t buffer_left = buffer_len; + uint16_t first_cluster_offset = (uint16_t) (fd->pos & (cluster_size - 1)); + + /* find cluster in which to start writing */ + if(!cluster_num) + { + cluster_num = fd->dir_entry.cluster; + + if(!cluster_num) + { + if(!fd->pos) + { + /* empty file */ + fd->dir_entry.cluster = cluster_num = fat_append_clusters(fd->fs, 0, 1); + if(!cluster_num) + return -1; + } + else + { + return -1; + } + } + + if(fd->pos) + { + uint32_t pos = fd->pos; + cluster_t cluster_num_next; + while(pos >= cluster_size) + { + pos -= cluster_size; + cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num); + if(!cluster_num_next && pos == 0) + /* the file exactly ends on a cluster boundary, and we append to it */ + cluster_num_next = fat_append_clusters(fd->fs, cluster_num, 1); + if(!cluster_num_next) + return -1; + + cluster_num = cluster_num_next; + } + } + } + + /* write data */ + do + { + /* calculate data size to write to cluster */ + offset_t cluster_offset = fat_cluster_offset(fd->fs, cluster_num) + first_cluster_offset; + uint16_t write_length = cluster_size - first_cluster_offset; + if(write_length > buffer_left) + write_length = buffer_left; + + /* write data which fits into the current cluster */ + if(!fd->fs->partition->device_write(cluster_offset, buffer, write_length)) + break; + + /* calculate new file position */ + buffer += write_length; + buffer_left -= write_length; + fd->pos += write_length; + + if(first_cluster_offset + write_length >= cluster_size) + { + /* we are on a cluster boundary, so get the next cluster */ + cluster_t cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num); + if(!cluster_num_next && buffer_left > 0) + /* we reached the last cluster, append a new one */ + cluster_num_next = fat_append_clusters(fd->fs, cluster_num, 1); + if(!cluster_num_next) + { + fd->pos_cluster = 0; + break; + } + + cluster_num = cluster_num_next; + first_cluster_offset = 0; + } + + fd->pos_cluster = cluster_num; + + } while(buffer_left > 0); /* check if we are done */ + + /* update directory entry */ + if(fd->pos > fd->dir_entry.file_size) + { + uint32_t size_old = fd->dir_entry.file_size; + + /* update file size */ + fd->dir_entry.file_size = fd->pos; + /* write directory entry */ + if(!fat_write_dir_entry(fd->fs, &fd->dir_entry)) + { + /* We do not return an error here since we actually wrote + * some data to disk. So we calculate the amount of data + * we wrote to disk and which lies within the old file size. + */ + buffer_left = fd->pos - size_old; + fd->pos = size_old; + } + } + + return buffer_len - buffer_left; +} + +/** + * \ingroup fat_file + * Repositions the read/write file offset. + * + * Changes the file offset where the next call to fat_read_file() + * or fat_write_file() starts reading/writing. + * + * If the new offset is beyond the end of the file, fat_resize_file() + * is implicitly called, i.e. the file is expanded. + * + * The new offset can be given in different ways determined by + * the \c whence parameter: + * - \b FAT_SEEK_SET: \c *offset is relative to the beginning of the file. + * - \b FAT_SEEK_CUR: \c *offset is relative to the current file position. + * - \b FAT_SEEK_END: \c *offset is relative to the end of the file. + * + * The resulting absolute offset is written to the location the \c offset + * parameter points to. + * + * \param[in] fd The file decriptor of the file on which to seek. + * \param[in,out] offset A pointer to the new offset, as affected by the \c whence + * parameter. The function writes the new absolute offset + * to this location before it returns. + * \param[in] whence Affects the way \c offset is interpreted, see above. + * \returns 0 on failure, 1 on success. + */ +uint8_t fat_seek_file(struct fat_file_struct* fd, int32_t* offset, uint8_t whence) +{ + if(!fd || !offset) + return 0; + + uint32_t new_pos = fd->pos; + switch(whence) + { + case FAT_SEEK_SET: + new_pos = *offset; + break; + case FAT_SEEK_CUR: + new_pos += *offset; + break; + case FAT_SEEK_END: + new_pos = fd->dir_entry.file_size + *offset; + break; + default: + return 0; + } + + if(new_pos > fd->dir_entry.file_size +#if FAT_WRITE_SUPPORT + && !fat_resize_file(fd, new_pos) +#endif + ) + return 0; + + fd->pos = new_pos; + fd->pos_cluster = 0; + + *offset = (int32_t) new_pos; + return 1; +} + +#if FAT_WRITE_SUPPORT +/** + * \ingroup fat_file + * Resizes a file to have a specific size. + * + * Enlarges or shrinks the file pointed to by the file descriptor to have + * exactly the specified size. + * + * If the file is truncated, all bytes having an equal or larger offset + * than the given size are lost. If the file is expanded, the additional + * bytes are allocated. + * + * \note Please be aware that this function just allocates or deallocates disk + * space, it does not explicitely clear it. To avoid data leakage, this + * must be done manually. + * + * \param[in] fd The file decriptor of the file which to resize. + * \param[in] size The new size of the file. + * \returns 0 on failure, 1 on success. + */ +uint8_t fat_resize_file(struct fat_file_struct* fd, uint32_t size) +{ + if(!fd) + return 0; + + cluster_t cluster_num = fd->dir_entry.cluster; + uint16_t cluster_size = fd->fs->header.cluster_size; + uint32_t size_new = size; + + do + { + if(cluster_num == 0 && size_new == 0) + /* the file stays empty */ + break; + + /* seek to the next cluster as long as we need the space */ + while(size_new > cluster_size) + { + /* get next cluster of file */ + cluster_t cluster_num_next = fat_get_next_cluster(fd->fs, cluster_num); + if(cluster_num_next) + { + cluster_num = cluster_num_next; + size_new -= cluster_size; + } + else + { + break; + } + } + + if(size_new > cluster_size || cluster_num == 0) + { + /* Allocate new cluster chain and append + * it to the existing one, if available. + */ + cluster_t cluster_count = (size_new + cluster_size - 1) / cluster_size; + cluster_t cluster_new_chain = fat_append_clusters(fd->fs, cluster_num, cluster_count); + if(!cluster_new_chain) + return 0; + + if(!cluster_num) + { + cluster_num = cluster_new_chain; + fd->dir_entry.cluster = cluster_num; + } + } + + /* write new directory entry */ + fd->dir_entry.file_size = size; + if(size == 0) + fd->dir_entry.cluster = 0; + if(!fat_write_dir_entry(fd->fs, &fd->dir_entry)) + return 0; + + if(size == 0) + { + /* free all clusters of file */ + fat_free_clusters(fd->fs, cluster_num); + } + else if(size_new <= cluster_size) + { + /* free all clusters no longer needed */ + fat_terminate_clusters(fd->fs, cluster_num); + } + + } while(0); + + /* correct file position */ + if(size < fd->pos) + { + fd->pos = size; + fd->pos_cluster = 0; + } + + return 1; +} +#endif + +/** + * \ingroup fat_dir + * Opens a directory. + * + * \param[in] fs The filesystem on which the directory to open resides. + * \param[in] dir_entry The directory entry which stands for the directory to open. + * \returns An opaque directory descriptor on success, 0 on failure. + * \see fat_close_dir + */ +struct fat_dir_struct* fat_open_dir(struct fat_fs_struct* fs, const struct fat_dir_entry_struct* dir_entry) +{ + if(!fs || !dir_entry || !(dir_entry->attributes & FAT_ATTRIB_DIR)) + return 0; + +#if USE_DYNAMIC_MEMORY + struct fat_dir_struct* dd = malloc(sizeof(*dd)); + if(!dd) + return 0; +#else + struct fat_dir_struct* dd = fat_dir_handles; + uint8_t i; + for(i = 0; i < FAT_DIR_COUNT; ++i) + { + if(!dd->fs) + break; + + ++dd; + } + if(i >= FAT_DIR_COUNT) + return 0; +#endif + + memcpy(&dd->dir_entry, dir_entry, sizeof(*dir_entry)); + dd->fs = fs; + dd->entry_cluster = dir_entry->cluster; + dd->entry_offset = 0; + + return dd; +} + +/** + * \ingroup fat_dir + * Closes a directory descriptor. + * + * This function destroys a directory descriptor which was + * previously obtained by calling fat_open_dir(). When this + * function returns, the given descriptor will be invalid. + * + * \param[in] dd The directory descriptor to close. + * \see fat_open_dir + */ +void fat_close_dir(struct fat_dir_struct* dd) +{ + if(dd) +#if USE_DYNAMIC_MEMORY + free(dd); +#else + dd->fs = 0; +#endif +} + +/** + * \ingroup fat_dir + * Reads the next directory entry contained within a parent directory. + * + * \param[in] dd The descriptor of the parent directory from which to read the entry. + * \param[out] dir_entry Pointer to a buffer into which to write the directory entry information. + * \returns 0 on failure, 1 on success. + * \see fat_reset_dir + */ +uint8_t fat_read_dir(struct fat_dir_struct* dd, struct fat_dir_entry_struct* dir_entry) +{ + if(!dd || !dir_entry) + return 0; + + /* get current position of directory handle */ + struct fat_fs_struct* fs = dd->fs; + const struct fat_header_struct* header = &fs->header; + uint16_t cluster_size = header->cluster_size; + cluster_t cluster_num = dd->entry_cluster; + uint16_t cluster_offset = dd->entry_offset; + struct fat_read_dir_callback_arg arg; + + /* reset directory entry */ + memset(dir_entry, 0, sizeof(*dir_entry)); + + /* reset callback arguments */ + memset(&arg, 0, sizeof(arg)); + arg.dir_entry = dir_entry; + + /* check if we read from the root directory */ + if(cluster_num == 0) + { +#if FAT_FAT32_SUPPORT + if(fs->partition->type == PARTITION_TYPE_FAT32) + cluster_num = header->root_dir_cluster; + else +#endif + cluster_size = header->cluster_zero_offset - header->root_dir_offset; + } + + /* read entries */ + uint8_t buffer[32]; + while(!arg.finished) + { + /* read directory entries up to the cluster border */ + uint16_t cluster_left = cluster_size - cluster_offset; + uint32_t pos = cluster_offset; + if(cluster_num == 0) + pos += header->root_dir_offset; + else + pos += fat_cluster_offset(fs, cluster_num); + + arg.bytes_read = 0; + if(!fs->partition->device_read_interval(pos, + buffer, + sizeof(buffer), + cluster_left, + fat_dir_entry_read_callback, + &arg) + ) + return 0; + + cluster_offset += arg.bytes_read; + + if(cluster_offset >= cluster_size) + { + /* we reached the cluster border and switch to the next cluster */ + cluster_offset = 0; + + /* get number of next cluster */ + if(!(cluster_num = fat_get_next_cluster(fs, cluster_num))) + { + /* directory entry not found, reset directory handle */ + cluster_num = dd->dir_entry.cluster; + break; + } + } + } + + dd->entry_cluster = cluster_num; + dd->entry_offset = cluster_offset; + + return dir_entry->long_name[0] != '\0' ? 1 : 0; +} + +/** + * \ingroup fat_dir + * Resets a directory handle. + * + * Resets the directory handle such that reading restarts + * with the first directory entry. + * + * \param[in] dd The directory handle to reset. + * \returns 0 on failure, 1 on success. + * \see fat_read_dir + */ +uint8_t fat_reset_dir(struct fat_dir_struct* dd) +{ + if(!dd) + return 0; + + dd->entry_cluster = dd->dir_entry.cluster; + dd->entry_offset = 0; + return 1; +} + +/** + * \ingroup fat_fs + * Callback function for reading a directory entry. + */ +uint8_t fat_dir_entry_read_callback(uint8_t* buffer, offset_t offset, void* p) +{ + struct fat_read_dir_callback_arg* arg = p; + struct fat_dir_entry_struct* dir_entry = arg->dir_entry; + + arg->bytes_read += 32; + + /* skip deleted or empty entries */ + if(buffer[0] == FAT_DIRENTRY_DELETED || !buffer[0]) + return 1; + + if(!dir_entry->entry_offset) + dir_entry->entry_offset = offset; + + switch(fat_interpret_dir_entry(dir_entry, buffer)) + { + case 0: /* failure */ + { + return 0; + } + case 1: /* buffer successfully parsed, continue */ + { + return 1; + } + case 2: /* directory entry complete, finish */ + { + arg->finished = 1; + return 0; + } + } + + return 0; +} + +/** + * \ingroup fat_fs + * Interprets a raw directory entry and puts the contained + * information into the directory entry. + * + * For a single file there may exist multiple directory + * entries. All except the last one are lfn entries, which + * contain parts of the long filename. The last directory + * entry is a traditional 8.3 style one. It contains all + * other information like size, cluster, date and time. + * + * \param[in,out] dir_entry The directory entry to fill. + * \param[in] raw_entry A pointer to 32 bytes of raw data. + * \returns 0 on failure, 1 on success and 2 if the + * directory entry is complete. + */ +uint8_t fat_interpret_dir_entry(struct fat_dir_entry_struct* dir_entry, const uint8_t* raw_entry) +{ + if(!dir_entry || !raw_entry || !raw_entry[0]) + return 0; + + char* long_name = dir_entry->long_name; + if(raw_entry[11] == 0x0f) + { + /* Lfn supports unicode, but we do not, for now. + * So we assume pure ascii and read only every + * second byte. + */ + uint16_t char_offset = ((raw_entry[0] & 0x3f) - 1) * 13; + const uint8_t char_mapping[] = { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 }; + for(i = 0; i <= 12 && char_offset + i < sizeof(dir_entry->long_name) - 1; ++i) + long_name[char_offset + i] = raw_entry[char_mapping[i]]; + + return 1; + } + else + { + /* if we do not have a long name, take the short one */ + if(long_name[0] == '\0') + { + uint8_t i; + for(i = 0; i < 8; ++i) + { + if(raw_entry[i] == ' ') + break; + long_name[i] = raw_entry[i]; + + /* Windows NT and later versions do not store LFN entries + * for 8.3 names which have a lowercase basename, extension + * or both when everything else is uppercase. They use two + * extra bits to signal a lowercase basename or extension. + */ + if((raw_entry[12] & 0x08) && raw_entry[i] >= 'A' && raw_entry[i] <= 'Z') + long_name[i] += 'a' - 'A'; + } + if(long_name[0] == 0x05) + long_name[0] = (char) FAT_DIRENTRY_DELETED; + + if(raw_entry[8] != ' ') + { + long_name[i++] = '.'; + + uint8_t j = 8; + for(; j < 11; ++j) + { + if(raw_entry[j] == ' ') + break; + long_name[i] = raw_entry[j]; + + /* See above for the lowercase 8.3 name handling of + * Windows NT and later. + */ + if((raw_entry[12] & 0x10) && raw_entry[j] >= 'A' && raw_entry[j] <= 'Z') + long_name[i] += 'a' - 'A'; + + ++i; + } + } + + long_name[i] = '\0'; + } + + /* extract properties of file and store them within the structure */ + dir_entry->attributes = raw_entry[11]; + dir_entry->cluster = ltoh16(*((uint16_t*) &raw_entry[26])); +#if FAT_FAT32_SUPPORT + dir_entry->cluster |= ((cluster_t) ltoh16(*((uint16_t*) &raw_entry[20]))) << 16; +#endif + dir_entry->file_size = ltoh32(*((uint32_t*) &raw_entry[28])); + +#if FAT_DATETIME_SUPPORT + dir_entry->modification_time = ltoh16(*((uint16_t*) &raw_entry[22])); + dir_entry->modification_date = ltoh16(*((uint16_t*) &raw_entry[24])); +#endif + + return 2; + } +} + +#if FAT_WRITE_SUPPORT +/** + * \ingroup fat_fs + * Searches for space where to store a directory entry. + * + * \param[in] fs The filesystem on which to operate. + * \param[in] parent The directory in which to search. + * \param[in] dir_entry The directory entry for which to search space. + * \returns 0 on failure, a device offset on success. + */ +offset_t fat_find_offset_for_dir_entry(const struct fat_fs_struct* fs, const struct fat_dir_struct* parent, const struct fat_dir_entry_struct* dir_entry) +{ + if(!fs || !dir_entry) + return 0; + + /* search for a place where to write the directory entry to disk */ + uint8_t free_dir_entries_needed = (strlen(dir_entry->long_name) + 12) / 13 + 1; + uint8_t free_dir_entries_found = 0; + cluster_t cluster_num = parent->dir_entry.cluster; + offset_t dir_entry_offset = 0; + offset_t offset = 0; + offset_t offset_to = 0; +#if FAT_FAT32_SUPPORT + uint8_t is_fat32 = (fs->partition->type == PARTITION_TYPE_FAT32); +#endif + + if(cluster_num == 0) + { +#if FAT_FAT32_SUPPORT + if(is_fat32) + { + cluster_num = fs->header.root_dir_cluster; + } + else +#endif + { + /* we read/write from the root directory entry */ + offset = fs->header.root_dir_offset; + offset_to = fs->header.cluster_zero_offset; + dir_entry_offset = offset; + } + } + + while(1) + { + if(offset == offset_to) + { + if(cluster_num == 0) + /* We iterated through the whole root directory and + * could not find enough space for the directory entry. + */ + return 0; + + if(offset) + { + /* We reached a cluster boundary and have to + * switch to the next cluster. + */ + + cluster_t cluster_next = fat_get_next_cluster(fs, cluster_num); + if(!cluster_next) + { + cluster_next = fat_append_clusters(fs, cluster_num, 1); + if(!cluster_next) + return 0; + + /* we appended a new cluster and know it is free */ + dir_entry_offset = fs->header.cluster_zero_offset + + (offset_t) (cluster_next - 2) * fs->header.cluster_size; + + /* clear cluster to avoid garbage directory entries */ + fat_clear_cluster(fs, cluster_next); + + break; + } + cluster_num = cluster_next; + } + + offset = fat_cluster_offset(fs, cluster_num); + offset_to = offset + fs->header.cluster_size; + dir_entry_offset = offset; + free_dir_entries_found = 0; + } + + /* read next lfn or 8.3 entry */ + uint8_t first_char; + if(!fs->partition->device_read(offset, &first_char, sizeof(first_char))) + return 0; + + /* check if we found a free directory entry */ + if(first_char == FAT_DIRENTRY_DELETED || !first_char) + { + /* check if we have the needed number of available entries */ + ++free_dir_entries_found; + if(free_dir_entries_found >= free_dir_entries_needed) + break; + + offset += 32; + } + else + { + offset += 32; + dir_entry_offset = offset; + free_dir_entries_found = 0; + } + } + + return dir_entry_offset; +} +#endif + +#if FAT_WRITE_SUPPORT +/** + * \ingroup fat_fs + * Writes a directory entry to disk. + * + * \note The file name is not checked for invalid characters. + * + * \note The generation of the short 8.3 file name is quite + * simple. The first eight characters are used for the filename. + * The extension, if any, is made up of the first three characters + * following the last dot within the long filename. If the + * filename (without the extension) is longer than eight characters, + * the lower byte of the cluster number replaces the last two + * characters to avoid name clashes. In any other case, it is your + * responsibility to avoid name clashes. + * + * \param[in] fs The filesystem on which to operate. + * \param[in] dir_entry The directory entry to write. + * \returns 0 on failure, 1 on success. + */ +uint8_t fat_write_dir_entry(const struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry) +{ + if(!fs || !dir_entry) + return 0; + +#if FAT_DATETIME_SUPPORT + { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + + fat_get_datetime(&year, &month, &day, &hour, &min, &sec); + fat_set_file_modification_date(dir_entry, year, month, day); + fat_set_file_modification_time(dir_entry, hour, min, sec); + } +#endif + + device_write_t device_write = fs->partition->device_write; + offset_t offset = dir_entry->entry_offset; + const char* name = dir_entry->long_name; + uint8_t name_len = strlen(name); + uint8_t lfn_entry_count = (name_len + 12) / 13; + uint8_t buffer[32]; + + /* write 8.3 entry */ + + /* generate 8.3 file name */ + memset(&buffer[0], ' ', 11); + char* name_ext = strrchr(name, '.'); + if(name_ext && *++name_ext) + { + uint8_t name_ext_len = strlen(name_ext); + name_len -= name_ext_len + 1; + + if(name_ext_len > 3) + name_ext_len = 3; + + memcpy(&buffer[8], name_ext, name_ext_len); + } + + if(name_len <= 8) + { + memcpy(buffer, name, name_len); + + /* For now, we create lfn entries for all files, + * except the "." and ".." directory references. + * This is to avoid difficulties with capitalization, + * as 8.3 filenames allow uppercase letters only. + * + * Theoretically it would be possible to leave + * the 8.3 entry alone if the basename and the + * extension have no mixed capitalization. + */ + if(name[0] == '.' && + ((name[1] == '.' && name[2] == '\0') || + name[1] == '\0') + ) + lfn_entry_count = 0; + } + else + { + memcpy(buffer, name, 8); + + /* Minimize 8.3 name clashes by appending + * the lower byte of the cluster number. + */ + uint8_t num = dir_entry->cluster & 0xff; + + buffer[6] = (num < 0xa0) ? ('0' + (num >> 4)) : ('a' + (num >> 4)); + num &= 0x0f; + buffer[7] = (num < 0x0a) ? ('0' + num) : ('a' + num); + } + if(buffer[0] == FAT_DIRENTRY_DELETED) + buffer[0] = 0x05; + + /* fill directory entry buffer */ + memset(&buffer[11], 0, sizeof(buffer) - 11); + buffer[0x0b] = dir_entry->attributes; +#if FAT_DATETIME_SUPPORT + *((uint16_t*) &buffer[0x16]) = htol16(dir_entry->modification_time); + *((uint16_t*) &buffer[0x18]) = htol16(dir_entry->modification_date); +#endif +#if FAT_FAT32_SUPPORT + *((uint16_t*) &buffer[0x14]) = htol16((uint16_t) (dir_entry->cluster >> 16)); +#endif + *((uint16_t*) &buffer[0x1a]) = htol16(dir_entry->cluster); + *((uint32_t*) &buffer[0x1c]) = htol32(dir_entry->file_size); + + /* write to disk */ + if(!device_write(offset + (uint16_t) lfn_entry_count * 32, buffer, sizeof(buffer))) + return 0; + + /* calculate checksum of 8.3 name */ + uint8_t checksum = buffer[0]; + for(i = 1; i < 11; ++i) + checksum = ((checksum >> 1) | (checksum << 7)) + buffer[i]; + + /* write lfn entries */ + uint8_t lfn_entry=0; + for(lfn_entry = lfn_entry_count; lfn_entry > 0; --lfn_entry) + { + memset(buffer, 0xff, sizeof(buffer)); + + /* set file name */ + const char* long_name_curr = name + (lfn_entry - 1) * 13; + uint8_t i = 1; + while(i < 0x1f) + { + buffer[i++] = *long_name_curr; + buffer[i++] = 0; + + switch(i) + { + case 0x0b: + i = 0x0e; + break; + case 0x1a: + i = 0x1c; + break; + } + + if(!*long_name_curr++) + break; + } + + /* set index of lfn entry */ + buffer[0x00] = lfn_entry; + if(lfn_entry == lfn_entry_count) + buffer[0x00] |= FAT_DIRENTRY_LFNLAST; + + /* mark as lfn entry */ + buffer[0x0b] = 0x0f; + + /* set 8.3 checksum */ + buffer[0x0d] = checksum; + + /* clear reserved bytes */ + buffer[0x0c] = 0; + buffer[0x1a] = 0; + buffer[0x1b] = 0; + + /* write entry */ + device_write(offset, buffer, sizeof(buffer)); + + offset += sizeof(buffer); + } + + return 1; +} +#endif + +/** + * \ingroup fat_file + * Creates a file. + * + * Creates a file and obtains the directory entry of the + * new file. If the file to create already exists, the + * directory entry of the existing file will be returned + * within the dir_entry parameter. + * + * \note The file name is not checked for invalid characters. + * + * \note The generation of the short 8.3 file name is quite + * simple. The first eight characters are used for the filename. + * The extension, if any, is made up of the first three characters + * following the last dot within the long filename. If the + * filename (without the extension) is longer than eight characters, + * the lower byte of the cluster number replaces the last two + * characters to avoid name clashes. In any other case, it is your + * responsibility to avoid name clashes. + * + * \param[in] parent The handle of the directory in which to create the file. + * \param[in] file The name of the file to create. + * \param[out] dir_entry The directory entry to fill for the new file. + * \returns 0 on failure, 1 on success. + * \see fat_delete_file + */ +uint8_t fat_create_file(struct fat_dir_struct* parent, const char* file, struct fat_dir_entry_struct* dir_entry) +{ + if(!parent || !file || !file[0] || !dir_entry) + return 0; + + /* check if the file already exists */ + while(1) + { + if(!fat_read_dir(parent, dir_entry)) + break; + + if(strcmp(file, dir_entry->long_name) == 0) + { + fat_reset_dir(parent); + return 0; + } + } + + struct fat_fs_struct* fs = parent->fs; + + /* prepare directory entry with values already known */ + memset(dir_entry, 0, sizeof(*dir_entry)); + strncpy(dir_entry->long_name, file, sizeof(dir_entry->long_name) - 1); + + /* find place where to store directory entry */ + if(!(dir_entry->entry_offset = fat_find_offset_for_dir_entry(fs, parent, dir_entry))) + return 0; + + /* write directory entry to disk */ + if(!fat_write_dir_entry(fs, dir_entry)) + return 0; + + return 1; +} + +/** + * \ingroup fat_file + * Deletes a file or directory. + * + * If a directory is deleted without first deleting its + * subdirectories and files, disk space occupied by these + * files will get wasted as there is no chance to release + * it and mark it as free. + * + * \param[in] fs The filesystem on which to operate. + * \param[in] dir_entry The directory entry of the file to delete. + * \returns 0 on failure, 1 on success. + * \see fat_create_file + */ +uint8_t fat_delete_file(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry) +{ + if(!fs || !dir_entry) + return 0; + + /* get offset of the file's directory entry */ + offset_t dir_entry_offset = dir_entry->entry_offset; + if(!dir_entry_offset) + return 0; + + uint8_t buffer[12]; + while(1) + { + /* read directory entry */ + if(!fs->partition->device_read(dir_entry_offset, buffer, sizeof(buffer))) + return 0; + + /* mark the directory entry as deleted */ + buffer[0] = FAT_DIRENTRY_DELETED; + + /* write back entry */ + if(!fs->partition->device_write(dir_entry_offset, buffer, sizeof(buffer))) + return 0; + + /* check if we deleted the whole entry */ + if(buffer[11] != 0x0f) + break; + + dir_entry_offset += 32; + } + + /* We deleted the directory entry. The next thing to do is + * marking all occupied clusters as free. + */ + return (dir_entry->cluster == 0 || fat_free_clusters(fs, dir_entry->cluster)); +} + +/** + * \ingroup fat_dir + * Creates a directory. + * + * Creates a directory and obtains its directory entry. + * If the directory to create already exists, its + * directory entry will be returned within the dir_entry + * parameter. + * + * \note The notes which apply to fat_create_file also + * apply to this function. + * + * \param[in] parent The handle of the parent directory of the new directory. + * \param[in] dir The name of the directory to create. + * \param[out] dir_entry The directory entry to fill for the new directory. + * \returns 0 on failure, 1 on success. + * \see fat_delete_dir + */ +uint8_t fat_create_dir(struct fat_dir_struct* parent, const char* dir, struct fat_dir_entry_struct* dir_entry) +{ + if(!parent || !dir || !dir[0] || !dir_entry) + return 0; + + /* check if the file or directory already exists */ + while(fat_read_dir(parent, dir_entry)) + { + if(strcmp(dir, dir_entry->long_name) == 0) + { + fat_reset_dir(parent); + return 0; + } + } + + struct fat_fs_struct* fs = parent->fs; + + /* allocate cluster which will hold directory entries */ + cluster_t dir_cluster = fat_append_clusters(fs, 0, 1); + if(!dir_cluster) + return 0; + + /* clear cluster to prevent bogus directory entries */ + fat_clear_cluster(fs, dir_cluster); + + memset(dir_entry, 0, sizeof(*dir_entry)); + dir_entry->attributes = FAT_ATTRIB_DIR; + + /* create "." directory self reference */ + dir_entry->entry_offset = fs->header.cluster_zero_offset + + (offset_t) (dir_cluster - 2) * fs->header.cluster_size; + dir_entry->long_name[0] = '.'; + dir_entry->cluster = dir_cluster; + if(!fat_write_dir_entry(fs, dir_entry)) + { + fat_free_clusters(fs, dir_cluster); + return 0; + } + + /* create ".." parent directory reference */ + dir_entry->entry_offset += 32; + dir_entry->long_name[1] = '.'; + dir_entry->cluster = parent->dir_entry.cluster; + if(!fat_write_dir_entry(fs, dir_entry)) + { + fat_free_clusters(fs, dir_cluster); + return 0; + } + + /* fill directory entry */ + strncpy(dir_entry->long_name, dir, sizeof(dir_entry->long_name) - 1); + dir_entry->cluster = dir_cluster; + + /* find place where to store directory entry */ + if(!(dir_entry->entry_offset = fat_find_offset_for_dir_entry(fs, parent, dir_entry))) + { + fat_free_clusters(fs, dir_cluster); + return 0; + } + + /* write directory to disk */ + if(!fat_write_dir_entry(fs, dir_entry)) + { + fat_free_clusters(fs, dir_cluster); + return 0; + } + + return 1; +} + +/** + * \ingroup fat_dir + * Deletes a directory. + * + * This is just a synonym for fat_delete_file(). + * If a directory is deleted without first deleting its + * subdirectories and files, disk space occupied by these + * files will get wasted as there is no chance to release + * it and mark it as free. + * + * \param[in] fs The filesystem on which to operate. + * \param[in] dir_entry The directory entry of the directory to delete. + * \returns 0 on failure, 1 on success. + * \see fat_create_dir + */ +#ifdef DOXYGEN +uint8_t fat_delete_dir(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry); +#endif + +#if FAT_DATETIME_SUPPORT +/** + * \ingroup fat_file + * Returns the modification date of a file. + * + * \param[in] dir_entry The directory entry of which to return the modification date. + * \param[out] year The year the file was last modified. + * \param[out] month The month the file was last modified. + * \param[out] day The day the file was last modified. + */ +void fat_get_file_modification_date(const struct fat_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day) +{ + if(!dir_entry) + return; + + *year = 1980 + ((dir_entry->modification_date >> 9) & 0x7f); + *month = (dir_entry->modification_date >> 5) & 0x0f; + *day = (dir_entry->modification_date >> 0) & 0x1f; +} +#endif + +#if FAT_DATETIME_SUPPORT +/** + * \ingroup fat_file + * Returns the modification time of a file. + * + * \param[in] dir_entry The directory entry of which to return the modification time. + * \param[out] hour The hour the file was last modified. + * \param[out] min The min the file was last modified. + * \param[out] sec The sec the file was last modified. + */ +void fat_get_file_modification_time(const struct fat_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec) +{ + if(!dir_entry) + return; + + *hour = (dir_entry->modification_time >> 11) & 0x1f; + *min = (dir_entry->modification_time >> 5) & 0x3f; + *sec = ((dir_entry->modification_time >> 0) & 0x1f) * 2; +} +#endif + +#if (FAT_WRITE_SUPPORT && FAT_DATETIME_SUPPORT) +/** + * \ingroup fat_file + * Sets the modification time of a date. + * + * \param[in] dir_entry The directory entry for which to set the modification date. + * \param[in] year The year the file was last modified. + * \param[in] month The month the file was last modified. + * \param[in] day The day the file was last modified. + */ +void fat_set_file_modification_date(struct fat_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day) +{ + if(!dir_entry) + return; + + dir_entry->modification_date = + ((year - 1980) << 9) | + ((uint16_t) month << 5) | + ((uint16_t) day << 0); +} +#endif + +#if (FAT_WRITE_SUPPORT && FAT_DATETIME_SUPPORT) +/** + * \ingroup fat_file + * Sets the modification time of a file. + * + * \param[in] dir_entry The directory entry for which to set the modification time. + * \param[in] hour The year the file was last modified. + * \param[in] min The month the file was last modified. + * \param[in] sec The day the file was last modified. + */ +void fat_set_file_modification_time(struct fat_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec) +{ + if(!dir_entry) + return; + + dir_entry->modification_time = + ((uint16_t) hour << 11) | + ((uint16_t) min << 5) | + ((uint16_t) sec >> 1) ; +} +#endif + +/** + * \ingroup fat_fs + * Returns the amount of total storage capacity of the filesystem in bytes. + * + * \param[in] fs The filesystem on which to operate. + * \returns 0 on failure, the filesystem size in bytes otherwise. + */ +offset_t fat_get_fs_size(const struct fat_fs_struct* fs) +{ + if(!fs) + return 0; + +#if FAT_FAT32_SUPPORT + if(fs->partition->type == PARTITION_TYPE_FAT32) + return (offset_t) (fs->header.fat_size / 4 - 2) * fs->header.cluster_size; + else +#endif + return (offset_t) (fs->header.fat_size / 2 - 2) * fs->header.cluster_size; +} + +/** + * \ingroup fat_fs + * Returns the amount of free storage capacity on the filesystem in bytes. + * + * \note As the FAT filesystem is cluster based, this function does not + * return continuous values but multiples of the cluster size. + * + * \param[in] fs The filesystem on which to operate. + * \returns 0 on failure, the free filesystem space in bytes otherwise. + */ +offset_t fat_get_fs_free(const struct fat_fs_struct* fs) +{ + if(!fs) + return 0; + + uint8_t fat[32]; + struct fat_usage_count_callback_arg count_arg; + count_arg.cluster_count = 0; + count_arg.buffer_size = sizeof(fat); + + offset_t fat_offset = fs->header.fat_offset; + uint32_t fat_size = fs->header.fat_size; + while(fat_size > 0) + { + uintptr_t length = UINTPTR_MAX - 1; + if(fat_size < length) + length = fat_size; + + if(!fs->partition->device_read_interval(fat_offset, + fat, + sizeof(fat), + length, +#if FAT_FAT32_SUPPORT + (fs->partition->type == PARTITION_TYPE_FAT16) ? + fat_get_fs_free_16_callback : + fat_get_fs_free_32_callback, +#else + fat_get_fs_free_16_callback, +#endif + &count_arg + ) + ) + return 0; + + fat_offset += length; + fat_size -= length; + } + + return (offset_t) count_arg.cluster_count * fs->header.cluster_size; +} + +/** + * \ingroup fat_fs + * Callback function used for counting free clusters in a FAT. + */ +uint8_t fat_get_fs_free_16_callback(uint8_t* buffer, offset_t offset, void* p) +{ + struct fat_usage_count_callback_arg* count_arg = (struct fat_usage_count_callback_arg*) p; + uintptr_t buffer_size = count_arg->buffer_size; + + uintptr_t j=0; + for(j = 0; i < buffer_size; j += 2, buffer += 2) + { + uint16_t cluster = *((uint16_t*) &buffer[0]); + if(cluster == HTOL16(FAT16_CLUSTER_FREE)) + ++(count_arg->cluster_count); + } + + return 1; +} + +#if FAT_FAT32_SUPPORT +/** + * \ingroup fat_fs + * Callback function used for counting free clusters in a FAT32. + */ +uint8_t fat_get_fs_free_32_callback(uint8_t* buffer, offset_t offset, void* p) +{ + struct fat_usage_count_callback_arg* count_arg = (struct fat_usage_count_callback_arg*) p; + uintptr_t buffer_size = count_arg->buffer_size; + + for(i = 0; i < buffer_size; i += 4, buffer += 4) + { + uint32_t cluster = *((uint32_t*) &buffer[0]); + if(cluster == HTOL32(FAT32_CLUSTER_FREE)) + ++(count_arg->cluster_count); + } + + return 1; +} +#endif + diff --git a/FAT16/fat.h b/FAT16/fat.h new file mode 100644 index 0000000..846dccc --- /dev/null +++ b/FAT16/fat.h @@ -0,0 +1,129 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef FAT_H +#define FAT_H + +#include +#include "fat_config.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup fat + * + * @{ + */ +/** + * \file + * FAT header (license: GPLv2 or LGPLv2.1) + * + * \author Roland Riegel + */ + +/** + * \addtogroup fat_file + * @{ + */ + +/** The file is read-only. */ +#define FAT_ATTRIB_READONLY (1 << 0) +/** The file is hidden. */ +#define FAT_ATTRIB_HIDDEN (1 << 1) +/** The file is a system file. */ +#define FAT_ATTRIB_SYSTEM (1 << 2) +/** The file is empty and has the volume label as its name. */ +#define FAT_ATTRIB_VOLUME (1 << 3) +/** The file is a directory. */ +#define FAT_ATTRIB_DIR (1 << 4) +/** The file has to be archived. */ +#define FAT_ATTRIB_ARCHIVE (1 << 5) + +/** The given offset is relative to the beginning of the file. */ +#define FAT_SEEK_SET 0 +/** The given offset is relative to the current read/write position. */ +#define FAT_SEEK_CUR 1 +/** The given offset is relative to the end of the file. */ +#define FAT_SEEK_END 2 + +/** + * @} + */ + +struct partition_struct; +struct fat_fs_struct; +struct fat_file_struct; +struct fat_dir_struct; + +/** + * \ingroup fat_file + * Describes a directory entry. + */ +struct fat_dir_entry_struct +{ + /** The file's name, truncated to 31 characters. */ + char long_name[32]; + /** The file's attributes. Mask of the FAT_ATTRIB_* constants. */ + uint8_t attributes; +#if FAT_DATETIME_SUPPORT + /** Compressed representation of modification time. */ + uint16_t modification_time; + /** Compressed representation of modification date. */ + uint16_t modification_date; +#endif + /** The cluster in which the file's first byte resides. */ + cluster_t cluster; + /** The file's size. */ + uint32_t file_size; + /** The total disk offset of this directory entry. */ + offset_t entry_offset; +}; + +struct fat_fs_struct* fat_open(struct partition_struct* partition); +void fat_close(struct fat_fs_struct* fs); + +struct fat_file_struct* fat_open_file(struct fat_fs_struct* fs, const struct fat_dir_entry_struct* dir_entry); +void fat_close_file(struct fat_file_struct* fd); +intptr_t fat_read_file(struct fat_file_struct* fd, uint8_t* buffer, uintptr_t buffer_len); +intptr_t fat_write_file(struct fat_file_struct* fd, const uint8_t* buffer, uintptr_t buffer_len); +uint8_t fat_seek_file(struct fat_file_struct* fd, int32_t* offset, uint8_t whence); +uint8_t fat_resize_file(struct fat_file_struct* fd, uint32_t size); + +struct fat_dir_struct* fat_open_dir(struct fat_fs_struct* fs, const struct fat_dir_entry_struct* dir_entry); +void fat_close_dir(struct fat_dir_struct* dd); +uint8_t fat_read_dir(struct fat_dir_struct* dd, struct fat_dir_entry_struct* dir_entry); +uint8_t fat_reset_dir(struct fat_dir_struct* dd); + +uint8_t fat_create_file(struct fat_dir_struct* parent, const char* file, struct fat_dir_entry_struct* dir_entry); +uint8_t fat_delete_file(struct fat_fs_struct* fs, struct fat_dir_entry_struct* dir_entry); +uint8_t fat_create_dir(struct fat_dir_struct* parent, const char* dir, struct fat_dir_entry_struct* dir_entry); +#define fat_delete_dir fat_delete_file + +void fat_get_file_modification_date(const struct fat_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day); +void fat_get_file_modification_time(const struct fat_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec); + +uint8_t fat_get_dir_entry_of_path(struct fat_fs_struct* fs, const char* path, struct fat_dir_entry_struct* dir_entry); + +offset_t fat_get_fs_size(const struct fat_fs_struct* fs); +offset_t fat_get_fs_free(const struct fat_fs_struct* fs); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/FAT16/fat_config.h b/FAT16/fat_config.h new file mode 100644 index 0000000..cb053a5 --- /dev/null +++ b/FAT16/fat_config.h @@ -0,0 +1,111 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef FAT_CONFIG_H +#define FAT_CONFIG_H + +#include +#include "sd_raw_config.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup fat + * + * @{ + */ +/** + * \file + * FAT configuration (license: GPLv2 or LGPLv2.1) + */ + +/** + * \ingroup fat_config + * Controls FAT write support. + * + * Set to 1 to enable FAT write support, set to 0 to disable it. + */ +#define FAT_WRITE_SUPPORT 1 + +/** + * \ingroup fat_config + * Controls FAT date and time support. + * + * Set to 1 to enable FAT date and time stamping support. + */ +#define FAT_DATETIME_SUPPORT 0 + +/** + * \ingroup fat_config + * Controls FAT32 support. + * + * Set to 1 to enable FAT32 support. + */ +#define FAT_FAT32_SUPPORT SD_RAW_SDHC +//#define FAT_FAT32_SUPPORT 1 + +/** + * \ingroup fat_config + * Determines the function used for retrieving current date and time. + * + * Define this to the function call which shall be used to retrieve + * current date and time. + * + * \note Used only when FAT_DATETIME_SUPPORT is 1. + * + * \param[out] year Pointer to a \c uint16_t which receives the current year. + * \param[out] month Pointer to a \c uint8_t which receives the current month. + * \param[out] day Pointer to a \c uint8_t which receives the current day. + * \param[out] hour Pointer to a \c uint8_t which receives the current hour. + * \param[out] min Pointer to a \c uint8_t which receives the current minute. + * \param[out] sec Pointer to a \c uint8_t which receives the current sec. + */ +#define fat_get_datetime(year, month, day, hour, min, sec) \ + get_datetime(year, month, day, hour, min, sec) +/* forward declaration for the above */ +void get_datetime(uint16_t* year, uint8_t* month, uint8_t* day, uint8_t* hour, uint8_t* min, uint8_t* sec); + +/** + * \ingroup fat_config + * Maximum number of filesystem handles. + */ +#define FAT_FS_COUNT 1 + +/** + * \ingroup fat_config + * Maximum number of file handles. + */ +#define FAT_FILE_COUNT 1 + +/** + * \ingroup fat_config + * Maximum number of directory handles. + */ +#define FAT_DIR_COUNT 2 + +/** + * @} + */ + +#if FAT_FAT32_SUPPORT + typedef uint32_t cluster_t; +#else + typedef uint16_t cluster_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/FAT16/partition.c b/FAT16/partition.c new file mode 100644 index 0000000..9f1d5b6 --- /dev/null +++ b/FAT16/partition.c @@ -0,0 +1,160 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include "partition.h" +#include "partition_config.h" +#include "sd-reader_config.h" + +#include + +#if USE_DYNAMIC_MEMORY + #include +#endif + +/** + * \addtogroup partition Partition table support + * + * Support for reading partition tables and access to partitions. + * + * @{ + */ +/** + * \file + * Partition table implementation (license: GPLv2 or LGPLv2.1) + * + * \author Roland Riegel + */ + +/** + * \addtogroup partition_config Configuration of partition table support + * Preprocessor defines to configure the partition support. + */ + +#if !USE_DYNAMIC_MEMORY +static struct partition_struct partition_handles[PARTITION_COUNT]; +#endif + +/** + * Opens a partition. + * + * Opens a partition by its index number and returns a partition + * handle which describes the opened partition. + * + * \note This function does not support extended partitions. + * + * \param[in] device_read A function pointer which is used to read from the disk. + * \param[in] device_read_interval A function pointer which is used to read in constant intervals from the disk. + * \param[in] device_write A function pointer which is used to write to the disk. + * \param[in] device_write_interval A function pointer which is used to write a data stream to disk. + * \param[in] index The index of the partition which should be opened, range 0 to 3. + * A negative value is allowed as well. In this case, the partition opened is + * not checked for existance, begins at offset zero, has a length of zero + * and is of an unknown type. Use this in case you want to open the whole device + * as a single partition (e.g. for "super floppy" use). + * \returns 0 on failure, a partition descriptor on success. + * \see partition_close + */ +struct partition_struct* partition_open(device_read_t device_read, device_read_interval_t device_read_interval, device_write_t device_write, device_write_interval_t device_write_interval, int8_t index) +{ + struct partition_struct* new_partition = 0; + uint8_t buffer[0x10]; + + if(!device_read || !device_read_interval || index >= 4) + return 0; + + if(index >= 0) + { + /* read specified partition table index */ + if(!device_read(0x01be + index * 0x10, buffer, sizeof(buffer))) + return 0; + + /* abort on empty partition entry */ + if(buffer[4] == 0x00) + return 0; + } + + /* allocate partition descriptor */ +#if USE_DYNAMIC_MEMORY + new_partition = malloc(sizeof(*new_partition)); + if(!new_partition) + return 0; +#else + new_partition = partition_handles; + uint8_t i; + for(i = 0; i < PARTITION_COUNT; ++i) + { + if(new_partition->type == PARTITION_TYPE_FREE) + break; + + ++new_partition; + } + if(i >= PARTITION_COUNT) + return 0; +#endif + + memset(new_partition, 0, sizeof(*new_partition)); + + /* fill partition descriptor */ + new_partition->device_read = device_read; + new_partition->device_read_interval = device_read_interval; + new_partition->device_write = device_write; + new_partition->device_write_interval = device_write_interval; + + if(index >= 0) + { + new_partition->type = buffer[4]; + new_partition->offset = ((uint32_t) buffer[8]) | + ((uint32_t) buffer[9] << 8) | + ((uint32_t) buffer[10] << 16) | + ((uint32_t) buffer[11] << 24); + new_partition->length = ((uint32_t) buffer[12]) | + ((uint32_t) buffer[13] << 8) | + ((uint32_t) buffer[14] << 16) | + ((uint32_t) buffer[15] << 24); + } + else + { + new_partition->type = 0xff; + } + + return new_partition; +} + +/** + * Closes a partition. + * + * This function destroys a partition descriptor which was + * previously obtained from a call to partition_open(). + * When this function returns, the given descriptor will be + * invalid. + * + * \param[in] partition The partition descriptor to destroy. + * \returns 0 on failure, 1 on success. + * \see partition_open + */ +uint8_t partition_close(struct partition_struct* partition) +{ + if(!partition) + return 0; + + /* destroy partition descriptor */ +#if USE_DYNAMIC_MEMORY + free(partition); +#else + partition->type = PARTITION_TYPE_FREE; +#endif + + return 1; +} + +/** + * @} + */ + diff --git a/FAT16/partition.h b/FAT16/partition.h new file mode 100644 index 0000000..433f1fe --- /dev/null +++ b/FAT16/partition.h @@ -0,0 +1,212 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef PARTITION_H +#define PARTITION_H + +#include +#include "sd_raw_config.h" +#include "partition_config.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup partition + * + * @{ + */ +/** + * \file + * Partition table header (license: GPLv2 or LGPLv2.1) + * + * \author Roland Riegel + */ + +/** + * The partition table entry is not used. + */ +#define PARTITION_TYPE_FREE 0x00 +/** + * The partition contains a FAT12 filesystem. + */ +#define PARTITION_TYPE_FAT12 0x01 +/** + * The partition contains a FAT16 filesystem with 32MB maximum. + */ +#define PARTITION_TYPE_FAT16_32MB 0x04 +/** + * The partition is an extended partition with its own partition table. + */ +#define PARTITION_TYPE_EXTENDED 0x05 +/** + * The partition contains a FAT16 filesystem. + */ +#define PARTITION_TYPE_FAT16 0x06 +/** + * The partition contains a FAT32 filesystem. + */ +#define PARTITION_TYPE_FAT32 0x0b +/** + * The partition contains a FAT32 filesystem with LBA. + */ +#define PARTITION_TYPE_FAT32_LBA 0x0c +/** + * The partition contains a FAT16 filesystem with LBA. + */ +#define PARTITION_TYPE_FAT16_LBA 0x0e +/** + * The partition is an extended partition with LBA. + */ +#define PARTITION_TYPE_EXTENDED_LBA 0x0f +/** + * The partition has an unknown type. + */ +#define PARTITION_TYPE_UNKNOWN 0xff + +/** + * A function pointer used to read from the partition. + * + * \param[in] offset The offset on the device where to start reading. + * \param[out] buffer The buffer into which to place the data. + * \param[in] length The count of bytes to read. + */ +typedef uint8_t (*device_read_t)(offset_t offset, uint8_t* buffer, uintptr_t length); +/** + * A function pointer passed to a \c device_read_interval_t. + * + * \param[in] buffer The buffer which contains the data just read. + * \param[in] offset The offset from which the data in \c buffer was read. + * \param[in] p An opaque pointer. + * \see device_read_interval_t + */ +typedef uint8_t (*device_read_callback_t)(uint8_t* buffer, offset_t offset, void* p); +/** + * A function pointer used to continuously read units of \c interval bytes + * and call a callback function. + * + * This function starts reading at the specified offset. Every \c interval bytes, + * it calls the callback function with the associated data buffer. + * + * By returning zero, the callback may stop reading. + * + * \param[in] offset Offset from which to start reading. + * \param[in] buffer Pointer to a buffer which is at least interval bytes in size. + * \param[in] interval Number of bytes to read before calling the callback function. + * \param[in] length Number of bytes to read altogether. + * \param[in] callback The function to call every interval bytes. + * \param[in] p An opaque pointer directly passed to the callback function. + * \returns 0 on failure, 1 on success + * \see device_read_t + */ +typedef uint8_t (*device_read_interval_t)(offset_t offset, uint8_t* buffer, uintptr_t interval, uintptr_t length, device_read_callback_t callback, void* p); +/** + * A function pointer used to write to the partition. + * + * \param[in] offset The offset on the device where to start writing. + * \param[in] buffer The buffer which to write. + * \param[in] length The count of bytes to write. + */ +typedef uint8_t (*device_write_t)(offset_t offset, const uint8_t* buffer, uintptr_t length); +/** + * A function pointer passed to a \c device_write_interval_t. + * + * \param[in] buffer The buffer which receives the data to write. + * \param[in] offset The offset to which the data in \c buffer will be written. + * \param[in] p An opaque pointer. + * \returns The number of bytes put into \c buffer + * \see device_write_interval_t + */ +typedef uintptr_t (*device_write_callback_t)(uint8_t* buffer, offset_t offset, void* p); +/** + * A function pointer used to continuously write a data stream obtained from + * a callback function. + * + * This function starts writing at the specified offset. To obtain the + * next bytes to write, it calls the callback function. The callback fills the + * provided data buffer and returns the number of bytes it has put into the buffer. + * + * By returning zero, the callback may stop writing. + * + * \param[in] offset Offset where to start writing. + * \param[in] buffer Pointer to a buffer which is used for the callback function. + * \param[in] length Number of bytes to write in total. May be zero for endless writes. + * \param[in] callback The function used to obtain the bytes to write. + * \param[in] p An opaque pointer directly passed to the callback function. + * \returns 0 on failure, 1 on success + * \see device_write_t + */ +typedef uint8_t (*device_write_interval_t)(offset_t offset, uint8_t* buffer, uintptr_t length, device_write_callback_t callback, void* p); + +/** + * Describes a partition. + */ +struct partition_struct +{ + /** + * The function which reads data from the partition. + * + * \note The offset given to this function is relative to the whole disk, + * not to the start of the partition. + */ + device_read_t device_read; + /** + * The function which repeatedly reads a constant amount of data from the partition. + * + * \note The offset given to this function is relative to the whole disk, + * not to the start of the partition. + */ + device_read_interval_t device_read_interval; + /** + * The function which writes data to the partition. + * + * \note The offset given to this function is relative to the whole disk, + * not to the start of the partition. + */ + device_write_t device_write; + /** + * The function which repeatedly writes data to the partition. + * + * \note The offset given to this function is relative to the whole disk, + * not to the start of the partition. + */ + device_write_interval_t device_write_interval; + + /** + * The type of the partition. + * + * Compare this value to the PARTITION_TYPE_* constants. + */ + uint8_t type; + /** + * The offset in blocks on the disk where this partition starts. + */ + uint32_t offset; + /** + * The length in blocks of this partition. + */ + uint32_t length; +}; + +struct partition_struct* partition_open(device_read_t device_read, device_read_interval_t device_read_interval, device_write_t device_write, device_write_interval_t device_write_interval, int8_t index); +uint8_t partition_close(struct partition_struct* partition); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/FAT16/partition_config.h b/FAT16/partition_config.h new file mode 100644 index 0000000..0040378 --- /dev/null +++ b/FAT16/partition_config.h @@ -0,0 +1,44 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef PARTITION_CONFIG_H +#define PARTITION_CONFIG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup partition + * + * @{ + */ +/** + * \file + * Partition configuration (license: GPLv2 or LGPLv2.1) + */ + +/** + * \ingroup partition_config + * Maximum number of partition handles. + */ +#define PARTITION_COUNT 1 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/FAT16/sd-reader_config.h b/FAT16/sd-reader_config.h new file mode 100644 index 0000000..0819f05 --- /dev/null +++ b/FAT16/sd-reader_config.h @@ -0,0 +1,53 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef SD_READER_CONFIG_H +#define SD_READER_CONFIG_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup config Sd-reader configuration + * + * @{ + */ + +/** + * \file + * Common sd-reader configuration used by all modules (license: GPLv2 or LGPLv2.1) + * + * \note This file contains only configuration items relevant to + * all sd-reader implementation files. For module specific configuration + * options, please see the files fat_config.h, partition_config.h + * and sd_raw_config.h. + */ + +/** + * Controls allocation of memory. + * + * Set to 1 to use malloc()/free() for allocation of structures + * like file and directory handles, set to 0 to use pre-allocated + * fixed-size handle arrays. + */ +#define USE_DYNAMIC_MEMORY 0 + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/FAT16/sd_raw.c b/FAT16/sd_raw.c new file mode 100644 index 0000000..10cddbb --- /dev/null +++ b/FAT16/sd_raw.c @@ -0,0 +1,1011 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include +#include +#include "sd_raw.h" +//ADDED! +#include +#include +#include +#include + +#include + +/** + * \addtogroup sd_raw MMC/SD/SDHC card raw access + * + * This module implements read and write access to MMC, SD + * and SDHC cards. It serves as a low-level driver for the + * higher level modules such as partition and file system + * access. + * + * @{ + */ +/** + * \file + * MMC/SD/SDHC raw access implementation (license: GPLv2 or LGPLv2.1) + * + * \author Roland Riegel + */ + +/** + * \addtogroup sd_raw_config MMC/SD configuration + * Preprocessor defines to configure the MMC/SD support. + */ + +/** + * @} + */ + +/* commands available in SPI mode */ + +/* CMD0: response R1 */ +#define CMD_GO_IDLE_STATE 0x00 +/* CMD1: response R1 */ +#define CMD_SEND_OP_COND 0x01 +/* CMD8: response R7 */ +#define CMD_SEND_IF_COND 0x08 +/* CMD9: response R1 */ +#define CMD_SEND_CSD 0x09 +/* CMD10: response R1 */ +#define CMD_SEND_CID 0x0a +/* CMD12: response R1 */ +#define CMD_STOP_TRANSMISSION 0x0c +/* CMD13: response R2 */ +#define CMD_SEND_STATUS 0x0d +/* CMD16: arg0[31:0]: block length, response R1 */ +#define CMD_SET_BLOCKLEN 0x10 +/* CMD17: arg0[31:0]: data address, response R1 */ +#define CMD_READ_SINGLE_BLOCK 0x11 +/* CMD18: arg0[31:0]: data address, response R1 */ +#define CMD_READ_MULTIPLE_BLOCK 0x12 +/* CMD24: arg0[31:0]: data address, response R1 */ +#define CMD_WRITE_SINGLE_BLOCK 0x18 +/* CMD25: arg0[31:0]: data address, response R1 */ +#define CMD_WRITE_MULTIPLE_BLOCK 0x19 +/* CMD27: response R1 */ +#define CMD_PROGRAM_CSD 0x1b +/* CMD28: arg0[31:0]: data address, response R1b */ +#define CMD_SET_WRITE_PROT 0x1c +/* CMD29: arg0[31:0]: data address, response R1b */ +#define CMD_CLR_WRITE_PROT 0x1d +/* CMD30: arg0[31:0]: write protect data address, response R1 */ +#define CMD_SEND_WRITE_PROT 0x1e +/* CMD32: arg0[31:0]: data address, response R1 */ +#define CMD_TAG_SECTOR_START 0x20 +/* CMD33: arg0[31:0]: data address, response R1 */ +#define CMD_TAG_SECTOR_END 0x21 +/* CMD34: arg0[31:0]: data address, response R1 */ +#define CMD_UNTAG_SECTOR 0x22 +/* CMD35: arg0[31:0]: data address, response R1 */ +#define CMD_TAG_ERASE_GROUP_START 0x23 +/* CMD36: arg0[31:0]: data address, response R1 */ +#define CMD_TAG_ERASE_GROUP_END 0x24 +/* CMD37: arg0[31:0]: data address, response R1 */ +#define CMD_UNTAG_ERASE_GROUP 0x25 +/* CMD38: arg0[31:0]: stuff bits, response R1b */ +#define CMD_ERASE 0x26 +/* ACMD41: arg0[31:0]: OCR contents, response R1 */ +#define CMD_SD_SEND_OP_COND 0x29 +/* CMD42: arg0[31:0]: stuff bits, response R1b */ +#define CMD_LOCK_UNLOCK 0x2a +/* CMD55: arg0[31:0]: stuff bits, response R1 */ +#define CMD_APP 0x37 +/* CMD58: arg0[31:0]: stuff bits, response R3 */ +#define CMD_READ_OCR 0x3a +/* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */ +#define CMD_CRC_ON_OFF 0x3b + +/* command responses */ +/* R1: size 1 byte */ +#define R1_IDLE_STATE 0 +#define R1_ERASE_RESET 1 +#define R1_ILL_COMMAND 2 +#define R1_COM_CRC_ERR 3 +#define R1_ERASE_SEQ_ERR 4 +#define R1_ADDR_ERR 5 +#define R1_PARAM_ERR 6 +/* R1b: equals R1, additional busy bytes */ +/* R2: size 2 bytes */ +#define R2_CARD_LOCKED 0 +#define R2_WP_ERASE_SKIP 1 +#define R2_ERR 2 +#define R2_CARD_ERR 3 +#define R2_CARD_ECC_FAIL 4 +#define R2_WP_VIOLATION 5 +#define R2_INVAL_ERASE 6 +#define R2_OUT_OF_RANGE 7 +#define R2_CSD_OVERWRITE 7 +#define R2_IDLE_STATE (R1_IDLE_STATE + 8) +#define R2_ERASE_RESET (R1_ERASE_RESET + 8) +#define R2_ILL_COMMAND (R1_ILL_COMMAND + 8) +#define R2_COM_CRC_ERR (R1_COM_CRC_ERR + 8) +#define R2_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 8) +#define R2_ADDR_ERR (R1_ADDR_ERR + 8) +#define R2_PARAM_ERR (R1_PARAM_ERR + 8) +/* R3: size 5 bytes */ +#define R3_OCR_MASK (0xffffffffUL) +#define R3_IDLE_STATE (R1_IDLE_STATE + 32) +#define R3_ERASE_RESET (R1_ERASE_RESET + 32) +#define R3_ILL_COMMAND (R1_ILL_COMMAND + 32) +#define R3_COM_CRC_ERR (R1_COM_CRC_ERR + 32) +#define R3_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 32) +#define R3_ADDR_ERR (R1_ADDR_ERR + 32) +#define R3_PARAM_ERR (R1_PARAM_ERR + 32) +/* Data Response: size 1 byte */ +#define DR_STATUS_MASK 0x0e +#define DR_STATUS_ACCEPTED 0x05 +#define DR_STATUS_CRC_ERR 0x0a +#define DR_STATUS_WRITE_ERR 0x0c + +/* status bits for card types */ +#define SD_RAW_SPEC_1 0 +#define SD_RAW_SPEC_2 1 +#define SD_RAW_SPEC_SDHC 2 + +#if !SD_RAW_SAVE_RAM +/* static data buffer for acceleration */ +static uint8_t raw_block[512]; +/* offset where the data within raw_block lies on the card */ +static offset_t raw_block_address; +#if SD_RAW_WRITE_BUFFERING +/* flag to remember if raw_block was written to the card */ +static uint8_t raw_block_written; +#endif +#endif + +/* card type state */ +static uint8_t sd_raw_card_type; + +/* private helper functions */ +static void sd_raw_send_byte(uint8_t b); +static uint8_t sd_raw_rec_byte(void); +static uint8_t sd_raw_send_command(uint8_t command, uint32_t arg); + +uint16_t i2 = 0; + +/** + * \ingroup sd_raw + * Initializes memory card communication. + * + * \returns 0 on failure, 1 on success. + */ +uint8_t sd_raw_init() +{ + /* enable inputs for reading card status */ + configure_pin_available(); + configure_pin_locked(); + + /* enable outputs for MOSI, SCK, SS, input for MISO */ + configure_pin_mosi(); + configure_pin_sck(); + configure_pin_ss(); + configure_pin_miso(); + PORTB |= (1<> 24) & 0xff); + sd_raw_send_byte((arg >> 16) & 0xff); + sd_raw_send_byte((arg >> 8) & 0xff); + sd_raw_send_byte((arg >> 0) & 0xff); + switch(command) + { + case CMD_GO_IDLE_STATE: + sd_raw_send_byte(0x95); + break; + case CMD_SEND_IF_COND: + sd_raw_send_byte(0x87); + break; + default: + sd_raw_send_byte(0xff); + break; + } + + /* receive response */ + for(i2 = 0; i2 < 10; ++i2) + { + response = sd_raw_rec_byte(); + if(response != 0xff) + break; + } + + return response; +} + +/** + * \ingroup sd_raw + * Reads raw data from the card. + * + * \param[in] offset The offset from which to read. + * \param[out] buffer The buffer into which to write the data. + * \param[in] length The number of bytes to read. + * \returns 0 on failure, 1 on success. + * \see sd_raw_read_interval, sd_raw_write, sd_raw_write_interval + */ +uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length) +{ + offset_t block_address; + uint16_t block_offset; + uint16_t read_length; + while(length > 0) + { + /* determine byte count to read at once */ + block_offset = offset & 0x01ff; + block_address = offset - block_offset; + read_length = 512 - block_offset; /* read up to block border */ + if(read_length > length) + read_length = length; + +#if !SD_RAW_SAVE_RAM + /* check if the requested data is cached */ + if(block_address != raw_block_address) +#endif + { +#if SD_RAW_WRITE_BUFFERING + if(!sd_raw_sync()) + return 0; +#endif + + /* address card */ + select_card(); + + /* send single block request */ +#if SD_RAW_SDHC + if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) +#else + if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, block_address)) +#endif + { + unselect_card(); + return 0; + } + + /* wait for data block (start byte 0xfe) */ + while(sd_raw_rec_byte() != 0xfe); + +#if SD_RAW_SAVE_RAM + /* read byte block */ + uint16_t read_to = block_offset + read_length; + for(i2 = 0; i < 512; ++i) + { + uint8_t b = sd_raw_rec_byte(); + if(i >= block_offset && i < read_to) + *buffer++ = b; + } +#else + /* read byte block */ + uint8_t* cache = raw_block; + for(i2 = 0; i2 < 512; ++i2) + *cache++ = sd_raw_rec_byte(); + raw_block_address = block_address; + + memcpy(buffer, raw_block + block_offset, read_length); + buffer += read_length; +#endif + + /* read crc16 */ + sd_raw_rec_byte(); + sd_raw_rec_byte(); + + /* deaddress card */ + unselect_card(); + + /* let card some time to finish */ + sd_raw_rec_byte(); + } +#if !SD_RAW_SAVE_RAM + else + { + /* use cached data */ + memcpy(buffer, raw_block + block_offset, read_length); + buffer += read_length; + } +#endif + + length -= read_length; + offset += read_length; + } + + return 1; +} + +/** + * \ingroup sd_raw + * Continuously reads units of \c interval bytes and calls a callback function. + * + * This function starts reading at the specified offset. Every \c interval bytes, + * it calls the callback function with the associated data buffer. + * + * By returning zero, the callback may stop reading. + * + * \note Within the callback function, you can not start another read or + * write operation. + * \note This function only works if the following conditions are met: + * - (offset - (offset % 512)) % interval == 0 + * - length % interval == 0 + * + * \param[in] offset Offset from which to start reading. + * \param[in] buffer Pointer to a buffer which is at least interval bytes in size. + * \param[in] interval Number of bytes to read before calling the callback function. + * \param[in] length Number of bytes to read altogether. + * \param[in] callback The function to call every interval bytes. + * \param[in] p An opaque pointer directly passed to the callback function. + * \returns 0 on failure, 1 on success + * \see sd_raw_write_interval, sd_raw_read, sd_raw_write + */ +uint8_t sd_raw_read_interval(offset_t offset, uint8_t* buffer, uintptr_t interval, uintptr_t length, sd_raw_read_interval_handler_t callback, void* p) +{ + if(!buffer || interval == 0 || length < interval || !callback) + return 0; + +#if !SD_RAW_SAVE_RAM + while(length >= interval) + { + /* as reading is now buffered, we directly + * hand over the request to sd_raw_read() + */ + if(!sd_raw_read(offset, buffer, interval)) + return 0; + if(!callback(buffer, offset, p)) + break; + offset += interval; + length -= interval; + } + + return 1; +#else + /* address card */ + select_card(); + + uint16_t block_offset; + uint16_t read_length; + uint8_t* buffer_cur; + uint8_t finished = 0; + do + { + /* determine byte count to read at once */ + block_offset = offset & 0x01ff; + read_length = 512 - block_offset; + + /* send single block request */ +#if SD_RAW_SDHC + if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? offset / 512 : offset - block_offset))) +#else + if(sd_raw_send_command(CMD_READ_SINGLE_BLOCK, offset - block_offset)) +#endif + { + unselect_card(); + return 0; + } + + /* wait for data block (start byte 0xfe) */ + while(sd_raw_rec_byte() != 0xfe); + + /* read up to the data of interest */ + for(i2 = 0; i < block_offset; ++i) + sd_raw_rec_byte(); + + /* read interval bytes of data and execute the callback */ + do + { + if(read_length < interval || length < interval) + break; + + buffer_cur = buffer; + for(i2 = 0; i < interval; ++i) + *buffer_cur++ = sd_raw_rec_byte(); + + if(!callback(buffer, offset + (512 - read_length), p)) + { + finished = 1; + break; + } + + read_length -= interval; + length -= interval; + + } while(read_length > 0 && length > 0); + + /* read rest of data block */ + while(read_length-- > 0) + sd_raw_rec_byte(); + + /* read crc16 */ + sd_raw_rec_byte(); + sd_raw_rec_byte(); + + if(length < interval) + break; + + offset = offset - block_offset + 512; + + } while(!finished); + + /* deaddress card */ + unselect_card(); + + /* let card some time to finish */ + sd_raw_rec_byte(); + + return 1; +#endif +} + +#if SD_RAW_WRITE_SUPPORT +/** + * \ingroup sd_raw + * Writes raw data to the card. + * + * \note If write buffering is enabled, you might have to + * call sd_raw_sync() before disconnecting the card + * to ensure all remaining data has been written. + * + * \param[in] offset The offset where to start writing. + * \param[in] buffer The buffer containing the data to be written. + * \param[in] length The number of bytes to write. + * \returns 0 on failure, 1 on success. + * \see sd_raw_write_interval, sd_raw_read, sd_raw_read_interval + */ +uint8_t sd_raw_write(offset_t offset, const uint8_t* buffer, uintptr_t length) +{ + if(sd_raw_locked()) + return 0; + + offset_t block_address; + uint16_t block_offset; + uint16_t write_length; + while(length > 0) + { + /* determine byte count to write at once */ + block_offset = offset & 0x01ff; + block_address = offset - block_offset; + write_length = 512 - block_offset; /* write up to block border */ + if(write_length > length) + write_length = length; + + /* Merge the data to write with the content of the block. + * Use the cached block if available. + */ + if(block_address != raw_block_address) + { +#if SD_RAW_WRITE_BUFFERING + if(!sd_raw_sync()) + return 0; +#endif + if(block_offset || write_length < 512) + { + if(!sd_raw_read(block_address, raw_block, sizeof(raw_block))) + return 0; + } + raw_block_address = block_address; + } + + if(buffer != raw_block) + { + memcpy(raw_block + block_offset, buffer, write_length); + +#if SD_RAW_WRITE_BUFFERING + raw_block_written = 0; + + if(length == write_length) + return 1; +#endif + } + + /* address card */ + select_card(); + + /* send single block request */ +#if SD_RAW_SDHC + if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, (sd_raw_card_type & (1 << SD_RAW_SPEC_SDHC) ? block_address / 512 : block_address))) +#else + if(sd_raw_send_command(CMD_WRITE_SINGLE_BLOCK, block_address)) +#endif + { + unselect_card(); + return 0; + } + + /* send start byte */ + sd_raw_send_byte(0xfe); + + /* write byte block */ + uint8_t* cache = raw_block; + for(i2 = 0; i2 < 512; ++i2) + sd_raw_send_byte(*cache++); + + /* write dummy crc16 */ + sd_raw_send_byte(0xff); + sd_raw_send_byte(0xff); + + /* wait while card is busy */ + while(sd_raw_rec_byte() != 0xff); + sd_raw_rec_byte(); + + /* deaddress card */ + unselect_card(); + + buffer += write_length; + offset += write_length; + length -= write_length; + +#if SD_RAW_WRITE_BUFFERING + raw_block_written = 1; +#endif + } + + return 1; +} +#endif + +#if SD_RAW_WRITE_SUPPORT +/** + * \ingroup sd_raw + * Writes a continuous data stream obtained from a callback function. + * + * This function starts writing at the specified offset. To obtain the + * next bytes to write, it calls the callback function. The callback fills the + * provided data buffer and returns the number of bytes it has put into the buffer. + * + * By returning zero, the callback may stop writing. + * + * \param[in] offset Offset where to start writing. + * \param[in] buffer Pointer to a buffer which is used for the callback function. + * \param[in] length Number of bytes to write in total. May be zero for endless writes. + * \param[in] callback The function used to obtain the bytes to write. + * \param[in] p An opaque pointer directly passed to the callback function. + * \returns 0 on failure, 1 on success + * \see sd_raw_read_interval, sd_raw_write, sd_raw_read + */ +uint8_t sd_raw_write_interval(offset_t offset, uint8_t* buffer, uintptr_t length, sd_raw_write_interval_handler_t callback, void* p) +{ +#if SD_RAW_SAVE_RAM + #error "SD_RAW_WRITE_SUPPORT is not supported together with SD_RAW_SAVE_RAM" +#endif + + if(!buffer || !callback) + return 0; + + uint8_t endless = (length == 0); + while(endless || length > 0) + { + uint16_t bytes_to_write = callback(buffer, offset, p); + if(!bytes_to_write) + break; + if(!endless && bytes_to_write > length) + return 0; + + /* as writing is always buffered, we directly + * hand over the request to sd_raw_write() + */ + if(!sd_raw_write(offset, buffer, bytes_to_write)) + return 0; + + offset += bytes_to_write; + length -= bytes_to_write; + } + + return 1; +} +#endif + +#if SD_RAW_WRITE_SUPPORT +/** + * \ingroup sd_raw + * Writes the write buffer's content to the card. + * + * \note When write buffering is enabled, you should + * call this function before disconnecting the + * card to ensure all remaining data has been + * written. + * + * \returns 0 on failure, 1 on success. + * \see sd_raw_write + */ +uint8_t sd_raw_sync() +{ +#if SD_RAW_WRITE_BUFFERING + if(raw_block_written) + return 1; + if(!sd_raw_write(raw_block_address, raw_block, sizeof(raw_block))) + return 0; + raw_block_written = 1; +#endif + return 1; +} +#endif + +/** + * \ingroup sd_raw + * Reads informational data from the card. + * + * This function reads and returns the card's registers + * containing manufacturing and status information. + * + * \note: The information retrieved by this function is + * not required in any way to operate on the card, + * but it might be nice to display some of the data + * to the user. + * + * \param[in] info A pointer to the structure into which to save the information. + * \returns 0 on failure, 1 on success. + */ +uint8_t sd_raw_get_info(struct sd_raw_info* info) +{ + if(!info || !sd_raw_available()) + return 0; + + memset(info, 0, sizeof(*info)); + + select_card(); + + /* read cid register */ + if(sd_raw_send_command(CMD_SEND_CID, 0)) + { + unselect_card(); + return 0; + } + while(sd_raw_rec_byte() != 0xfe); + for(i2 = 0; i2 < 18; ++i2) + { + uint8_t b = sd_raw_rec_byte(); + + switch(i2) + { + case 0: + info->manufacturer = b; + break; + case 1: + case 2: + info->oem[i2 - 1] = b; + break; + case 3: + case 4: + case 5: + case 6: + case 7: + info->product[i2 - 3] = b; + break; + case 8: + info->revision = b; + break; + case 9: + case 10: + case 11: + case 12: + info->serial |= (uint32_t) b << ((12 - i2) * 8); + break; + case 13: + info->manufacturing_year = b << 4; + break; + case 14: + info->manufacturing_year |= b >> 4; + info->manufacturing_month = b & 0x0f; + break; + } + } + + /* read csd register */ + uint8_t csd_read_bl_len = 0; + uint8_t csd_c_size_mult = 0; +#if SD_RAW_SDHC + uint16_t csd_c_size = 0; +#else + uint32_t csd_c_size = 0; +#endif + if(sd_raw_send_command(CMD_SEND_CSD, 0)) + { + unselect_card(); + return 0; + } + while(sd_raw_rec_byte() != 0xfe); + for(i2 = 0; i2 < 18; ++i2) + { + uint8_t b = sd_raw_rec_byte(); + + if(i2 == 14) + { + if(b & 0x40) + info->flag_copy = 1; + if(b & 0x20) + info->flag_write_protect = 1; + if(b & 0x10) + info->flag_write_protect_temp = 1; + info->format = (b & 0x0c) >> 2; + } + else + { +#if SD_RAW_SDHC + if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) + { + switch(i) + { + case 7: + b &= 0x3f; + case 8: + case 9: + csd_c_size <<= 8; + csd_c_size |= b; + break; + } + if(i2 == 9) + { + ++csd_c_size; + info->capacity = (offset_t) csd_c_size * 512 * 1024; + } + } + else +#endif + { + switch(i2) + { + case 5: + csd_read_bl_len = b & 0x0f; + break; + case 6: + csd_c_size = b & 0x03; + csd_c_size <<= 8; + break; + case 7: + csd_c_size |= b; + csd_c_size <<= 2; + break; + case 8: + csd_c_size |= b >> 6; + ++csd_c_size; + break; + case 9: + csd_c_size_mult = b & 0x03; + csd_c_size_mult <<= 1; + break; + case 10: + csd_c_size_mult |= b >> 7; + + info->capacity = (uint32_t) csd_c_size << (csd_c_size_mult + csd_read_bl_len + 2); + + break; + } + } + } + } + + unselect_card(); + + return 1; +} + diff --git a/FAT16/sd_raw.h b/FAT16/sd_raw.h new file mode 100644 index 0000000..549c080 --- /dev/null +++ b/FAT16/sd_raw.h @@ -0,0 +1,148 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef SD_RAW_H +#define SD_RAW_H + +#include +#include "sd_raw_config.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup sd_raw + * + * @{ + */ +/** + * \file + * MMC/SD/SDHC raw access header (license: GPLv2 or LGPLv2.1) + * + * \author Roland Riegel + */ + +/** + * The card's layout is harddisk-like, which means it contains + * a master boot record with a partition table. + */ +#define SD_RAW_FORMAT_HARDDISK 0 +/** + * The card contains a single filesystem and no partition table. + */ +#define SD_RAW_FORMAT_SUPERFLOPPY 1 +/** + * The card's layout follows the Universal File Format. + */ +#define SD_RAW_FORMAT_UNIVERSAL 2 +/** + * The card's layout is unknown. + */ +#define SD_RAW_FORMAT_UNKNOWN 3 + +/** + * This struct is used by sd_raw_get_info() to return + * manufacturing and status information of the card. + */ +struct sd_raw_info +{ + /** + * A manufacturer code globally assigned by the SD card organization. + */ + uint8_t manufacturer; + /** + * A string describing the card's OEM or content, globally assigned by the SD card organization. + */ + uint8_t oem[3]; + /** + * A product name. + */ + uint8_t product[6]; + /** + * The card's revision, coded in packed BCD. + * + * For example, the revision value \c 0x32 means "3.2". + */ + uint8_t revision; + /** + * A serial number assigned by the manufacturer. + */ + uint32_t serial; + /** + * The year of manufacturing. + * + * A value of zero means year 2000. + */ + uint8_t manufacturing_year; + /** + * The month of manufacturing. + */ + uint8_t manufacturing_month; + /** + * The card's total capacity in bytes. + */ + offset_t capacity; + /** + * Defines wether the card's content is original or copied. + * + * A value of \c 0 means original, \c 1 means copied. + */ + uint8_t flag_copy; + /** + * Defines wether the card's content is write-protected. + * + * \note This is an internal flag and does not represent the + * state of the card's mechanical write-protect switch. + */ + uint8_t flag_write_protect; + /** + * Defines wether the card's content is temporarily write-protected. + * + * \note This is an internal flag and does not represent the + * state of the card's mechanical write-protect switch. + */ + uint8_t flag_write_protect_temp; + /** + * The card's data layout. + * + * See the \c SD_RAW_FORMAT_* constants for details. + * + * \note This value is not guaranteed to match reality. + */ + uint8_t format; +}; + +typedef uint8_t (*sd_raw_read_interval_handler_t)(uint8_t* buffer, offset_t offset, void* p); +typedef uintptr_t (*sd_raw_write_interval_handler_t)(uint8_t* buffer, offset_t offset, void* p); + +uint8_t sd_raw_init(void); +uint8_t sd_raw_available(void); +uint8_t sd_raw_locked(void); + +uint8_t sd_raw_read(offset_t offset, uint8_t* buffer, uintptr_t length); +uint8_t sd_raw_read_interval(offset_t offset, uint8_t* buffer, uintptr_t interval, uintptr_t length, sd_raw_read_interval_handler_t callback, void* p); +uint8_t sd_raw_write(offset_t offset, const uint8_t* buffer, uintptr_t length); +uint8_t sd_raw_write_interval(offset_t offset, uint8_t* buffer, uintptr_t length, sd_raw_write_interval_handler_t callback, void* p); +uint8_t sd_raw_sync(void); + +uint8_t sd_raw_get_info(struct sd_raw_info* info); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/FAT16/sd_raw_config.h b/FAT16/sd_raw_config.h new file mode 100644 index 0000000..afe6969 --- /dev/null +++ b/FAT16/sd_raw_config.h @@ -0,0 +1,146 @@ + +/* + * Copyright (c) 2006-2009 by Roland Riegel + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef SD_RAW_CONFIG_H +#define SD_RAW_CONFIG_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \addtogroup sd_raw + * + * @{ + */ +/** + * \file + * MMC/SD support configuration (license: GPLv2 or LGPLv2.1) + */ + +/** + * \ingroup sd_raw_config + * Controls MMC/SD write support. + * + * Set to 1 to enable MMC/SD write support, set to 0 to disable it. + */ +#define SD_RAW_WRITE_SUPPORT 1 + +/** + * \ingroup sd_raw_config + * Controls MMC/SD write buffering. + * + * Set to 1 to buffer write accesses, set to 0 to disable it. + * + * \note This option has no effect when SD_RAW_WRITE_SUPPORT is 0. + */ +#define SD_RAW_WRITE_BUFFERING 1 + +/** + * \ingroup sd_raw_config + * Controls MMC/SD access buffering. + * + * Set to 1 to save static RAM, but be aware that you will + * lose performance. + * + * \note When SD_RAW_WRITE_SUPPORT is 1, SD_RAW_SAVE_RAM will + * be reset to 0. + */ +#define SD_RAW_SAVE_RAM 1 + +/** + * \ingroup sd_raw_config + * Controls support for SDHC cards. + * + * Set to 1 to support so-called SDHC memory cards, i.e. SD + * cards with more than 2 gigabytes of memory. + */ +#define SD_RAW_SDHC 0 + +/** + * @} + */ + +/* defines for customisation of sd/mmc port access */ +/*#if defined(__AVR_ATmega8__) || \ + defined(__AVR_ATmega48__) || \ + defined(__AVR_ATmega88__) || \ + defined(__AVR_ATmega168__) || \ + defined(__AVR_ATmega328__) || \ + defined(__AVR_atmega328p__) +*/ + #define configure_pin_mosi() DDRB |= (1 << DDB3) + #define configure_pin_sck() DDRB |= (1 << DDB5) + #define configure_pin_ss() DDRB |= (1 << DDB0) + #define configure_pin_miso() DDRB &= ~(1 << DDB4) + + #define select_card() PORTB &= ~(1 << PINB0) + #define unselect_card() PORTB |= (1 << PINB0) +/* +#elif defined(__AVR_ATmega16__) || \ + defined(__AVR_ATmega32__) + #define configure_pin_mosi() DDRB |= (1 << DDB5) + #define configure_pin_sck() DDRB |= (1 << DDB7) + #define configure_pin_ss() DDRB |= (1 << DDB4) + #define configure_pin_miso() DDRB &= ~(1 << DDB6) + + #define select_card() PORTB &= ~(1 << PB4) + #define unselect_card() PORTB |= (1 << PB4) +#elif defined(__AVR_ATmega64__) || \ + defined(__AVR_ATmega128__) || \ + defined(__AVR_ATmega169__) + #define configure_pin_mosi() DDRB |= (1 << DDB2) + #define configure_pin_sck() DDRB |= (1 << DDB1) + #define configure_pin_ss() DDRB |= (1 << DDB0) + #define configure_pin_miso() DDRB &= ~(1 << DDB3) + + #define select_card() PORTB &= ~(1 << PB0) + #define unselect_card() PORTB |= (1 << PB0) +#else + #error "no sd/mmc pin mapping available!" +#endif +*/ +/* +#define configure_pin_available() DDRC &= ~(1 << DDC4) +#define configure_pin_locked() DDRC &= ~(1 << DDC5) + +#define get_pin_available() ((PINC >> PINC4) & 0x01) +#define get_pin_locked() ((PINC >> PINC5) & 0x01) +*/ +#define configure_pin_available() //NOTHING +#define configure_pin_locked() //Nothing + +#define get_pin_available() 0 +#define get_pin_locked() 1 + +#if SD_RAW_SDHC + typedef uint64_t offset_t; +#else + typedef uint32_t offset_t; +#endif + +/* configuration checks */ +#if SD_RAW_WRITE_SUPPORT +#undef SD_RAW_SAVE_RAM +#define SD_RAW_SAVE_RAM 0 +#else +#undef SD_RAW_WRITE_BUFFERING +#define SD_RAW_WRITE_BUFFERING 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif + -- 2.25.1