|
-
- #include <SPI.h>
- #include <SdFat.h>
- #include <SdFatUtil.h>
-
-
- #include "UserDataType.h"
-
-
- void acquireData(data_t* data) {
- data->time = micros();
- for (int i = 0; i < ADC_DIM; i++) {
- data->adc[i] = analogRead(i);
- }
- }
-
-
- void printData(Print* pr, data_t* data) {
- pr->print(data->time);
- for (int i = 0; i < ADC_DIM; i++) {
- pr->write(',');
- pr->print(data->adc[i]);
- }
- pr->println();
- }
-
-
- void printHeader(Print* pr) {
- pr->print(F("time"));
- for (int i = 0; i < ADC_DIM; i++) {
- pr->print(F(",adc"));
- pr->print(i);
- }
- pr->println();
- }
-
-
-
-
- const uint32_t LOG_INTERVAL_USEC = 2000;
-
-
-
-
- const uint8_t SD_CS_PIN = SS;
-
-
-
-
- const int8_t ERROR_LED_PIN = -1;
-
-
-
-
-
-
-
- const uint32_t FILE_BLOCK_COUNT = 256000;
-
-
- #define FILE_BASE_NAME "data"
-
-
-
-
-
-
- #ifndef RAMEND
-
- const uint8_t BUFFER_BLOCK_COUNT = 8;
-
- #elif RAMEND < 0X8FF
- #error Too little SRAM
-
- #elif RAMEND < 0X10FF
-
- const uint8_t BUFFER_BLOCK_COUNT = 1;
-
- #elif RAMEND < 0X20FF
-
- const uint8_t BUFFER_BLOCK_COUNT = 4;
-
- #else
-
- const uint8_t BUFFER_BLOCK_COUNT = 12;
- #endif
-
-
-
-
- #define TMP_FILE_NAME "tmp_log.bin"
-
-
- const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
-
- SdFat sd;
-
- SdBaseFile binFile;
-
- char binName[13] = FILE_BASE_NAME "00.bin";
-
-
- const uint16_t DATA_DIM = (512 - 4)/sizeof(data_t);
-
-
- const uint16_t FILL_DIM = 512 - 4 - DATA_DIM*sizeof(data_t);
-
- struct block_t {
- uint16_t count;
- uint16_t overrun;
- data_t data[DATA_DIM];
- uint8_t fill[FILL_DIM];
- };
-
- const uint8_t QUEUE_DIM = BUFFER_BLOCK_COUNT + 2;
-
- block_t* emptyQueue[QUEUE_DIM];
- uint8_t emptyHead;
- uint8_t emptyTail;
-
- block_t* fullQueue[QUEUE_DIM];
- uint8_t fullHead;
- uint8_t fullTail;
-
-
- inline uint8_t queueNext(uint8_t ht) {
- return ht < (QUEUE_DIM - 1) ? ht + 1 : 0;
- }
-
-
- #define error(msg) errorFlash(F(msg))
-
- void errorFlash(const __FlashStringHelper* msg) {
- sd.errorPrint(msg);
- fatalBlink();
- }
-
-
- void fatalBlink() {
- while (true) {
- if (ERROR_LED_PIN >= 0) {
- digitalWrite(ERROR_LED_PIN, HIGH);
- delay(200);
- digitalWrite(ERROR_LED_PIN, LOW);
- delay(200);
- }
- }
- }
-
-
- void binaryToCsv() {
- uint8_t lastPct = 0;
- block_t block;
- uint32_t t0 = millis();
- uint32_t syncCluster = 0;
- SdFile csvFile;
- char csvName[13];
-
- if (!binFile.isOpen()) {
- Serial.println();
- Serial.println(F("No current binary file"));
- return;
- }
- binFile.rewind();
-
- strcpy(csvName, binName);
- strcpy(&csvName[BASE_NAME_SIZE + 3], "csv");
-
- if (!csvFile.open(csvName, O_WRITE | O_CREAT | O_TRUNC)) {
- error("open csvFile failed");
- }
- Serial.println();
- Serial.print(F("Writing: "));
- Serial.print(csvName);
- Serial.println(F(" - type any character to stop"));
- printHeader(&csvFile);
- uint32_t tPct = millis();
- while (!Serial.available() && binFile.read(&block, 512) == 512) {
- uint16_t i;
- if (block.count == 0) {
- break;
- }
- if (block.overrun) {
- csvFile.print(F("OVERRUN,"));
- csvFile.println(block.overrun);
- }
- for (i = 0; i < block.count; i++) {
- printData(&csvFile, &block.data[i]);
- }
- if (csvFile.curCluster() != syncCluster) {
- csvFile.sync();
- syncCluster = csvFile.curCluster();
- }
- if ((millis() - tPct) > 1000) {
- uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100);
- if (pct != lastPct) {
- tPct = millis();
- lastPct = pct;
- Serial.print(pct, DEC);
- Serial.println('%');
- }
- }
- if (Serial.available()) {
- break;
- }
- }
- csvFile.close();
- Serial.print(F("Done: "));
- Serial.print(0.001*(millis() - t0));
- Serial.println(F(" Seconds"));
- }
-
-
- void checkOverrun() {
- bool headerPrinted = false;
- block_t block;
- uint32_t bgnBlock, endBlock;
- uint32_t bn = 0;
-
- if (!binFile.isOpen()) {
- Serial.println();
- Serial.println(F("No current binary file"));
- return;
- }
- if (!binFile.contiguousRange(&bgnBlock, &endBlock)) {
- error("contiguousRange failed");
- }
- binFile.rewind();
- Serial.println();
- Serial.println(F("Checking overrun errors - type any character to stop"));
- while (binFile.read(&block, 512) == 512) {
- if (block.count == 0) {
- break;
- }
- if (block.overrun) {
- if (!headerPrinted) {
- Serial.println();
- Serial.println(F("Overruns:"));
- Serial.println(F("fileBlockNumber,sdBlockNumber,overrunCount"));
- headerPrinted = true;
- }
- Serial.print(bn);
- Serial.print(',');
- Serial.print(bgnBlock + bn);
- Serial.print(',');
- Serial.println(block.overrun);
- }
- bn++;
- }
- if (!headerPrinted) {
- Serial.println(F("No errors found"));
- } else {
- Serial.println(F("Done"));
- }
- }
-
-
- void dumpData() {
- block_t block;
- if (!binFile.isOpen()) {
- Serial.println();
- Serial.println(F("No current binary file"));
- return;
- }
- binFile.rewind();
- Serial.println();
- Serial.println(F("Type any character to stop"));
- delay(1000);
- printHeader(&Serial);
- while (!Serial.available() && binFile.read(&block , 512) == 512) {
- if (block.count == 0) {
- break;
- }
- if (block.overrun) {
- Serial.print(F("OVERRUN,"));
- Serial.println(block.overrun);
- }
- for (uint16_t i = 0; i < block.count; i++) {
- printData(&Serial, &block.data[i]);
- }
- }
- Serial.println(F("Done"));
- }
-
-
-
- uint32_t const ERASE_SIZE = 262144L;
- void logData() {
- uint32_t bgnBlock, endBlock;
-
-
- block_t block[BUFFER_BLOCK_COUNT];
- block_t* curBlock = 0;
- Serial.println();
-
-
- if (BASE_NAME_SIZE > 6) {
- error("FILE_BASE_NAME too long");
- }
- while (sd.exists(binName)) {
- if (binName[BASE_NAME_SIZE + 1] != '9') {
- binName[BASE_NAME_SIZE + 1]++;
- } else {
- binName[BASE_NAME_SIZE + 1] = '0';
- if (binName[BASE_NAME_SIZE] == '9') {
- error("Can't create file name");
- }
- binName[BASE_NAME_SIZE]++;
- }
- }
-
- if (sd.exists(TMP_FILE_NAME)) {
- Serial.println(F("Deleting tmp file"));
- if (!sd.remove(TMP_FILE_NAME)) {
- error("Can't remove tmp file");
- }
- }
-
- Serial.println(F("Creating new file"));
- binFile.close();
- if (!binFile.createContiguous(sd.vwd(),
- TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) {
- error("createContiguous failed");
- }
-
- if (!binFile.contiguousRange(&bgnBlock, &endBlock)) {
- error("contiguousRange failed");
- }
-
- uint8_t* cache = (uint8_t*)sd.vol()->cacheClear();
- if (cache == 0) {
- error("cacheClear failed");
- }
-
-
- Serial.println(F("Erasing all data"));
- uint32_t bgnErase = bgnBlock;
- uint32_t endErase;
- while (bgnErase < endBlock) {
- endErase = bgnErase + ERASE_SIZE;
- if (endErase > endBlock) {
- endErase = endBlock;
- }
- if (!sd.card()->erase(bgnErase, endErase)) {
- error("erase failed");
- }
- bgnErase = endErase + 1;
- }
-
- if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) {
- error("writeBegin failed");
- }
-
- emptyHead = emptyTail = 0;
- fullHead = fullTail = 0;
-
-
- emptyQueue[emptyHead] = (block_t*)cache;
- emptyHead = queueNext(emptyHead);
-
-
- for (uint8_t i = 0; i < BUFFER_BLOCK_COUNT; i++) {
- emptyQueue[emptyHead] = &block[i];
- emptyHead = queueNext(emptyHead);
- }
- Serial.println(F("Logging - type any character to stop"));
-
- Serial.flush();
- delay(10);
- uint32_t bn = 0;
- uint32_t t0 = millis();
- uint32_t t1 = t0;
- uint32_t overrun = 0;
- uint32_t overrunTotal = 0;
- uint32_t count = 0;
- uint32_t maxLatency = 0;
- int32_t diff;
-
- uint32_t logTime = micros()/LOG_INTERVAL_USEC + 1;
- logTime *= LOG_INTERVAL_USEC;
- bool closeFile = false;
- while (1) {
-
- logTime += LOG_INTERVAL_USEC;
- if (Serial.available()) {
- closeFile = true;
- }
-
- if (closeFile) {
- if (curBlock != 0 && curBlock->count >= 0) {
-
- fullQueue[fullHead] = curBlock;
- fullHead = queueNext(fullHead);
- curBlock = 0;
- }
- } else {
- if (curBlock == 0 && emptyTail != emptyHead) {
- curBlock = emptyQueue[emptyTail];
- emptyTail = queueNext(emptyTail);
- curBlock->count = 0;
- curBlock->overrun = overrun;
- overrun = 0;
- }
- do {
- diff = logTime - micros();
- } while(diff > 0);
- if (diff < -10) {
- error("LOG_INTERVAL_USEC too small");
- }
- if (curBlock == 0) {
- overrun++;
- } else {
- acquireData(&curBlock->data[curBlock->count++]);
- if (curBlock->count == DATA_DIM) {
- fullQueue[fullHead] = curBlock;
- fullHead = queueNext(fullHead);
- curBlock = 0;
- }
- }
- }
-
- if (fullHead == fullTail) {
-
- if (closeFile) {
- break;
- }
- } else if (!sd.card()->isBusy()) {
-
- block_t* pBlock = fullQueue[fullTail];
- fullTail = queueNext(fullTail);
-
- uint32_t usec = micros();
- if (!sd.card()->writeData((uint8_t*)pBlock)) {
- error("write data failed");
- }
- usec = micros() - usec;
- t1 = millis();
- if (usec > maxLatency) {
- maxLatency = usec;
- }
- count += pBlock->count;
-
-
- if (pBlock->overrun) {
- overrunTotal += pBlock->overrun;
- if (ERROR_LED_PIN >= 0) {
- digitalWrite(ERROR_LED_PIN, HIGH);
- }
- }
-
- emptyQueue[emptyHead] = pBlock;
- emptyHead = queueNext(emptyHead);
- bn++;
- if (bn == FILE_BLOCK_COUNT) {
-
- break;
- }
- }
- }
- if (!sd.card()->writeStop()) {
- error("writeStop failed");
- }
-
- if (bn != FILE_BLOCK_COUNT) {
- Serial.println(F("Truncating file"));
- if (!binFile.truncate(512L * bn)) {
- error("Can't truncate file");
- }
- }
- if (!binFile.rename(sd.vwd(), binName)) {
- error("Can't rename file");
- }
- Serial.print(F("File renamed: "));
- Serial.println(binName);
- Serial.print(F("Max block write usec: "));
- Serial.println(maxLatency);
- Serial.print(F("Record time sec: "));
- Serial.println(0.001*(t1 - t0), 3);
- Serial.print(F("Sample count: "));
- Serial.println(count);
- Serial.print(F("Samples/sec: "));
- Serial.println((1000.0)*count/(t1-t0));
- Serial.print(F("Overruns: "));
- Serial.println(overrunTotal);
- Serial.println(F("Done"));
- }
-
- void setup(void) {
- if (ERROR_LED_PIN >= 0) {
- pinMode(ERROR_LED_PIN, OUTPUT);
- }
- Serial.begin(9600);
- while (!Serial) {}
-
- Serial.print(F("FreeRam: "));
- Serial.println(FreeRam());
- Serial.print(F("Records/block: "));
- Serial.println(DATA_DIM);
- if (sizeof(block_t) != 512) {
- error("Invalid block size");
- }
-
- if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) {
- sd.initErrorPrint();
- fatalBlink();
- }
- }
-
- void loop(void) {
-
- while (Serial.read() >= 0) {}
- Serial.println();
- Serial.println(F("type:"));
- Serial.println(F("c - convert file to csv"));
- Serial.println(F("d - dump data to Serial"));
- Serial.println(F("e - overrun error details"));
- Serial.println(F("r - record data"));
-
- while(!Serial.available()) {}
- char c = tolower(Serial.read());
-
-
- do {
- delay(10);
- } while (Serial.read() >= 0);
-
- if (ERROR_LED_PIN >= 0) {
- digitalWrite(ERROR_LED_PIN, LOW);
- }
- if (c == 'c') {
- binaryToCsv();
- } else if (c == 'd') {
- dumpData();
- } else if (c == 'e') {
- checkOverrun();
- } else if (c == 'r') {
- logData();
- } else {
- Serial.println(F("Invalid entry"));
- }
- }
|