C++ Library for the PsiSwarm Robot - Version 0.8
Dependents: PsiSwarm_V8_Blank_CPP Autonomia_RndmWlk
Fork of PsiSwarmV7_CPP by
serial.cpp
00001 /* University of York Robotics Laboratory PsiSwarm Library: SerialControlControlControlControlControl Control Source File 00002 * 00003 * Copyright 2016 University of York 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 00007 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS 00008 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00009 * See the License for the specific language governing permissions and limitations under the License. 00010 * 00011 * File: serial.cpp 00012 * 00013 * (C) Dept. Electronics & Computer Science, University of York 00014 * James Hilder, Alan Millard, Alexander Horsfield, Homero Elizondo, Jon Timmis 00015 * 00016 * PsiSwarm Library Version: 0.8 00017 * 00018 * October 2016 00019 * 00020 * 00021 */ 00022 00023 #include "psiswarm.h" 00024 00025 static float command_timeout_period = 0.1f; //If a complete command message is not received in 0.1s then consider it a user message 00026 char pc_command_message_started = 0; 00027 char pc_command_message_byte = 0; 00028 char pc_command_message[3]; 00029 char bt_command_message_started = 0; 00030 char bt_command_message_byte = 0; 00031 char bt_command_message[3]; 00032 00033 char allow_commands = 1; 00034 char allow_requests = 1; 00035 char file_transfer_state = 0; 00036 00037 int block_size = 88; // The data block size for file transfer 00038 char data_block[89]; // Stores the data block to write for Bluetooth file transfer 00039 int data_written; // Stores if partial data has been written to a file 00040 int file_length; // Stores the file length for a Bluetooth file transfer 00041 int final_block; // Stores the index of the final data block for a Bluetooth file transfer 00042 int block_index; // Stores the current block index for a Bluetooth file transfer 00043 char filename [21]; // Stores the filename for a Bluetooth file transfer 00044 00045 Timeout ft_timeout; 00046 Timeout pc_command_timeout; 00047 Timeout bt_command_timeout; 00048 00049 // A predefined message structure for command messages is as follows: 00050 // [Byte 0][Byte 1][Byte 2][Byte 3][Byte 4] 00051 // Byte 0 and Byte 4 must be equal to COMMAND_MESSAGE_BYTE [in psiswarm.h] or message is treated as a user message 00052 00053 00054 void SerialControl::setup_serial_interfaces() 00055 { 00056 if(ENABLE_PC_SERIAL) { 00057 pc.baud(PC_BAUD); 00058 pc.attach(this,&SerialControl::IF_pc_rx_callback, Serial::RxIrq); 00059 } 00060 if(ENABLE_BLUETOOTH) { 00061 bt.baud(BLUETOOTH_BAUD); 00062 bt.attach(this,&SerialControl::IF_bt_rx_callback, Serial::RxIrq); 00063 } 00064 } 00065 00066 00067 void SerialControl::IF_start_file_transfer_mode() 00068 { 00069 display.clear_display(); 00070 display.set_position(0,0); 00071 display.write_string("FILE TRANSFER"); 00072 display.set_position(1,0); 00073 display.write_string("MODE..."); 00074 data_written = 0; 00075 file_transfer_mode = 1; 00076 file_transfer_state = 0; 00077 file_length = 0; 00078 user_code_restore_mode = user_code_running; 00079 user_code_running = 0; 00080 ft_timeout.attach(this,&SerialControl::IF_file_transfer_timeout,2.0); 00081 } 00082 00083 00084 void SerialControl::IF_invalid_transfer(void) 00085 { 00086 psi.debug("File transfer failed\n"); 00087 if(data_written == 1) { 00088 psi.debug("Deleting corrupted file\n"); 00089 remove(filename); 00090 } 00091 display.clear_display(); 00092 display.set_position(0,0); 00093 display.write_string("TRANSFER FAILED"); 00094 wait(0.5); 00095 IF_end_file_transfer_mode(); 00096 } 00097 00098 void SerialControl::IF_file_transfer_timeout(void) 00099 { 00100 psi.debug("File transfer failed: timeout\n"); 00101 display.clear_display(); 00102 display.set_position(0,0); 00103 display.write_string("TRANSFER TIMEOUT"); 00104 wait(0.5); 00105 IF_end_file_transfer_mode(); 00106 } 00107 00108 void SerialControl::IF_end_file_transfer_mode(void) 00109 { 00110 display.clear_display(); 00111 file_transfer_mode = 0; 00112 user_code_running = user_code_restore_mode; 00113 } 00114 00115 00116 void SerialControl::IF_handle_file_transfer_serial_message(char * message, char length, char interface) 00117 { 00118 // Code for handling a serial (Bluetooth) message when in file-transfer mode 00119 // 00120 // message = pointer to message char array 00121 // length = length of message 00122 // interface = 0 for PC serial connection, 1 for Bluetooth [NB only Bluetooth used for file transfer in this version] 00123 00124 if(file_transfer_state < 2)psi.debug("FTM Message:%.*s [%d]\n",length,message,length); 00125 else psi.debug("FTM data block received (%d bytes)\n",length); 00126 int expected_size; 00127 // The first byte in EVERY message received should be 33; if it isn't, abort the transfer 00128 if(message[0] != 33) { 00129 IF_invalid_transfer(); 00130 } else { 00131 switch(file_transfer_state) { 00132 case 0: //First message received is the target filename 00133 //The filenames cannot be more that 8.3 characters long (FAT12 format) 00134 if(length == 1 || length > 13) IF_invalid_transfer(); 00135 else { 00136 strcpy(filename, "/local/"); 00137 strncat(filename, message + 1, length - 1); 00138 psi.debug("Target filename:%s\n",filename); 00139 //Send acknowledge ("FN") 00140 ft_timeout.detach(); 00141 ft_timeout.attach(this,&SerialControl::IF_file_transfer_timeout,2.0); 00142 bt.printf("%c%c%s",RESPONSE_MESSAGE_BYTE,2,"FN"); 00143 file_transfer_state = 1; 00144 } 00145 break; 00146 case 1: //Second message is the length of the file in bytes 00147 //Length is encoded as a 3-byte value 00148 if(length != 4) IF_invalid_transfer(); 00149 else { 00150 file_length = (message[1]) * 256; 00151 file_length += (message[2]); 00152 file_length *= 256; 00153 file_length += message[3]; 00154 file_transfer_state = 2; 00155 display.clear_display(); 00156 char display_message[17]; 00157 sprintf(display_message,"F:%s",filename); 00158 display.set_position(0,0); 00159 display.write_string(display_message); 00160 display.set_position(1,0); 00161 sprintf(display_message,"S:%d b",file_length); 00162 display.write_string(display_message); 00163 block_index = 0; 00164 //Work out how many blocks the file will be sent in (size = block_size, tested at 100 bytes) 00165 //Allocate memory for the file up to a limit of 16 blocks; larger files will be split across 00166 //multiple blocks.... 00167 final_block = file_length / block_size; 00168 if(file_length % block_size != 0) final_block ++; 00169 //int target_size = file_length; 00170 //if(file_length > (block_size * 16)) target_size = block_size * 16; 00171 //file_data = (char *) malloc(target_size); 00172 psi.debug("File size %d bytes (%d blocks of %d bytes)\n",file_length,final_block,block_size); 00173 ft_timeout.detach(); 00174 ft_timeout.attach(this,&SerialControl::IF_file_transfer_timeout,1.0); 00175 //Send acknowledge (size of file) 00176 bt.printf("%c%c%c%c%c",RESPONSE_MESSAGE_BYTE,3,message[1],message[2],message[3]); 00177 } 00178 break; 00179 case 2: 00180 block_index ++; 00181 display.clear_display(); 00182 display.set_position(0,0); 00183 display.write_string("FILE TRANSFER"); 00184 display.set_position(1,0); 00185 char details_string[17]; 00186 sprintf(details_string,"BLOCK %d OF %d",block_index,final_block); 00187 display.write_string(details_string); 00188 expected_size = block_size; 00189 if(block_index == final_block) expected_size = file_length % block_size; 00190 if(expected_size == 0) expected_size = block_size; 00191 if(length!=expected_size + 1) { 00192 // Unexpected length 00193 psi.debug("File data unexpected length in packet %d (%d bytes received, %d bytes expected)\n",block_index,length-1,expected_size); 00194 } else { 00195 char transfer_mode[2]= {'a'}; 00196 if(block_index == 1) { 00197 transfer_mode[0]='w'; 00198 } 00199 FILE *fp = fopen(filename,transfer_mode); 00200 //strncpy(data_block,message+1,length); 00201 //data_block[length]=0; 00202 //fprintf(fp,data_block); 00203 int bytes_written; 00204 bytes_written = fwrite(message+1,expected_size,1,fp); 00205 fclose(fp); 00206 if(data_written == false && bytes_written > 0) data_written = true; 00207 psi.debug("Bytes written: %d\n",expected_size * bytes_written); 00208 if(block_index < final_block) { 00209 psi.debug("Message packet %d received and written\n",block_index); 00210 //Send acknowledge ("D") 00211 ft_timeout.detach(); 00212 ft_timeout.attach(this,&SerialControl::IF_file_transfer_timeout,1.0); 00213 bt.printf("%c%c%s",RESPONSE_MESSAGE_BYTE,1,"D"); 00214 } else { 00215 //Last data block written 00216 //[Put file checking code here] 00217 //Send acknowledge ("P"); 00218 bt.printf("%c%c%s",RESPONSE_MESSAGE_BYTE,1,"F"); 00219 ft_timeout.detach(); 00220 psi.debug("File transfer completed successfully\n"); 00221 wait(0.25); 00222 //Calculate CRC16 value for file 00223 IF_calculateCRC16(file_length); 00224 00225 display.clear_display(); 00226 display.write_string("FILE TRANSFER"); 00227 display.set_position(1,0); 00228 display.write_string("COMPLETE"); 00229 wait(1); 00230 psi.debug("File transfer mode ended\n"); 00231 IF_end_file_transfer_mode(); 00232 } 00233 } 00234 break; 00235 } 00236 } 00237 } 00238 00239 00240 void SerialControl::IF_handle_user_serial_message(char * message, char length, char interface) 00241 { 00242 char buffer[255]; 00243 sprintf(buffer,message,length); 00244 for(int i=0; i<length; i++) { 00245 buffer[i]=message[i]; 00246 } 00247 buffer[length]=0; 00248 // if(interface) debug("Received BT message:%s [%d chars]\n",buffer,length); 00249 // else debug("Received USB message:%s [%d chars]\n",buffer,length); 00250 handle_user_serial_message(message,length,interface); 00251 } 00252 00253 void SerialControl::IF_handle_command_serial_message(char message[3], char interface) 00254 { 00255 char iface [4]; 00256 if(interface) strcpy(iface,"BT"); 00257 else strcpy(iface,"USB"); 00258 char command [26]; 00259 char subcommand[30]; 00260 float dec; 00261 float l_dec; 00262 float r_dec; 00263 int irp_delay; 00264 char colour_string[7]; 00265 char ret_message[50]; 00266 char send_message = 0; 00267 char command_status = 0; 00268 // command_status values: 00269 // 0 - unrecognised command 00270 // 1 - command actioned 00271 // 2 - command blocked 00272 // 3 - invalid parameters 00273 00274 subcommand[0]=0; 00275 command[0]=0; 00276 switch(message[0]) { 00277 00278 // MOTOR COMMANDS 00279 00280 case 1: 00281 strcpy(command,"SET LEFT MOTOR"); 00282 dec = IF_decode_float(message[1],message[2]); 00283 sprintf(subcommand,"%1.5f",dec); 00284 if(allow_commands) { 00285 command_status = 1; 00286 motors.set_left_motor_speed(dec); 00287 } else command_status = 2; 00288 break; 00289 case 2: 00290 strcpy(command,"SET RIGHT MOTOR"); 00291 dec = IF_decode_float(message[1],message[2]); 00292 sprintf(subcommand,"%1.5f",dec); 00293 if(allow_commands) { 00294 motors.set_right_motor_speed(dec); 00295 command_status = 1; 00296 } else command_status = 2; 00297 break; 00298 case 3: 00299 strcpy(command,"SET BOTH MOTORS"); 00300 dec = IF_decode_float(message[1],message[2]); 00301 sprintf(subcommand,"%1.5f",dec); 00302 if(allow_commands) { 00303 command_status = 1; 00304 motors.forward(dec); 00305 } else command_status = 2; 00306 break; 00307 case 4: 00308 strcpy(command,"BRAKE LEFT MOTOR"); 00309 sprintf(subcommand,""); 00310 if(allow_commands) { 00311 command_status = 1; 00312 motors.brake_left_motor(); 00313 } else command_status = 2; 00314 break; 00315 case 5: 00316 strcpy(command,"BRAKE RIGHT MOTOR"); 00317 sprintf(subcommand,""); 00318 if(allow_commands) { 00319 command_status = 1; 00320 motors.brake_right_motor(); 00321 } else command_status = 2; 00322 break; 00323 case 6: 00324 strcpy(command,"BRAKE BOTH MOTORS"); 00325 sprintf(subcommand,""); 00326 if(allow_commands) { 00327 command_status = 1; 00328 motors.brake(); 00329 } else command_status = 2; 00330 break; 00331 case 7: 00332 strcpy(command,"STOP BOTH MOTORS"); 00333 sprintf(subcommand,""); 00334 if(allow_commands) { 00335 command_status = 1; 00336 motors.stop(); 00337 } else command_status = 2; 00338 break; 00339 case 8: 00340 strcpy(command,"TURN ON SPOT"); 00341 dec = IF_decode_float(message[1],message[2]); 00342 sprintf(subcommand,"%1.5f",dec); 00343 if(allow_commands) { 00344 command_status = 1; 00345 motors.turn(dec); 00346 } else command_status = 2; 00347 break; 00348 case 9: 00349 strcpy(command,"SET EACH MOTOR"); 00350 l_dec = IF_decode_float(message[1]); 00351 r_dec = IF_decode_float(message[2]); 00352 sprintf(subcommand,"L=%1.3f R=%1.3f",l_dec,r_dec); 00353 if(allow_commands) { 00354 command_status = 1; 00355 motors.set_left_motor_speed(l_dec); 00356 motors.set_right_motor_speed(r_dec); 00357 } else command_status = 2; 00358 break; 00359 // LED COMMANDS 00360 00361 case 10: 00362 strcpy(command,"SET LED STATES"); 00363 sprintf(subcommand,"G:%s R:%s",IF_char_to_binary_char(message[1]), IF_char_to_binary_char(message[2])); 00364 if(allow_commands) { 00365 command_status = 1; 00366 led.set_leds(message[1],message[2]); 00367 } else command_status = 2; 00368 break; 00369 case 11: 00370 strcpy(command,"SET RED LED STATES"); 00371 sprintf(subcommand,"%s",IF_char_to_binary_char(message[1])); 00372 if(allow_commands) { 00373 command_status = 1; 00374 led.set_red_leds(message[1]); 00375 } else command_status = 2; 00376 break; 00377 case 12: 00378 strcpy(command,"SET GREEN LED STATES"); 00379 sprintf(subcommand,"%s",IF_char_to_binary_char(message[1])); 00380 if(allow_commands) { 00381 command_status = 1; 00382 led.set_green_leds(message[1]); 00383 } else command_status = 2; 00384 break; 00385 case 13: 00386 strcpy(command,"SET LED"); 00387 switch(message[2]) { 00388 case 1: 00389 strcpy(colour_string,"RED"); 00390 break; 00391 case 2: 00392 strcpy(colour_string,"GREEN"); 00393 break; 00394 case 3: 00395 strcpy(colour_string,"BOTH"); 00396 break; 00397 case 0: 00398 strcpy(colour_string,"OFF"); 00399 break; 00400 } 00401 if(message[1] < 8 && message[2] < 4) { 00402 sprintf(subcommand,"%d %s",message[1],colour_string); 00403 if(allow_commands) { 00404 command_status = 1; 00405 led.set_led(message[1],message[2]); 00406 } else command_status = 2; 00407 } else { 00408 sprintf(subcommand,"[INVALID CODE]"); 00409 command_status = 3; 00410 } 00411 break; 00412 case 14: 00413 strcpy(command,"SET CENTER LED STATE"); 00414 switch(message[1]) { 00415 case 1: 00416 strcpy(colour_string,"RED"); 00417 break; 00418 case 2: 00419 strcpy(colour_string,"GREEN"); 00420 break; 00421 case 3: 00422 strcpy(colour_string,"BOTH"); 00423 break; 00424 case 0: 00425 strcpy(colour_string,"OFF"); 00426 break; 00427 } 00428 if(message[1] < 4) { 00429 sprintf(subcommand,"%s",colour_string); 00430 if(allow_commands) { 00431 command_status = 1; 00432 led.set_center_led(message[1]); 00433 } else command_status = 2; 00434 } else { 00435 sprintf(subcommand,"[INVALID CODE]"); 00436 command_status = 3; 00437 } 00438 break; 00439 case 15: 00440 strcpy(command,"SET C.LED BRIGHTNESS"); 00441 dec = IF_decode_unsigned_float(message[1],message[2]); 00442 sprintf(subcommand,"%1.5f",dec); 00443 if(allow_commands) { 00444 command_status = 1; 00445 led.set_center_led_brightness(dec); 00446 } else command_status = 2; 00447 break; 00448 case 16: 00449 strcpy(command,"SET MBED LEDS"); 00450 sprintf(subcommand,"%s",IF_nibble_to_binary_char(message[1])); 00451 if(allow_commands) { 00452 command_status = 1; 00453 mbed_led1 = (message[1] & 128) >> 7; 00454 mbed_led2 = (message[1] & 64) >> 6; 00455 mbed_led3 = (message[1] & 32) >> 5; 00456 mbed_led4 = (message[1] & 16) >> 4; 00457 } else command_status = 2; 00458 break; 00459 case 17: 00460 strcpy(command,"BLINK OUTER LEDS"); 00461 dec = IF_decode_unsigned_float(message[1],message[2]); 00462 sprintf(subcommand,"FOR %1.5fS",dec); 00463 if(allow_commands) { 00464 command_status = 1; 00465 led.blink_leds(dec); 00466 } else command_status = 2; 00467 break; 00468 case 18: 00469 strcpy(command,"SET BASE LED STATE"); 00470 switch(message[1]) { 00471 case 1: 00472 strcpy(subcommand,"ON"); 00473 break; 00474 case 0: 00475 strcpy(subcommand,"OFF"); 00476 break; 00477 } 00478 if(allow_commands) { 00479 command_status = 1; 00480 led.set_base_led(message[1]); 00481 } else command_status = 2; 00482 break; 00483 case 19: 00484 strcpy(command,"SET CENTER LED "); 00485 switch(message[1]) { 00486 case 1: 00487 strcpy(colour_string,"RED"); 00488 break; 00489 case 2: 00490 strcpy(colour_string,"GREEN"); 00491 break; 00492 case 3: 00493 strcpy(colour_string,"BOTH"); 00494 break; 00495 case 0: 00496 strcpy(colour_string,"OFF"); 00497 break; 00498 } 00499 dec = IF_decode_unsigned_float(message[2]); 00500 sprintf(subcommand,"%s @ %1.5f brightness",colour_string,dec); 00501 if(allow_commands) { 00502 command_status = 1; 00503 led.set_center_led(message[1],dec); 00504 } else command_status = 2; 00505 break; 00506 00507 // DISPLAY COMMANDS 00508 00509 case 20: 00510 strcpy(command,"SET DISPLAY "); 00511 switch(message[1]) { 00512 case 0: 00513 strcpy(subcommand,"CLEAR"); 00514 if(allow_commands) { 00515 command_status = 1; 00516 display.clear_display(); 00517 } else command_status = 2; 00518 break; 00519 case 1: 00520 strcpy(subcommand,"MESSAGE 1"); 00521 if(allow_commands) { 00522 command_status = 1; 00523 display.clear_display(); 00524 display.home(); 00525 display.write_string("PC CONNECTION"); 00526 display.set_position(1,0); 00527 display.write_string("STARTED"); 00528 } else command_status = 2; 00529 break; 00530 case 2: 00531 strcpy(subcommand,"MESSAGE 2"); 00532 if(allow_commands) { 00533 command_status = 1; 00534 display.clear_display(); 00535 display.home(); 00536 display.write_string("PC CONNECTION"); 00537 display.set_position(1,0); 00538 display.write_string("TERMINATED"); 00539 } else command_status = 2; 00540 break; 00541 case 3: 00542 strcpy(subcommand,"MESSAGE 3"); 00543 if(allow_commands) { 00544 command_status = 1; 00545 display.clear_display(); 00546 display.home(); 00547 display.write_string("ANDROID DEVICE"); 00548 display.set_position(1,0); 00549 display.write_string("CONNECTED"); 00550 } else command_status = 2; 00551 break; 00552 case 4: 00553 strcpy(subcommand,"MESSAGE 4"); 00554 if(allow_commands) { 00555 command_status = 1; 00556 display.clear_display(); 00557 display.home(); 00558 display.write_string("ANDROID DEVICE"); 00559 display.set_position(1,0); 00560 display.write_string("DISCONNECTED"); 00561 } else command_status = 2; 00562 break; 00563 case 5: 00564 strcpy(subcommand,"MESSAGE 5"); 00565 if(allow_commands) { 00566 command_status = 1; 00567 display.clear_display(); 00568 display.home(); 00569 display.write_string("PSI CONSOLE"); 00570 display.set_position(1,0); 00571 display.write_string("CONNECTED"); 00572 } else command_status = 2; 00573 break; 00574 case 6: 00575 strcpy(subcommand,"MESSAGE 6"); 00576 if(allow_commands) { 00577 command_status = 1; 00578 display.clear_display(); 00579 display.home(); 00580 display.write_string("PSI CONSOLE"); 00581 display.set_position(1,0); 00582 display.write_string("DISCONNECTED"); 00583 } else command_status = 2; 00584 break; 00585 } 00586 break; 00587 case 21: 00588 strcpy(command,"SET CURSOR "); 00589 if(message[1] < 2 && message[2] < 16) { 00590 sprintf(subcommand,"[%d,%d]",message[1],message[2]); 00591 if(allow_commands) { 00592 display.set_position(message[1],message[2]); 00593 } else command_status = 2; 00594 } else { 00595 sprintf(subcommand,"[INVALID]"); 00596 command_status = 3; 00597 } 00598 break; 00599 case 22: { 00600 strcpy(command,"PRINT CHARACTERS "); 00601 char print_message[2]; 00602 print_message[0]=message[1]; 00603 print_message[1]=message[2]; 00604 sprintf(subcommand,"[%c,%c]",message[1],message[2]); 00605 if(allow_commands) { 00606 display.write_string(print_message,2); 00607 } else command_status = 2; 00608 break; 00609 } 00610 case 23: 00611 strcpy(command,"SET DISPLAY B.NESS"); 00612 dec = IF_decode_unsigned_float(message[1],message[2]); 00613 sprintf(subcommand,"%1.5f",dec); 00614 if(allow_commands) { 00615 command_status = 1; 00616 display.set_backlight_brightness(dec); 00617 } else command_status = 2; 00618 break; 00619 00620 case 30: 00621 strcpy(command,"SET DEBUG MODE"); 00622 switch(message[1]) { 00623 case 1: 00624 strcpy(subcommand,"ON"); 00625 break; 00626 case 0: 00627 strcpy(subcommand,"OFF"); 00628 break; 00629 } 00630 if(message[2] & 1) strcat (subcommand,"-PC"); 00631 if(message[2] & 2) strcat (subcommand,"-BT"); 00632 if(message[2] & 4) strcat (subcommand,"-DISP"); 00633 if(allow_commands) { 00634 command_status = 1; 00635 debug_mode = message[1]; 00636 debug_output = message[2]; 00637 } else command_status = 2; 00638 break; 00639 case 31: 00640 strcpy(command,"SET DEMO MODE"); 00641 switch(message[1] % 2) { 00642 case 1: 00643 strcpy(subcommand,"ON"); 00644 break; 00645 case 0: 00646 strcpy(subcommand,"OFF"); 00647 break; 00648 } 00649 if(allow_commands) { 00650 command_status = 1; 00651 demo_on = message[1] % 2; 00652 if(demo_on == 1) { 00653 user_code_restore_mode = user_code_running; 00654 user_code_running = 0; 00655 } else { 00656 user_code_running = user_code_restore_mode; 00657 } 00658 } else command_status = 2; 00659 break; 00660 case 32: 00661 strcpy(command,"SET USER CODE"); 00662 switch(message[1] % 2) { 00663 case 1: 00664 strcpy(subcommand,"ON"); 00665 break; 00666 case 0: 00667 strcpy(subcommand,"OFF"); 00668 break; 00669 } 00670 if(allow_commands) { 00671 command_status = 1; 00672 user_code_running = message[1] % 2; 00673 } else command_status = 2; 00674 break; 00675 case 33: 00676 strcpy(command,"PAUSE USER CODE"); 00677 dec = IF_decode_unsigned_float(message[1],message[2]) * 10; 00678 sprintf(subcommand,"FOR %2.3fS",dec); 00679 if(allow_commands) { 00680 command_status = 1; 00681 psi.pause_user_code(dec); 00682 } else command_status = 2; 00683 break; 00684 00685 case 34: 00686 strcpy(command,"RESET ENCODERS"); 00687 if(allow_commands) { 00688 command_status = 1; 00689 psi.reset_encoders(); 00690 } else command_status = 2; 00691 break; 00692 00693 case 35: 00694 strcpy(command,"SET ALLOW COMMANDS"); 00695 switch(message[1] % 2) { 00696 case 1: 00697 strcpy(subcommand,"ON"); 00698 break; 00699 case 0: 00700 strcpy(subcommand,"OFF"); 00701 break; 00702 } 00703 allow_commands = message[1] % 2; 00704 command_status = 1; 00705 break; 00706 00707 case 36: 00708 irp_delay = (message[1] << 8) + message[2]; 00709 sprintf(command,"SET IR PULSE DELAY %d MS",irp_delay); 00710 if(allow_commands) { 00711 command_status = 1; 00712 ir_pulse_delay = irp_delay; 00713 } else command_status = 2; 00714 break; 00715 case 37: 00716 irp_delay = (message[1] << 8) + message[2]; 00717 sprintf(command,"SET BASE IR PULSE DELAY %d MS",irp_delay); 00718 if(allow_commands) { 00719 command_status = 1; 00720 base_ir_pulse_delay = irp_delay; 00721 } else command_status = 2; 00722 break; 00723 00724 // MOTOR REQUESTS 00725 case 40: 00726 strcpy(command,"GET LEFT MOTOR SPEED"); 00727 sprintf(ret_message,"%1.5f",motor_left_speed); 00728 send_message = 1; 00729 break; 00730 00731 case 41: 00732 strcpy(command,"GET RIGHT MOTOR SPEED"); 00733 sprintf(ret_message,"%1.5f",motor_right_speed); 00734 send_message = 1; 00735 break; 00736 case 42: 00737 strcpy(command,"GET BRAKE STATES"); 00738 sprintf(ret_message,"%d,%d",motor_left_brake,motor_right_brake); 00739 send_message = 1; 00740 break; 00741 case 43: 00742 strcpy(command,"GET MOTOR STATES"); 00743 //sprintf(ret_message,"%d,%d",motor_left_brake,motor_right_brake); 00744 send_message = 1; 00745 break; 00746 case 44: 00747 strcpy(command,"GET ENCODERS"); 00748 sprintf(ret_message,"%d,%d",left_encoder,right_encoder); 00749 send_message = 1; 00750 break; 00751 00752 // LED REQUESTS 00753 case 50: 00754 strcpy(command,"GET LED STATES"); 00755 sprintf(ret_message,"%04x",led.get_led_states()); 00756 send_message = 1; 00757 break; 00758 00759 // GENERAL REQUESTS 00760 case 60: 00761 strcpy(command,"GET SOFTWARE VERSION"); 00762 sprintf(ret_message,"%1.2f",SOFTWARE_VERSION_CODE); 00763 send_message = 1; 00764 break; 00765 00766 case 61: 00767 strcpy(command,"GET UPTIME"); 00768 sprintf(ret_message,"%6.2f",psi.get_uptime()); 00769 send_message = 1; 00770 break; 00771 00772 case 62: 00773 strcpy(command,"GET ID"); 00774 sprintf(ret_message,"%d",robot_id); 00775 send_message = 1; 00776 break; 00777 00778 case 63: 00779 strcpy(command,"GET SWITCH BYTE"); 00780 sprintf(ret_message,"%02x",switch_byte); 00781 send_message = 1; 00782 break; 00783 case 64: 00784 strcpy(command,"GET USER CODE"); 00785 sprintf(ret_message,"%d",user_code_running); 00786 send_message = 1; 00787 break; 00788 case 65: 00789 strcpy(command,"GET RESPONSE STRING"); 00790 sprintf(ret_message,"PSI"); 00791 send_message = 1; 00792 break; 00793 case 66: 00794 strcpy(command,"GET PROGRAM NAME"); 00795 sprintf(ret_message,"%s",program_name); 00796 send_message = 1; 00797 break; 00798 case 67: 00799 strcpy(command,"GET AUTHOR NAME"); 00800 sprintf(ret_message,"%s",author_name); 00801 send_message = 1; 00802 break; 00803 case 68: 00804 strcpy(command,"GET DEBUG MODE"); 00805 sprintf(ret_message,"%1d%1d",debug_mode,debug_output); 00806 send_message = 1; 00807 break; 00808 case 69: 00809 strcpy(command,"GET SYSTEM WARNINGS"); 00810 sprintf(ret_message,"%d",system_warnings); 00811 send_message = 1; 00812 break; 00813 00814 00815 // Sensors 00816 case 80: 00817 strcpy(command,"STORE BG. IR VALUES"); 00818 if(allow_commands) { 00819 command_status = 1; 00820 sensors.store_background_raw_ir_values(); 00821 } else command_status = 2; 00822 break; 00823 case 81: 00824 strcpy(command,"STORE IL. IR VALUES"); 00825 if(allow_commands) { 00826 command_status = 1; 00827 sensors.store_illuminated_raw_ir_values(); 00828 } else command_status = 2; 00829 break; 00830 case 82: 00831 strcpy(command,"STORE IR VALUES"); 00832 if(allow_commands) { 00833 command_status = 1; 00834 sensors.store_ir_values(); 00835 } else command_status = 2; 00836 break; 00837 case 83: 00838 strcpy(command,"STORE BG BASE IR VALUES"); 00839 if(allow_commands) { 00840 command_status = 1; 00841 sensors.store_background_base_ir_values(); 00842 } else command_status = 2; 00843 break; 00844 case 84: 00845 strcpy(command,"STORE IL. BASE IR VALUES"); 00846 if(allow_commands) { 00847 command_status = 1; 00848 sensors.store_illuminated_base_ir_values(); 00849 } else command_status = 2; 00850 break; 00851 case 85: 00852 strcpy(command,"STORE BASE IR VALUES"); 00853 if(allow_commands) { 00854 command_status = 1; 00855 sensors.store_base_ir_values(); 00856 } else command_status = 2; 00857 break; 00858 case 86: 00859 strcpy(command,"STORE ALL IR VALUES"); 00860 if(allow_commands) { 00861 command_status = 1; 00862 sensors.store_ir_values(); 00863 sensors.store_base_ir_values(); 00864 } else command_status = 2; 00865 break; 00866 case 90: 00867 sprintf(command,"%s %d","GET BG IR VALUE",message[1]); 00868 sprintf(ret_message,"%d",sensors.get_background_raw_ir_value(message[1])); 00869 send_message = 1; 00870 break; 00871 case 91: 00872 sprintf(command,"%s %d","GET IL IR VALUE",message[1]); 00873 sprintf(ret_message,"%d",sensors.get_illuminated_raw_ir_value(message[1])); 00874 send_message = 1; 00875 break; 00876 case 92: 00877 strcpy(command,"GET BG IR VALUES"); 00878 sprintf(ret_message,"%03X%03X%03X%03X%03X%03X%03X%03X",sensors.get_background_raw_ir_value(0),sensors.get_background_raw_ir_value(1),sensors.get_background_raw_ir_value(2),sensors.get_background_raw_ir_value(3),sensors.get_background_raw_ir_value(4),sensors.get_background_raw_ir_value(5),sensors.get_background_raw_ir_value(6),sensors.get_background_raw_ir_value(7)); 00879 send_message = 1; 00880 break; 00881 case 93: 00882 strcpy(command,"GET ILLUMINATED IR VALUES"); 00883 sprintf(ret_message,"%03X%03X%03X%03X%03X%03X%03X%03X",sensors.get_illuminated_raw_ir_value(0),sensors.get_illuminated_raw_ir_value(1),sensors.get_illuminated_raw_ir_value(2),sensors.get_illuminated_raw_ir_value(3),sensors.get_illuminated_raw_ir_value(4),sensors.get_illuminated_raw_ir_value(5),sensors.get_illuminated_raw_ir_value(6),sensors.get_illuminated_raw_ir_value(7)); 00884 send_message = 1; 00885 break; 00886 case 94: 00887 sprintf(command,"%s %d","GET BG BASE IR VALUE",message[1]); 00888 sprintf(ret_message,"%d",sensors.get_background_base_ir_value(message[1])); 00889 send_message = 1; 00890 break; 00891 case 95: 00892 sprintf(command,"%s %d","GET IL BASE IR VALUE",message[1]); 00893 sprintf(ret_message,"%d",sensors.get_illuminated_base_ir_value(message[1])); 00894 send_message = 1; 00895 break; 00896 case 96: 00897 strcpy(command,"GET BG BASE IR VALUES"); 00898 sprintf(ret_message,"%03X%03X%03X%03X%03X",sensors.get_background_base_ir_value(0),sensors.get_background_base_ir_value(1),sensors.get_background_base_ir_value(2),sensors.get_background_base_ir_value(3),sensors.get_background_base_ir_value(4)); 00899 send_message = 1; 00900 break; 00901 case 97: 00902 strcpy(command,"GET IL BASE IR VALUES"); 00903 sprintf(ret_message,"%03X%03X%03X%03X%03X",sensors.get_illuminated_base_ir_value(0),sensors.get_illuminated_base_ir_value(1),sensors.get_illuminated_base_ir_value(2),sensors.get_illuminated_base_ir_value(3),sensors.get_illuminated_base_ir_value(4)); 00904 send_message = 1; 00905 break; 00906 case 98: 00907 strcpy(command,"CALCULATE BASE IR VALUES"); 00908 sprintf(ret_message,"%03X%03X%03X%03X%03X",sensors.calculate_base_ir_value(0),sensors.calculate_base_ir_value(1),sensors.calculate_base_ir_value(2),sensors.calculate_base_ir_value(3),sensors.calculate_base_ir_value(4)); 00909 send_message = 1; 00910 break; 00911 case 99: 00912 strcpy(command,"CALCULATE SIDE IR VALUES"); 00913 sprintf(ret_message,"%03X%03X%03X%03X%03X%03X%03X%03X",sensors.calculate_side_ir_value(0),sensors.calculate_side_ir_value(1),sensors.calculate_side_ir_value(2),sensors.calculate_side_ir_value(3),sensors.calculate_side_ir_value(4),sensors.calculate_side_ir_value(5),sensors.calculate_side_ir_value(6),sensors.calculate_side_ir_value(7)); 00914 send_message = 1; 00915 break; 00916 case 100: 00917 strcpy(command,"START FILE TRANSFER MODE"); 00918 if(allow_commands) { 00919 command_status = 1; 00920 IF_start_file_transfer_mode(); 00921 sprintf(ret_message,"OK"); 00922 send_message = 1; 00923 } else command_status = 2; 00924 break; 00925 case 110: 00926 strcpy(command,"GET FIRMWARE VERSION"); 00927 sprintf(ret_message,"%1.2f",firmware_version); 00928 send_message = 1; 00929 break; 00930 case 111: 00931 strcpy(command,"GET SERIAL NUMBER"); 00932 sprintf(ret_message,"%2.3f",serial_number); 00933 send_message = 1; 00934 break; 00935 case 112: 00936 strcpy(command,"GET HAS SIDE IR"); 00937 sprintf(ret_message,"%d",has_side_ir); 00938 send_message = 1; 00939 break; 00940 case 113: 00941 strcpy(command,"GET HAS BASE IR"); 00942 sprintf(ret_message,"%d",has_base_ir); 00943 send_message = 1; 00944 break; 00945 case 114: 00946 strcpy(command,"GET HAS ENCODERS"); 00947 sprintf(ret_message,"%d",has_wheel_encoders); 00948 send_message = 1; 00949 break; 00950 case 115: 00951 strcpy(command,"GET HAS AUDIO"); 00952 sprintf(ret_message,"%d",has_audio_pic); 00953 send_message = 1; 00954 break; 00955 case 116: 00956 strcpy(command,"GET HAS RECHARGING"); 00957 sprintf(ret_message,"%d",has_recharging_circuit); 00958 send_message = 1; 00959 break; 00960 case 117: 00961 strcpy(command,"GET HAS COMPASS"); 00962 sprintf(ret_message,"%d",has_compass); 00963 send_message = 1; 00964 break; 00965 case 118: 00966 strcpy(command,"GET HAS ULTRASONIC"); 00967 sprintf(ret_message,"%d",has_ultrasonic_sensor); 00968 send_message = 1; 00969 break; 00970 case 119: 00971 strcpy(command,"GET HAS TEMPERATURE"); 00972 sprintf(ret_message,"%d",has_temperature_sensor); 00973 send_message = 1; 00974 break; 00975 case 120: 00976 strcpy(command,"GET HAS BASE COLOUR"); 00977 sprintf(ret_message,"%d",has_base_colour_sensor); 00978 send_message = 1; 00979 break; 00980 case 121: 00981 strcpy(command,"GET HAS TOP COLOUR"); 00982 sprintf(ret_message,"%d",has_top_colour_sensor); 00983 send_message = 1; 00984 break; 00985 case 122: 00986 strcpy(command,"GET HAS RADIO"); 00987 sprintf(ret_message,"%d",has_433_radio); 00988 send_message = 1; 00989 break; 00990 case 123: { 00991 strcpy(command,"GET FIRMWARE H-DESC"); 00992 char byte0 = 0; 00993 char byte1 = 1; 00994 if(has_side_ir)byte0+=128; 00995 if(has_base_ir)byte0+=64; 00996 if(has_wheel_encoders)byte0+=32; 00997 if(has_audio_pic)byte0+=16; 00998 if(has_recharging_circuit)byte0+=8; 00999 if(has_compass)byte0+=4; 01000 if(has_ultrasonic_sensor)byte0+=2; 01001 if(has_temperature_sensor)byte0+=1; 01002 if(has_base_colour_sensor)byte1+=128; 01003 if(has_top_colour_sensor)byte1+=64; 01004 if(has_433_radio)byte1+=32; 01005 sprintf(ret_message,"%c%c",byte0,byte1); 01006 send_message = 1; 01007 break; 01008 } 01009 case 124: 01010 strcpy(command,"GET PCB VERSION"); 01011 sprintf(ret_message,"%1.2f",pcb_version); 01012 send_message = 1; 01013 break; 01014 case 125: 01015 send_message = 2; 01016 strcpy(command,"GET BEACON DATA"); 01017 unsigned short beacon_data[8]; 01018 sensors.store_background_raw_ir_values(); 01019 for(int sensor=0; sensor<8; sensor++) { 01020 beacon_data[sensor] = sensors.get_background_raw_ir_value(sensor); 01021 } 01022 // beacon_data holds the array of IR values at the middle of the beacon flash 01023 01024 // As an example - we will now wait for 20% of the beacon period and check the background value 01025 // background_data holds the true background values (no beacon) 01026 int maximum1 = 0, maximum2 = 0, max1_sensor = 8, max2_sensor = 8; 01027 for(int i = 0; i < 8; i++){ 01028 if(beacon_data[i] > maximum1){ 01029 maximum2 = maximum1; 01030 max2_sensor = max1_sensor; 01031 max1_sensor = i; 01032 maximum1 = beacon_data[i]; 01033 } 01034 else if(beacon_data[i] > maximum2){ 01035 max2_sensor = i; 01036 maximum2 = beacon_data[i]; 01037 } 01038 } 01039 pc.printf("%c%1d,%4d,%1d,%4d,",RESPONSE_MESSAGE_BYTE,max1_sensor,maximum1,max2_sensor,maximum2); 01040 break; 01041 case 255: 01042 send_message = 2; 01043 pc.printf("swarm"); 01044 break; 01045 01046 } 01047 01048 01049 if(send_message>0) { 01050 if(send_message == 1){ 01051 char message_length = strlen(ret_message); 01052 switch(interface) { 01053 case 0: 01054 pc.printf("%c%c%s",RESPONSE_MESSAGE_BYTE,message_length,ret_message); 01055 break; 01056 case 1: 01057 bt.printf("%c%c%s",RESPONSE_MESSAGE_BYTE,message_length,ret_message); 01058 break; 01059 } 01060 psi.debug("Received %s request message: %s %s [%02x%02x%02x]\nReply: %s [%d ch]\n",iface, command, subcommand,message[0],message[1],message[2],ret_message,message_length); 01061 } 01062 } else { 01063 switch(interface) { 01064 case 0: 01065 pc.printf("%c%c",ACKNOWLEDGE_MESSAGE_BYTE,command_status); 01066 break; 01067 case 1: 01068 bt.printf("%c%c",ACKNOWLEDGE_MESSAGE_BYTE,command_status); 01069 break; 01070 } 01071 switch(command_status) { 01072 case 0: 01073 psi.debug("Unrecognised %s command message [%02x%02x%02x]\n",iface,message[0],message[1],message[2]); 01074 break; 01075 case 1: 01076 psi.debug("Actioned %s command message:%s %s [%02x%02x%02x]\n",iface, command, subcommand,message[0],message[1],message[2]); 01077 break; 01078 case 2: 01079 psi.debug("Blocked %s command message:%s %s [%02x%02x%02x]\n",iface, command, subcommand,message[0],message[1],message[2]); 01080 break; 01081 case 3: 01082 psi.debug("Invalid %s command message:%s %s [%02x%02x%02x]\n",iface, command, subcommand,message[0],message[1],message[2]); 01083 break; 01084 } 01085 } 01086 } 01087 01088 char * SerialControl::IF_nibble_to_binary_char(char in) 01089 { 01090 char * ret = (char*)malloc(sizeof(char)*5); 01091 for(int i=0; i<4; i++) { 01092 if(in & (128 >> i)) ret[i]='1'; 01093 else ret[i]='0'; 01094 } 01095 ret[4]=0; 01096 return ret; 01097 } 01098 01099 char * SerialControl::IF_char_to_binary_char(char in) 01100 { 01101 char * ret = (char*)malloc(sizeof(char)*9); 01102 for(int i=0; i<8; i++) { 01103 if(in & (128 >> i)) ret[i]='1'; 01104 else ret[i]='0'; 01105 } 01106 ret[8]=0; 01107 return ret; 01108 } 01109 01110 float SerialControl::IF_decode_unsigned_float(char byte0, char byte1) 01111 { 01112 unsigned short sval = (byte0) << 8; 01113 sval += byte1; 01114 float scaled = sval / 65535.0f; 01115 return scaled; 01116 } 01117 01118 float SerialControl::IF_decode_float(char byte0, char byte1) 01119 { 01120 // MSB is byte 0 is sign, rest is linear spread between 0 and 1 01121 char sign = byte0 / 128; 01122 short sval = (byte0 % 128) << 8; 01123 sval += byte1; 01124 float scaled = sval / 32767.0f; 01125 if(sign == 0) scaled = 0-scaled; 01126 return scaled; 01127 } 01128 01129 float SerialControl::IF_decode_unsigned_float(char byte0) 01130 { 01131 unsigned short sval = (byte0); 01132 float scaled = sval / 255.0f; 01133 return scaled; 01134 } 01135 01136 float SerialControl::IF_decode_float(char byte0) 01137 { 01138 // MSB is byte 0 is sign, rest is linear spread between 0 and 1 01139 char sign = byte0 / 128; 01140 short sval = (byte0 % 128); 01141 float scaled = sval / 127.0f; 01142 if(sign == 0) scaled = 0-scaled; 01143 return scaled; 01144 } 01145 01146 01147 void SerialControl::IF_pc_rx_command_timeout() 01148 { 01149 char message_array[6]; 01150 char length = 1 + pc_command_message_byte; 01151 pc_command_message_started = 0; 01152 message_array[0] = COMMAND_MESSAGE_BYTE; 01153 for(int k=0; k<pc_command_message_byte; k++) { 01154 message_array[k+1] = pc_command_message[k]; 01155 } 01156 IF_handle_user_serial_message(message_array, length, 0); 01157 } 01158 01159 void SerialControl::IF_bt_rx_command_timeout() 01160 { 01161 char message_array[6]; 01162 char length = 1 + bt_command_message_byte; 01163 bt_command_message_started = 0; 01164 message_array[0] = COMMAND_MESSAGE_BYTE; 01165 for(int k=0; k<bt_command_message_byte; k++) { 01166 message_array[k+1] = bt_command_message[k]; 01167 } 01168 IF_handle_user_serial_message(message_array, length, 1); 01169 } 01170 01171 void SerialControl::IF_pc_rx_callback() 01172 { 01173 int count = 0; 01174 char message_array[255]; 01175 01176 while(pc.readable()) { 01177 char tc = pc.getc(); 01178 message_array[count] = tc; 01179 count ++; 01180 if(pc_command_message_started == 1) { 01181 if(pc_command_message_byte == 3) { 01182 pc_command_timeout.detach(); 01183 if(tc == COMMAND_MESSAGE_BYTE) { 01184 // A complete command message succesfully received, call handler 01185 pc_command_message_started = 0; 01186 count = 0; 01187 IF_handle_command_serial_message(pc_command_message , 0); 01188 } else { 01189 // Message is not a valid command message as 5th byte is not correct; treat whole message as a user message 01190 pc_command_message_started = 0; 01191 message_array[0] = COMMAND_MESSAGE_BYTE; 01192 message_array[1] = pc_command_message[0]; 01193 message_array[2] = pc_command_message[1]; 01194 message_array[3] = pc_command_message[2]; 01195 message_array[4] = tc; 01196 count = 5; 01197 } 01198 } else { 01199 pc_command_message[pc_command_message_byte] = tc; 01200 pc_command_message_byte ++; 01201 } 01202 } else { 01203 if(count == 1) { 01204 if(tc == COMMAND_MESSAGE_BYTE) { 01205 pc_command_timeout.attach(this,&SerialControl::IF_pc_rx_command_timeout,command_timeout_period); 01206 pc_command_message_started = 1; 01207 pc_command_message_byte = 0; 01208 01209 } 01210 } 01211 } 01212 } 01213 if(!pc_command_message_started && count>0) IF_handle_user_serial_message(message_array, count, 0); 01214 } 01215 01216 Timeout bt_message_timeout; 01217 //static float bt_message_timeout_period = 0.001; // 1 millisecond 01218 char bt_buffer[255]; 01219 int bt_buffer_index = 0; 01220 01221 void SerialControl::IF_bt_message_timeout() 01222 { 01223 char buffer[255]; 01224 01225 sprintf(buffer, bt_buffer, bt_buffer_index); 01226 buffer[bt_buffer_index] = 0; 01227 if(file_transfer_mode == 1) { 01228 IF_handle_file_transfer_serial_message(bt_buffer, bt_buffer_index, 1); 01229 } else { 01230 // debug("BT message timeout: %s [%d chars]\n", buffer, bt_buffer_index); 01231 if(bt_buffer_index == 5 && buffer[0] == COMMAND_MESSAGE_BYTE && buffer[4] == COMMAND_MESSAGE_BYTE) { 01232 bt_command_message[0] = buffer[1]; 01233 bt_command_message[1] = buffer[2]; 01234 bt_command_message[2] = buffer[3]; 01235 IF_handle_command_serial_message(bt_command_message , 1); 01236 } else IF_handle_user_serial_message(bt_buffer, bt_buffer_index, 1); 01237 } 01238 bt_buffer_index = 0; 01239 } 01240 01241 01242 void SerialControl::IF_set_filename(char * filename_in) 01243 { 01244 strcpy(filename,filename_in); 01245 } 01246 01247 unsigned short SerialControl::IF_calculateCRC16(int file_length) 01248 { 01249 unsigned short crc16table[256] = { 01250 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, 01251 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, 01252 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, 01253 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, 01254 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, 01255 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, 01256 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, 01257 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, 01258 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, 01259 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, 01260 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, 01261 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, 01262 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, 01263 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, 01264 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, 01265 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, 01266 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, 01267 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, 01268 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, 01269 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, 01270 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, 01271 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, 01272 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, 01273 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, 01274 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, 01275 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, 01276 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, 01277 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, 01278 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, 01279 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, 01280 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, 01281 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 01282 }; 01283 01284 //Opens, reads and calculates the CRC16 value for file pointed to by filename 01285 unsigned short crc_value = 0; 01286 FILE *fp = fopen(filename,"r"); 01287 char * buffer; 01288 int limit = 512; 01289 if(file_length < 512) limit = file_length; 01290 buffer = (char*) malloc (sizeof(char)*limit); 01291 int blocks = 1; 01292 if(file_length > limit) blocks += file_length / limit; 01293 for(int i=0; i<blocks; i++) { 01294 //Determine size of this block 01295 int blocksize = limit; 01296 if(i == blocks-1) { 01297 if((file_length % limit) != 0) blocksize = file_length % limit; 01298 } 01299 psi.debug("Calculating %d bytes of CRC data...\n",blocksize); 01300 int result; 01301 result = fread(buffer,1,blocksize,fp); 01302 psi.debug("Data read: %d\n",result); 01303 for(int j=0; j<blocksize; j++) { 01304 int subindex = ((crc_value>>8)^*(char *)(buffer[j]))&0x00FF; 01305 //debug("J:%d Subindex:%d\n",j,subindex); 01306 unsigned short table_value = crc16table[subindex]; 01307 crc_value=(crc_value<<8)^table_value; 01308 } 01309 } 01310 fclose(fp); 01311 psi.debug("CRC Calculated: %x\n",crc_value); 01312 return crc_value; 01313 } 01314 01315 void SerialControl::IF_bt_rx_callback() 01316 { 01317 int count = 0; 01318 char message_array[255]; 01319 01320 wait_ms(500); // Wait 0.5ms to allow a complete message to arrive before atttempting to process it 01321 01322 while(bt.readable()) { 01323 char tc = bt.getc(); 01324 message_array[count] = tc; 01325 count ++; 01326 if(bt_command_message_started == 1) { 01327 if(bt_command_message_byte == 3) { 01328 bt_command_timeout.detach(); 01329 if(tc == COMMAND_MESSAGE_BYTE) { 01330 // A complete command message succesfully received, call handler 01331 bt_command_message_started = 0; 01332 count = 0; 01333 IF_handle_command_serial_message(bt_command_message , 1); 01334 } else { 01335 // Message is not a valid command message as 5th byte is not correct; treat whole message as a user message 01336 bt_command_message_started = 0; 01337 message_array[0] = COMMAND_MESSAGE_BYTE; 01338 message_array[1] = bt_command_message[0]; 01339 message_array[2] = bt_command_message[1]; 01340 message_array[3] = bt_command_message[2]; 01341 message_array[4] = tc; 01342 count = 5; 01343 } 01344 } else { 01345 bt_command_timeout.attach(this,&SerialControl::IF_bt_rx_command_timeout,command_timeout_period); 01346 bt_command_message[bt_command_message_byte] = tc; 01347 bt_command_message_byte ++; 01348 } 01349 } else { 01350 if(count == 1) { 01351 if(tc == COMMAND_MESSAGE_BYTE) { 01352 bt_command_message_started = 1; 01353 bt_command_message_byte = 0; 01354 01355 } 01356 } 01357 } 01358 } 01359 if(!bt_command_message_started && count>0) IF_handle_user_serial_message(message_array, count, 1); 01360 }
Generated on Tue Jul 12 2022 21:11:24 by 1.7.2