/************************************************************************************************** * * uDrive * * Version: 1.0.0 - Mai 2009 * Author: Etienne Ribeiro / tutorial assistant caad / eribeiro[at]ethz.ch * Supervisor: Christoph Wartmann / chair for caad - ETH Zürich / wartmann[at].arch.ethz.ch * * Desc: Library to write string-, int- and long-values to an SD-card using uDrive and a * FAT16 formated SD-Card. * Note: You need to upload the latest firmware to your uDrive (this library was * tested with G1-DOS-r07.PmmC released at 26-Apr-2009) * Note: This library uses NewSoftSerial. Make sure you get the latest version at * least V8. Visit: http://arduiniana.org/libraries/NewSoftSerial/ * See: http://www.4dsystems.com.au * * Not implemented: - Low level disk drive commands * - DOS: Reading from uDrive * - DOS: Delete file * - DOS: List directory * - Device info * * Functions: - boolean uDrive_Initialize (int baud) * needs to be called at startup * returns true if successfull * - boolean uDrive_LoadDisk () * needs to be called at startup * returns true if successfull * - boolean uDrive_writeFile (char* Filename, int Value) * Writing int-values to a file on a FAT16 formated uDrive. If the file doesn't exist, it will be created. * returns true if successfull * - boolean uDrive_writeFile (char* Filename, int Value, boolean appendMode) * Writing int-values to a file on a FAT16 formated uDrive. If the file doesn't exist, it will be created. * appendMode: if true, values will be append to existing data, if false file will be overritten. * returns true if successfull * - boolean uDrive_writeFile (char* Filename, long Value) * Writing long-values to a file on a FAT16 formated uDrive. If the file doesn't exist, it will be created. * returns true if successfull * - boolean uDrive_writeFile (char* Filename, long Value, boolean appendMode) * Writing long-values to a file on a FAT16 formated uDrive. If the file doesn't exist, it will be created. * appendMode: if true, values will be append to existing data, if false file will be overritten. * returns true if successfull * - boolean uDrive_writeFile (char* Filename, char* Data) * Writing string-values to a file on a FAT16 formated uDrive. If the file doesn't exist, it will be created. * returns true if successfull * - boolean uDrive_writeFile (char* Filename, char* Data, long Filesize, boolean appendMode) * Writing string-values to a file on a FAT16 formated uDrive. If the file doesn't exist, it will be created. * appendMode: if true, values will be append to existing data, if false file will be overritten. * returns true if successfull * - int uDrive_LengthOfString (char* data) * Get the length of a string. * returns -1 if string too long. * - int uDrive_LengthOfString (char* data, int abort) * Get the length of a string. * abort: max possible length. * returns -1 if string too long. * - int uDrive_Parse (int Value, char* ret) * Parse an int to string * ret: buffer to return the string value. Note: needs to be a char-array larger then the expected return value. * example: char buffer[10] * returns the length of the string * - int uDrive_Parse (int Value, char* ret, int base) * Parse an int to string * ret: buffer to return the string value. Note: needs to be a char-array larger then the expected return value. * example: char buffer[10] * base: 10 for DEC, ... * returns the length of the string * - int uDrive_Parse (long Value, char* ret) * Parse a long to string * ret: buffer to return the string value. Note: needs to be a char-array larger then the expected return value. * example: char buffer[10] * returns the length of the string * - int uDrive_Parse (long Value, char* ret, int base) * Parse a long to string * ret: buffer to return the string value. Note: needs to be a char-array larger then the expected return value. * example: char buffer[10] * base: 10 for DEC, ... * returns the length of the string * - boolean uDrive_HasErrors () * can be called to find out, if an error occured while writing. * * Pins: (starting from left, with chip on top) * Pin 1: Reset * Pin 2: Gnd * Pin 3: Rx (100 to 220 Ohms resister is needed at voltages higher then 3.6V, however my uDrive works without at 5V) * Pin 4: Tx * Pin 5: Vcc 3.3V and 5V works * * Pins on Arduino: Pin 7 to Reset, rest as usual. * ***************************************************************************************************/ //#include <HardwareSerial.h> #include <NewSoftSerial.h> // configurate const int uDrive_AcknoledgementTimeout = 1000; // Time (in ms) to wait for ack // const #define ACK 0x06 // Acknoledge byte (means ok) #define NACK 0x15 // Negative acknoledge byte (means not ok) #define EXTENDED 0x40 #define INITIALIZE_MODULE 0x55 #define INITIALIZE_DISK 0x69 #define READ_FILE 0x61 #define WRITE_FILE 0x74 // var int uDrive_resetPin; //HardwareSerial* uDrive_serial = &Serial1; // Hardware Serial NewSoftSerial uDrive_serial(10, 11); boolean uDrive_isIntitialized = false; boolean uDrive_isDiskloaded = false; boolean uDrive_errors = false; // SETUP // Initialize uDrive boolean uDrive_Initialize (long baud, int resetPin) { // Reset device uDrive_resetPin = resetPin; pinMode (uDrive_resetPin, OUTPUT); digitalWrite (uDrive_resetPin, LOW); delay (10); digitalWrite (uDrive_resetPin, HIGH); delay (1000); // Setup device uDrive_serial.begin(baud); uDrive_serial.print (INITIALIZE_MODULE, BYTE); if (!private_uDrive_CheckAcknoledgement (5000)) return false; // return uDrive_isIntitialized = true; return true; } // Load Disk boolean uDrive_LoadDisk () { uDrive_serial.print (EXTENDED, BYTE); uDrive_serial.print (INITIALIZE_DISK, BYTE); // check if successful if (!private_uDrive_CheckAcknoledgement ()) return false; // return uDrive_isDiskloaded = true; return true; } // FUNCTIONS // Write File boolean uDrive_writeFile (char* Filename, int Value) { char str[] = "/0/0/0/0/0/0/0/0/0/0"; int len = uDrive_Parse (Value, str); return uDrive_writeFile (Filename, str, len, true); } boolean uDrive_writeFile (char* Filename, long Value) { char str[] = "/0/0/0/0/0/0/0/0/0/0"; int len = uDrive_Parse (Value, str); return uDrive_writeFile (Filename, str, len, true); } boolean uDrive_writeFile (char* Filename, char* Data) { int size = uDrive_LengthOfString(Data); return uDrive_writeFile (Filename, Data, size, true); } boolean uDrive_writeFile (char* Filename, char* Data, long Filesize, boolean appendMode) { // check if (Data == NULL) // check if array was passed return false; if (!uDrive_isIntitialized || !uDrive_isDiskloaded) // check if device was initialized return false; // Filename int filenamelength = uDrive_LengthOfString (Filename, 12); if (filenamelength == -1) { // return if filename has more then 12 characters (including .txt or whatever) uDrive_errors = true; return false; } // Options int handshaking = 0; // handshaking: values 0 to 50 (32hex) if (Filesize > 50) handshaking = 50; byte options = 0x00; options += handshaking; // handshaking if (appendMode) // appendmode: 0x00 (no append) or 0x80 (append) options += 0x80; // Write Header uDrive_serial.print (EXTENDED, BYTE); uDrive_serial.print (WRITE_FILE, BYTE); uDrive_serial.print (options, BYTE); // Options for (int i=0;i<filenamelength;i++) // Filename uDrive_serial.print (Filename[i], BYTE); uDrive_serial.print (0x00, BYTE); uDrive_serial.print (((Filesize >> 24) & 0xff), BYTE); // Filesize uDrive_serial.print (((Filesize >> 16) & 0xff), BYTE); uDrive_serial.print (((Filesize >> 8) & 0xff), BYTE); uDrive_serial.print (((Filesize) & 0xff), BYTE); // OK? if (!private_uDrive_CheckAcknoledgement (5000)) { uDrive_errors = true; return false; } // Write Data (Filesize bytes) int loops = 1; if (handshaking > 0) loops = ceil((float)Filesize / (float)handshaking); int tmpFilesize = handshaking; if (tmpFilesize == 0) tmpFilesize = Filesize; for (int iBlocks=0;iBlocks<loops;iBlocks++) { if (iBlocks+1 == loops) tmpFilesize = Filesize - (iBlocks*handshaking); // Write Block for (int i=0; i<tmpFilesize;i++) uDrive_serial.print(Data[i + iBlocks * handshaking]); // OK? if (!private_uDrive_CheckAcknoledgement (5000)) { uDrive_errors = true; return false; } } // return return true; } // PRIVATE FUNCTIONS // Check response if OK boolean private_uDrive_CheckAcknoledgement () { private_uDrive_CheckAcknoledgement (uDrive_AcknoledgementTimeout); } boolean private_uDrive_CheckAcknoledgement (int timeout) { // wait for ack int iDelay = 10; int i = 0; while (!uDrive_serial.available()) { delay (iDelay); if (timeout / iDelay < i) return false; i += 1; } // Read int val = uDrive_serial.read(); // Return if (val != ACK) return false; return true; } // ADDITIONAL FUNCTIONS // uDrive_LengthOfString // return -1 if no end character was found int uDrive_LengthOfString (char* data) { return uDrive_LengthOfString (data, 32000); } int uDrive_LengthOfString (char* data, int abort) { int count = 0; char *p = data; abort += 1; while (*p != '\0') { p++; count++; if (count == abort) return -1; } return count; } // uDrive_Parse // returns the length of the string int uDrive_Parse (int Value, char* ret) { return uDrive_Parse ((long) Value, ret); } int uDrive_Parse (long Value, char* ret) { int base = 10; int buf[8 * sizeof(long)]; // Assumes 8-bit chars. int i = 0; if (Value == 0) { *ret++ = '0'; return 1; } while (Value > 0) { buf[i++] = Value % base; Value /= base; } int len = i; for (i--; i >= 0; i--){ *ret++ = (char)(buf[i] < 10 ? '0' + buf[i] : 'A' + buf[i] - 10); } *ret++ = 0; return len; } // uDrive_HasErrors boolean uDrive_HasErrors () { boolean tmp = uDrive_errors; uDrive_errors = false; return tmp; }