mirror of https://github.com/JorjBauer/aiie.git
convert from uSDFS to SdFat
This commit is contained in:
parent
4f31e16fd2
commit
e2884d2a90
14
README.md
14
README.md
|
@ -92,20 +92,12 @@ case-insensitive, you'll have to do something like this:
|
||||||
|
|
||||||
I'm also using these libraries that don't come with TeensyDuino:
|
I'm also using these libraries that don't come with TeensyDuino:
|
||||||
|
|
||||||
### uSDFS ###
|
### SdFat ###
|
||||||
|
|
||||||
This has long filename support, where the Teensy SD library
|
SD card support - accelerated for the Teensy, and with long filename support.
|
||||||
doesn't. It's pretty messy code, though, and I hope to abandon it
|
|
||||||
eventually.
|
|
||||||
|
|
||||||
https://github.com/WMXZ-EU/uSDFS
|
https://github.com/greiman/SdFat
|
||||||
|
|
||||||
### RadioHead ###
|
|
||||||
|
|
||||||
This library comes with TeensyDuino, but I found the version that's
|
|
||||||
with 1.35 hangs. Using the stock v1.70 seems to be fine.
|
|
||||||
|
|
||||||
http://www.airspayce.com/mikem/arduino/RadioHead
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,42 +1,22 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include "ff.h" // File System
|
#include <SdFat.h>
|
||||||
#include "teensy-filemanager.h"
|
#include "teensy-filemanager.h"
|
||||||
#include <string.h> // strcpy
|
#include <string.h> // strcpy
|
||||||
|
|
||||||
|
|
||||||
// FIXME: globals are yucky.
|
// FIXME: globals are yucky.
|
||||||
DIR dir;
|
SdFatSdio sd;
|
||||||
FILINFO fno;
|
File file;
|
||||||
FIL fil;
|
|
||||||
|
|
||||||
int8_t rawFd = -1;
|
|
||||||
FIL rawFil;
|
|
||||||
|
|
||||||
static TCHAR *char2tchar( const char *charString, int nn, TCHAR *output)
|
|
||||||
{
|
|
||||||
int ii;
|
|
||||||
for (ii=0; ii<nn; ii++) {
|
|
||||||
output[ii] = (TCHAR)charString[ii];
|
|
||||||
if (!charString[ii])
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char * tchar2char( const TCHAR * tcharString, int nn, char * charString)
|
|
||||||
{ int ii;
|
|
||||||
for(ii = 0; ii<nn; ii++)
|
|
||||||
{ charString[ii] = (char)tcharString[ii];
|
|
||||||
if(!charString[ii]) break;
|
|
||||||
}
|
|
||||||
return charString;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
uint8_t rawFd;
|
||||||
|
File rawFile;
|
||||||
|
|
||||||
TeensyFileManager::TeensyFileManager()
|
TeensyFileManager::TeensyFileManager()
|
||||||
{
|
{
|
||||||
numCached = 0;
|
numCached = 0;
|
||||||
|
|
||||||
|
enabled = sd.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
TeensyFileManager::~TeensyFileManager()
|
TeensyFileManager::~TeensyFileManager()
|
||||||
|
@ -45,9 +25,8 @@ TeensyFileManager::~TeensyFileManager()
|
||||||
|
|
||||||
int8_t TeensyFileManager::openFile(const char *name)
|
int8_t TeensyFileManager::openFile(const char *name)
|
||||||
{
|
{
|
||||||
// invalidate the raw file cache
|
|
||||||
if (rawFd != -1) {
|
if (rawFd != -1) {
|
||||||
f_close(&rawFil);
|
rawFile.close();
|
||||||
rawFd = -1;
|
rawFd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,11 +56,8 @@ int8_t TeensyFileManager::openFile(const char *name)
|
||||||
|
|
||||||
void TeensyFileManager::closeFile(int8_t fd)
|
void TeensyFileManager::closeFile(int8_t fd)
|
||||||
{
|
{
|
||||||
// invalidate the raw file cache
|
|
||||||
if (rawFd != -1) {
|
if (rawFd != -1) {
|
||||||
Serial.print("Invalidating raw file cache ");
|
rawFile.close();
|
||||||
Serial.println(rawFd);
|
|
||||||
f_close(&rawFil);
|
|
||||||
rawFd = -1;
|
rawFd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,35 +91,28 @@ int8_t TeensyFileManager::readDir(const char *where, const char *suffix, char *o
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t idxCount = 1;
|
int8_t idxCount = 1;
|
||||||
TCHAR buf[MAXPATH];
|
File f = sd.open(where);
|
||||||
char2tchar(where, MAXPATH, buf);
|
|
||||||
buf[strlen(where)-1] = '\0'; // this library doesn't want trailing slashes
|
|
||||||
FRESULT rc = f_opendir(&dir, buf);
|
|
||||||
if (rc) {
|
|
||||||
Serial.printf("f_opendir '%s' failed: %d\n", where, rc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
rc = f_readdir(&dir, &fno);
|
File e = f.openNextFile();
|
||||||
if (rc || !fno.fname[0]) {
|
if (!e) {
|
||||||
// No more - all done.
|
// No more - all done.
|
||||||
f_closedir(&dir);
|
f.close();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fno.fname[0] == '.' || fno.fname[0] == '_' || fno.fname[0] == '~') {
|
// Skip MAC fork files
|
||||||
// skip MAC fork files and any that have been deleted :/
|
e.getName(outputFN, maxlen-1); // -1 for trailing '/' on directories
|
||||||
|
if (outputFN[0] == '.') {
|
||||||
|
e.close();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip anything that has the wrong suffix
|
// skip anything that has the wrong suffix and isn't a directory
|
||||||
char fn[MAXPATH];
|
if (suffix && !e.isDirectory() && strlen(outputFN) >= 3) {
|
||||||
tchar2char(fno.fname, MAXPATH, fn);
|
const char *fsuff = &outputFN[strlen(outputFN)-3];
|
||||||
if (suffix && !(fno.fattrib & AM_DIR) && strlen(fn) >= 3) {
|
|
||||||
const char *fsuff = &fn[strlen(fn)-3];
|
|
||||||
if (strstr(suffix, ",")) {
|
if (strstr(suffix, ",")) {
|
||||||
// multiple suffixes to check
|
// multiple suffixes to check - all must be 3 chars long, FIXME
|
||||||
bool matchesAny = false;
|
bool matchesAny = false;
|
||||||
const char *p = suffix;
|
const char *p = suffix;
|
||||||
while (p && strlen(p)) {
|
while (p && strlen(p)) {
|
||||||
|
@ -153,21 +122,25 @@ int8_t TeensyFileManager::readDir(const char *where, const char *suffix, char *o
|
||||||
}
|
}
|
||||||
p = strstr(p, ",")+1;
|
p = strstr(p, ",")+1;
|
||||||
}
|
}
|
||||||
if (!matchesAny)
|
if (!matchesAny) {
|
||||||
|
e.close();
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// one suffix to check
|
// one suffix to check
|
||||||
if (strcasecmp(fsuff, suffix))
|
if (strcasecmp(fsuff, suffix)) {
|
||||||
|
e.close();
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idxCount == startIdx) {
|
if (idxCount == startIdx) {
|
||||||
if (fno.fattrib & AM_DIR) {
|
if (e.isDirectory()) {
|
||||||
strcat(fn, "/");
|
strcat(outputFN, "/");
|
||||||
}
|
}
|
||||||
strncpy(outputFN, fn, maxlen);
|
e.close();
|
||||||
f_closedir(&dir);
|
f.close();
|
||||||
return idxCount;
|
return idxCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,25 +168,21 @@ bool TeensyFileManager::readTrack(int8_t fd, uint8_t *toWhere, bool isNib)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// open, seek, read, close.
|
// open, seek, read, close.
|
||||||
TCHAR buf[MAXPATH];
|
File f = sd.open(cachedNames[fd], FILE_READ);
|
||||||
char2tchar(cachedNames[fd], MAXPATH, buf);
|
if (!f) {
|
||||||
FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_READ);
|
|
||||||
if (rc) {
|
|
||||||
Serial.println("failed to open");
|
Serial.println("failed to open");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = f_lseek(&fil, fileSeekPositions[fd]);
|
if (!f.seek(fileSeekPositions[fd])) {
|
||||||
if (rc) {
|
|
||||||
Serial.println("readTrack: seek failed");
|
Serial.println("readTrack: seek failed");
|
||||||
f_close(&fil);
|
f.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT v;
|
int nRead = f.read(toWhere, isNib ? 0x1a00 : (256 * 16));
|
||||||
f_read(&fil, toWhere, isNib ? 0x1a00 : (256 * 16), &v);
|
f.close();
|
||||||
f_close(&fil);
|
return (nRead == (isNib ? 0x1a00 : (256 * 16)));
|
||||||
return (v == (isNib ? 0x1a00 : (256 * 16)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TeensyFileManager::readBlock(int8_t fd, uint8_t *toWhere, bool isNib)
|
bool TeensyFileManager::readBlock(int8_t fd, uint8_t *toWhere, bool isNib)
|
||||||
|
@ -226,24 +195,21 @@ bool TeensyFileManager::readBlock(int8_t fd, uint8_t *toWhere, bool isNib)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// open, seek, read, close.
|
// open, seek, read, close.
|
||||||
TCHAR buf[MAXPATH];
|
File f = sd.open(cachedNames[fd], FILE_READ);
|
||||||
char2tchar(cachedNames[fd], MAXPATH, buf);
|
if (!f) {
|
||||||
FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_READ);
|
|
||||||
if (rc) {
|
|
||||||
Serial.println("failed to open");
|
Serial.println("failed to open");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = f_lseek(&fil, fileSeekPositions[fd]);
|
if (!f.seek(fileSeekPositions[fd])) {
|
||||||
if (rc) {
|
|
||||||
Serial.println("readBlock: seek failed");
|
Serial.println("readBlock: seek failed");
|
||||||
f_close(&fil);
|
f.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UINT v;
|
|
||||||
f_read(&fil, toWhere, isNib ? 416 : 256, &v);
|
int nRead = f.read(toWhere, isNib ? 416 : 256);
|
||||||
f_close(&fil);
|
f.close();
|
||||||
return (v == (isNib ? 416 : 256));
|
return (nRead == (isNib ? 416 : 256));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TeensyFileManager::writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib)
|
bool TeensyFileManager::writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib)
|
||||||
|
@ -260,14 +226,16 @@ bool TeensyFileManager::writeBlock(int8_t fd, uint8_t *fromWhere, bool isNib)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// open, seek, write, close.
|
// open, seek, write, close.
|
||||||
TCHAR buf[MAXPATH];
|
File f = sd.open(cachedNames[fd], FILE_WRITE);
|
||||||
char2tchar(cachedNames[fd], MAXPATH, buf);
|
if (!f ||
|
||||||
FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_WRITE);
|
!f.seek(fileSeekPositions[fd])) {
|
||||||
rc = f_lseek(&fil, fileSeekPositions[fd]);
|
f.close();
|
||||||
UINT v;
|
return false;
|
||||||
f_write(&fil, fromWhere, 256, &v);
|
}
|
||||||
f_close(&fil);
|
|
||||||
return (v == 256);
|
int nWritten = f.write(fromWhere, 256);
|
||||||
|
f.close();
|
||||||
|
return (nWritten == 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TeensyFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib)
|
bool TeensyFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib)
|
||||||
|
@ -280,20 +248,22 @@ bool TeensyFileManager::writeTrack(int8_t fd, uint8_t *fromWhere, bool isNib)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// open, seek, write, close.
|
// open, seek, write, close.
|
||||||
TCHAR buf[MAXPATH];
|
File f = sd.open(cachedNames[fd], FILE_WRITE);
|
||||||
char2tchar(cachedNames[fd], MAXPATH, buf);
|
if (!f)
|
||||||
FRESULT rc = f_open(&fil, (TCHAR*) buf, FA_WRITE);
|
return false;
|
||||||
rc = f_lseek(&fil, fileSeekPositions[fd]);
|
|
||||||
UINT v;
|
if (!f.seek(fileSeekPositions[fd])) {
|
||||||
f_write(&fil, fromWhere, isNib ? 0x1a00 : (256*16), &v);
|
f.close();
|
||||||
f_close(&fil);
|
return false;
|
||||||
return (v == (isNib ? 0x1a00 : (256*16)));
|
}
|
||||||
|
|
||||||
|
int nWritten = f.write(fromWhere, isNib ? 0x1a00 : (256*16));
|
||||||
|
f.close();
|
||||||
|
return (nWritten == (isNib ? 0x1a00 : (256*16)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TeensyFileManager::_prepCache(int8_t fd)
|
bool TeensyFileManager::_prepCache(int8_t fd)
|
||||||
{
|
{
|
||||||
FRESULT rc;
|
|
||||||
|
|
||||||
if (rawFd == -1 ||
|
if (rawFd == -1 ||
|
||||||
rawFd != fd) {
|
rawFd != fd) {
|
||||||
|
|
||||||
|
@ -301,16 +271,13 @@ bool TeensyFileManager::_prepCache(int8_t fd)
|
||||||
if (rawFd != -1) {
|
if (rawFd != -1) {
|
||||||
// Close the old one if we had one
|
// Close the old one if we had one
|
||||||
Serial.println("closing old cache file");
|
Serial.println("closing old cache file");
|
||||||
f_close(&rawFil);
|
rawFile.close();
|
||||||
rawFd = -1;
|
rawFd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println("opening new cache file");
|
Serial.println("opening new cache file");
|
||||||
// Open the new one
|
// Open the new one
|
||||||
TCHAR buf[MAXPATH];
|
if (!sd.open(cachedNames[fd], O_RDWR | O_CREAT)) {
|
||||||
char2tchar(cachedNames[fd], MAXPATH, buf);
|
|
||||||
rc = f_open(&rawFil, (TCHAR*) buf, FA_READ|FA_WRITE|FA_OPEN_ALWAYS);
|
|
||||||
if (rc) {
|
|
||||||
Serial.print("_prepCache: failed to open ");
|
Serial.print("_prepCache: failed to open ");
|
||||||
Serial.println(cachedNames[fd]);
|
Serial.println(cachedNames[fd]);
|
||||||
return false;
|
return false;
|
||||||
|
@ -322,7 +289,7 @@ bool TeensyFileManager::_prepCache(int8_t fd)
|
||||||
// Serial.println("reopning same cache");
|
// Serial.println("reopning same cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (!rc);
|
return true; // FIXME error handling
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos)
|
uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos)
|
||||||
|
@ -334,21 +301,14 @@ uint8_t TeensyFileManager::readByteAt(int8_t fd, uint32_t pos)
|
||||||
if (cachedNames[fd][0] == 0)
|
if (cachedNames[fd][0] == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FRESULT rc;
|
|
||||||
|
|
||||||
_prepCache(fd);
|
_prepCache(fd);
|
||||||
|
|
||||||
rc = f_lseek(&rawFil, pos);
|
if (!rawFile.seek(pos)) {
|
||||||
if (rc) {
|
|
||||||
Serial.println("readByteAt: seek failed");
|
Serial.println("readByteAt: seek failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
UINT v;
|
return (rawFile.read(&b, 1) == 1);
|
||||||
f_read(&rawFil, &b, 1, &v);
|
|
||||||
|
|
||||||
// FIXME: check v == 1 & handle error
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TeensyFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos)
|
bool TeensyFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos)
|
||||||
|
@ -360,15 +320,12 @@ bool TeensyFileManager::writeByteAt(int8_t fd, uint8_t v, uint32_t pos)
|
||||||
if (cachedNames[fd][0] == 0)
|
if (cachedNames[fd][0] == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FRESULT rc;
|
|
||||||
|
|
||||||
_prepCache(fd);
|
_prepCache(fd);
|
||||||
|
|
||||||
rc = f_lseek(&rawFil, pos);
|
if (!rawFile.seek(pos))
|
||||||
UINT ret;
|
return false;
|
||||||
f_write(&rawFil, &v, 1, &ret);
|
|
||||||
|
|
||||||
return (ret == 1);
|
return (rawFile.write(&v, 1) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t TeensyFileManager::readByte(int8_t fd)
|
uint8_t TeensyFileManager::readByte(int8_t fd)
|
||||||
|
@ -380,22 +337,17 @@ uint8_t TeensyFileManager::readByte(int8_t fd)
|
||||||
if (cachedNames[fd][0] == 0)
|
if (cachedNames[fd][0] == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FRESULT rc;
|
|
||||||
|
|
||||||
_prepCache(fd);
|
_prepCache(fd);
|
||||||
|
|
||||||
uint32_t pos = fileSeekPositions[fd];
|
uint32_t pos = fileSeekPositions[fd];
|
||||||
|
|
||||||
rc = f_lseek(&rawFil, pos);
|
if (!rawFile.seek(pos)) {
|
||||||
if (rc) {
|
|
||||||
Serial.println("readByteAt: seek failed");
|
Serial.println("readByteAt: seek failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint8_t b;
|
|
||||||
UINT v;
|
|
||||||
f_read(&rawFil, &b, 1, &v);
|
|
||||||
|
|
||||||
fileSeekPositions[fd]++;
|
uint8_t b;
|
||||||
|
rawFile.read(&b, 1);
|
||||||
|
|
||||||
// FIXME: check v == 1 & handle error
|
// FIXME: check v == 1 & handle error
|
||||||
return b;
|
return b;
|
||||||
|
@ -414,22 +366,20 @@ bool TeensyFileManager::writeByte(int8_t fd, uint8_t v)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FRESULT rc;
|
|
||||||
|
|
||||||
_prepCache(fd);
|
_prepCache(fd);
|
||||||
|
|
||||||
uint32_t pos = fileSeekPositions[fd];
|
uint32_t pos = fileSeekPositions[fd];
|
||||||
|
|
||||||
rc = f_lseek(&rawFil, pos);
|
if (!rawFile.seek(pos)) {
|
||||||
UINT ret;
|
return false;
|
||||||
f_write(&rawFil, &v, 1, &ret);
|
}
|
||||||
|
|
||||||
|
if (rawFile.write(&v, 1) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fileSeekPositions[fd]++;
|
fileSeekPositions[fd]++;
|
||||||
|
|
||||||
if (ret != 1) {
|
return true;
|
||||||
Serial.println("Write failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ret == 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ class TeensyFileManager : public FileManager {
|
||||||
bool _prepCache(int8_t fd);
|
bool _prepCache(int8_t fd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool enabled;
|
||||||
|
|
||||||
int8_t numCached;
|
int8_t numCached;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ff.h> // uSDFS
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include <TimeLib.h>
|
#include <TimeLib.h>
|
||||||
|
@ -23,7 +22,6 @@
|
||||||
uint32_t nextInstructionMicros;
|
uint32_t nextInstructionMicros;
|
||||||
uint32_t startMicros;
|
uint32_t startMicros;
|
||||||
|
|
||||||
FATFS fatfs; /* File system object */
|
|
||||||
BIOS bios;
|
BIOS bios;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -72,9 +70,6 @@ void setup()
|
||||||
Serial.println("Error while setting RTC");
|
Serial.println("Error while setting RTC");
|
||||||
}
|
}
|
||||||
|
|
||||||
TCHAR *device = (TCHAR *)_T("0:/");
|
|
||||||
f_mount (&fatfs, device, 0); /* Mount/Unmount a logical drive */
|
|
||||||
|
|
||||||
pinMode(RESETPIN, INPUT);
|
pinMode(RESETPIN, INPUT);
|
||||||
digitalWrite(RESETPIN, HIGH);
|
digitalWrite(RESETPIN, HIGH);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue