diff --git a/css/style.css b/css/style.css index 54b0d0b0..2a455cff 100644 --- a/css/style.css +++ b/css/style.css @@ -730,7 +730,36 @@ a:hover { } .tab-sensors #baro { height: 120px; - } + } +.tab-cli { +} + .tab-cli p { + padding: 5px; + border: 1px dotted silver; + } + .tab-cli .window { + margin-top: 10px; + height: 400px; + + padding: 5px; + + overflow-y: scroll; + overflow-x: hidden; + + color: white; + + border: 1px solid silver; + background-color: black; + } + .tab-cli input { + margin-top: 10px; + display: block; + + width: 911px; + padding-left: 5px; + + border: 1px solid silver; + } /* Flotr related styles */ .flotr-legend { diff --git a/js/main.js b/js/main.js index e34995fd..ac4d50e2 100644 --- a/js/main.js +++ b/js/main.js @@ -1,7 +1,7 @@ var timers = new Array(); $(document).ready(function() { - var tabs = $('#tabs > ul'); + tabs = $('#tabs > ul'); $('a', tabs).click(function() { if ($(this).parent().hasClass('active') == false) { // only initialize when the tab isn't already active if (connectionId < 1) { // if there is no active connection, return @@ -11,6 +11,11 @@ $(document).ready(function() { // Disable any active "data pulling" timer disable_timers(); + // Disable CLI (there is no "nicer way of doing so right now) + if (CLI_active == true) { + leave_CLI(); + } + // Disable previous active button $('li', tabs).removeClass('active'); @@ -29,12 +34,15 @@ $(document).ready(function() { $('#content').load("./tabs/motor_outputs.html", tab_initialize_motor_outputs); } else if ($(this).parent().hasClass('tab_sensors')) { $('#content').load("./tabs/sensors.html", tab_initialize_sensors); + } else if ($(this).parent().hasClass('tab_cli')) { + $('#content').load("./tabs/cli.html", tab_initialize_cli); } + } }); // temporary - //$('#content').load("./tabs/initial_setup.html", tab_initialize_initial_setup); + //$('#content').load("./tabs/cli.html", tab_initialize_cli); }); function disable_timers() { diff --git a/js/serial_backend.js b/js/serial_backend.js index 3d5fbab5..1d849447 100644 --- a/js/serial_backend.js +++ b/js/serial_backend.js @@ -103,6 +103,8 @@ var GPS_DATA = { update: 0 }; +var CLI_active = false; + $(document).ready(function() { port_picker = $('div#port-picker .port select'); baud_picker = $('div#port-picker #baud'); @@ -146,20 +148,30 @@ $(document).ready(function() { if (selected_port != '0') { if (clicks) { // odd number of clicks // Disable any active "data pulling" timer - disable_timers(); - - chrome.serial.close(connectionId, onClosed); - - clearTimeout(connection_delay); - clearInterval(serial_poll); - clearInterval(port_usage_poll); + disable_timers(); + + // Disable CLI (there is no "nicer way of doing so right now) + if (CLI_active == true) { + leave_CLI(function() { + chrome.serial.close(connectionId, onClosed); + + clearTimeout(connection_delay); + clearInterval(serial_poll); + clearInterval(port_usage_poll); + }); + } else { + chrome.serial.close(connectionId, onClosed); + + clearTimeout(connection_delay); + clearInterval(serial_poll); + clearInterval(port_usage_poll); + } // Change port utilization to 0 $('span.port-usage').html('0%'); - - + $(this).text('Connect'); - $(this).removeClass('active'); + $(this).removeClass('active'); } else { // even number of clicks console.log('Connecting to: ' + selected_port); @@ -234,68 +246,74 @@ function onCharRead(readInfo) { var data = new Uint8Array(readInfo.data); for (var i = 0; i < data.length; i++) { - switch (message_state) { - case 0: // sync char 1 - if (data[i] == 36) { // $ + if (CLI_active != true) { + // Standard "GUI" MSP handling + switch (message_state) { + case 0: // sync char 1 + if (data[i] == 36) { // $ + message_state++; + } + break; + case 1: // sync char 2 + if (data[i] == 77) { // M + message_state++; + } else { // restart and try again + message_state = 0; + } + break; + case 2: // direction (should be >) + if (data[i] == 62) { // > + message_status = 1; + } else { // unknown + message_status = 0; + } + message_state++; - } - break; - case 1: // sync char 2 - if (data[i] == 77) { // M + break; + case 3: + message_length_expected = data[i]; // data length + + message_checksum = data[i]; + + // setup arraybuffer + message_buffer = new ArrayBuffer(message_length_expected); + message_buffer_uint8_view = new Uint8Array(message_buffer); + message_state++; - } else { // restart and try again - message_state = 0; - } - break; - case 2: // direction (should be >) - if (data[i] == 62) { // > - message_status = 1; - } else { // unknown - message_status = 0; - } - - message_state++; - break; - case 3: - message_length_expected = data[i]; // data length - - message_checksum = data[i]; - - // setup arraybuffer - message_buffer = new ArrayBuffer(message_length_expected); - message_buffer_uint8_view = new Uint8Array(message_buffer); - - message_state++; - break; - case 4: - message_code = data[i]; // code - message_checksum ^= data[i]; - - if (message_length_expected != 0) { // standard message - message_state++; - } else { // MSP_ACC_CALIBRATION, etc... - message_state += 2; - } - break; - case 5: // data / payload - message_buffer_uint8_view[message_length_received] = data[i]; - message_checksum ^= data[i]; - message_length_received++; - - if (message_length_received >= message_length_expected) { - message_state++; - } - break; - case 6: // CRC - if (message_checksum == data[i]) { - // process data - process_message(message_code, message_buffer); - } - - // Reset variables - message_length_received = 0; - message_state = 0; - break; + break; + case 4: + message_code = data[i]; // code + message_checksum ^= data[i]; + + if (message_length_expected != 0) { // standard message + message_state++; + } else { // MSP_ACC_CALIBRATION, etc... + message_state += 2; + } + break; + case 5: // data / payload + message_buffer_uint8_view[message_length_received] = data[i]; + message_checksum ^= data[i]; + message_length_received++; + + if (message_length_received >= message_length_expected) { + message_state++; + } + break; + case 6: // CRC + if (message_checksum == data[i]) { + // process data + process_message(message_code, message_buffer); + } + + // Reset variables + message_length_received = 0; + message_state = 0; + break; + } + } else { + // CLI Enabled (Terminal "style" handling) + handle_CLI(data[i]); } char_counter++; diff --git a/main.html b/main.html index 0a13e825..5cb339f8 100644 --- a/main.html +++ b/main.html @@ -17,6 +17,7 @@ +
@@ -82,6 +83,7 @@
  • Auxiliary Configuration
  • Motor/Servo Outputs
  • Raw Sensor Data
  • +
  • CLI
  • diff --git a/tabs/cli.html b/tabs/cli.html new file mode 100644 index 00000000..da903b44 --- /dev/null +++ b/tabs/cli.html @@ -0,0 +1,9 @@ +
    +

    + Note: Leaving CLI tab or pressing Disconnect will automatically + send "exit" to the board, which will make the controller save all the changes and restart. +

    +
    +
    + +
    \ No newline at end of file diff --git a/tabs/cli.js b/tabs/cli.js new file mode 100644 index 00000000..59ec7434 --- /dev/null +++ b/tabs/cli.js @@ -0,0 +1,68 @@ +function tab_initialize_cli() { + CLI_active = true; + + // Enter CLI mode + var bufferOut = new ArrayBuffer(1); + var bufView = new Uint8Array(bufferOut); + + bufView[0] = 0x23; // # + + chrome.serial.write(connectionId, bufferOut, function(writeInfo) { + // used for debugging purposes (should be disabled in "stable" builds + console.log("Wrote: " + writeInfo.bytesWritten + " bytes"); + }); + + $('.tab-cli input').keypress(function(event) { + if (event.which == 13) { // enter + var out_string = $('.tab-cli input').val(); + + var bufferOut = new ArrayBuffer(out_string.length + 1); // +1 for enter character + var bufView = new Uint8Array(bufferOut); + + for (var i = 0; i < out_string.length; i++) { + bufView[i] = out_string.charCodeAt(i); + } + + bufView[out_string.length] = 0x0D; // enter + + chrome.serial.write(connectionId, bufferOut, function(writeInfo) { + $('.tab-cli input').val(''); + }); + } + }); + + // give input element user focus + $('.tab-cli input').focus(); +} + +function leave_CLI(callback) { + var bufferOut = new ArrayBuffer(5); + var bufView = new Uint8Array(bufferOut); + + bufView[0] = 0x65; // e + bufView[1] = 0x78; // x + bufView[2] = 0x69; // i + bufView[3] = 0x74; // t + bufView[4] = 0x0D; // enter + + chrome.serial.write(connectionId, bufferOut, function(writeInfo) { + if (typeof callback !== 'undefined') { + callback(); + } + }); + + CLI_active = false; +} + +function handle_CLI(data) { + switch (data) { + case 10: // line feed + break; + case 13: // carriage return + $('.tab-cli .window').append("
    "); + break; + default: + $('.tab-cli .window').append(String.fromCharCode(data)); + $('.tab-cli .window').scrollTop($('.tab-cli .window').height()); + } +} \ No newline at end of file