vehicle CAN message log to SD file system using ring buffer memory

Dependencies:   SDFileSystem mbed

Revision:
0:de9553dd79ec
Child:
1:4a538cae9042
diff -r 000000000000 -r de9553dd79ec main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Jan 25 21:04:19 2013 +0000
@@ -0,0 +1,161 @@
+// CAN message log to SD card using can2.attach with ring buffer
+// 2013/Jan/25 using official SDFileSyatem library
+
+#include "mbed.h"
+#include "SDFileSystem.h"
+
+CAN can2(p30, p29);
+CANMessage can_MsgRx;
+Timer timer;
+
+// LED to know the status
+DigitalOut User_Led1(LED1);
+DigitalOut User_Led2(LED2);
+DigitalOut User_Led3(LED3);
+DigitalOut User_Led4(LED4);
+#define LED_ON 1
+#define LED_OFF 0
+
+// status monitor
+Serial pc(USBTX, USBRX); 
+
+SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sclk, cs, name
+FILE *fp;
+int file_open = 0;
+
+// button switch for closing file
+DigitalIn button1(p16);
+DigitalIn button2(p17);
+DigitalIn button3(p18);
+DigitalIn button4(p19);
+int SW0 = 0x0f, SW1 = 0x0f, SW2 = 0x0f, BUTTON = 0;
+Ticker sw_check;
+
+// function prototypes
+void can_check(void);
+void check_sw();
+
+// CAN message buffer
+#define BUFFER_SIZE 512  // buffer size must be power of 2
+#define BUFFER_MASK ( BUFFER_SIZE - 1 )
+unsigned int second[BUFFER_SIZE];
+unsigned short can_id[BUFFER_SIZE];
+unsigned char msg_length[BUFFER_SIZE];
+unsigned char data[8][BUFFER_SIZE];
+volatile unsigned int head = 0;
+volatile unsigned int tail = 0;
+
+int main()
+{
+    button1.mode(PullUp);
+    button2.mode(PullUp);
+    button3.mode(PullUp);
+    button4.mode(PullUp);
+    sw_check.attach_us(&check_sw, 5000);    // status check every 5 msec
+
+    can2.frequency(500000);
+    pc.baud(9600);
+    pc.printf("CAN log to SD card using ring buffer, 9600 bps\r\n");
+
+    User_Led1 = LED_OFF;
+    User_Led2 = LED_OFF;
+    User_Led3 = LED_OFF;
+    User_Led4 = LED_OFF;
+
+    char file_name[20];
+
+    time_t t;
+    t = time( NULL ) + 32400;  // UTC + 9 hours for JST
+    strftime( file_name, 20, "/sd/%y%m%d%H%M.log", localtime( &t ) );
+    pc.printf( "log file is %s\r\n", file_name );
+
+    fp = fopen(file_name, "w");
+    if ( fp == NULL ) {
+        pc.printf("Unable to create the file '%s'\r\n", file_name);
+        pc.printf("Please try again\r\n");
+
+        User_Led1 = LED_OFF;
+        file_open = 0;
+    } else {
+        User_Led1 = LED_ON;
+        file_open = 1;
+    }
+
+    timer.stop();
+    timer.reset();
+    timer.start();
+    can2.attach(&can_check);
+
+    int tmptail;
+    while(1) {
+        if ( head != tail ) {
+            tmptail = (tail + 1) & BUFFER_MASK;
+            fprintf(fp, "%03X,%03X,", head&0xfff, tmptail&0xfff);
+            fprintf(fp, "%08X,", second[tmptail]);
+            fprintf(fp, "t%03X%d", can_id[tmptail], msg_length[tmptail]);
+
+            for (int i=0; i<msg_length[tmptail]; i++) {
+                fprintf(fp, "%02X", data[i][tmptail]);
+            } // for
+            fprintf(fp, "\r\n");
+
+            tail = tmptail; // update tail after data sent
+            if ( tail == 0 ) {
+                // toggle led3
+                User_Led3 = !User_Led3;
+                t = time( NULL ) + 32400;  // UTC + 9 hours for JST
+                strftime( file_name, 20, "%T", localtime( &t ) );
+                pc.printf("new cycle of ring buffer at %s\r\n", file_name);
+            }
+        } // if head != tail
+
+        if ( BUTTON&0x01 ) {    // button1 pressed
+            BUTTON &= 0xfe;     // clear button status
+            can2.attach(0);     // detach CAN interrupt
+            file_open = 0;
+            //Close the file
+            fclose(fp);
+            pc.printf("file closed\r\n");
+            User_Led1 = LED_OFF;
+        } // if button
+    } // while
+} // main
+
+// read CAN2 message using intterupt and ring buffer
+void can_check(void) {
+    int temp_head;
+    if ( file_open == 1 ) {
+        while ( can2.read(can_MsgRx) ) {
+            temp_head = (head + 1) & BUFFER_MASK;
+            if ( temp_head == tail ) {          // buffer overflow error
+                fclose(fp);
+                fprintf(stderr, "buffer overflow\r\n");
+                fprintf(stderr, "head = %d\r\n", head);
+                fprintf(stderr, "tail = %d\r\n", tail);
+                User_Led4 = 1;
+                exit(1);
+            } // if
+
+            second[temp_head] = timer.read_us();
+            can_id[temp_head] = can_MsgRx.id & 0xFFF;
+            msg_length[temp_head] = can_MsgRx.len;
+            for (int i=0; i<can_MsgRx.len; i++) {
+                data[i][temp_head] = can_MsgRx.data[i];
+            } // for
+            head = temp_head;   // update head after data stored
+            // toggle led2
+            User_Led2 = !User_Led2;
+        } // while
+    } // if open
+} // can_check
+
+// read switch status, called every 5 msec
+void check_sw() {
+    SW2 = SW1;      // shift previous status
+    SW1 = SW0;      // shift previous status
+// get new status
+    SW0 = button1.read()+(button2.read()<<1)+(button3.read()<<2)+(button4.read()<<3);
+// following sequence detects switch press edge
+// HIGH(SW2) -> LOW(SW1) -> LOW(SW0)
+    BUTTON |= ((~(SW0|SW1))&SW2);   // update button status
+} // check_sw