Library for the PsiSwarm Robot - Version 0.7

Dependents:   PsiSwarm_V7_Blank

Fork of PsiSwarmLibrary by James Hilder

Revision:
2:c6986ee3c7c5
Parent:
1:060690a934a9
Child:
3:7c0d1f581757
--- a/serial.cpp	Thu Mar 03 23:21:47 2016 +0000
+++ b/serial.cpp	Fri Mar 11 13:51:24 2016 +0000
@@ -5,9 +5,9 @@
  * (C) Dept. Electronics & Computer Science, University of York
  * James Hilder, Alan Millard, Alexander Horsfield, Homero Elizondo, Jon Timmis
  *
- * PsiSwarm Library Version: 0.4
+ * PsiSwarm Library Version: 0.41
  *
- * February 2016
+ * March 2016
  *
  *
  */
@@ -24,11 +24,15 @@
 
 char allow_commands = 1;
 char allow_requests = 1;
+char file_transfer_state = 0;
 
-char file_transfer_state = 0;
-int file_length;
-char filename [13];
-
+int block_size = 88;   // The data block size for file transfer
+char data_block[89];   // Stores the data block to write for Bluetooth file transfer
+int data_written;       // Stores if partial data has been written to a file
+int file_length;        // Stores the file length for a Bluetooth file transfer
+int final_block;        // Stores the index of the final data block for a Bluetooth file transfer
+int block_index;        // Stores the current block index for a Bluetooth file transfer
+char filename [21];     // Stores the filename for a Bluetooth file transfer
 
 Timeout ft_timeout;
 Timeout pc_command_timeout;
@@ -78,6 +82,7 @@
     display.write_string("FILE TRANSFER");
     display.set_position(1,0);
     display.write_string("MODE...");
+    data_written = 0;
     file_transfer_mode = 1;
     file_transfer_state = 0;
     file_length = 0;
@@ -90,6 +95,10 @@
 void IF_invalid_transfer(void)
 {
     debug("File transfer failed\n");
+    if(data_written == 1){
+        debug("Deleting corrupted file\n");
+        remove(filename);
+    }
     display.clear_display();
     display.set_position(0,0);
     display.write_string("TRANSFER FAILED");
@@ -123,12 +132,9 @@
     // length = length of message
     // interface = 0 for PC serial connection, 1 for Bluetooth [NB only Bluetooth used for file transfer in this version]
 
-    debug("FTM Message:%.*s [%d]\n",length,message,length);
-    char * file_data;
-    int block_index;
-    int final_block;
+    if(file_transfer_state < 2)debug("FTM Message:%.*s [%d]\n",length,message,length);
+    else debug("FTM data block received (%d bytes)\n",length);
     int expected_size;
-    int block_size = 100;
     // The first byte in EVERY message received should be 33; if it isn't, abort the transfer
     if(message[0] != 33) {
         IF_invalid_transfer();
@@ -138,7 +144,9 @@
                 //The filenames cannot be more that 8.3 characters long (FAT12 format)
                 if(length == 1 || length > 13) IF_invalid_transfer();
                 else {
-                    strncpy(filename, message + 1, length - 1);
+                    strcpy(filename, "/local/");
+                    strncat(filename, message + 1, length - 1);
+                    debug("Target filename:%s\n",filename);
                     //Send acknowledge ("FN")
                     ft_timeout.detach();
                     ft_timeout.attach(IF_file_transfer_timeout,2.0);
@@ -169,9 +177,10 @@
                     //multiple blocks....
                     final_block = file_length / block_size;
                     if(file_length % block_size != 0) final_block ++;
-                    int target_size = file_length;
-                    if(file_length > (block_size * 16)) target_size = block_size * 16;
-                    file_data = (char *) malloc(target_size);
+                    //int target_size = file_length;
+                    //if(file_length > (block_size * 16)) target_size = block_size * 16;
+                    //file_data = (char *) malloc(target_size);
+                    debug("File size %d bytes (%d blocks of %d bytes)\n",file_length,final_block,block_size);
                     ft_timeout.detach();
                     ft_timeout.attach(IF_file_transfer_timeout,1.0);
                     //Send acknowledge (size of file)
@@ -180,16 +189,61 @@
                 break;
             case 2:
                 block_index ++;
+                display.clear_display();
+                display.set_position(0,0);
+                display.write_string("FILE TRANSFER");
+                display.set_position(1,0);
+                char details_string[17];
+                sprintf(details_string,"BLOCK %d OF %d",block_index,final_block);
+                display.write_string(details_string);
+                expected_size = block_size;
                 if(block_index == final_block) expected_size = file_length % block_size;
                 if(expected_size == 0) expected_size = block_size;
                 if(length!=expected_size + 1){
                     // Unexpected length   
-                    
+                    debug("File data unexpected length in packet %d (%d bytes received, %d bytes expected)\n",block_index,length-1,expected_size);
                 }else{
-                 
+                    char transfer_mode[2]={'a'};
+                    if(block_index == 1){
+                        transfer_mode[0]='w';
+                    }
+                    FILE *fp = fopen(filename,transfer_mode);
+                    //strncpy(data_block,message+1,length);
+                    //data_block[length]=0;
+                    //fprintf(fp,data_block);
+                    int bytes_written;
+                    bytes_written = fwrite(message+1,expected_size,1,fp);
+                    fclose(fp);
+                    if(data_written == false && bytes_written > 0) data_written = true;
+                    debug("Bytes written: %d\n",expected_size * bytes_written);
+                    if(block_index < final_block){
+                    debug("Message packet %d received and written\n",block_index);
+                    //Send acknowledge ("D")
                     ft_timeout.detach();
                     ft_timeout.attach(IF_file_transfer_timeout,1.0);   
+                    bt.printf("%c%c%s",RESPONSE_MESSAGE_BYTE,1,"D");
+                    }
+                    else{
+                        //Last data block written
+                        //[Put file checking code here]
+                        //Send acknowledge ("P");
+                        bt.printf("%c%c%s",RESPONSE_MESSAGE_BYTE,1,"F");
+                        ft_timeout.detach();
+                        debug("File transfer completed successfully\n");
+                        wait(0.25);
+                        //Calculate CRC16 value for file
+                        IF_calculateCRC16(file_length);
+                        
+                        display.clear_display();
+                        display.write_string("FILE TRANSFER");
+                        display.set_position(1,0);
+                        display.write_string("COMPLETE");   
+                        wait(1);
+                        debug("File transfer mode ended\n");
+                        IF_end_file_transfer_mode();
+                    }
                 }
+                break;
         }
     }
 }
@@ -836,6 +890,16 @@
             sprintf(ret_message,"%03X%03X%03X%03X%03X",get_illuminated_base_ir_value(0),get_illuminated_base_ir_value(1),get_illuminated_base_ir_value(2),get_illuminated_base_ir_value(3),get_illuminated_base_ir_value(4));
             send_message = 1;
             break;
+        case 98:
+            strcpy(command,"CALCULATE BASE IR VALUES");
+            sprintf(ret_message,"%03X%03X%03X%03X%03X",calculate_base_ir_value(0),calculate_base_ir_value(1),calculate_base_ir_value(2),calculate_base_ir_value(3),calculate_base_ir_value(4));
+            send_message = 1;
+            break;
+        case 99:
+            strcpy(command,"CALCULATE SIDE IR VALUES");
+            sprintf(ret_message,"%03X%03X%03X%03X%03X%03X%03X%03X",calculate_side_ir_value(0),calculate_side_ir_value(1),calculate_side_ir_value(2),calculate_side_ir_value(3),calculate_side_ir_value(4),calculate_side_ir_value(5),calculate_side_ir_value(6),calculate_side_ir_value(7));
+            send_message = 1;
+            break;
         case 100:
             strcpy(command,"START FILE TRANSFER MODE");
             if(allow_commands) {
@@ -1061,6 +1125,76 @@
     bt_message_timeout.attach(&IF_bt_message_timeout, bt_message_timeout_period);
 }
 
+void IF_set_filename(char * filename_in){
+    strcpy(filename,filename_in);
+}
+ 
+unsigned short IF_calculateCRC16(int file_length){
+    unsigned short crc16table[256] = { 
+        0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
+        0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
+        0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
+        0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
+        0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
+        0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
+        0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
+        0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
+        0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
+        0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
+        0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
+        0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
+        0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
+        0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
+        0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
+        0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, 
+        0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
+        0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
+        0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
+        0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
+        0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
+        0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
+        0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
+        0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
+        0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
+        0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
+        0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
+        0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
+        0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
+        0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
+        0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
+        0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202};
+        
+    //Opens, reads and calculates the CRC16 value for file pointed to by filename
+    unsigned short crc_value = 0;
+    FILE *fp = fopen(filename,"r");
+    char * buffer;
+    int limit = 512;
+    if(file_length < 512) limit = file_length;
+    buffer = (char*) malloc (sizeof(char)*limit);
+    int blocks = 1;
+    if(file_length > limit) blocks += file_length / limit;
+    for(int i=0;i<blocks;i++){
+        //Determine size of this block
+        int blocksize = limit;
+        if(i == blocks-1){
+            if((file_length % limit) != 0) blocksize = file_length % limit;   
+        }               
+        debug("Calculating %d bytes of CRC data...\n",blocksize);
+        int result;
+        result = fread(buffer,1,blocksize,fp);
+        debug("Data read: %d\n",result);
+        for(int j=0;j<blocksize;j++){
+            int subindex = ((crc_value>>8)^*(char *)(buffer[j]))&0x00FF;
+            //debug("J:%d Subindex:%d\n",j,subindex);
+            unsigned short table_value = crc16table[subindex];
+            crc_value=(crc_value<<8)^table_value;   
+        }
+    }
+    fclose(fp);
+    debug("CRC Calculated: %x\n",crc_value);
+    return crc_value;               
+}
+
 //void IF_bt_rx_callback()
 //{
 //    int count = 0;