/* * Just another FatFs Library * Ross Marchant, ross.marchant@my.jcu.edu.au * * Based on: * Arduino Wrapper Function Library for FatFs * (c) 2010, David Sirkin sirkin@stanford.edu * * FatFS by ChaN: * http://elm-chan.org/fsw/ff/00index_e.html */ #include <msp430.h> #include "SPI.h" #include "Jaffl.h" extern "C" { #include "FatFs2Jaffl.h" } FATFS FFS::fatfs_obj; // Working copy of FATFS DIR FFS::dir_obj; // Working copy of DIR FIL FFS::fil_obj; // Working copy of FIL FILINFO FFS::fno; // Working copy of FILINFO unsigned char FFS::CS; // Pin to sd card's CS uint8_t _clkdivider = 2; // Default spi clock 8Mhz / 2 = 4MHz /*-----------------------------------------------------------------------*/ /* Constructor */ /*-----------------------------------------------------------------------*/ /* Don't instantiate from the sketch; it's done at the end of this file. */ FFS::FFS() { } /*-----------------------------------------------------------------------*/ /* Chip Select/Deselect Functions for the Card's CS Pin */ /*-----------------------------------------------------------------------*/ void FFS::CS_LOW(void) { digitalWrite(CS, LOW); //digitalWrite(RED_LED, HIGH); //SDCard_setCSLow(); } void FFS::CS_HIGH(void) { digitalWrite(CS, HIGH); //digitalWrite(RED_LED, LOW); //SDCard_setCSHigh(); } int FFS::CS_READ(void) { return !digitalRead(CS); } /*-----------------------------------------------------------------------*/ /* SPI Functions for diskio driver */ /*-----------------------------------------------------------------------*/ void FFS::SPI_RECEIVE(uint8_t *pBuffer, uint16_t size) { uint16_t gie = __read_status_register() & GIE; //Store current GIE state __disable_interrupt(); //Make this operation atomic UCB0IFG &= ~UCRXIFG; //Ensure RXIFG is clear //Clock the actual data transfer and receive the bytes while (size--){ while (!(UCB0IFG & UCTXIFG)) ; //Wait while not ready for TX UCB0TXBUF = 0xff; //Write dummy byte while (!(UCB0IFG & UCRXIFG)) ; //Wait for RX buffer (full) *pBuffer++ = UCB0RXBUF; } __bis_SR_register(gie); //Restore original GIE state } void FFS::SPI_SEND(uint8_t *pBuffer, uint16_t size) { uint16_t gie = __read_status_register() & GIE; //Store current GIE state __disable_interrupt(); //Make this operation atomic //Clock the actual data transfer and send the bytes. Note that we //intentionally not read out the receive buffer during frame transmission //in order to optimize transfer speed, however we need to take care of the //resulting overrun condition. while (size--){ while (!(UCB0IFG & UCTXIFG)) ; //Wait while not ready for TX UCB0TXBUF = *pBuffer++; //Write byte } while (UCB0STAT & UCBUSY) ; //Wait for all TX/RX to finish UCB0RXBUF; //Dummy read to empty RX buffer //and clear any overrun conditions __bis_SR_register(gie); //Restore original GIE state } void FFS::SPI_SET_DIVIDER(const uint8_t _clkdivider) { SPI.setClockDivider(_clkdivider); } void FFS::SPI_HIGH_SPEED(void) { SPI.setClockDivider(_clkdivider); } void FFS::SPI_INIT(void) { pinMode(P1_7, INPUT_PULLUP); SPI.begin(); SPI.setClockDivider(128); } /*-----------------------------------------------------------------------*/ /* Delay function for diskio driver */ /*-----------------------------------------------------------------------*/ void FFS::DLY10U(void) { delayMicroseconds(10); } /*-----------------------------------------------------------------------*/ /* Setup FS Structures and Register CS Pin */ /*-----------------------------------------------------------------------*/ FRESULT FFS::begin( unsigned char cs_pin /* Pin to connect to CS */ ) { FRESULT res; res = begin(cs_pin, _clkdivider); // begin with def spi divider return res; } FRESULT FFS::begin( unsigned char cs_pin, /* Pin to connect to CS */ uint8_t clkdivider // parameter for spi clock divider ) { _clkdivider = clkdivider; FRESULT res; CS = cs_pin; pinMode(CS, OUTPUT); attach_pins(CS_LOW, CS_HIGH); attach_SPIdriver(SPI_RECEIVE, SPI_SEND, SPI_INIT, SPI_HIGH_SPEED); disk_init(); res = mount(0, &fatfs_obj); #if _USE_DIR res = f_opendir(&dir_obj, (const CHAR *) "/"); #endif return res; } /*-----------------------------------------------------------------------*/ /* Initialize Disk Drive */ /*-----------------------------------------------------------------------*/ DSTATUS FFS::disk_init( void //unsigned char drv /* Physical drive number (0) */ ) { return disk_initialize(0); } /*------------------------------------------------------------------------- FatFs Module Public Functions (In ff.c and ff.h) --------------------------------------------------------------------------- Overloaded methods use working copy of FATFS, DIR or FIL -------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ /* Mount/Unmount a Locical Drive */ /*-----------------------------------------------------------------------*/ FRESULT FFS::mount( unsigned char vol, /* Logical drive number to be mounted/unmounted */ FATFS *fs /* Pointer to new file system object (NULL for unmount) */ ) { return f_mount(fs,"0:",1); } /*-----------------------------------------------------------------------*/ /* Open or Create a File */ /*-----------------------------------------------------------------------*/ FRESULT FFS::open( FIL *fp, /* Pointer to the blank file object */ const TCHAR *path, /* Pointer to the file name */ unsigned char mode /* Access mode and file open mode flags */ ) { return f_open(fp, path, mode); } FRESULT FFS::open( const TCHAR *path, /* Pointer to the file name */ unsigned char mode /* Access mode and file open mode flags */ ) { return f_open(&fil_obj, path, mode); } /*-----------------------------------------------------------------------*/ /* Read File */ /*-----------------------------------------------------------------------*/ FRESULT FFS::read( FIL *fp, /* Pointer to the file object */ void *buff, /* Pointer to data buffer */ UINT btr, /* Number of bytes to read */ UINT *br /* Pointer to number of bytes read */ ) { return f_read(fp, buff, btr, br); } FRESULT FFS::read( void *buff, /* Pointer to data buffer */ UINT btr, /* Number of bytes to read */ UINT *br /* Pointer to number of bytes read */ ) { return f_read(&fil_obj, buff, btr, br); } /*-----------------------------------------------------------------------*/ /* Write File */ /*-----------------------------------------------------------------------*/ #if !_FS_READONLY FRESULT FFS::write( FIL *fp, /* Pointer to the file object */ const void *buff, /* Pointer to the data to be written */ UINT btw, /* Number of bytes to write */ UINT *bw /* Pointer to number of bytes written */ ) { return f_write(fp, buff, btw, bw); } FRESULT FFS::write( const void *buff, /* Pointer to the data to be written */ UINT btw, /* Number of bytes to write */ UINT *bw /* Pointer to number of bytes written */ ) { return f_write(&fil_obj, buff, btw, bw); } size_t FFS::write(uint8_t character){ UINT bw; f_write(&fil_obj, &character, 1, &bw); //ok return (bw == 1) ? 1 : -1; } size_t FFS::write(FIL *fp, uint8_t character){ UINT bw; f_write(fp, &character, 1, &bw); return (bw == 1) ? 1 : -1; } #endif /* !_FS_READONLY */ /*-----------------------------------------------------------------------*/ /* Close File */ /*-----------------------------------------------------------------------*/ FRESULT FFS::close( FIL *fp /* Pointer to the file object to be closed */ ) { return f_close(fp); } FRESULT FFS::close( void /* Working copy file object will be closed */ ) { return f_close(&fil_obj); } #if _FS_RPATH /*-----------------------------------------------------------------------*/ /* Change Current Drive/Directory */ /*-----------------------------------------------------------------------*/ FRESULT FFS::chdrive( unsigned char drv /* Drive number */ ) { return f_chdrive(drv); } FRESULT FFS::chdir( const TCHAR *path /* Pointer to the directory path */ ) { return f_chdir(path); } #endif /* _FS_RPATH */ #if _FS_MINIMIZE <= 2 /*-----------------------------------------------------------------------*/ /* Seek File R/W Pointer */ /*-----------------------------------------------------------------------*/ FRESULT FFS::lseek( FIL *fp, /* Pointer to the file object */ DWORD ofs /* File pointer from top of file */ ) { return f_lseek(fp, ofs); } FRESULT FFS::lseek( DWORD ofs /* File pointer from top of file */ ) { return f_lseek(&fil_obj, ofs); } #if _FS_MINIMIZE <= 1 /*-----------------------------------------------------------------------*/ /* Create a Directory Object */ /*-----------------------------------------------------------------------*/ FRESULT FFS::opendir( DIR *dj, /* Pointer to directory object to create */ const TCHAR *path /* Pointer to the directory path */ ) { return f_opendir(dj, path); } FRESULT FFS::opendir( const TCHAR *path /* Pointer to the directory path */ ) { return f_opendir(&dir_obj, path); } FRESULT FFS::opendir( void /* Working copies of directory object & path */ ) { return f_opendir(&dir_obj, (const TCHAR *) "/"); } /*-----------------------------------------------------------------------*/ /* Read Directory Entry in Sequence */ /*-----------------------------------------------------------------------*/ FRESULT FFS::readdir( DIR *dj, /* Pointer to the open directory object */ FILINFO *fno /* Pointer to file information to return */ ) { return f_readdir(dj, fno); } FRESULT FFS::readdir( FILINFO *fno /* Pointer to file information to return */ ) { return f_readdir(&dir_obj, fno); } FRESULT FFS::readdir( void /* Working copies of directory object & file */ ) { return f_readdir(&dir_obj, NULL); } #if _FS_MINIMIZE == 0 /*-----------------------------------------------------------------------*/ /* Get File Status */ /*-----------------------------------------------------------------------*/ FRESULT FFS::stat( const TCHAR *path, /* Pointer to the file path */ FILINFO *fno /* Pointer to file information to return */ ) { return f_stat(path, fno); } #if !_FS_READONLY /*-----------------------------------------------------------------------*/ /* Get Number of Free Clusters */ /*-----------------------------------------------------------------------*/ FRESULT FFS::getfree( const TCHAR *path, /* Pointer to the logical drive number (root dir) */ DWORD *nclst, /* Pointer to the variable to return number of free clusters */ FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ ) { return f_getfree(path, nclst, fatfs); } /*-----------------------------------------------------------------------*/ /* Truncate File */ /*-----------------------------------------------------------------------*/ FRESULT FFS::truncate( FIL *fp /* Pointer to the file object */ ) { return f_truncate(fp); } FRESULT FFS::truncate( void /* Working copy file object */ ) { return f_truncate(&fil_obj); } #if !_FS_READONLY /*-----------------------------------------------------------------------*/ /* Synchronize the File Object */ /*-----------------------------------------------------------------------*/ FRESULT FFS::sync( FIL *fp /* Pointer to the file object */ ) { return f_sync(fp); } FRESULT FFS::sync( void /* Working copy file object */ ) { return f_sync(&fil_obj); } #endif /* !_FS_READONLY */ /*-----------------------------------------------------------------------*/ /* Delete a File or Directory */ /*-----------------------------------------------------------------------*/ FRESULT FFS::unlink( const TCHAR *path /* Pointer to the file or directory path */ ) { return f_unlink(path); } /*-----------------------------------------------------------------------*/ /* Create a Directory */ /*-----------------------------------------------------------------------*/ FRESULT FFS::mkdir( const TCHAR *path /* Pointer to the directory path */ ) { return f_mkdir(path); } /*-----------------------------------------------------------------------*/ /* Change File Attribute */ /*-----------------------------------------------------------------------*/ FRESULT FFS::chmod( const TCHAR *path, /* Pointer to the file path */ unsigned char value, /* Attribute bits */ unsigned char mask /* Attribute mask to change */ ) { return f_chmod(path, value, mask); } /*-----------------------------------------------------------------------*/ /* Change Timestamp */ /*-----------------------------------------------------------------------*/ FRESULT FFS::utime( const TCHAR *path, /* Pointer to the file/directory name */ const FILINFO *fno /* Pointer to the timestamp to be set */ ) { return f_utime(path, fno); } /*-----------------------------------------------------------------------*/ /* Rename File/Directory */ /*-----------------------------------------------------------------------*/ FRESULT FFS::rename( const TCHAR *path_old, /* Pointer to the old name */ const TCHAR *path_new /* Pointer to the new name */ ) { return f_rename(path_old, path_new); } #endif /* !_FS_READONLY */ #endif /* _FS_MINIMIZE == 0 */ #endif /* _FS_MINIMIZE <= 1 */ #endif /* _FS_MINIMIZE <= 2 */ #if _USE_FORWARD && _FS_TINY /*-----------------------------------------------------------------------*/ /* Forward data to the stream directly (Available on only _FS_TINY cfg) */ /*-----------------------------------------------------------------------*/ FRESULT FFS::forward( FIL *fp, /* Pointer to the file object */ UINT(*func)(const unsigned char*, UINT) out_stream, /* Pointer to the streaming function */ UINT btr, /* Number of bytes to forward */ UINT *bf /* Pointer to number of bytes forwarded */ ) { return f_forward(fp, out_stream, btr, bf); } #endif /* _USE_FORWARD */ #if _USE_MKFS && !_FS_READONLY /*-----------------------------------------------------------------------*/ /* Create File System on the Drive */ /*-----------------------------------------------------------------------*/ FRESULT FFS::mkfs( unsigned char drv, /* Logical drive number */ unsigned char partition, /* Partitioning rule 0:FDISK, 1:SFD */ WORD allocsize /* Allocation unit size [bytes] */ ) { return f_mkfs(drv, partition, allocsize); } #endif /* _USE_MKFS && !_FS_READONLY */ #if _USE_STRFUNC /*-----------------------------------------------------------------------*/ /* Get a string from the file */ /*-----------------------------------------------------------------------*/ char* FFS::gets( char* buff, /* Pointer to the string buffer to read */ int len, /* Size of string buffer */ FIL* fil /* Pointer to the file object */ ) { return f_gets(buff, len, fil); } char* FFS::gets( char* buff, /* Pointer to the string buffer to read */ int len /* Size of string buffer */ ) { return f_gets(buff, len, &fil_obj); } #if !_FS_READONLY #include <stdarg.h> /*-----------------------------------------------------------------------*/ /* Put a character to the file */ /*-----------------------------------------------------------------------*/ /* Since putc is also a macro, use fputc to avoid any parameter conflict */ int FFS::fputc( int chr, /* A character to be output */ FIL* fil /* Ponter to the file object */ ) { return f_putc(chr, fil); } int FFS::fputc( int chr /* A character to be output */ ) { return f_putc(chr, &fil_obj); } /*-----------------------------------------------------------------------*/ /* Put a string to the file */ /*-----------------------------------------------------------------------*/ int FFS::puts( const char* str, /* Pointer to the string to be output */ FIL* fil /* Pointer to the file object */ ) { return f_puts(str, fil); } int FFS::puts( const char* str /* Pointer to the string to be output */ ) { return f_puts(str, &fil_obj); } /*-----------------------------------------------------------------------*/ /* Put a formatted string to the file */ /*-----------------------------------------------------------------------*/ int FFS::printf( FIL* fil, /* Pointer to the file object */ const char* str, /* Pointer to the format string */ ... /* Optional arguments... */ ) { int res; va_list arp; va_start(arp, str); res = f_vprintf(fil, str, arp); va_end(arp); return res; } int FFS::printf( const char* str, /* Pointer to the format string */ ... /* Optional arguments... */ ) { int res; va_list arp; va_start(arp, str); res = f_vprintf(&fil_obj, str, arp); va_end(arp); return res; } #endif /* !_FS_READONLY */ #endif /* _USE_STRFUNC */ /*-----------------------------------------------------------------------*/ /* Instantiate FFS for use by MSP430 */ /*-----------------------------------------------------------------------*/ FFS Jaffl = FFS(); /* Create usable instance */