
 * Nombre de librera: remi_fat
 * AUTOR: FRANCISO JAVIER LPEZ GORDILLO (av_remi04@yahoo.es)
 * DISPOSITIVO: PIC18F4550
 * COMPILADOR: XC8.
 * 
 *
 *
 *    ADVERTENCIA:
 * 
 *      Esta librera es experimental y puede contener errores. 
 *          El uso de la misma queda bajo la responsabilidad de quien la utiliza. Manipular funciones de bajo nivel puede causar la perdida total y/o parcial
 *    de los datos de la tarjeta de memoria. Se recomienda utilizar tarjetas donde no se tenga informacin sensible o tener copias de seguridad realizadas.  
 *   Solo se recomienda utilizar las funciones abajo listadas siguiendo las instrucciones descritas.
 * 
 * 
 *  
 * 
 *    Se permite su libre distribucin, uso y modificacin tanto a nivel personal como profesional. 
 * 
 * 
 * ********************************************** PRECAUCIONES ***********************************************************************
 * 
 * 1- Solo se puede tener abierto un archivo a la misma vez. 
 * 2- Mientras se tiene un archivo abierto no es posible utilizar funciones de explorador, como new_file, new_folder,delete_file,open_folder,back_folder,root, etc.
 *    - Cualquier intento de uso de una de estas funciones habiendo un archivo abierto terminar con retorno de valor booleano "0" para indicar condicin de error.
 * 3- El numero mximo de caracteres que se pueden transferir de una sola vez mediante la funcion file_gets() est limitado por defecto a 64 bytes. Si necesita habilitar
 * un buffer mayor o menor puede cambiar este lmite modificando el valor de una macro ubicada en el archivo de cabecera remi_fat.h  " #define max_string_lenght 64 " 
 * 
 * 4- No cerrar un archivo antes de terminar el programa puede ocasionar perdida de datos del ultimo sector que se tuviese cargado y activo.    
 *
 * 5- No se recomienda utilizar las funciones de bajo y medio nivel, a nivel del sistema de archivos ni de la tarjeta de memoria salvo que se tenga
 * muy claro lo que se est haciendo. El uso de esas funciones puede dar lugar a la perdida total o parcial de datos en la tarjeta de memoria. 
 *****************************************************************************************************************************************************
 * 
 *    
 *     DESCRIPCION:
 * 
 *  Implementa FAT12/16/32. Se han probado tarjetas sd y micro sd de hasta 32 Gb. 
 *  Implementa LFN, por lo que se pueden manejar archivos y carpetas con nombre largo, maysculas, minsculas, que tengan uno o mas caracteres
 *  "." en su nombre a parte del de la extensin. Con o sin extensin, extensiones de mas de tres caracteres, etc..
 * 
 *  Fat no es Case Sensitive. Pero LFN si. 
 *  
 *
 *  INSTRUCCIONES PARA UTILIZAR EN (MPLABX):
 * 
 * 	- Colocar todos los archivos .c y .h en la carpeta de su proyecto. (Excepto filesystem.c) el cual es un main con codigo de ejemplo.
 *
 *      - Desde el arbol de proyecto en mplab, click boton derecho sobre "Header files", elegir Add existing item e importar todos los archivos .h
 *      - Desde el arbol de proyecto en mplab, click boton derecho sobre "Source files", elegir Add existing item e importar todos los archivos .c
 *      - Aadir en la cabecera de su archivo main.c:
 *       #include"remi_fat.h"
 *      
 *
 *
 *
 *
 *
 *
 * // Lista de funciones principales. 
 * 
 * 
 * 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * set_date_time(dia,mes,ao,hora,minutos,segundos);       Establece los metadatos de fecha y hora de creacin, modificacin o ultimo acceso a los archivos.
 *                                                         Para que funcione correctamente, antes de crear, abrir o cerrar un archivo o una carpeta
 *                                                         se debe llamar a esta funcin y cargar sus argumentos con datos actualizados de fecha y hora
 *                                                         bien sea de forma manual u obtenido de un RTC, GPS, etc de forma peridica.  
 *                                                         Es optativo. Si no se especifica, los metadatos de fecha y hora sern fijados a cero.
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * (Todas devuelven TRUE si cursan bien o FALSE en caso contrario). 
 * 
 * ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * new_file("nombre_archivo.extension",x);       Busca en el directorio activo un archivo con ese nombre. Si no existe lo crea. el argumento "x" es 
 *                                               para los atributos del archivo a crear. (Oculto, solo lectura, de sistema, etc).  
 *                                               El archivo se genera vaco. Sin contenido y por lo tanto sin cluster. 
 *                                            
 *                                  // valor del byte de atributos del archivo:
 *                                               // BIT 7: Reservado. Siempre a cero
 *                                               // BIT 6: Reservado. Siempre a cero. 
 *                                               // BIT 5: Archivo. (No indica que se trate de un archivo, dejarlo siempre en cero)
 *                                               // BIT 4: Carpeta. (1 = Es una carpeta. 0 = Es un archivo) " Esto S que indica si se trata de un archivo o una carpeta. 
 *                                               // BIT 3: VolumenID (Indica que se trata de una entrada de informacin de volumen del sistema). No utilizar, siempre a cero. 
 *                                               // BIT 2: Sistema. (Indica que es un archivo de sistema).
 *                                               // BIT 1: Oculto. Indica que el archivo es oculto.
 *                                               // BIT 0: Solo lectura. Indica que el archivo es de solo lectura. 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 * 
 *
 * 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * new_folder("nombre_carpeta");                 Misma operacin que la anterior. Genera una carpeta. A diferencia del archivo, a una carpeta si se le asigna cluster
 *                                            , ese cluster se inicializa. 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * 
 * 
 * 
 * 
 * 
 * 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * delete_file("nombre_archivo.extension");      Busca el archivo indicado en el directorio activo y si lo encuentra lo elimina.  
 *                                              NOTA: El contenido que tenga el archivo NO SE ELIMINA. Simplemente se marca su entrada de directorio como libre
 *                                              y se marcan los clusteres de datos como libres en las tablas fat. 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * 
 * 
 * 
 * 
 *
 *
 * 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * open_folder("nombre_carpeta");               Busca la carpeta indicada en el directorio activo y accede a ella. Si la encuentra, el puntero de directorio activo
 *                                              pasa a ser el del primer cluster de esa carpeta, por lo que a partir de entonces, todas las operaciones de crear
 *                                              ,eliminar, ficheros y/o carpetas se efectan dentro de este directorio
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * back_folder();                              Establece como directorio activo a la carpeta "padre" de donde estemos actualmente. Es decir, retrocede a la carpeta
 *                                             anterior.
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * root();                          Establece como directorio activo el directorio raiz de forma directa sin importar en qu parte del volumen se encuentre
 *                                  el puntero de directorio activo. 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 *
 * 
 * 
 * 
 * 
 *
 * 
 * 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * open_file("nombre_archivo.ext");                     Busca el archivo en el directorio y si lo encuentra lo abre y lo deja listo para leer/escribir
 *                                                      contenido del/hacia el mismo. 
 *                                                      Se fijan los metadatos de fecha y hora como datos de ultimo acceso al archivo. 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 *
 * 

 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * close_file();                             Cierra el archivo que est abierto en ese momento.  En el momento de cerrar, el contenido del buffer que no se hubiere
 *                                              grabado en la tarjeta SD se graba en ese instante. Se fijan tambin los metadatos de fecha y hora como datos
 *                                            de ultima modificacin siempre que hayamos modificado algo. 
 * /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 * 
 * 
 * 
 
 * 
 * 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * save_file();                           Cuando se escribe contenido a un archivo, en realidad el contenido se graba en un buffer en memoria ram.
 *                                          Solo cuando ese buffer se llena,su contenido es volcado fisicamente de forma automtica en la tarjeta de memoria. 
 *                                       Al usar la funcion close_file(); todo el contenido que haya en el buffer se graba fisicamente en la tarjeta.
 *                                      Con el fin de asegurar que en un momento dado el contenido del buffer sea grabado en la tarjeta sin esperar a que se llene
 *                                      o a ejecutar close_file() se provee de esta funcin, que grabar inmediatamente el contenido del buffer en la tarjeta de memoria
 *                                      y mantendr el archivo abierto para seguir leyendo o escribiendo en l. 
 *                                      save_file(); NO CIERRA EL ARCHIVO. 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * file_seek();                         Establece el cursor de lectura/escritura de byte en una determinada posicion del archivo. 
 *                                      La posicion debe estar compredida entre 0 y tamao mximo del archivo en bytes. 
 *                                      Si se enva una posicin ilegal (fuera de rango) la funcin devuelve FALSE y el cursor no cambia, permaneciendo donde estaba anteriormente.
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * file_tell();                                Donde estoy?. 
 *                                            - Devuelve el indice de la posicin del cursor actual en el archivo. 
 *                                            Si hay algun error devuelve EOF. (0xffffffff)
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 *  
 *
 * 
 * 
 * 
 * 
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * file_getc();                    devuelve el valor del byte al que apunta el cursor. 
 *                                 - El cursor es incrementado automticamente en una posicin. 
 *                                 - Si se alcanza el final del fichero el cursor no se puede incrementar ms. 
 *                                 La funcin devolver siempre el ultimo caracter. La unica forma segura
 *                                 de saber si estamos en el final del fichero es comparar la posicion del cursor con el valor en bytes
 *                                 del tamao del archivo. El valor en bytes del archivo abierto est disponible en la variable frw.size

 *                                   
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * file_gets(longitud);                    Lee una cadena de n caracteres indicados en el argumento (longitud) Termina en NULL. Devuelve por referencia. 
 *                                         ejemplo de uso:
 *                                         char cadena[10] = file_gets(10);
 *                                         printf("\r\n La cadena leida es: %s",cadena);
 *                                         printf("\r\n Otra forma de leer e imprimir la cadena: %s",file_gets(10));
 * 
 *                                         - El cursor es incrementado automticamente en tantas posicines como caracteres se hayan leido.
 *                                         - Si se alcanza el final del fichero el cursor no se puede incrementar ms. 
 *                                         La funcin devolver EOF 0xff. La funcin vovler a devolver el ultimo caracter. La unica forma segura
 *                                         de saber si estamos en el final del fichero es comprara la posicion del cursor con el valor en bytes
 *                                         del tamao del archivo. El valor en bytes del archivo abierto est disponible en la variable frw.size
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 *
 *  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 * file_putc(caracter);                  Graba el caracter indicado en el byte del archivo al que apunta el cursor.
 *                                       La operacin siempre es de sobreescritura. No de insercin.
 *                                       Ello significa que el caracter apuntado existente ser reemplazado.
 *                                      - El cursor es incrementado automticamente en una posicin. 
 *                                      - Si se alcanza el final del archivo, el mismo ser automticamente ampliado y los caracteres se seguirn escribiendo por orden.
 *                                        El cursor se sigue incrementando.
 *                                      - El limite mximo del tamao del archivo depende del sistema de archivos y de su formato.  
 *                                       
 *                            
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 *
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 *  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 * file_puts("cadena");                  Graba la cadena indicada a partir del byte del archivo al que apunta el cursor. 
 *                                       La operacin siempre es de sobreescritura. No de insercin.
 *                                       Ello significa que cada caracter existente ser reemplazado.
 *                                      - El cursor es incrementado automticamente en tantas posicines como caracteres contenga la cadena. 
 *                                      - Si se alcanza el final del archivo, el mismo ser automticamente ampliado y los caracteres se seguirn escribiendo por orden.
 *                                        El cursor se sigue incrementando.
 *                                      - El limite mximo del tamao del archivo depende del sistema de archivos y de su formato.  
 * 
 * 
 
 * 
 * 
 * CODIGO DE EJEMPLO DE USO LIBRERIA FAT
 * 
 
 * La libreria fat consta de los siguientes archivos:
 * remi_fat.h   Cabecera que contiene los prototipos de las funciones, estructuras de variables y macros
 * remi_fat.c   Contiene el codigo fuente de todas las funciones para el manejo del sistema de archivos fat.
 * 
 * Los dos archivos anteriores incorporan a su vez todo lo necesario para inicializar cualquier tipo de tarjeta sd,microsd, de hasta 32 Gb.       
 * remi_spi.h      // Configura el modulo SPI usando al principio el timer2 como fuente del mdulo para negociar con la tarjeta SD.
 * remi_spi.c       // Tras la negociacin, el timer 2 queda liberado. 
 * remi_uart.h      // Configura el modulo Uart para poder usar printf y enviar datos a una terminal si se requiere. Es optativo. 
 * remi_uart.c
 */





// Para este codigo de ejemplo, se utiliza un PIC18F4550 con cristal de 20 Mhz. Se configura el PLL para 48 Mhz de salida final. 

// La conexin SPI entre el pic y la tarjeta es bajo el modulo SPI. 
// !! OJO CON EL VOLTAJE DE ALIMENTACIN DE LA TARJETA SD !!, Casi todas funcionan a 3,3 voltios. Lo mismo para las seales de comunicacin. 
// Su placa lectora de tarjeta debe incorporar un buffer de conversion de niveles de 5v a 3v3 bidireccional. 


//PIC18F4550                    TARJETA SD
// PIN SDO                      PIN SDI  (MOSI)
// PIN SDI                      PIN SDO  (MISO)
// PIN SCK                      PIN SCK
// PIN CS                       PIN CS
// VCC 5V                       VCC 3V3
// GND                          GND



// Si se quiere utilizar el switch mecnico de deteccin de tarjeta insertada en el zcalo de la tarjeta sd, hay que definir un PIN para el mismo. 
// Por defecto el switch est desactivado y no se tendr en cuenta. El pin asignado es el pin E1.
// Para definir el pin y activar el switch en el programa ir a la cabecera del archivo remi_fat.h, linea 35.
// configurar all mismo tambin la polaridad del switch, si s pullup, push_pull, y si el nivel el presencia de tarjeta es nivel alto o bajo.
// Por defecto nada de esto se tiene en cuenta. 


// La conexin USART entre el pic y el terminal (OPCIONAL):

// PIC18F4550               TERMINAL
// PIN TX                   PIN RX

// RX no utilizado. El Pic18f4550 comparte el pin RX con SDO del modulo SPI, por lo que no es posible su uso simultneo. 

// EL PIN CS utilizado en este ejemplo es el PIN.RE0. 
// Para cambiar estos pines, tanto del Switch como de la seal CS para la tarjeta de memoria se debe abrir el archivo remi_fat.h. Localice las macros
// para su definicin arriba del archivo. 
