Skip to content

Instantly share code, notes, and snippets.

@kubark42
Created August 7, 2020 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kubark42/75f25d1570aae85f5f0d4fc26522ab4c to your computer and use it in GitHub Desktop.
Save kubark42/75f25d1570aae85f5f0d4fc26522ab4c to your computer and use it in GitHub Desktop.
'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("&nbsp;&nbsp;&nbsp;&nbsp;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("&nbsp;&nbsp;&nbsp;&nbsp;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("&nbsp;&nbsp;&nbsp;&nbsp;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("&nbsp;&nbsp;&nbsp;&nbsp;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