2013-04-08 15:29:52 +00:00
var connectionId = - 1 ;
2013-04-13 00:32:35 +00:00
var configuration _received = false ;
2014-01-04 09:08:13 +00:00
var CLI _active = false ;
2013-04-08 15:29:52 +00:00
2013-04-08 17:09:10 +00:00
var CONFIG = {
2013-04-08 18:07:47 +00:00
version : 0 ,
multiType : 0 ,
2013-11-11 12:33:50 +00:00
msp _version : 0 ,
capability : 0 ,
2013-04-08 18:07:47 +00:00
cycleTime : 0 ,
i2cError : 0 ,
activeSensors : 0 ,
2013-04-15 08:03:34 +00:00
mode : 0 ,
2013-06-21 12:46:21 +00:00
profile : 0 ,
2013-04-15 08:03:34 +00:00
uid : [ 0 , 0 , 0 ] ,
accelerometerTrims : [ 0 , 0 ]
2013-12-12 16:10:10 +00:00
} ;
2013-04-08 17:09:10 +00:00
2013-04-09 12:31:37 +00:00
var PIDs = new Array ( 10 ) ;
for ( var i = 0 ; i < 10 ; i ++ ) {
PIDs [ i ] = new Array ( 3 ) ;
}
2013-04-08 22:39:36 +00:00
var RC = {
roll : 0 ,
pitch : 0 ,
yaw : 0 ,
throttle : 0 ,
AUX1 : 0 ,
AUX2 : 0 ,
AUX3 : 0 ,
AUX4 : 0
2013-12-12 16:10:10 +00:00
} ;
2013-04-08 22:39:36 +00:00
2013-04-09 15:58:54 +00:00
var RC _tuning = {
RC _RATE : 0 ,
RC _EXPO : 0 ,
roll _pitch _rate : 0 ,
yaw _rate : 0 ,
dynamic _THR _PID : 0 ,
throttle _MID : 0 ,
throttle _EXPO : 0 ,
2013-12-12 16:10:10 +00:00
} ;
2013-04-09 15:58:54 +00:00
2013-04-10 11:53:48 +00:00
var AUX _CONFIG = new Array ( ) ;
var AUX _CONFIG _values = new Array ( ) ;
2013-11-08 09:24:12 +00:00
var SERVO _CONFIG = new Array ( ) ;
2013-04-09 12:31:37 +00:00
var SENSOR _DATA = {
gyroscope : [ 0 , 0 , 0 ] ,
accelerometer : [ 0 , 0 , 0 ] ,
magnetometer : [ 0 , 0 , 0 ] ,
2013-04-11 09:50:01 +00:00
altitude : 0 ,
kinematicsX : 0.0 ,
kinematicsY : 0.0 ,
2013-10-31 21:45:07 +00:00
kinematicsZ : 0.0 ,
debug : [ 0 , 0 , 0 , 0 ]
2013-12-12 16:10:10 +00:00
} ;
2013-04-08 22:39:36 +00:00
2013-04-10 16:49:25 +00:00
var MOTOR _DATA = new Array ( 8 ) ;
var SERVO _DATA = new Array ( 8 ) ;
2013-04-11 11:16:51 +00:00
var GPS _DATA = {
fix : 0 ,
numSat : 0 ,
lat : 0 ,
lon : 0 ,
alt : 0 ,
speed : 0 ,
2013-11-09 08:28:37 +00:00
ground _course : 0 ,
2013-04-11 11:16:51 +00:00
distanceToHome : 0 ,
ditectionToHome : 0 ,
2013-05-29 17:24:34 +00:00
update : 0 ,
// baseflight specific gps stuff
chn : new Array ( ) ,
svid : new Array ( ) ,
quality : new Array ( ) ,
cno : new Array ( )
2013-12-12 16:10:10 +00:00
} ;
2013-04-15 06:44:08 +00:00
var BATTERY = {
voltage : 0 ,
pMeterSum : 0 ,
2013-12-12 16:10:10 +00:00
} ;
2013-04-11 11:16:51 +00:00
2014-01-13 15:16:16 +00:00
var MISC = {
PowerTrigger1 : 0 , // intPowerTrigger1 (aka useless trash)
minthrottle : 0 ,
maxthrottle : 0 ,
mincommand : 0 ,
failsafe _throttle : 0 ,
plog0 : 0 , // plog useless shit
plog1 : 0 , // plog useless shit
mag _declination : 0 , // not checked
vbatscale : 0 ,
vbatmincellvoltage : 0 ,
vbatmaxcellvoltage : 0 ,
empty : 0 // unknown
} ;
2013-12-15 17:41:25 +00:00
$ ( document ) . ready ( function ( ) {
2013-11-20 11:26:00 +00:00
console . log ( 'Scanning for new ports...' ) ;
update _ports ( ) ;
2013-04-08 15:29:52 +00:00
$ ( 'div#port-picker a.connect' ) . click ( function ( ) {
2013-11-14 06:27:35 +00:00
if ( GUI . connect _lock != true ) { // GUI control overrides the user control
var clicks = $ ( this ) . data ( 'clicks' ) ;
2013-12-15 17:41:25 +00:00
var selected _port = String ( $ ( 'div#port-picker .port select' ) . val ( ) ) ;
var selected _baud = parseInt ( $ ( 'div#port-picker #baud' ) . val ( ) ) ;
2013-11-14 06:27:35 +00:00
if ( selected _port != '0' ) {
2013-11-20 11:26:00 +00:00
if ( ! clicks ) {
console . log ( 'Connecting to: ' + selected _port ) ;
GUI . connecting _to = selected _port ;
2013-11-22 10:59:38 +00:00
// lock port select & baud while we are connecting / connected
$ ( 'div#port-picker #port, div#port-picker #baud, div#port-picker #delay' ) . prop ( 'disabled' , true ) ;
$ ( 'div#port-picker a.connect' ) . text ( 'Connecting' ) ;
2013-11-20 11:26:00 +00:00
2013-11-22 10:59:38 +00:00
chrome . serial . open ( selected _port , { bitrate : selected _baud } , onOpen ) ;
2013-11-20 11:26:00 +00:00
} else {
2013-11-14 06:27:35 +00:00
// Disable any active "data pulling" timer
2013-12-11 17:57:29 +00:00
GUI . interval _kill _all ( [ 'port-update' ] ) ;
2013-11-14 06:27:35 +00:00
GUI . tab _switch _cleanup ( ) ;
2013-12-11 17:57:29 +00:00
GUI . timeout _remove ( 'connecting' ) ;
2013-11-14 06:27:35 +00:00
chrome . serial . close ( connectionId , onClosed ) ;
2013-11-20 11:26:00 +00:00
GUI . connected _to = false ;
2013-12-15 17:45:46 +00:00
// Reset various UI elements
2013-11-14 06:27:35 +00:00
$ ( 'span.port-usage' ) . html ( '0%' ) ;
2013-12-15 17:45:46 +00:00
$ ( '.software-version' ) . html ( '0.0' ) ;
$ ( 'span.cycle-time' ) . html ( '0' ) ;
2013-11-14 06:27:35 +00:00
2014-01-04 09:08:13 +00:00
MSP . state = 0 ; // reset packet state for "clean" initial entry (this is only required if user hot-disconnects)
2013-12-15 17:45:46 +00:00
MSP . packet _error = 0 ; // reset CRC packet error counter for next session
2013-12-11 17:57:29 +00:00
configuration _received = false ; // reset valid config received variable (used to block tabs while not connected properly)
2013-11-22 10:59:38 +00:00
// unlock port select & baud
2013-12-29 10:15:04 +00:00
$ ( 'div#port-picker #port' ) . prop ( 'disabled' , false ) ;
if ( ! GUI . auto _connect ) $ ( 'div#port-picker #baud' ) . prop ( 'disabled' , false ) ;
2013-11-22 10:59:38 +00:00
2013-11-14 06:27:35 +00:00
$ ( this ) . text ( 'Connect' ) ;
2013-11-20 11:26:00 +00:00
$ ( this ) . removeClass ( 'active' ) ;
2013-11-14 06:27:35 +00:00
}
2013-04-08 15:29:52 +00:00
2013-11-14 06:27:35 +00:00
$ ( this ) . data ( "clicks" , ! clicks ) ;
2013-04-08 15:29:52 +00:00
}
}
2013-12-29 10:15:04 +00:00
} ) ;
// auto-connect
chrome . storage . local . get ( 'auto_connect' , function ( result ) {
if ( typeof result . auto _connect === 'undefined' ) {
// auto_connect wasn't saved yet, save and push true to the GUI
chrome . storage . local . set ( { 'auto_connect' : true } ) ;
GUI . auto _connect = true ;
$ ( 'select#baud' ) . val ( 115200 ) . prop ( 'disabled' , true ) ;
} else {
if ( result . auto _connect ) {
// enabled by user
GUI . auto _connect = true ;
$ ( 'input.auto_connect' ) . prop ( 'checked' , true ) ;
2013-12-29 10:32:21 +00:00
$ ( 'input.auto_connect, span.auto_connect' ) . prop ( 'title' , 'Auto-Connect: Enabled - Configurator automatically tries to connect when new serial port is detected' ) ;
2013-12-29 10:15:04 +00:00
$ ( 'select#baud' ) . val ( 115200 ) . prop ( 'disabled' , true ) ;
} else {
// disabled by user
GUI . auto _connect = false ;
$ ( 'input.auto_connect' ) . prop ( 'checked' , false ) ;
2013-12-29 10:32:21 +00:00
$ ( 'input.auto_connect, span.auto_connect' ) . prop ( 'title' , 'Auto-Connect: Disabled - User needs to select the correct serial port and click "Connect" button on its own' ) ;
2013-12-29 10:15:04 +00:00
}
}
// bind UI hook to auto-connect checkbos
$ ( 'input.auto_connect' ) . change ( function ( ) {
GUI . auto _connect = $ ( this ) . is ( ':checked' ) ;
// update title/tooltip
if ( GUI . auto _connect ) {
2013-12-29 10:32:21 +00:00
$ ( 'input.auto_connect, span.auto_connect' ) . prop ( 'title' , 'Auto-Connect: Enabled - Configurator automatically tries to connect when new port is detected' ) ;
2013-12-29 10:15:04 +00:00
$ ( 'select#baud' ) . val ( 115200 ) . prop ( 'disabled' , true ) ;
} else {
2013-12-29 10:32:21 +00:00
$ ( 'input.auto_connect, span.auto_connect' ) . prop ( 'title' , 'Auto-Connect: Disabled - User needs to select the correct serial port and click "Connect" button on its own' ) ;
2013-12-29 10:15:04 +00:00
if ( ! GUI . connected _to && ! GUI . connecting _to ) $ ( 'select#baud' ) . prop ( 'disabled' , false ) ;
}
chrome . storage . local . set ( { 'auto_connect' : GUI . auto _connect } , function ( ) { } ) ;
} ) ;
} ) ;
2013-04-08 15:29:52 +00:00
} ) ;
2013-12-06 17:32:32 +00:00
function onOpen ( openInfo ) {
if ( openInfo . connectionId > 0 ) {
connectionId = openInfo . connectionId ;
2013-11-20 11:26:00 +00:00
// update connected_to
GUI . connected _to = GUI . connecting _to ;
// reset connecting_to
GUI . connecting _to = false ;
2013-04-08 15:29:52 +00:00
console . log ( 'Connection was opened with ID: ' + connectionId ) ;
2013-06-18 18:13:26 +00:00
// save selected port with chrome.storage if the port differs
chrome . storage . local . get ( 'last_used_port' , function ( result ) {
if ( typeof result . last _used _port != 'undefined' ) {
2013-12-15 17:41:25 +00:00
if ( result . last _used _port != GUI . connected _to ) {
2013-06-18 18:13:26 +00:00
// last used port doesn't match the one found in local db, we will store the new one
2013-12-15 17:41:25 +00:00
chrome . storage . local . set ( { 'last_used_port' : GUI . connected _to } , function ( ) {
2013-06-18 18:13:26 +00:00
// Debug message is currently disabled (we dont need to spam the console log with that)
// console.log('Last selected port was saved in chrome.storage.');
} ) ;
}
2013-06-18 23:21:09 +00:00
} else {
// variable isn't stored yet, saving
2013-12-15 17:41:25 +00:00
chrome . storage . local . set ( { 'last_used_port' : GUI . connected _to } , function ( ) {
2013-06-18 23:21:09 +00:00
// Debug message is currently disabled (we dont need to spam the console log with that)
// console.log('Last selected port was saved in chrome.storage.');
} ) ;
2013-06-18 18:13:26 +00:00
}
} ) ;
2013-12-15 17:41:25 +00:00
// start polling
GUI . interval _add ( 'serial_read' , readPoll , 10 ) ;
GUI . interval _add ( 'port_usage' , port _usage , 1000 ) ;
// disconnect after 10 seconds with error if we don't get IDENT data
GUI . timeout _add ( 'connecting' , function ( ) {
if ( ! configuration _received ) {
notify ( 'Did not received configuration within <span style="color: red">10 seconds</span>, communication <span style="color: red">failed</span> - Disconnecting' ) ;
2013-12-05 09:17:49 +00:00
2013-12-15 17:41:25 +00:00
$ ( 'div#port-picker a.connect' ) . click ( ) ; // disconnect
}
} , 10000 ) ;
// request configuration data
send _message ( MSP _codes . MSP _UID , MSP _codes . MSP _UID ) ;
send _message ( MSP _codes . MSP _STATUS , MSP _codes . MSP _STATUS ) ; // in theory this could be removed (MSP_STATUS is pulled in initial tab)
send _message ( MSP _codes . MSP _IDENT , MSP _codes . MSP _IDENT , false , function ( ) {
GUI . timeout _remove ( 'connecting' ) ; // kill connecting timer
// Update UI elements that doesn't need consistent refreshing
$ ( '.software-version' ) . html ( CONFIG . version ) ;
configuration _received = true ;
$ ( 'div#port-picker a.connect' ) . text ( 'Disconnect' ) . addClass ( 'active' ) ;
$ ( '#tabs li a:first' ) . click ( ) ;
} ) ;
2013-11-08 14:34:52 +00:00
} else {
console . log ( 'Failed to open serial port' ) ;
2013-11-08 17:31:19 +00:00
notify ( 'Failed to open serial port' , 'red' ) ;
2013-11-08 14:34:52 +00:00
$ ( 'div#port-picker a.connect' ) . text ( 'Connect' ) ;
$ ( 'div#port-picker a.connect' ) . removeClass ( 'active' ) ;
2013-12-05 11:40:10 +00:00
// unlock port select & baud
$ ( 'div#port-picker #port, div#port-picker #baud, div#port-picker #delay' ) . prop ( 'disabled' , false ) ;
2013-11-08 14:34:52 +00:00
// reset data
$ ( 'div#port-picker a.connect' ) . data ( "clicks" , false ) ;
2013-04-08 15:29:52 +00:00
}
}
function onClosed ( result ) {
2013-12-06 17:32:32 +00:00
connectionId = - 1 ; // reset connection id
if ( result ) { // All went as expected
2013-04-08 18:07:47 +00:00
sensor _status ( sensors _detected = 0 ) ; // reset active sensor indicators
2013-04-08 19:10:47 +00:00
$ ( '#tabs > ul li' ) . removeClass ( 'active' ) ; // de-select any selected tabs
2013-10-30 16:41:29 +00:00
tab _initialize _default ( ) ;
2013-04-08 19:10:47 +00:00
2013-04-08 15:29:52 +00:00
console . log ( 'Connection closed successfully.' ) ;
} else { // Something went wrong
2013-12-06 17:32:32 +00:00
console . log ( 'There was an error that happened during "connection-close" procedure.' ) ;
notify ( 'Failed to close serial port' , 'red' ) ;
2013-04-08 15:29:52 +00:00
}
}
function readPoll ( ) {
2013-11-09 02:52:06 +00:00
chrome . serial . read ( connectionId , 128 , MSP _char _read ) ;
2013-04-08 18:07:47 +00:00
}
2013-04-10 16:49:25 +00:00
function port _usage ( ) {
2013-12-15 17:41:25 +00:00
var port _usage = ( char _counter * 10 / parseInt ( $ ( 'div#port-picker #baud' ) . val ( ) ) ) * 100 ;
2013-04-10 16:49:25 +00:00
$ ( 'span.port-usage' ) . html ( parseInt ( port _usage ) + '%' ) ;
// reset counter
char _counter = 0 ;
}
2013-11-20 11:26:00 +00:00
function update _ports ( ) {
var initial _ports = false ;
GUI . interval _add ( 'port-update' , function ( ) {
chrome . serial . getPorts ( function ( current _ports ) {
if ( initial _ports . length > current _ports . length || ! initial _ports ) {
// port got removed or initial_ports wasn't initialized yet
var removed _ports = array _difference ( initial _ports , current _ports ) ;
if ( initial _ports != false ) console . log ( 'Port removed: ' + removed _ports ) ;
// disconnect "UI" if necessary
if ( GUI . connected _to != false && removed _ports [ 0 ] == GUI . connected _to ) {
$ ( 'div#port-picker a.connect' ) . click ( ) ;
}
// update COM port list
update _port _select _menu ( current _ports ) ;
// auto-select last used port (only during initialization)
if ( ! initial _ports ) {
chrome . storage . local . get ( 'last_used_port' , function ( result ) {
// if last_used_port was set, we try to select it
if ( result . last _used _port ) {
current _ports . forEach ( function ( port ) {
if ( port == result . last _used _port ) {
console . log ( 'Selecting last used port: ' + result . last _used _port ) ;
$ ( 'div#port-picker .port select' ) . val ( result . last _used _port ) ;
}
} ) ;
} else {
console . log ( 'Last used port wasn\'t saved "yet", auto-select disabled.' ) ;
}
} ) ;
}
// reset initial_ports
initial _ports = current _ports ;
}
var new _ports = array _difference ( current _ports , initial _ports ) ;
if ( new _ports . length > 0 ) {
console . log ( 'New port found: ' + new _ports [ 0 ] ) ;
// generate new COM port list
update _port _select _menu ( current _ports ) ;
2013-12-29 10:15:04 +00:00
// select / highlight new port, if connected -> select connected port
2013-11-20 11:26:00 +00:00
if ( ! GUI . connected _to ) {
$ ( 'div#port-picker .port select' ) . val ( new _ports [ 0 ] ) ;
} else {
$ ( 'div#port-picker .port select' ) . val ( GUI . connected _to ) ;
}
2013-12-29 10:15:04 +00:00
// start connect procedure (if statement is valid)
if ( GUI . auto _connect && ! GUI . connecting _to && ! GUI . connected _to ) {
// we need firmware flasher protection over here
if ( GUI . active _tab != 'firmware_flasher' ) {
GUI . timeout _add ( 'auto-connect_timeout' , function ( ) {
$ ( 'div#port-picker a.connect' ) . click ( ) ;
} , 50 ) ; // small timeout so we won't get any nasty connect errors due to system initializing the bus
}
}
2013-11-20 11:26:00 +00:00
// reset initial_ports
initial _ports = current _ports ;
}
} ) ;
2014-01-03 09:40:34 +00:00
} , 250 , true ) ;
2013-11-20 11:26:00 +00:00
}
function update _port _select _menu ( ports ) {
$ ( 'div#port-picker .port select' ) . html ( '' ) ; // drop previous one
if ( ports . length > 0 ) {
for ( var i = 0 ; i < ports . length ; i ++ ) {
$ ( 'div#port-picker .port select' ) . append ( $ ( "<option/>" , { value : ports [ i ] , text : ports [ i ] } ) ) ;
}
} else {
$ ( 'div#port-picker .port select' ) . append ( $ ( "<option/>" , { value : 0 , text : 'NOT FOUND' } ) ) ;
}
}
2013-04-08 18:07:47 +00:00
function sensor _status ( sensors _detected ) {
2013-12-24 18:17:59 +00:00
// initialize variable (if it wasn't)
if ( typeof sensor _status . previous _sensors _detected == 'undefined' ) {
sensor _status . previous _sensors _detected = 0 ;
2013-04-08 18:07:47 +00:00
}
2013-12-24 18:17:59 +00:00
// update UI (if necessary)
if ( sensor _status . previous _sensors _detected != sensors _detected ) {
var e _sensor _status = $ ( 'div#sensor-status' ) ;
if ( bit _check ( sensors _detected , 0 ) ) { // Gyroscope & accel detected
$ ( '.gyro' , e _sensor _status ) . addClass ( 'on' ) ;
$ ( '.accel' , e _sensor _status ) . addClass ( 'on' ) ;
} else {
$ ( '.gyro' , e _sensor _status ) . removeClass ( 'on' ) ;
$ ( '.accel' , e _sensor _status ) . removeClass ( 'on' ) ;
}
2013-04-08 18:07:47 +00:00
2013-12-24 18:17:59 +00:00
if ( bit _check ( sensors _detected , 1 ) ) { // Barometer detected
$ ( '.baro' , e _sensor _status ) . addClass ( 'on' ) ;
} else {
$ ( '.baro' , e _sensor _status ) . removeClass ( 'on' ) ;
}
if ( bit _check ( sensors _detected , 2 ) ) { // Magnetometer detected
$ ( '.mag' , e _sensor _status ) . addClass ( 'on' ) ;
} else {
$ ( '.mag' , e _sensor _status ) . removeClass ( 'on' ) ;
}
if ( bit _check ( sensors _detected , 3 ) ) { // GPS detected
$ ( '.gps' , e _sensor _status ) . addClass ( 'on' ) ;
} else {
$ ( '.gps' , e _sensor _status ) . removeClass ( 'on' ) ;
}
if ( bit _check ( sensors _detected , 4 ) ) { // Sonar detected
$ ( '.sonar' , e _sensor _status ) . addClass ( 'on' ) ;
} else {
$ ( '.sonar' , e _sensor _status ) . removeClass ( 'on' ) ;
}
// set current value
sensor _status . previous _sensors _detected = sensors _detected ;
}
2013-04-08 18:07:47 +00:00
}
function highByte ( num ) {
return num >> 8 ;
}
function lowByte ( num ) {
return 0x00FF & num ;
}
function bit _check ( num , bit ) {
2013-12-12 16:10:10 +00:00
return ( ( num >> bit ) % 2 != 0 ) ;
2013-04-10 13:31:51 +00:00
}
function bit _set ( num , bit ) {
return num | 1 << bit ;
}
function bit _clear ( num , bit ) {
return num & ~ ( 1 << bit ) ;
2013-04-08 15:29:52 +00:00
}