Browse Source

Fixed support of SD-cards

Dmitry Yu Okunev 7 years ago
parent
commit
13184efa6d
1 changed files with 157 additions and 66 deletions
  1. 157 66
      voltloggera0000.ino

+ 157 - 66
voltloggera0000.ino

@@ -1,26 +1,50 @@
 #include <SPI.h>
 #include <TimerOne.h>
+#include <digitalWriteFast.h>
 
 #define FASTADC 1
 
+#define CHANNELS 3 /* possible values: 1, 3, 7 */
+
 #define ETHERNET 1
 #define SDCARD 2
+#define STORETO ETHERNET
+//#define STORETO SDCARD
 
-//#define STORETO ETHERNET
-#define STORETO SDCARD
-
+#define HAVE_LEDS
+//#define LOCKS
+#define DEBUG
 
 #if STORETO == ETHERNET
 #include <EthernetV2_0.h>
 //#define UDP_BUFSIZE UDP_TX_PACKET_MAX_SIZE
-#define UDP_BUFSIZE 800
+#define UDP_BUFSIZE 768
+
+#define STORAGE_LATENCY 25
+
+#define BUFSIZE UDP_BUFSIZE
+
 #endif
 #if STORETO == SDCARD
-#include <SD.h>
+#include <SdFat.h>
+#include <SdFatUtil.h>
+Sd2Card sdCard;
+
+#define SD_BLOCKSIZE 512
+#define SD_BUFSIZE (SD_BLOCKSIZE + 512)
+#define SD_HEADERS "\000voltlogger\000\001\000\000\000VoltloggerA0000\0000"
+
+#define STORAGE_LATENCY 25
+
+#define BUFSIZE SD_BUFSIZE
+
+uint32_t sdWriteBlockAddress;
+uint32_t sdCardSizeBlocks;
+#endif
 
-//#define DUMPFILENAME "voltloggera0000-dump.txt"
-#define DUMPFILENAME "datalog.txt"
-#define SD_BUFSIZE 512
+#ifdef LOCKS
+volatile uint8_t WriteBufferLock_loop = 0;
+volatile uint8_t WriteBufferLock_pushValue = 0;
 #endif
 
 
@@ -82,33 +106,65 @@ void resetFunc() {
 void (*resetFunc)(void) = 0;
 
 
-#if STORETO == ETHERNET
-unsigned char WriteBuffer[UDP_BUFSIZE];
-#endif
-#if STORETO == SDCARD
-unsigned char WriteBuffer[SD_BUFSIZE];
-#endif
-int WriteBufferFilled;
+unsigned char WriteBuffer[BUFSIZE];
+
+volatile uint16_t WriteBufferFilled;
 
 void pushValue()
 {
-  if (WriteBufferFilled >= sizeof(WriteBuffer) - 3) {
+  if (WriteBufferFilled >= BUFSIZE - (1+CHANNELS)*2) {
     return;
   }
 
+#ifdef LOCKS
+  WriteBufferLock_pushValue = 1;
+  if (WriteBufferLock_loop) {
+    WriteBufferLock_pushValue = 0;
+    return;
+  }
+#endif
+
+  //volatile uint16_t newWriteBufferFilled = WriteBufferFilled;
   uint16_t value;
   uint16_t timestamp;
-  value     = analogRead(5);
   timestamp = micros();
   WriteBuffer[WriteBufferFilled++] = timestamp;
   WriteBuffer[WriteBufferFilled++] = timestamp >> 8;
-  WriteBuffer[WriteBufferFilled++] = value;
-  WriteBuffer[WriteBufferFilled++] = value >> 8;
+  
+  uint8_t chan = 0;
+  while (chan < CHANNELS) {
+    value     = analogRead(chan++);
+    WriteBuffer[WriteBufferFilled++] = value;
+    WriteBuffer[WriteBufferFilled++] = value >> 8;
+  }
+  //WriteBufferFilled = newWriteBufferFilled;
+#ifdef LOCKS
+  WriteBufferLock_pushValue = 0;
+#endif
+  //Serial.println(WriteBufferFilled);
+}
+
+
+/* ========= */
+
+void stateWarning() {
+#ifdef HAVE_LEDS
+    digitalWrite(LED_GREEN, LOW);
+    delay(250);
+    digitalWrite(LED_GREEN, HIGH);
+    delay(250);
+    digitalWrite(LED_GREEN, LOW);
+    delay(250);
+    digitalWrite(LED_GREEN, HIGH);
+#endif
+    delay(250);
+    return;
 }
 
+
 void setup()
 {
-  Serial.begin(9600);
+  Serial.begin(115200);
 #ifdef WAIT_FOR_SERIAL
   while (!Serial) {
     ; // wait for serial port to connect. Needed for Leonardo only
@@ -116,26 +172,31 @@ void setup()
 #endif
   Serial.println("Welcome to VoltloggerA0000!\n");
   Serial.println("Starting initialization...");
-/*
+
+#ifdef HAVE_LEDS
   pinMode(LED_GREEN, OUTPUT);
   digitalWrite(LED_GREEN, HIGH);
   pinMode(LED_RED, OUTPUT);
   digitalWrite(LED_RED, HIGH);
-*/
-  SPI.setClockDivider(SPI_CLOCK_DIV2);
+#endif
+
 #if FASTADC
   sbi(ADCSRA, ADPS2);
   cbi(ADCSRA, ADPS1);
   cbi(ADCSRA, ADPS0);
 #endif
-  
+  SPI.setClockDivider(SPI_CLOCK_DIV2);
 #if STORETO == ETHERNET
+
+  
   pinMode(SDCARD_CS,	OUTPUT);
   digitalWrite(SDCARD_CS,	HIGH);		// disable SD card if one in the slot
 #endif
 #if STORETO == SDCARD
   pinMode(W5200_CS, OUTPUT);
+  digitalWrite(W5200_CS,	HIGH);          // disable W5200
 #endif
+
   pinMode(SS,		OUTPUT);
   pinMode(nRST,		OUTPUT);
   pinMode(nPWDN,		OUTPUT);
@@ -151,6 +212,7 @@ void setup()
 
   while(!Ethernet.begin(mac)) {
     Serial.println("Retring DHCP...");
+    stateWarning();
   }
 
   Serial.print("Local address: ");
@@ -158,7 +220,7 @@ void setup()
   Serial.print(":");
   Serial.println(port_local);
   ip_remote = Ethernet.localIP();
-  ip_remote[3] = 2;
+  ip_remote[3] = 3;
   Serial.print("Remote address: ");
   Serial.print(ip_remote);
   Serial.print(":");
@@ -169,54 +231,47 @@ void setup()
 
 #if STORETO == SDCARD
   Serial.println("Initializing SD card...");
-
-  // see if the card is present and can be initialized:
-  while (!SD.begin(SDCARD_CS)) {
-    Serial.println("Card failed, or not present! Retrying...");
-    digitalWrite(LED_GREEN, LOW);
-    delay(250);
-    digitalWrite(LED_GREEN, HIGH);
-    delay(250);
-    digitalWrite(LED_GREEN, LOW);
-    delay(250);
-    digitalWrite(LED_GREEN, HIGH);
-    delay(250);
-  }
-  Serial.println("The card is initialized");
-
-  Serial.println("Trying to open file \""DUMPFILENAME"\" for writting...");
-  sddumpfile = SD.open(DUMPFILENAME, FILE_WRITE);
-  if (!sddumpfile) {
-    Serial.println("Error: Cannot open file \""DUMPFILENAME"\" for writting!");
-    //digitalWrite(LED_GREEN, LOW);
-    delay(1000);
-    resetFunc();
+ 
+  while (!sdCard.begin(SDCARD_CS, SPI_FULL_SPEED)) {
+    Serial.println("Error: Initialization of the SD card failed or it doesn't present! Retrying...");
+    stateWarning();
   }
-
+  sdCardSizeBlocks = sdCard.cardSize();
+  memset(WriteBuffer, 0, SD_BLOCKSIZE);
+  memcpy(WriteBuffer, SD_HEADERS, sizeof(SD_HEADERS));
+  WriteBuffer[13] = CHANNELS;
+  sdCard.writeBlock(0, WriteBuffer);
+  sdWriteBlockAddress = 1;
+  Serial.print("The SD card is initialized. Availiable block-count (512 bytes): ");
+  Serial.println(sdCardSizeBlocks);
 #endif
 
   WriteBufferFilled = 0;
-  //Timer1.initialize(50);
-  //Timer1.attachInterrupt(pushValue);
-  //digitalWrite(LED_RED, LOW);
+  Timer1.initialize(STORAGE_LATENCY * (1 + CHANNELS));
+  Timer1.attachInterrupt(pushValue);
+#ifdef HAVE_LEDS
+  digitalWrite(LED_RED, LOW);
+  //digitalWrite(LED_GREEN, LOW);
+#endif
   Serial.println("Initialization complete.");
   
 }
 
-#define BYTES_PER_PACKET (UDP_BUFSIZE << 2)
 
+/* ========= */
+
+//uint16_t count = 0;
 void loop()
 {
   
-  int oldWriteBufferFilled;
-  int newWriteBufferFilled;
+  volatile uint16_t oldWriteBufferFilled;
 
 #if STORETO == ETHERNET
   udp.beginPacket(ip_remote, port_remote);
 
   oldWriteBufferFilled = WriteBufferFilled;
   udp.write(WriteBuffer, WriteBufferFilled);
-  newWriteBufferFilled = WriteBufferFilled;
+  int newWriteBufferFilled = WriteBufferFilled;
   WriteBufferFilled = 0;
 
   if (oldWriteBufferFilled != newWriteBufferFilled) {
@@ -226,19 +281,55 @@ void loop()
   udp.endPacket();
 #endif
 #if STORETO == SDCARD
-    Serial.print("Writting ");
-    Serial.print(WriteBufferFilled);
-    Serial.println(" bytes to the SD card");
-    while (WriteBufferFilled < );
+/*
+    count++;
+    if (count >> 8 != 0) {
+      Serial.println(count);
+      count = 0;
+    }*/
+
+    //Serial.println("Waiting for data...");
+    if (WriteBufferFilled < SD_BLOCKSIZE) {
+      //pushValue();
+      return;
+    }
+    //Serial.println("Writting the data...");
     oldWriteBufferFilled = WriteBufferFilled;
-    if (sddumpfile.write(WriteBuffer, WriteBufferFilled) != WriteBufferFilled) {
-      Serial.println("problem");
+    sdCard.writeBlock(sdWriteBlockAddress++, WriteBuffer);
+#ifdef LOCKS
+    WriteBufferLock_loop = 1;
+    while(WriteBufferLock_pushValue);
+#endif
+    volatile uint16_t leftLen = WriteBufferFilled - oldWriteBufferFilled;
+    
+    WriteBufferFilled = leftLen;
+
+    if (leftLen > 0) {
+#ifdef DEBUG
+        if (leftLen == 512) {
+          Serial.println("Overflow.");
+        }
+#endif
+        memcpy(WriteBuffer, &WriteBuffer[SD_BLOCKSIZE], leftLen);
     }
-    newWriteBufferFilled = WriteBufferFilled;
-    WriteBufferFilled = 0;
-
-    if (oldWriteBufferFilled != newWriteBufferFilled) {
-      //sddumpfile.write(&WriteBuffer[oldWriteBufferFilled], newWriteBufferFilled - oldWriteBufferFilled);
+#ifdef DEBUG
+    else {
+       Serial.println("No data queued");
+    }
+#endif
+#ifdef LOCKS
+    WriteBufferLock_loop = 0;
+#endif
+    while (sdWriteBlockAddress >= sdCardSizeBlocks) {
+      Serial.println("SD card is full...");
+#ifdef HAVE_LEDS
+      digitalWrite(LED_RED,   LOW);
+      digitalWrite(LED_GREEN, HIGH);
+      delay(500);
+      digitalWrite(LED_RED,   LOW);
+      digitalWrite(LED_GREEN, HIGH);
+#endif
+      delay(500);
     }
 #endif
 }