Created
August 7, 2020 14:09
-
-
Save kubark42/75f25d1570aae85f5f0d4fc26522ab4c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
// MSP_codes needs to be re-integrated inside MSP object | |
var MSP_codes = { | |
MSP_DEBUG: 0, | |
MSP_FIRMWARE: 1, | |
MSP_BOARD: 2, | |
MSP_POLL: 3, | |
MSP_GETOHM: 4, | |
MSP_POLL_1780: 5, | |
MSP_CB_SET: 6 | |
}; | |
var MSP = { | |
state: 0, | |
debug_string: [], | |
debug_string_13_detect: 0, | |
ready_detected: 0, | |
code: 0, | |
message_length_expected: 0, | |
message_length_received: 0, | |
message_buffer: null, | |
message_buffer_uint8_view: null, | |
message_checksum: 0, | |
tempProbesHtml: 1, | |
callbacks: [], | |
packet_error: 0, | |
supportedBaudRates: [ // 0 based index. | |
'AUTO', | |
'9600', | |
'19200', | |
'38400', | |
'57600', | |
'115200', | |
'230400', | |
'250000', | |
], | |
read: function (readInfo) { | |
var data = new Uint8Array(readInfo.data); | |
for (var i = 0; i < data.length; i++) { | |
switch (this.state) { | |
case 0: // sync char 1 | |
if (data[i] == 36) { // $ | |
this.state++; | |
} else { | |
this.debug_string_fct(data[i]); | |
} | |
break; | |
case 1: // sync char 2 | |
if (data[i] == 82) { // R | |
this.state++; | |
} else { // restart and try again | |
this.state = 0; | |
this.debug_string_fct(data[i]); | |
} | |
break; | |
case 2: // direction (should be >) | |
if (data[i] == 62) { // > | |
this.state++; | |
} else { // restart and try again | |
this.state = 0; | |
this.debug_string_fct(data[i]); | |
} | |
break; | |
case 3: | |
this.message_length_expected = data[i]; | |
this.message_checksum = data[i]; | |
// setup arraybuffer | |
this.message_buffer = new ArrayBuffer(this.message_length_expected); | |
this.message_buffer_uint8_view = new Uint8Array(this.message_buffer); | |
this.state++; | |
break; | |
case 4: | |
this.code = data[i]; | |
this.message_checksum ^= data[i]; | |
if (this.message_length_expected > 0) { | |
// process payload | |
this.state++; | |
} else { | |
// no payload | |
this.state += 2; | |
} | |
break; | |
case 5: // payload | |
this.message_buffer_uint8_view[this.message_length_received] = data[i]; | |
this.message_checksum ^= data[i]; | |
this.message_length_received++; | |
if (this.message_length_received >= this.message_length_expected) { | |
this.state++; | |
} | |
break; | |
case 6: | |
if (this.message_checksum == data[i]) { | |
// message received, process | |
//console.log('Received code: ' + this.code + ' - crc passed'); | |
this.process_data(this.code, this.message_buffer, this.message_length_expected); | |
} else { | |
GUI.log('Received code: ' + this.code + ' - crc failed'); | |
GUI.log('Received crc: ' + data[i] + ', expect crc: ' + this.message_checksum); | |
// this.packet_error++; | |
$('span.packet-error').html(this.packet_error); | |
} | |
// Reset variables | |
this.message_length_received = 0; | |
this.state = 0; | |
break; | |
default: | |
console.log('Unknown state detected: ' + this.state); | |
} | |
} | |
}, | |
//Displays anything that is not a protocol as debug strings. | |
//(allows using Serial.println() anywhere in the firmware...) | |
debug_string_fct: function (char) { | |
if(char == 13){ | |
this.debug_string_13_detect = 1; | |
}else{ | |
if(this.debug_string_13_detect && char == 10){ | |
GUI.log('Firmware message: <strong>' + this.debug_string + '</strong>'); | |
if(this.debug_string === "Ready") { | |
GUI.log('Board ready to poll'); | |
MSP.ready_detected = true; | |
CONFIG.readyCallback(); //board is ready and initialized, we can now start polling data | |
} | |
this.debug_string = []; | |
}else{ | |
this.debug_string += String.fromCharCode(char); | |
} | |
this.debug_string_13_detect = 0; | |
} | |
}, | |
msp_refresh_temp_probes: function (){ | |
if(MSP.tempProbesHtml){ | |
htmlTempProbes(); | |
MSP.tempProbesHtml = 0; | |
} | |
refreshTempProbes(); | |
}, | |
//Fixed a bug where the temp probe reading is a glitch | |
filterTemp: function(val, old){ | |
// Due to electrical noise, the temperature probe seems to reset sometimes and it's default value is zero. | |
/*if(math.abs(val)<0.01){ | |
return old; | |
}*/ | |
return val; | |
}, | |
//Processes the received serial data | |
process_data: function (code, message_buffer, message_length) { | |
var data = new DataView(message_buffer, 0); // DataView (allowing us to view arrayBuffer as struct/union) | |
switch (code) { | |
case MSP_codes.MSP_POLL: | |
var index = 0; | |
var acc_scale = 512; | |
// Ignoring first data after chip init because it can send wrong values | |
if(CONFIGURATOR.firstReadingDiscarted){ | |
SENSOR_DATA.ESCvoltage = data.getFloat32(index, 1); index+=4; //in V | |
SENSOR_DATA.ESCcurrent = data.getFloat32(index, 1); index+=4; //in A | |
SENSOR_DATA.power = data.getFloat32(index,1); index+=4; //in W | |
SENSOR_DATA.loadCellThrust = data.getFloat32(index, 1); index+=4; //V | |
SENSOR_DATA.loadCellLeft = data.getFloat32(index, 1); index+=4; //V | |
SENSOR_DATA.eRPM_HZ = data.getFloat32(index, 1); index+=4; //V | |
SENSOR_DATA.oRPM_HZ = data.getFloat32(index, 1); index+=4; //V | |
SENSOR_DATA.temperature[0].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[0].value); index+=4; //in degC | |
SENSOR_DATA.temperature[1].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[1].value); index+=4; //in degC | |
SENSOR_DATA.temperature[2].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[2].value); index+=4; //in degC | |
SENSOR_DATA.basicDataFlag = data.getUint8(index, 1); index+=1; | |
if(SENSOR_DATA.ESCvoltage<0) SENSOR_DATA.ESCvoltage = 0; | |
SENSOR_DATA.accelerometer[0] = data.getInt16(index, 1) / acc_scale; index+=2; | |
SENSOR_DATA.accelerometer[1] = data.getInt16(index, 1) / acc_scale; index+=2; | |
SENSOR_DATA.accelerometer[2] = data.getInt16(index, 1) / acc_scale; index+=2; | |
SENSOR_DATA.vibration = data.getInt16(index, 1) / acc_scale; index+=2; | |
SENSOR_DATA.rawPressureP = data.getInt16(index, 1); index+=2; | |
SENSOR_DATA.rawPressureT = data.getInt16(index, 1); index+=2; | |
SENSOR_DATA.loadCellRight = data.getFloat32(index, 1); index+=4; | |
SENSOR_DATA.proDataFlag = data.getUint8(index, 1); index+=1; | |
//Separating bits for flags | |
FIRMWARE_FLAGS.oRPMFlag = SENSOR_DATA.basicDataFlag&(1<<6); | |
FIRMWARE_FLAGS.eRPMFlag = SENSOR_DATA.basicDataFlag&(1<<5); | |
FIRMWARE_FLAGS.loadCellLeftFlag = SENSOR_DATA.basicDataFlag&(1<<4); | |
FIRMWARE_FLAGS.loadCellThrustFlag = SENSOR_DATA.basicDataFlag&(1<<3); | |
FIRMWARE_FLAGS.power = SENSOR_DATA.basicDataFlag&(1<<2); | |
FIRMWARE_FLAGS.escCurrentFlag = SENSOR_DATA.basicDataFlag&(1<<1); | |
FIRMWARE_FLAGS.escVoltageFlag = SENSOR_DATA.basicDataFlag&(1<<0); | |
FIRMWARE_FLAGS.temperatureProbes = SENSOR_DATA.basicDataFlag&(1<<7); | |
FIRMWARE_FLAGS.loadCellRightFlag = SENSOR_DATA.proDataFlag&(1<<1); | |
FIRMWARE_FLAGS.accelerometerFlag = SENSOR_DATA.proDataFlag&(1<<0); | |
//Process RPM readings | |
if(FIRMWARE_FLAGS.eRPMFlag) DATA.processElectricalRPM(SENSOR_DATA.eRPM_HZ); | |
if(FIRMWARE_FLAGS.oRPMFlag) DATA.processOpticalRPM(SENSOR_DATA.oRPM_HZ); | |
//Apply Low Pass Filter | |
if(FIRMWARE_FLAGS.loadCellLeftFlag) LPFLeft.update(SENSOR_DATA.loadCellLeft); | |
if(FIRMWARE_FLAGS.loadCellRightFlag) LPFRight.update(SENSOR_DATA.loadCellRight); | |
if(FIRMWARE_FLAGS.loadCellThrustFlag) LPFThrust.update(SENSOR_DATA.loadCellThrust); | |
if(FIRMWARE_FLAGS.power) LPFpower.update(SENSOR_DATA.power); | |
if(FIRMWARE_FLAGS.escCurrentFlag) LPFescCurrent.update(SENSOR_DATA.ESCcurrent); | |
if(FIRMWARE_FLAGS.escCurrentFlag) LPFescCurrentBurst.update(SENSOR_DATA.ESCcurrent); | |
if(FIRMWARE_FLAGS.escVoltageFlag) LPFescVoltage.update(SENSOR_DATA.ESCvoltage); | |
LPFpressure.update(SENSOR_DATA.rawPressureP); | |
LPFpressureT.update(SENSOR_DATA.rawPressureT); | |
if(FIRMWARE_FLAGS.temperatureProbes){ | |
MSP.msp_refresh_temp_probes(); | |
} | |
SENSOR_DATA.newDataToPlot = true; | |
} | |
CONFIGURATOR.firstReadingDiscarted = true; | |
break; | |
case MSP_codes.MSP_POLL_1780: | |
// Ignoring first data after chip init because it can send wrong values | |
if(CONFIGURATOR.firstReadingDiscarted){ | |
var index = 0; | |
SENSOR_DATA.ESCvoltage = data.getFloat32(index, 1); index+=4; //in V | |
SENSOR_DATA.ESCcurrent = data.getFloat32(index, 1); index+=4; //in A | |
isNaN(SENSOR_DATA.ESCcurrent) ? 0 : LPFescCurrentA.update(SENSOR_DATA.ESCcurrent); | |
isNaN(SENSOR_DATA.ESCcurrent) ? 0 : LPFescCurrentBurstA.update(SENSOR_DATA.ESCcurrent); | |
isNaN(SENSOR_DATA.ESCvoltage) ? 0 : LPFescVoltageA.update(SENSOR_DATA.ESCvoltage); | |
for (var i = 0; i < 6; i++){ | |
SENSOR_DATA.sixAxisForcesNA[i] = data.getFloat32(index, 1); index+=4; | |
isNaN(SENSOR_DATA.sixAxisForcesNA[i]) ? 0 : LPFforcesA[i].update(SENSOR_DATA.sixAxisForcesNA[i]); | |
} | |
//SENSOR_DATA.eRPM_HZ = data.getFloat32(index, 1); index+=4; //Hz | |
SENSOR_DATA.s1780AopticalRPM = data.getFloat32(index, 1); index+=4; //Hz | |
// SENSOR_DATA.temperature[0].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[0].value); index+=4; //in degC | |
// SENSOR_DATA.temperature[1].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[1].value); index+=4; //in degC | |
// SENSOR_DATA.temperature[2].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[2].value); index+=4; //in degC | |
// SENSOR_DATA.temperature[3].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[3].value); index+=4; //in degC | |
// SENSOR_DATA.temperature[4].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[4].value); index+=4; //in degC | |
// SENSOR_DATA.temperature[5].value = MSP.filterTemp(data.getFloat32(index,1),SENSOR_DATA.temperature[5].value); index+=4; //in degC | |
var temperature0 = (data.getFloat32(index,1)); index+=4; //in degC | |
var temperature1 = (data.getFloat32(index,1)); index+=4; //in degC | |
var temperature2 = (data.getFloat32(index,1)); index+=4; //in degC | |
var temperature3 = (data.getFloat32(index,1)); index+=4; //in degC | |
var temperature4 = (data.getFloat32(index,1)); index+=4; //in degC | |
var temperature5 = (data.getFloat32(index,1)); index+=4; //in degC | |
// SENSOR_DATA.temperature[0].value = temperature0 | |
// SENSOR_DATA.temperature[1].value = temperature1 | |
// SENSOR_DATA.temperature[2].value = temperature2 | |
// SENSOR_DATA.temperature[3].value = temperature3 | |
// SENSOR_DATA.temperature[4].value = temperature4 | |
// SENSOR_DATA.temperature[5].value = temperature5 | |
if (!isNaN(temperature0)) { | |
GUI.log(MSP.filterTemp(temperature0, SENSOR_DATA.temperature[0].value)); | |
} | |
isNaN(temperature0) ? 0 : SENSOR_DATA.temperature[0].value = MSP.filterTemp(temperature0, SENSOR_DATA.temperature[0].value); | |
isNaN(temperature1) ? 0 : SENSOR_DATA.temperature[1].value = MSP.filterTemp(temperature1, SENSOR_DATA.temperature[1].value); | |
isNaN(temperature2) ? 0 : SENSOR_DATA.temperature[2].value = MSP.filterTemp(temperature2, SENSOR_DATA.temperature[2].value); | |
isNaN(temperature3) ? 0 : SENSOR_DATA.temperature[3].value = MSP.filterTemp(temperature3, SENSOR_DATA.temperature[3].value); | |
isNaN(temperature4) ? 0 : SENSOR_DATA.temperature[4].value = MSP.filterTemp(temperature4, SENSOR_DATA.temperature[4].value); | |
isNaN(temperature5) ? 0 : SENSOR_DATA.temperature[5].value = MSP.filterTemp(temperature5, SENSOR_DATA.temperature[5].value); | |
SENSOR_DATA.rawPressureP = data.getInt16(index, 1); index+=2; | |
SENSOR_DATA.rawPressureT = data.getInt16(index, 1); index+=2; | |
if (SENSOR_DATA.rawPressureP > 0) { | |
LPFpressure.update(SENSOR_DATA.rawPressureP); | |
} | |
if (SENSOR_DATA.rawPressureT > -274) { | |
LPFpressureT.update(SENSOR_DATA.rawPressureT); | |
} | |
SENSOR_DATA.s1780Bvoltage = data.getFloat32(index,1); index+=4; //in V | |
SENSOR_DATA.s1780Bcurrent = data.getFloat32(index,1); index+=4; //in A | |
isNaN(SENSOR_DATA.s1780Bcurrent) ? 0 : LPFescCurrentB.update(SENSOR_DATA.s1780Bcurrent); | |
isNaN(SENSOR_DATA.s1780Bcurrent) ? 0 : LPFescCurrentBurstB.update(SENSOR_DATA.s1780Bcurrent); | |
isNaN(SENSOR_DATA.s1780Bvoltage) ? 0 : LPFescVoltageB.update(SENSOR_DATA.s1780Bvoltage); | |
for (var i = 0; i < 6; i++){ | |
SENSOR_DATA.sixAxisForcesNB[i] = data.getFloat32(index, 1); index+=4; | |
isNaN(SENSOR_DATA.sixAxisForcesNB[i]) ? 0 : LPFforcesB[i].update(SENSOR_DATA.sixAxisForcesNB[i]); | |
} | |
SENSOR_DATA.s1780BopticalRPM = data.getFloat32(index, 1); index+=4; //Hz | |
var flags = data.getUint8(index, 1); index+=1; | |
SENSOR_DATA.s1780loadCellOverload = flags&(1<<0); | |
SENSOR_DATA.s1780limitSwitch = (flags&(1<<1))>>1; | |
//DATA.processElectricalRPM(SENSOR_DATA.eRPM_HZ); | |
if (!isNaN(SENSOR_DATA.s1780AopticalRPM)) { | |
DATA.processOpticalRPM(SENSOR_DATA.s1780AopticalRPM); | |
} | |
if (!isNaN(SENSOR_DATA.s1780BopticalRPM)) { | |
DATA.processOpticalRPM(SENSOR_DATA.s1780BopticalRPM); | |
} | |
MSP.msp_refresh_temp_probes(); | |
SENSOR_DATA.newDataToPlot = true; | |
} | |
CONFIGURATOR.firstReadingDiscarted = true; | |
break; | |
case MSP_codes.MSP_DEBUG: | |
var index = 0; | |
for (var i = 0; i < 4; i++){ | |
SENSOR_DATA.debug[i] = data.getInt16(index, 1); index+=2; | |
} | |
for (var i = 0; i < 4; i++){ | |
SENSOR_DATA.pinState[i] = data.getUint8(index, 1); index+=1; | |
} | |
if(CONFIG.boardVersion === "Series 1780"){ | |
for (var i = 0; i < 6; i++){ | |
SENSOR_DATA.sixAxisForcesRawA[i] = data.getFloat32(index, 1); index+=4; | |
} | |
for (var i = 0; i < 6; i++){ | |
SENSOR_DATA.sixAxisForcesRawB[i] = data.getFloat32(index, 1); index+=4; | |
} | |
} | |
break; | |
case MSP_codes.MSP_FIRMWARE: | |
var offset = 0; | |
CONFIG.mspProtocolVersion = data.getUint8(offset++); | |
CONFIG.firmwareVersion = data.getUint8(offset++) + '.' + data.getUint8(offset++); | |
break; | |
case MSP_codes.MSP_BOARD: | |
var offset = 0; | |
var boardVersion = data.getUint8(offset++); | |
CONFIG.boardVersion = "Unknown board version"; | |
if(boardVersion===1) CONFIG.boardVersion = "Series 1580"; | |
if(boardVersion===2) CONFIG.boardVersion = "Series 1520"; | |
if(boardVersion===3) CONFIG.boardVersion = "Series 1580"; | |
if(boardVersion===4) CONFIG.boardVersion = "Series 1780"; | |
if(boardVersion===5) CONFIG.boardVersion = "Series 1580"; // setting this to Series 1585 will require us to change a LOT of code. | |
CONFIG.displayVersion = CONFIG.boardVersion; | |
if(boardVersion===5) { // APPLY DIFFERENCES BETWEEN THE 1580 and 1585. NOTE THIS PART NEEDS REFRACTORING.... | |
CONFIG.displayVersion = "Series 1585"; | |
SYSTEM_LIMITS_15xx.voltageMax = 50; | |
SYSTEM_LIMITS_15xx.currentMin = -55; | |
SYSTEM_LIMITS_15xx.currentMax = 55; | |
SYSTEM_LIMITS_15xx.currentBurstMin = -60; | |
SYSTEM_LIMITS_15xx.currentBurstMax = 60; | |
SYSTEM_LIMITS_15xx.powerMax = 2750; | |
console.log("Setting LPF cutoffs to null"); | |
var cutoffHz = 0; | |
LPFThrust = new LowPassFilter(cutoffHz); | |
LPFRight = new LowPassFilter(cutoffHz); | |
LPFLeft = new LowPassFilter(cutoffHz); | |
LPFescCurrent = new LowPassFilter(cutoffHz); | |
LPFescVoltage = new LowPassFilter(cutoffHz); | |
LPFpower = new LowPassFilter(cutoffHz); | |
}else{ | |
SYSTEM_LIMITS_15xx.voltageMax = 35; | |
SYSTEM_LIMITS_15xx.currentMax = -40; | |
SYSTEM_LIMITS_15xx.currentMax = 40; | |
SYSTEM_LIMITS_15xx.currentBurstMax = -50; | |
SYSTEM_LIMITS_15xx.currentBurstMax = 50; | |
SYSTEM_LIMITS_15xx.powerMax = 1400; | |
console.log("Setting LPF cutoffs to 1Hz"); | |
var cutoffHz = 1; | |
LPFThrust = new LowPassFilter(cutoffHz); | |
LPFRight = new LowPassFilter(cutoffHz); | |
LPFLeft = new LowPassFilter(cutoffHz); | |
LPFescCurrent = new LowPassFilter(cutoffHz); | |
LPFescVoltage = new LowPassFilter(cutoffHz); | |
LPFpower = new LowPassFilter(cutoffHz); | |
} | |
console.log(boardVersion); | |
showBoardSpecific(true); | |
//Get the board unique ID | |
var id = []; offset++; //skip family code | |
for (var i = 0; i < 7; i++){ | |
id += ("00" + data.getUint8(offset++).toString(16)).slice(-2); | |
} | |
CONFIG.boardId = id.toUpperCase(); | |
CONFIG.pSensorAvailable = data.getUint8(offset++); | |
CONFIG.tempProbesQty = data.getUint8(offset++); | |
console.log(CONFIG.tempProbesQty + " temperature probes detected."); | |
var tempProbesArray = 3; | |
if(CONFIG.boardVersion === "Series 1780"){ | |
tempProbesArray = 6; | |
} | |
//Get the temperature probe ID's | |
for(var probe = 0; probe < tempProbesArray; probe++){ | |
id = []; offset++; //skip family code | |
var dispid = 0; //A short version for display | |
for (var i = 0; i < 7; i++){ | |
var unit8val = data.getUint8(offset++); | |
id += ("00" + unit8val.toString(16)).slice(-2); | |
dispid = 3*dispid + unit8val; //number here controls the lenght of the short ID. short has higher risk of collision. For full resolution use 256. | |
} | |
id = id.toUpperCase(); | |
dispid = dispid.toString(32).toUpperCase(); | |
console.log("Probe ID: " + id + "(" + dispid + ")"); | |
SENSOR_DATA.temperature[probe].id = dispid; | |
} | |
MSP.tempProbesHtml = true; | |
if(CONFIG.boardVersion === "Series 1780"){ | |
var s1780detection = data.getUint8(offset++); | |
CONFIG.s1780detected.PSA = s1780detection&(1<<0); | |
CONFIG.s1780detected.LCA = s1780detection&(1<<1); | |
CONFIG.s1780detected.PSB = s1780detection&(1<<2); | |
CONFIG.s1780detected.LCB = s1780detection&(1<<3); | |
CONFIG.s1780detected.PSAboardVersion = data.getUint8(offset++); | |
CONFIG.s1780detected.LCAboardVersion = data.getUint8(offset++); | |
CONFIG.s1780detected.PSBboardVersion = data.getUint8(offset++); | |
CONFIG.s1780detected.LCBboardVersion = data.getUint8(offset++); | |
//Do not accept unsupported board versions | |
var PSAaccepted = [1,2,3,4]; | |
var PSBaccepted = [1,2,3,4]; | |
var LCAaccepted = [1,2,3,4]; | |
var LCBaccepted = [1,2,3,4]; | |
if(CONFIG.s1780detected.PSA && PSAaccepted.indexOf(CONFIG.s1780detected.PSAboardVersion) == -1){ | |
CONFIG.s1780detected.PSA = 0; | |
GUI.log("Error: PSA detected but board version is unsupported: " + CONFIG.s1780detected.PSAboardVersion); | |
} | |
if(CONFIG.s1780detected.PSB && PSBaccepted.indexOf(CONFIG.s1780detected.PSBboardVersion) == -1){ | |
CONFIG.s1780detected.PBB = 0; | |
GUI.log("Error: PSB detected but board version is unsupported: " + CONFIG.s1780detected.PSBboardVersion); | |
} | |
if(CONFIG.s1780detected.LCA && LCAaccepted.indexOf(CONFIG.s1780detected.LCAboardVersion) == -1){ | |
CONFIG.s1780detected.LCA = 0; | |
GUI.log("Error: LCA detected but board version is unsupported: " + CONFIG.s1780detected.LCAboardVersion); | |
} | |
if(CONFIG.s1780detected.LCB && LCBaccepted.indexOf(CONFIG.s1780detected.LCBboardVersion) == -1){ | |
CONFIG.s1780detected.LCB = 0; | |
GUI.log("Error: LCB detected but board version is unsupported: " + CONFIG.s1780detected.LCBboardVersion); | |
} | |
CONFIG.s1780detected.Aside = CONFIG.s1780detected.PSA || CONFIG.s1780detected.LCA; | |
CONFIG.s1780detected.Bside = CONFIG.s1780detected.PSB || CONFIG.s1780detected.LCB; | |
CONFIG.s1780detected.Dual = CONFIG.s1780detected.Aside && CONFIG.s1780detected.Bside; | |
CONFIG.s1780detected.Full = CONFIG.s1780detected.PSA && CONFIG.s1780detected.LCA && CONFIG.s1780detected.PSB && CONFIG.s1780detected.LCB; | |
//Set extended limits | |
SYSTEM_LIMITS_1780.extended = {}; //clear extended limits (prevents bug if switching to lower spec board) | |
if(CONFIG.s1780detected.Aside){ | |
GUI.log("Side A component(s) detected:"); | |
} | |
if(CONFIG.s1780detected.PSA){ | |
GUI.log(" Power sensor v" + CONFIG.s1780detected.PSAboardVersion); | |
//Adjust system limits as needed | |
var key = 'powerSensorV' + CONFIG.s1780detected.PSAboardVersion; | |
SYSTEM_LIMITS_1780.extended.currentMinA = SYSTEM_LIMITS_1780.boardSpecific[key].currentMin; | |
SYSTEM_LIMITS_1780.extended.currentMaxA = SYSTEM_LIMITS_1780.boardSpecific[key].currentMax; | |
SYSTEM_LIMITS_1780.extended.currentBurstMinA = SYSTEM_LIMITS_1780.boardSpecific[key].currentBurstMin; | |
SYSTEM_LIMITS_1780.extended.currentBurstMaxA = SYSTEM_LIMITS_1780.boardSpecific[key].currentBurstMax; | |
SYSTEM_LIMITS_1780.extended.powerMaxA = SYSTEM_LIMITS_1780.boardSpecific[key].powerMax; | |
SYSTEM_LIMITS_1780.extended.voltageMaxA = SYSTEM_LIMITS_1780.boardSpecific[key].voltageMax; | |
} | |
if(CONFIG.s1780detected.LCA){ | |
GUI.log(" Load sensor v" + CONFIG.s1780detected.LCAboardVersion); | |
//Adjust system limits as needed | |
var key = 'loadSensorV' + CONFIG.s1780detected.LCAboardVersion; | |
SYSTEM_LIMITS_1780.extended.thrustMinA = SYSTEM_LIMITS_1780.boardSpecific[key].thrustMin; | |
SYSTEM_LIMITS_1780.extended.thrustMaxA = SYSTEM_LIMITS_1780.boardSpecific[key].thrustMax; | |
SYSTEM_LIMITS_1780.extended.torqueMinA = SYSTEM_LIMITS_1780.boardSpecific[key].torqueMin; | |
SYSTEM_LIMITS_1780.extended.torqueMaxA = SYSTEM_LIMITS_1780.boardSpecific[key].torqueMax; | |
} | |
if(CONFIG.s1780detected.Bside){ | |
GUI.log("Side B component(s) detected:"); | |
} | |
if(CONFIG.s1780detected.PSB){ | |
GUI.log(" Power sensor v" + CONFIG.s1780detected.PSBboardVersion); | |
//Adjust system limits as needed | |
var key = 'powerSensorV' + CONFIG.s1780detected.PSBboardVersion; | |
SYSTEM_LIMITS_1780.extended.currentMinB = SYSTEM_LIMITS_1780.boardSpecific[key].currentMin; | |
SYSTEM_LIMITS_1780.extended.currentMaxB = SYSTEM_LIMITS_1780.boardSpecific[key].currentMax; | |
SYSTEM_LIMITS_1780.extended.currentBurstMinB = SYSTEM_LIMITS_1780.boardSpecific[key].currentBurstMin; | |
SYSTEM_LIMITS_1780.extended.currentBurstMaxB = SYSTEM_LIMITS_1780.boardSpecific[key].currentBurstMax; | |
SYSTEM_LIMITS_1780.extended.powerMaxB = SYSTEM_LIMITS_1780.boardSpecific[key].powerMax; | |
SYSTEM_LIMITS_1780.extended.voltageMaxB = SYSTEM_LIMITS_1780.boardSpecific[key].voltageMax; | |
} | |
if(CONFIG.s1780detected.LCB){ | |
GUI.log(" Load sensor v" + CONFIG.s1780detected.LCBboardVersion); | |
//Adjust system limits as needed | |
var key = 'loadSensorV' + CONFIG.s1780detected.LCBboardVersion; | |
SYSTEM_LIMITS_1780.extended.thrustMinB = SYSTEM_LIMITS_1780.boardSpecific[key].thrustMin; | |
SYSTEM_LIMITS_1780.extended.thrustMaxB = SYSTEM_LIMITS_1780.boardSpecific[key].thrustMax; | |
SYSTEM_LIMITS_1780.extended.torqueMinB = SYSTEM_LIMITS_1780.boardSpecific[key].torqueMin; | |
SYSTEM_LIMITS_1780.extended.torqueMaxB = SYSTEM_LIMITS_1780.boardSpecific[key].torqueMax; | |
} | |
} | |
console.log("SYSTEM LIMITS:"); | |
console.log(SYSTEM_LIMITS_1780); | |
break; | |
case MSP_codes.MSP_GETOHM: | |
var index = 0; | |
SENSOR_DATA.ohmStatus = data.getUint8(index++); | |
SENSOR_DATA.ohmReading = data.getFloat32(index, 1); index +=4; | |
break; | |
case MSP_codes.MSP_CB_SET: | |
var index = 0; | |
var flags = data.getUint8(index++); | |
CONFIG.controlBoard_flag_active = flags&(1<<0); | |
CONFIG.controlBoard_current_rc_type = data.getUint8(index++); | |
CONFIG.controlBoard_protocol = data.getUint8(index++); | |
CONFIG.controlBoard_version = data.getUint16(index, true); index+=2; | |
if(CONFIG.controlBoard_flag_active){ | |
GUI.log("External control board detected. Protocol: " + CONFIG.controlBoard_protocol + " Firmware: " + CONFIG.controlBoard_version); | |
}else{ | |
GUI.log("No control board detected"); | |
} | |
break; | |
default: | |
console.log('Unknown code detected: ' + code); | |
} | |
// trigger callbacks, cleanup/remove callback after trigger | |
for (var i = this.callbacks.length - 1; i >= 0; i--) { // itterating in reverse because we use .splice which modifies array length | |
if (this.callbacks[i].code == code) { | |
// save callback reference | |
var callback = this.callbacks[i].callback; | |
// remove timeout | |
clearInterval(this.callbacks[i].timer); | |
// remove object from array | |
this.callbacks.splice(i, 1); | |
// fire callback | |
if (callback) callback({'command': code, 'data': data, 'length': message_length}); | |
} | |
} | |
}, | |
//Sends the polled data | |
send_poll: function (callback) { | |
var data15xx = new ArrayBuffer(8); | |
var dataview15xx = new DataView(data15xx); // DataView (allowing us to view arrayBuffer as struct/union) | |
var data1780 = new ArrayBuffer(9); | |
var dataview1780 = new DataView(data1780); // DataView (allowing us to view arrayBuffer as struct/union) | |
var index = 0; | |
var protocol = CONFIG.controlBoard.value.protocol; | |
if(CONFIG.boardVersion === "Series 1780"){ | |
dataview1780.setUint16(index,OUTPUT_DATA.ESCA,1); index+=2; | |
dataview1780.setUint16(index,OUTPUT_DATA.ServoA,1); index+=2; | |
dataview1780.setUint16(index,OUTPUT_DATA.ESCB,1); index+=2; | |
dataview1780.setUint16(index,OUTPUT_DATA.ServoB,1); index+=2; | |
dataview1780.setUint8(index,CONFIG.reverseCutoffSwitch.value,1); index+=1; | |
data1780 = new Uint8Array(data1780); | |
}else{ | |
var pwm_min = CONTROL_PROTOCOLS[protocol].min_val; | |
var pwm_max = CONTROL_PROTOCOLS[protocol].max_val; | |
var msp_min = CONTROL_PROTOCOLS[protocol].msp_min; | |
var msp_max = CONTROL_PROTOCOLS[protocol].msp_max; | |
function convertToMSP(val){ | |
return math.round((msp_max - msp_min)*(val - pwm_min)/(pwm_max - pwm_min) + msp_min); | |
} | |
dataview15xx.setUint16(index,convertToMSP(OUTPUT_DATA.ESC_PWM),1); index+=2; | |
dataview15xx.setUint16(index,convertToMSP(OUTPUT_DATA.Servo_PWM[0]),1); index+=2; | |
dataview15xx.setUint16(index,convertToMSP(OUTPUT_DATA.Servo_PWM[1]),1); index+=2; | |
dataview15xx.setUint16(index,convertToMSP(OUTPUT_DATA.Servo_PWM[2]),1); index+=2; | |
data15xx = new Uint8Array(data15xx); | |
} | |
// set to zero the inactive outputs | |
for(var i=0; i<4; i++){ | |
if(!OUTPUT_DATA.active[i]){ | |
dataview1780.setUint16(2*i,0,1); | |
dataview15xx.setUint16(2*i,0xffff,1); | |
} | |
} | |
if(CONFIG.developper_mode){ | |
MSP.send_message(MSP_codes.MSP_DEBUG, false, false, false); //poll the debug info too | |
} | |
if(CONFIG.boardVersion === "Series 1780"){ | |
MSP.send_message(MSP_codes.MSP_POLL_1780, data1780, false, callback); | |
}else{ | |
MSP.send_message(MSP_codes.MSP_POLL, data15xx, false, callback); | |
} | |
}, | |
//Send a message to the serial port | |
send_message: function (code, data, callback_sent, callback_msp) { | |
var bufferOut, | |
bufView; | |
// always reserve 6 bytes for protocol overhead ! | |
if (data) { | |
var size = data.length + 6, | |
checksum = 0; | |
bufferOut = new ArrayBuffer(size); | |
bufView = new Uint8Array(bufferOut); | |
bufView[0] = 36; // $ | |
bufView[1] = 82; // R | |
bufView[2] = 60; // < | |
bufView[3] = data.length; | |
bufView[4] = code; | |
checksum = bufView[3] ^ bufView[4]; | |
for (var i = 0; i < data.length; i++) { | |
bufView[i + 5] = data[i]; | |
checksum ^= bufView[i + 5]; | |
} | |
bufView[5 + data.length] = checksum; | |
} else { | |
bufferOut = new ArrayBuffer(6); | |
bufView = new Uint8Array(bufferOut); | |
bufView[0] = 36; // $ | |
bufView[1] = 82; // R | |
bufView[2] = 60; // < | |
bufView[3] = 0; // data length | |
bufView[4] = code; // code | |
bufView[5] = bufView[3] ^ bufView[4]; // checksum | |
} | |
//console.log('Sending code: ' + code); | |
// dev version 0.57 code below got recently changed due to the fact that queueing same MSP codes was unsupported | |
// and was causing trouble while backup/restoring configurations | |
// watch out if the recent change create any inconsistencies and then adjust accordingly | |
var obj = {'code': code, 'requestBuffer': bufferOut, 'callback': (callback_msp) ? callback_msp : false, 'timer': false}; | |
var requestExists = false; | |
for (var i = 0; i < MSP.callbacks.length; i++) { | |
if (MSP.callbacks[i].code == code) { | |
// request already exist, we will just attach | |
requestExists = true; | |
break; | |
} | |
} | |
if (!requestExists) { | |
obj.timer = setInterval(function () { | |
GUI.log('MSP data request timed-out: ' + code); | |
if(isConnected()){ | |
//Restart the polling if it is the poll message, | |
//otherwise just try again until solved | |
if(code == MSP.POLL){ | |
repeated_sensor_poll(); | |
}else{ | |
serial.send(bufferOut, false); | |
} | |
// this.packet_error++; | |
console.log("Repeating"); | |
}else{ | |
this.packet_error = 0; | |
clearInterval(obj.timer); | |
} | |
}, 4000); // we should be able to define timeout in the future | |
} | |
if(this.packet_error > 6){ | |
// commError(); | |
} | |
MSP.callbacks.push(obj); | |
// always send messages with data payload (even when there is a message already in the queue) | |
if (data || !requestExists) { | |
serial.send(bufferOut, function (sendInfo) { | |
if (sendInfo.bytesSent == bufferOut.length) { | |
if (callback_sent) callback_sent(); | |
} | |
}); | |
} | |
return true; | |
}, | |
callbacks_cleanup: function () { | |
for (var i = 0; i < this.callbacks.length; i++) { | |
clearInterval(this.callbacks[i].timer); | |
} | |
this.callbacks = []; | |
}, | |
disconnect_cleanup: function () { | |
this.state = 0; // reset packet state for "clean" initial entry (this is only required if user hot-disconnects) | |
this.packet_error = 0; // reset CRC packet error counter for next session | |
this.callbacks_cleanup(); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment