Skip to content

Commit 70d0961

Browse files
committed
MZTC: match the corrected firmware MSP contract
Follows the firmware changes in iNavFlight/inav#11837. MSP codes The commands move from 0x3000 into INAV's own range and now sit contiguously from 0x2240 to 0x2249. 0x3000 and 0x3001 are MSP2_BETAFLIGHT_BIND and MSP2_RX_BIND. The old block collided with them. The codes nothing implemented are dropped. CALIBRATE, INIT_STATUS, SAVE_CONFIG, RESTORE_DEFAULTS and RECONNECT had no firmware handler. MSP2_SET_MZTC_VIGNETTING is added. Payloads MSP2_MZTC_CONFIG is a fixed 15 byte payload read one field at a time. The old parser assumed an unpadded C struct and read the thresholds at offsets 17 and 21. The firmware struct had alignment padding there. Both offsets were wrong on the wire in both directions. The send path no longer writes float32. MSP2_MZTC_STATUS is a fixed 7 byte payload and is parsed at all now. It was never handled. connected is a real field, set only after the camera answers a command. Removed fields The five RC channel fields were never in the payload. The temperature fields, the frame fields, bad pixel removal, vignetting correction and the crosshair flag are gone from the firmware. The camera reports no temperature and no frame over its serial protocol. The other three were stored but never transmitted. Serial port index mztc_port is the zero-based serialPortIdentifier_e value that the firmware hands to openSerialPort(). Three places added 1 to it and special-cased UART6. That pointed the driver at the wrong UART. OSD The ten elements at invented ids 200 to 209 are replaced with the one the firmware provides, MZTC_STATUS at id 171. The old entries were gated on FC.FEATURES.MZTC. That does not exist. A localization string is added for the name. State FC.MZTC_CONFIG and FC.MZTC_STATUS are declared in fc.js resetState like every other FC block. MZTC_CONFIG was previously created ad-hoc by the MSP handler. Localization The MassZero block had been inserted into messages.json twice. All 17 keys were duplicated. JSON keeps the last definition, leaving the earlier copy as dead weight. The earlier copy is removed along with the strings for the settings that no longer exist. The operating mode help text described frame capture modes the firmware does not have. Dependency electron-prebuilt-compile is reverted along with the 13385 lines of package-lock churn it pulled in. Nothing in the tree references it.
1 parent 8379ca2 commit 70d0961

10 files changed

Lines changed: 4031 additions & 9835 deletions

File tree

js/fc.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,29 @@ var FC = {
106106
return true; // Currently all platforms use D term
107107
},
108108
resetState: function () {
109+
// MassZero thermal camera. MZTC_CONFIG mirrors the 15 byte
110+
// MSP2_MZTC_CONFIG payload. MZTC_STATUS stays null until the flight
111+
// controller answers MSP2_MZTC_STATUS.
112+
this.MZTC_CONFIG = {
113+
enabled: 0,
114+
port: 1,
115+
baudrate: 8,
116+
mode: 1,
117+
update_rate: 9,
118+
palette_mode: 0,
119+
auto_shutter: 2,
120+
digital_enhancement: 50,
121+
spatial_denoise: 50,
122+
temporal_denoise: 50,
123+
brightness: 50,
124+
contrast: 50,
125+
zoom_level: 0,
126+
mirror_mode: 0,
127+
ffc_interval: 5
128+
};
129+
130+
this.MZTC_STATUS = null;
131+
109132
this.SENSOR_STATUS = {
110133
isHardwareHealthy: 0,
111134
gyroHwStatus: 0,

js/msp/MSPCodes.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -248,20 +248,20 @@ var MSPCodes = {
248248
MSP2_INAV_SET_GEOZONE: 0x2211,
249249
MSP2_INAV_GEOZONE_VERTEX: 0x2212,
250250

251-
// MassZero Thermal Camera MSP2 commands
252-
MSP2_MZTC_CONFIG: 0x3000,
253-
MSP2_SET_MZTC_CONFIG: 0x3001,
254-
MSP2_MZTC_STATUS: 0x3002,
255-
MSP2_MZTC_FRAME_DATA: 0x3003,
256-
MSP2_MZTC_CALIBRATE: 0x3004,
257-
MSP2_MZTC_MODE: 0x3005,
258-
MSP2_MZTC_PALETTE: 0x3006,
259-
MSP2_MZTC_ZOOM: 0x3007,
260-
MSP2_MZTC_SHUTTER: 0x3008,
261-
MSP2_MZTC_INIT_STATUS: 0x3009,
262-
MSP2_MZTC_SAVE_CONFIG: 0x300A,
263-
MSP2_MZTC_RESTORE_DEFAULTS: 0x300B,
264-
MSP2_MZTC_RECONNECT: 0x300C,
251+
// MassZero Thermal Camera MSP2 commands.
252+
// These sit in INAV's own 0x2000-0x2FFF range. The 0x3000 block belongs to
253+
// the Betaflight compatibility commands. MSP2_BETAFLIGHT_BIND is 0x3000.
254+
// MSP2_RX_BIND is 0x3001.
255+
MSP2_MZTC_CONFIG: 0x2240,
256+
MSP2_MZTC_STATUS: 0x2241,
257+
MSP2_SET_MZTC_CONFIG: 0x2242,
258+
MSP2_SET_MZTC_MODE: 0x2243,
259+
MSP2_SET_MZTC_PALETTE: 0x2244,
260+
MSP2_SET_MZTC_ZOOM: 0x2245,
261+
MSP2_SET_MZTC_SHUTTER: 0x2246,
262+
MSP2_SET_MZTC_IMAGE_PARAMS: 0x2247,
263+
MSP2_SET_MZTC_CORRECTION: 0x2248,
264+
MSP2_SET_MZTC_VIGNETTING: 0x2249,
265265
MSP2_INAV_SET_GEOZONE_VERTICE: 0x2213
266266

267267
};

js/msp/MSPHelper.js

Lines changed: 63 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,75 +1664,66 @@ var mspHelper = (function () {
16641664
break;
16651665

16661666
case MSPCodes.MSP2_MZTC_CONFIG:
1667-
// Process MZTC configuration data from flight controller
1668-
// The firmware sends only the msp_mztc_config_t structure (28 bytes + padding)
1669-
// Channel fields are not included in the MSP message
1670-
if (data.byteLength >= 28) { // Minimum expected bytes
1667+
// Fixed 15 byte payload, little endian, one field at a time.
1668+
// The firmware writes it with the sbufWrite helpers, so there is no
1669+
// compiler padding to account for here.
1670+
if (data.byteLength >= 15) {
16711671
FC.MZTC_CONFIG = {
16721672
enabled: data.getUint8(0),
16731673
port: data.getUint8(1),
16741674
baudrate: data.getUint8(2),
16751675
mode: data.getUint8(3),
16761676
update_rate: data.getUint8(4),
1677-
temperature_unit: data.getUint8(5),
1678-
palette_mode: data.getUint8(6),
1679-
auto_shutter: data.getUint8(7),
1680-
digital_enhancement: data.getUint8(8),
1681-
spatial_denoise: data.getUint8(9),
1682-
temporal_denoise: data.getUint8(10),
1683-
brightness: data.getUint8(11),
1684-
contrast: data.getUint8(12),
1685-
zoom_level: data.getUint8(13),
1686-
mirror_mode: data.getUint8(14),
1687-
crosshair_enabled: data.getUint8(15),
1688-
temperature_alerts: data.getUint8(16),
1689-
// Temperatures are stored as float32
1690-
alert_high_temp: data.getFloat32(17, true),
1691-
alert_low_temp: data.getFloat32(21, true),
1692-
ffc_interval: data.getUint8(25),
1693-
bad_pixel_removal: data.getUint8(26),
1694-
vignetting_correction: data.getUint8(27),
1695-
// Channel fields not included in firmware MSP message
1696-
zoom_channel: 0,
1697-
palette_channel: 0,
1698-
ffc_channel: 0,
1699-
brightness_channel: 0,
1700-
contrast_channel: 0
1677+
palette_mode: data.getUint8(5),
1678+
auto_shutter: data.getUint8(6),
1679+
digital_enhancement: data.getUint8(7),
1680+
spatial_denoise: data.getUint8(8),
1681+
temporal_denoise: data.getUint8(9),
1682+
brightness: data.getUint8(10),
1683+
contrast: data.getUint8(11),
1684+
zoom_level: data.getUint8(12),
1685+
mirror_mode: data.getUint8(13),
1686+
ffc_interval: data.getUint8(14)
17011687
};
1702-
} else {
1703-
console.log('MZTC_CONFIG data too short:', data.byteLength, 'bytes, expected at least 28');
1704-
// Initialize with defaults
1705-
FC.MZTC_CONFIG = {
1706-
enabled: 0,
1707-
port: 0,
1708-
baudrate: 8,
1709-
mode: 2,
1710-
update_rate: 9,
1711-
temperature_unit: 0,
1712-
brightness: 50,
1713-
contrast: 50,
1714-
digital_enhancement: 50,
1715-
spatial_denoise: 50,
1716-
temporal_denoise: 50,
1717-
palette_mode: 0,
1718-
zoom_level: 0,
1719-
mirror_mode: 0,
1720-
auto_shutter: 2,
1721-
crosshair_enabled: 0,
1722-
temperature_alerts: 0,
1723-
alert_high_temp: 80.0,
1724-
alert_low_temp: -10.0,
1725-
ffc_interval: 5,
1726-
bad_pixel_removal: 1,
1727-
vignetting_correction: 1,
1728-
zoom_channel: 0,
1729-
palette_channel: 0,
1730-
ffc_channel: 0,
1731-
brightness_channel: 0,
1732-
contrast_channel: 0
1733-
};
1734-
}
1735-
break;
1688+
} else {
1689+
console.log('MZTC_CONFIG payload too short:', data.byteLength, 'bytes, expected 15');
1690+
FC.MZTC_CONFIG = {
1691+
enabled: 0,
1692+
port: 1,
1693+
baudrate: 8,
1694+
mode: 1,
1695+
update_rate: 9,
1696+
palette_mode: 0,
1697+
auto_shutter: 2,
1698+
digital_enhancement: 50,
1699+
spatial_denoise: 50,
1700+
temporal_denoise: 50,
1701+
brightness: 50,
1702+
contrast: 50,
1703+
zoom_level: 0,
1704+
mirror_mode: 0,
1705+
ffc_interval: 5
1706+
};
1707+
}
1708+
break;
1709+
1710+
case MSPCodes.MSP2_MZTC_STATUS:
1711+
// Fixed 7 byte payload. connected is set only after the camera has
1712+
// answered a command. An open UART on its own does not set it.
1713+
if (data.byteLength >= 7) {
1714+
FC.MZTC_STATUS = {
1715+
status: data.getUint8(0),
1716+
mode: data.getUint8(1),
1717+
connected: data.getUint8(2),
1718+
connection_quality: data.getUint8(3),
1719+
last_calibration: data.getUint16(4, true),
1720+
error_flags: data.getUint8(6)
1721+
};
1722+
} else {
1723+
console.log('MZTC_STATUS payload too short:', data.byteLength, 'bytes, expected 7');
1724+
FC.MZTC_STATUS = null;
1725+
}
1726+
break;
17361727

17371728
case MSPCodes.MSP2_SET_MZTC_CONFIG:
17381729
console.log("MZTC config saved");
@@ -2341,51 +2332,25 @@ var mspHelper = (function () {
23412332
break;
23422333

23432334
case MSPCodes.MSP2_SET_MZTC_CONFIG:
2344-
// Prepare MZTC configuration data for sending to flight controller
2345-
// Must match msp_mztc_config_t structure exactly (no channel fields)
2346-
console.log('MSP2_SET_MZTC_CONFIG - sending:', {
2347-
enabled: FC.MZTC_CONFIG.enabled,
2348-
port: FC.MZTC_CONFIG.port,
2349-
baudrate: FC.MZTC_CONFIG.baudrate,
2350-
mode: FC.MZTC_CONFIG.mode
2351-
});
2352-
buffer.push(FC.MZTC_CONFIG.enabled);
2335+
// Fixed 15 byte payload matching MSP2_MZTC_CONFIG. The firmware
2336+
// validates the whole request before applying any of it, so an out
2337+
// of range value here is rejected in full.
2338+
buffer.push(FC.MZTC_CONFIG.enabled ? 1 : 0);
23532339
buffer.push(FC.MZTC_CONFIG.port);
23542340
buffer.push(FC.MZTC_CONFIG.baudrate);
23552341
buffer.push(FC.MZTC_CONFIG.mode);
2356-
buffer.push(FC.MZTC_CONFIG.update_rate || 9);
2357-
buffer.push(FC.MZTC_CONFIG.temperature_unit || 0);
2342+
buffer.push(FC.MZTC_CONFIG.update_rate);
23582343
buffer.push(FC.MZTC_CONFIG.palette_mode);
23592344
buffer.push(FC.MZTC_CONFIG.auto_shutter);
2360-
buffer.push(FC.MZTC_CONFIG.digital_enhancement || 50);
2361-
buffer.push(FC.MZTC_CONFIG.spatial_denoise || 50);
2362-
buffer.push(FC.MZTC_CONFIG.temporal_denoise || 50);
2345+
buffer.push(FC.MZTC_CONFIG.digital_enhancement);
2346+
buffer.push(FC.MZTC_CONFIG.spatial_denoise);
2347+
buffer.push(FC.MZTC_CONFIG.temporal_denoise);
23632348
buffer.push(FC.MZTC_CONFIG.brightness);
23642349
buffer.push(FC.MZTC_CONFIG.contrast);
23652350
buffer.push(FC.MZTC_CONFIG.zoom_level);
2366-
buffer.push(FC.MZTC_CONFIG.mirror_mode || 0);
2367-
buffer.push(FC.MZTC_CONFIG.crosshair_enabled || 0);
2368-
buffer.push(FC.MZTC_CONFIG.temperature_alerts);
2369-
// Temperatures are sent as float32
2370-
var highTempBytes = new ArrayBuffer(4);
2371-
var highTempView = new DataView(highTempBytes);
2372-
highTempView.setFloat32(0, FC.MZTC_CONFIG.alert_high_temp, true);
2373-
for (var i = 0; i < 4; i++) {
2374-
buffer.push(highTempView.getUint8(i));
2375-
}
2376-
2377-
var lowTempBytes = new ArrayBuffer(4);
2378-
var lowTempView = new DataView(lowTempBytes);
2379-
lowTempView.setFloat32(0, FC.MZTC_CONFIG.alert_low_temp, true);
2380-
for (var i = 0; i < 4; i++) {
2381-
buffer.push(lowTempView.getUint8(i));
2382-
}
2383-
2351+
buffer.push(FC.MZTC_CONFIG.mirror_mode);
23842352
buffer.push(FC.MZTC_CONFIG.ffc_interval);
2385-
buffer.push(FC.MZTC_CONFIG.bad_pixel_removal || 1);
2386-
buffer.push(FC.MZTC_CONFIG.vignetting_correction || 1);
2387-
// Do not send channel fields - they're not in msp_mztc_config_t
2388-
break;
2353+
break;
23892354

23902355
default:
23912356
return false;

locale/en/messages.json

Lines changed: 4 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,60 +1373,12 @@
13731373
"portsFunction_HEADTRACKER": {
13741374
"message": "Serial Headtracker"
13751375
},
1376-
"portsFunction_MZTC_CAMERA": {
1377-
"message": "MassZero Thermal Camera"
1376+
"osdElement_MZTC_STATUS": {
1377+
"message": "Thermal Camera Status"
13781378
},
1379-
"configurationThermalCamera": {
1379+
"portsFunction_MZTC_CAMERA": {
13801380
"message": "MassZero Thermal Camera"
13811381
},
1382-
"thermalCameraDisclaimer": {
1383-
"message": "Configure thermal camera settings for real-time thermal imaging. MZTC must be selected as a peripheral on a UART port in the Ports tab."
1384-
},
1385-
"configurationThermalCameraEnabled": {
1386-
"message": "Thermal Camera Enabled"
1387-
},
1388-
"configurationThermalCameraPort": {
1389-
"message": "Serial Port"
1390-
},
1391-
"configurationThermalCameraMode": {
1392-
"message": "Operating Mode"
1393-
},
1394-
"configurationThermalCameraBrightness": {
1395-
"message": "Brightness (0-100)"
1396-
},
1397-
"configurationThermalCameraContrast": {
1398-
"message": "Contrast (0-100)"
1399-
},
1400-
"configurationThermalCameraPalette": {
1401-
"message": "Color Palette"
1402-
},
1403-
"configurationThermalCameraZoom": {
1404-
"message": "Zoom Level"
1405-
},
1406-
"configurationThermalCameraAutoShutter": {
1407-
"message": "Auto Shutter Mode"
1408-
},
1409-
"configurationThermalCameraFFCInterval": {
1410-
"message": "FFC Interval (minutes)"
1411-
},
1412-
"configurationThermalCameraTemperatureAlerts": {
1413-
"message": "Temperature Alerts"
1414-
},
1415-
"configurationThermalCameraAlertHighTemp": {
1416-
"message": "High Temperature Alert (°C)"
1417-
},
1418-
"configurationThermalCameraAlertLowTemp": {
1419-
"message": "Low Temperature Alert (°C)"
1420-
},
1421-
"configurationThermalCameraZoomChannel": {
1422-
"message": "Zoom Control Channel"
1423-
},
1424-
"configurationThermalCameraPaletteChannel": {
1425-
"message": "Palette Control Channel"
1426-
},
1427-
"configurationThermalCameraFFCChannel": {
1428-
"message": "FFC Control Channel"
1429-
},
14301382
"pidTuning_Other": {
14311383
"message": "Other"
14321384
},
@@ -6269,26 +6221,8 @@
62696221
"configurationThermalCameraFFCInterval": {
62706222
"message": "FFC Interval (minutes)"
62716223
},
6272-
"configurationThermalCameraTemperatureAlerts": {
6273-
"message": "Temperature Alerts"
6274-
},
6275-
"configurationThermalCameraAlertHighTemp": {
6276-
"message": "High Temperature Alert (°C)"
6277-
},
6278-
"configurationThermalCameraAlertLowTemp": {
6279-
"message": "Low Temperature Alert (°C)"
6280-
},
6281-
"configurationThermalCameraZoomChannel": {
6282-
"message": "Zoom Channel"
6283-
},
6284-
"configurationThermalCameraPaletteChannel": {
6285-
"message": "Palette Channel"
6286-
},
6287-
"configurationThermalCameraFFCChannel": {
6288-
"message": "FFC Channel"
6289-
},
62906224
"configurationThermalCameraModeHelp": {
6291-
"message": "Operating modes:\n Disabled - Camera is off\n• Standby - Low power, periodic updates\n• Continuous - Real-time frame capture\n• Triggered - Capture on demand\n Alert - Only capture when temperature alerts triggered\n• Recording - High-speed recording mode\n• Calibration - Calibration mode\n Surveillance - Long-range optimized"
6225+
"message": "Operating modes:\n\u2022 Disabled: the driver holds the port and issues no periodic work\n\u2022 Standby: periodic status polling only. This is the default\n\u2022 Alert: raises the alert state when the reported temperature crosses a threshold\n\u2022 Continuous, Triggered, Recording, Calibration and Surveillance are reserved and behave like Standby"
62926226
},
62936227
"configurationThermalCameraBrightnessHelp": {
62946228
"message": "Adjusts image brightness (0-100). Default is 50. Lower values darken the image, higher values brighten it."

0 commit comments

Comments
 (0)