Compare commits
9 Commits
main
...
imu-kickof
| Author | SHA1 | Date |
|---|---|---|
|
|
e0cd593338 | |
|
|
33f8f61a14 | |
|
|
a6a714f92b | |
|
|
bdcf723ae9 | |
|
|
424403e130 | |
|
|
cc725fe357 | |
|
|
e11cc6b0b0 | |
|
|
f204abebe3 | |
|
|
b0c27a160b |
|
|
@ -29,6 +29,11 @@ work in progress; webxr support for xreal devices
|
||||||
- [XR Linux Driver](https://github.com/wheaney/XRLinuxDriver)
|
- [XR Linux Driver](https://github.com/wheaney/XRLinuxDriver)
|
||||||
- [OpenVR-xrealAirGlassesHMD](https://github.com/wheaney/OpenVR-xrealAirGlassesHMD)
|
- [OpenVR-xrealAirGlassesHMD](https://github.com/wheaney/OpenVR-xrealAirGlassesHMD)
|
||||||
|
|
||||||
|
### Community Resources
|
||||||
|
- [AR glasses USB protocols: the Good, the Bad and the Ugly](https://voidcomputing.hu/blog/good-bad-ugly) Void Computing AR API Write Up
|
||||||
|
- [AHRS Drift Analysis - Notebook Gist](https://gist.github.com/CGamesPlay/b3ea7740ea8715d19e89f5511491519f)
|
||||||
|
- [AHRS Drift Overview - Youtube](https://www.youtube.com/watch?v=Hvd9qVIusB0)
|
||||||
|
|
||||||
### Utilities
|
### Utilities
|
||||||
|
|
||||||
- 🪞 [Unofficial Firmware Archive Mirror](https://air.msmithdev.com/)
|
- 🪞 [Unofficial Firmware Archive Mirror](https://air.msmithdev.com/)
|
||||||
|
|
|
||||||
12
common.js
12
common.js
|
|
@ -128,7 +128,17 @@ export async function connectDevice() {
|
||||||
if (glasses) {
|
if (glasses) {
|
||||||
return glasses;
|
return glasses;
|
||||||
}
|
}
|
||||||
return await requestDevice();
|
return await requestDevice({
|
||||||
|
filters: [{
|
||||||
|
vendorId: 0x0486, // ? ASUS Computers Inc. ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0483, // STMicroelectronics ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0482, // Kyocera Corporation ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x3318, // Gleaming Reality (Wuxi) Technology Co., LTD ?
|
||||||
|
}]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function disconnectDevice() {
|
export async function disconnectDevice() {
|
||||||
|
|
|
||||||
12
index.html
12
index.html
|
|
@ -51,7 +51,17 @@
|
||||||
// Request USB device
|
// Request USB device
|
||||||
let device;
|
let device;
|
||||||
try {
|
try {
|
||||||
device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] });
|
device = await navigator.usb.requestDevice({
|
||||||
|
filters: [{
|
||||||
|
vendorId: 0x0486, // ? ASUS Computers Inc. ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0483, // STMicroelectronics ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0482, // Kyocera Corporation ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x3318, // Gleaming Reality (Wuxi) Technology Co., LTD ?
|
||||||
|
}]
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("No device was selected", err);
|
console.error("No device was selected", err);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,9 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="noSupportHid"></div>
|
<div id="noSupportHid"></div>
|
||||||
|
<div id="listEndpoints">
|
||||||
|
<button onclick="listEndpoints()">list endpoints</button>
|
||||||
|
</div>
|
||||||
<div id="connect"><button>connect</button></div>
|
<div id="connect"><button>connect</button></div>
|
||||||
<div id="disconnect" onclick="disconnectDevices()"><button>disconnect</button></div>
|
<div id="disconnect" onclick="disconnectDevices()"><button>disconnect</button></div>
|
||||||
<div id="startIMU" style="display: none;" onclick="startIMU()"><button>start headtracking</button></div>
|
<div id="startIMU" style="display: none;" onclick="startIMU()"><button>start headtracking</button></div>
|
||||||
|
|
@ -320,8 +323,11 @@
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
function connect() {
|
window.connected_devices = [];
|
||||||
|
|
||||||
|
window.connect = function() {
|
||||||
Common.connectDevice().then(async glasses => {
|
Common.connectDevice().then(async glasses => {
|
||||||
|
connected_devices.push(glasses);
|
||||||
if (glasses) {
|
if (glasses) {
|
||||||
document.getElementById('startIMU').style.display = 'block'
|
document.getElementById('startIMU').style.display = 'block'
|
||||||
document.getElementById('hadConnect').style.display = 'block'
|
document.getElementById('hadConnect').style.display = 'block'
|
||||||
|
|
@ -337,6 +343,8 @@
|
||||||
// document.getElementById('sn').innerHTML = getSN()
|
// document.getElementById('sn').innerHTML = getSN()
|
||||||
// document.getElementById('version').innerText = '版本号' + firmwareMcu()
|
// document.getElementById('version').innerText = '版本号' + firmwareMcu()
|
||||||
setOutput('glasses : ' + glasses.toString());
|
setOutput('glasses : ' + glasses.toString());
|
||||||
|
}).catch((err) => {
|
||||||
|
setOutput('glasses : ' + err.toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -446,6 +454,11 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.listEndpoints = () => {
|
||||||
|
// Manager.listEndpoints(connected_devices[0]);
|
||||||
|
window.listUsbEndpoints();
|
||||||
|
}
|
||||||
|
|
||||||
window.disconnectDevices = () => {
|
window.disconnectDevices = () => {
|
||||||
window.curGlassesArray.map(g=>{
|
window.curGlassesArray.map(g=>{
|
||||||
g._device.close();
|
g._device.close();
|
||||||
|
|
@ -455,31 +468,44 @@
|
||||||
|
|
||||||
window.endpoints = [];
|
window.endpoints = [];
|
||||||
|
|
||||||
window.listUsbEndpoints = () => {
|
window.listUsbEndpoints = async () => {
|
||||||
window.endpoints = [];
|
window.endpoints = [];
|
||||||
// list usb endpoints
|
// list usb endpoints
|
||||||
navigator.usb.requestDevice({filters:[]}).then((device)=>{
|
let device = await navigator.usb.requestDevice({
|
||||||
window.usb_device = device;
|
filters: [{
|
||||||
|
vendorId: 0x0486, // ? ASUS Computers Inc. ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0483, // STMicroelectronics ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0482, // Kyocera Corporation ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x3318, // Gleaming Reality (Wuxi) Technology Co., LTD ?
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
|
window.usb_device = device;
|
||||||
|
|
||||||
//usb_device.configurations[0].interfaces[1].alternates[1].endpoints[0]
|
//usb_device.configurations[0].interfaces[1].alternates[1].endpoints[0]
|
||||||
|
|
||||||
for(let configuration of device.configurations){
|
for(let configuration of device.configurations){
|
||||||
|
|
||||||
for(let _interface of configuration.interfaces){
|
for(let _interface of configuration.interfaces){
|
||||||
|
|
||||||
for(let alternate of _interface?.alternates ?? []){
|
for(let alternate of _interface?.alternates ?? []){
|
||||||
|
|
||||||
for(let endpoint of alternate.endpoints){
|
for(let endpoint of alternate.endpoints){
|
||||||
|
|
||||||
window.endpoints.push(endpoint);
|
window.endpoints.push(endpoint);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
console.table(window.endpoints);
|
|
||||||
})
|
|
||||||
|
|
||||||
|
console.warn('CONNECTED TO DEVICE: ENDPOINTS:')
|
||||||
|
console.table(window.endpoints);
|
||||||
|
|
||||||
|
// new recursive debug printout:
|
||||||
|
await Manager.listEndpoints(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,9 +132,6 @@ window.logPackets = () => {
|
||||||
|
|
||||||
export default class Glasses extends EventTarget {
|
export default class Glasses extends EventTarget {
|
||||||
|
|
||||||
/* RepeatingDeviceReportPoll */
|
|
||||||
imu_poller_instance = null;
|
|
||||||
|
|
||||||
constructor(device) {
|
constructor(device) {
|
||||||
console.log('constructing');
|
console.log('constructing');
|
||||||
super();
|
super();
|
||||||
|
|
@ -143,24 +140,6 @@ export default class Glasses extends EventTarget {
|
||||||
this._reports = new Map();
|
this._reports = new Map();
|
||||||
this._captures = [];
|
this._captures = [];
|
||||||
|
|
||||||
// creates it, but doesn't start it...
|
|
||||||
this.imu_poller_instance = new RepeatingDeviceReportPoll({
|
|
||||||
interval: 100,
|
|
||||||
callback: async ()=>{
|
|
||||||
this.sendReportTimeout(Protocol.MESSAGES.R_IMU_DATA, [0x40]).then((report)=>{
|
|
||||||
if(report){
|
|
||||||
console.log('got report',report)
|
|
||||||
}else{
|
|
||||||
console.log('no report')
|
|
||||||
}
|
|
||||||
}).catch((e)=>{
|
|
||||||
console.error('error sending report',e)
|
|
||||||
}).finally(()=>{
|
|
||||||
//console.log('finally')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// set input listener
|
// set input listener
|
||||||
device.oninputreport = this._handleInputReport.bind(this);
|
device.oninputreport = this._handleInputReport.bind(this);
|
||||||
|
|
||||||
|
|
@ -364,7 +343,7 @@ export default class Glasses extends EventTarget {
|
||||||
return out
|
return out
|
||||||
}).join(' ');
|
}).join(' ');
|
||||||
|
|
||||||
document.getElementById('imu').innerHTML = stringified
|
//document.getElementById('imu').innerHTML = stringified
|
||||||
|
|
||||||
// debugger;
|
// debugger;
|
||||||
if(current < stop_at){
|
if(current < stop_at){
|
||||||
|
|
@ -465,7 +444,7 @@ export default class Glasses extends EventTarget {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RepeatingDeviceReportPoll {
|
class StartableEndableRepeatingCallback {
|
||||||
timer = null;
|
timer = null;
|
||||||
constructor(opts){
|
constructor(opts){
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,39 @@ export async function getFirmwareVersionInDsp() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function listEndpoints(device) {
|
||||||
|
await device.open();
|
||||||
|
|
||||||
|
// Listing available configurations valid for selection
|
||||||
|
let configurations = device.configurations;
|
||||||
|
for (let i = 0; i < configurations.length; i++) {
|
||||||
|
console.log(`Configuration ${i}: ${configurations[i].configurationValue}`);
|
||||||
|
|
||||||
|
try{
|
||||||
|
// Select the current configuration
|
||||||
|
// Assuming the configuration is 0-based
|
||||||
|
await device.selectConfiguration(i+1);
|
||||||
|
|
||||||
|
// Iterate over all available interfaces for the current configuration and claim them
|
||||||
|
for (let j = 0; j < device.configuration.interfaces.length; j++) {
|
||||||
|
try{
|
||||||
|
await device.claimInterface(j);
|
||||||
|
device.configuration.interfaces[j].alternates.forEach((alternate) => {
|
||||||
|
console.log(`Configuration ${i}, iface ${j} Alternate ${alternate.alternateSetting}`);
|
||||||
|
alternate.endpoints.forEach((endpoint) => {
|
||||||
|
console.log(`Endpoint ${endpoint.endpointNumber} Direction ${endpoint.direction}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}catch(e){
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(e){
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parameters required for the progress bar
|
// Parameters required for the progress bar
|
||||||
// function progress(cur, all) {
|
// function progress(cur, all) {
|
||||||
// current = cur
|
// current = cur
|
||||||
|
|
@ -183,8 +216,19 @@ async function waitBootDevice() {
|
||||||
}
|
}
|
||||||
// await requestDevice()
|
// await requestDevice()
|
||||||
|
|
||||||
|
// await navigator.hid.requestDevice({
|
||||||
|
// filters: [{ vendorId: Protocol.NREAL_VENDOR_ID, productId: Protocol.NREAL_BOOT_PRODUCT_ID }]
|
||||||
|
// });
|
||||||
await navigator.hid.requestDevice({
|
await navigator.hid.requestDevice({
|
||||||
filters: [{ vendorId: Protocol.NREAL_VENDOR_ID, productId: Protocol.NREAL_BOOT_PRODUCT_ID }]
|
filters: [{
|
||||||
|
vendorId: 0x0486, // ? ASUS Computers Inc. ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0483, // STMicroelectronics ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0482, // Kyocera Corporation ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x3318, // Gleaming Reality (Wuxi) Technology Co., LTD ?
|
||||||
|
}]
|
||||||
});
|
});
|
||||||
const time = new Date().getTime();
|
const time = new Date().getTime();
|
||||||
while ((new Date().getTime() - time) < 2000) {
|
while ((new Date().getTime() - time) < 2000) {
|
||||||
|
|
@ -241,124 +285,124 @@ export function Asc2Hex(value) {
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
export async function upgradeInDsp(data) {
|
// export async function upgradeInDsp(data) {
|
||||||
let glasses = await common.connectDevice();
|
// let glasses = await common.connectDevice();
|
||||||
if (!glasses) {
|
// if (!glasses) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
return sendFirmwareInDsp(glasses, data);
|
// return sendFirmwareInDsp(glasses, data);
|
||||||
}
|
// }
|
||||||
|
|
||||||
/** need to upgrade firmware DP version? */
|
/** need to upgrade firmware DP version? */
|
||||||
export async function isNeedUpgradeInDp() {
|
// export async function isNeedUpgradeInDp() {
|
||||||
let glasses = await common.connectDevice();
|
// let glasses = await common.connectDevice();
|
||||||
if (!glasses) {
|
// if (!glasses) {
|
||||||
return 'not found device';
|
// return 'not found device';
|
||||||
}
|
// }
|
||||||
return glasses.sendReportTimeout(Protocol.MESSAGES.R_DP7911_FW_IS_UPDATE)
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.R_DP7911_FW_IS_UPDATE)
|
||||||
.then(report => {
|
// .then(report => {
|
||||||
if (reportSuccess(report)) {
|
// if (reportSuccess(report)) {
|
||||||
return report.payload[0]
|
// return report.payload[0]
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
export async function upgradeInDp() {
|
// export async function upgradeInDp() {
|
||||||
let glasses = await common.connectDevice();
|
// let glasses = await common.connectDevice();
|
||||||
if (!glasses) {
|
// if (!glasses) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
// 添加眼镜休眠时间
|
// // 添加眼镜休眠时间
|
||||||
const time = Protocol.time2Bytes('600');
|
// const time = Protocol.time2Bytes('600');
|
||||||
return glasses.sendReportTimeout(Protocol.MESSAGES.W_SLEEP_TIME, time)
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.W_SLEEP_TIME, time)
|
||||||
.then(report => {
|
// .then(report => {
|
||||||
if (reportSuccess(report)) {
|
// if (reportSuccess(report)) {
|
||||||
return glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DP)
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DP)
|
||||||
.then(async report => {
|
// .then(async report => {
|
||||||
if (reportSuccess(report)) {
|
// if (reportSuccess(report)) {
|
||||||
// wait for air dp upgrade completed
|
// // wait for air dp upgrade completed
|
||||||
while(!glasses._reports.has(27661) && common.curGlasses){
|
// while(!glasses._reports.has(27661) && common.curGlasses){
|
||||||
await sleep(500)
|
// await sleep(500)
|
||||||
dpCurrent = glasses._reports.get(27660) ? glasses._reports.get(27660).status : 0
|
// dpCurrent = glasses._reports.get(27660) ? glasses._reports.get(27660).status : 0
|
||||||
progressInDp(dpCurrent)
|
// progressInDp(dpCurrent)
|
||||||
}
|
// }
|
||||||
|
|
||||||
return glasses._reports.get(27661) ? glasses._reports.get(27661).status == 0 : false
|
// return glasses._reports.get(27661) ? glasses._reports.get(27661).status == 0 : false
|
||||||
}
|
// }
|
||||||
|
|
||||||
return false
|
// return false
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
async function sendFirmwareInMcu(bootDevice, data) {
|
// async function sendFirmwareInMcu(bootDevice, data) {
|
||||||
|
|
||||||
let ofs = 0;
|
// let ofs = 0;
|
||||||
const firstPackLen = 24;
|
// const firstPackLen = 24;
|
||||||
const fwLen = data.byteLength;
|
// const fwLen = data.byteLength;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let report = await bootDevice.sendReportTimeout(
|
// let report = await bootDevice.sendReportTimeout(
|
||||||
Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_START,
|
// Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_START,
|
||||||
data.slice(ofs, ofs + firstPackLen));
|
// data.slice(ofs, ofs + firstPackLen));
|
||||||
if (!reportSuccess(report)) {
|
// if (!reportSuccess(report)) {
|
||||||
console.error('send fw data failed');
|
// console.error('send fw data failed');
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
ofs += firstPackLen;
|
// ofs += firstPackLen;
|
||||||
|
|
||||||
while (ofs < fwLen) {
|
// while (ofs < fwLen) {
|
||||||
progress(ofs, fwLen)
|
// progress(ofs, fwLen)
|
||||||
if ((ofs + 42) > fwLen) {
|
// if ((ofs + 42) > fwLen) {
|
||||||
report = await bootDevice.sendReportTimeout(
|
// report = await bootDevice.sendReportTimeout(
|
||||||
Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_TRANSMIT,
|
// Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_TRANSMIT,
|
||||||
data.slice(ofs, fwLen));
|
// data.slice(ofs, fwLen));
|
||||||
if (!reportSuccess(report)) {
|
// if (!reportSuccess(report)) {
|
||||||
console.error('send fw data failed');
|
// console.error('send fw data failed');
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
report = await bootDevice.sendReportTimeout(
|
// report = await bootDevice.sendReportTimeout(
|
||||||
Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_TRANSMIT,
|
// Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_TRANSMIT,
|
||||||
data.slice(ofs, ofs + 42));
|
// data.slice(ofs, ofs + 42));
|
||||||
|
|
||||||
if (!reportSuccess(report)) {
|
// if (!reportSuccess(report)) {
|
||||||
console.error('send fw data failed');
|
// console.error('send fw data failed');
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
ofs += 42;
|
// ofs += 42;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/* send finish */
|
// /* send finish */
|
||||||
report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_FINISH);
|
// report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_FINISH);
|
||||||
// if (!reportSuccess(report)) {
|
// // if (!reportSuccess(report)) {
|
||||||
// console.error('send fw data failed');
|
// // console.error('send fw data failed');
|
||||||
// return false;
|
// // return false;
|
||||||
// }
|
// // }
|
||||||
/* jump to app */
|
// /* jump to app */
|
||||||
report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_BOOT_JUMP_TO_APP);
|
// report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_BOOT_JUMP_TO_APP);
|
||||||
// if (!reportSuccess(report)) {
|
// // if (!reportSuccess(report)) {
|
||||||
// console.error('send fw data failed');
|
// // console.error('send fw data failed');
|
||||||
// return false;
|
// // return false;
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
// Send the command to upgrade the DP
|
// // Send the command to upgrade the DP
|
||||||
// report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DP);
|
// // report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DP);
|
||||||
|
|
||||||
|
|
||||||
current = 0
|
// current = 0
|
||||||
total = 0
|
// total = 0
|
||||||
return true;
|
// return true;
|
||||||
|
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
async function sendFirmwareInDsp(glasses, data) {
|
async function sendFirmwareInDsp(glasses, data) {
|
||||||
|
|
||||||
let ofs = 0;
|
let ofs = 0;
|
||||||
|
|
@ -441,7 +485,7 @@ async function sendFirmwareInDsp(glasses, data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send finish */
|
/* send finish *-/
|
||||||
report = await glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DSP_APP_FW_FINISH);
|
report = await glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DSP_APP_FW_FINISH);
|
||||||
// if (!reportSuccess(report)) {
|
// if (!reportSuccess(report)) {
|
||||||
// console.error('send fw data failed');
|
// console.error('send fw data failed');
|
||||||
|
|
@ -449,7 +493,7 @@ async function sendFirmwareInDsp(glasses, data) {
|
||||||
// }
|
// }
|
||||||
// dsp write bin ==> first 100%
|
// dsp write bin ==> first 100%
|
||||||
progress(ofs,fwLen)
|
progress(ofs,fwLen)
|
||||||
/* Check whether the upgrade is complete */
|
/* Check whether the upgrade is complete *-/
|
||||||
// air DSP judge for flash&boot
|
// air DSP judge for flash&boot
|
||||||
// 删除之前刷新boot的过程,dsp重新刷新
|
// 删除之前刷新boot的过程,dsp重新刷新
|
||||||
glasses._reports.delete(27664)
|
glasses._reports.delete(27664)
|
||||||
|
|
@ -487,6 +531,9 @@ async function sendFirmwareInDsp(glasses, data) {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Delay synchronization program execution
|
// Delay synchronization program execution
|
||||||
function sleep(delay) {
|
function sleep(delay) {
|
||||||
|
|
@ -514,10 +561,7 @@ export async function startIMU() {
|
||||||
return Promise.reject('no device connected')
|
return Promise.reject('no device connected')
|
||||||
}
|
}
|
||||||
|
|
||||||
// kick off polling
|
return glasses.sendReportTimeout(0x00, Protocol.MAGIC_PAYLOAD)
|
||||||
glasses.startIMUPolling();
|
|
||||||
|
|
||||||
return glasses.sendReportTimeout(Protocol.MESSAGES.W_TOGGLE_IMU, [0x1])
|
|
||||||
.then(report => {
|
.then(report => {
|
||||||
console.warn('startIMU -> report',report);
|
console.warn('startIMU -> report',report);
|
||||||
if (reportSuccess(report)){
|
if (reportSuccess(report)){
|
||||||
|
|
@ -544,6 +588,32 @@ export async function stopIMU() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getDisplayMode(){
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_DISPLAY_MODE)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return report.payload[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setDisplayMode(mode){
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_DISPLAY_MODE, [mode])
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return report.payload[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** read air glassess Brightness */
|
/** read air glassess Brightness */
|
||||||
export async function getBrightness() {
|
export async function getBrightness() {
|
||||||
let glasses = await common.connectDevice();
|
let glasses = await common.connectDevice();
|
||||||
|
|
@ -551,7 +621,7 @@ export async function getBrightness() {
|
||||||
return 'not found device';
|
return 'not found device';
|
||||||
}
|
}
|
||||||
// what's the chance the getBrightness is the same as setBrightness?
|
// what's the chance the getBrightness is the same as setBrightness?
|
||||||
return glasses.sendReportTimeout(Protocol.MESSAGES.W_BRIGHTNESS)
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_BRIGHTNESS)
|
||||||
.then(report => {
|
.then(report => {
|
||||||
if (reportSuccess(report)) {
|
if (reportSuccess(report)) {
|
||||||
return report.payload;
|
return report.payload;
|
||||||
|
|
|
||||||
|
|
@ -7,79 +7,61 @@ const CRC_OFS = 1;
|
||||||
const TS_OFS = 7;
|
const TS_OFS = 7;
|
||||||
const RESERVED_OFS = 17;
|
const RESERVED_OFS = 17;
|
||||||
|
|
||||||
|
// send to device 3 to enable IMU tracking reporting (removed first byte 0x00)
|
||||||
|
export const MAGIC_PAYLOAD = new Uint8Array([0xaa, 0xc5, 0xd1, 0x21, 0x42, 0x04, 0x00, 0x19, 0x01]);
|
||||||
|
|
||||||
export const NREAL_VENDOR_ID = 0x3318;
|
class CliDisplayMode {
|
||||||
export const BOOT_PRODUCT_ID = 0x0423;
|
static SameOnBoth = "2d";
|
||||||
export const IMU_TIMEOUT = 250;
|
static Stereo = "3d";
|
||||||
|
static HalfSBS = "halfsbs";
|
||||||
|
static HighRefreshRate = "high-refresh-rate-2d";
|
||||||
|
static HighRefreshRateSBS = "high-refresh-rate-3d";
|
||||||
|
|
||||||
export const ERRORS = {
|
static getDisplayModeByte(displayMode) {
|
||||||
DEVICE3_ERROR_NO_ERROR: 0,
|
switch (displayMode) {
|
||||||
DEVICE3_ERROR_NO_DEVICE: 1,
|
case CliDisplayMode.SameOnBoth:
|
||||||
DEVICE3_ERROR_NO_HANDLE: 2,
|
return 1;
|
||||||
DEVICE3_ERROR_NO_ALLOCATION: 3,
|
case CliDisplayMode.Stereo:
|
||||||
DEVICE3_ERROR_WRONG_SIZE: 4,
|
return 3;
|
||||||
DEVICE3_ERROR_FILE_NOT_OPEN: 5,
|
case CliDisplayMode.HalfSBS:
|
||||||
DEVICE3_ERROR_FILE_NOT_CLOSED: 6,
|
return 8;
|
||||||
DEVICE3_ERROR_LOADING_FAILED: 7,
|
case CliDisplayMode.HighRefreshRate:
|
||||||
DEVICE3_ERROR_SAVING_FAILED: 8,
|
return 11;
|
||||||
DEVICE3_ERROR_UNPLUGGED: 9,
|
case CliDisplayMode.HighRefreshRateSBS:
|
||||||
DEVICE3_ERROR_UNEXPECTED: 10,
|
return 9;
|
||||||
DEVICE3_ERROR_WRONG_SIGNATURE: 11,
|
default:
|
||||||
DEVICE3_ERROR_INVALID_VALUE: 12,
|
throw new Error("Invalid display mode");
|
||||||
DEVICE3_ERROR_NOT_INITIALIZED: 13,
|
}
|
||||||
DEVICE3_ERROR_PAYLOAD_FAILED: 14,
|
|
||||||
DEVICE3_ERROR_UNKNOWN: 15,
|
|
||||||
}
|
|
||||||
|
|
||||||
class Device3Packet {
|
|
||||||
/*
|
|
||||||
uint8_t signature [2];
|
|
||||||
uint8_t temperature [2];
|
|
||||||
uint64_t timestamp;
|
|
||||||
uint8_t angular_multiplier [2];
|
|
||||||
uint8_t angular_divisor [4];
|
|
||||||
uint8_t angular_velocity_x [3];
|
|
||||||
uint8_t angular_velocity_y [3];
|
|
||||||
uint8_t angular_velocity_z [3];
|
|
||||||
uint8_t acceleration_multiplier [2];
|
|
||||||
uint8_t acceleration_divisor [4];
|
|
||||||
uint8_t acceleration_x [3];
|
|
||||||
uint8_t acceleration_y [3];
|
|
||||||
uint8_t acceleration_z [3];
|
|
||||||
uint8_t magnetic_multiplier [2];
|
|
||||||
uint8_t magnetic_divisor [4];
|
|
||||||
uint8_t magnetic_x [2];
|
|
||||||
uint8_t magnetic_y [2];
|
|
||||||
uint8_t magnetic_z [2];
|
|
||||||
uint32_t checksum;
|
|
||||||
uint8_t _padding [6];
|
|
||||||
*/
|
|
||||||
constructor() {
|
|
||||||
this.signature = new Uint8Array(2);
|
|
||||||
this.temperature = new Uint8Array(2);
|
|
||||||
this.timestamp = new Uint8Array(8);
|
|
||||||
this.angular_multiplier = new Uint8Array(2);
|
|
||||||
this.angular_divisor = new Uint8Array(4);
|
|
||||||
this.angular_velocity_x = new Uint8Array(3);
|
|
||||||
this.angular_velocity_y = new Uint8Array(3);
|
|
||||||
this.angular_velocity_z = new Uint8Array(3);
|
|
||||||
this.acceleration_multiplier = new Uint8Array(2);
|
|
||||||
this.acceleration_divisor = new Uint8Array(4);
|
|
||||||
this.acceleration_x = new Uint8Array(3);
|
|
||||||
this.acceleration_y = new Uint8Array(3);
|
|
||||||
this.acceleration_z = new Uint8Array(3);
|
|
||||||
this.magnetic_multiplier = new Uint8Array(2);
|
|
||||||
this.magnetic_divisor = new Uint8Array(4);
|
|
||||||
this.magnetic_x = new Uint8Array(2);
|
|
||||||
this.magnetic_y = new Uint8Array(2);
|
|
||||||
this.magnetic_z = new Uint8Array(2);
|
|
||||||
this.checksum = new Uint8Array(4);
|
|
||||||
this._padding = new Uint8Array(6);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Example usage
|
||||||
|
let displayMode = CliDisplayMode.Stereo; // This can be dynamically set
|
||||||
|
let displayModeByte = CliDisplayMode.getDisplayModeByte(displayMode);
|
||||||
|
console.log(displayModeByte);
|
||||||
|
|
||||||
|
|
||||||
|
export const NREAL_VENDOR_ID = 0x3318;
|
||||||
|
export const BOOT_PRODUCT_ID = 0x0423;
|
||||||
|
//export const IMU_RATE = 1000; // 1KHz
|
||||||
|
|
||||||
|
// based on 24bit signed int w/ FSR = +/-2000 dps, datasheet option
|
||||||
|
export const GYRO_SCALAR = (1.0 / 8388608.0 * 2000.0)
|
||||||
|
|
||||||
|
// based on 24bit signed int w/ FSR = +/-16 g, datasheet option
|
||||||
|
export const ACCEL_SCALAR = (1.0 / 8388608.0 * 16.0)
|
||||||
|
|
||||||
|
// ticks are in nanoseconds, 1000 Hz packets
|
||||||
|
// #define TICK_LEN (1.0f / 1E9f)
|
||||||
|
|
||||||
|
class AirSample {
|
||||||
|
tick;
|
||||||
|
ang_vel; // 3
|
||||||
|
accel; // 3
|
||||||
|
}
|
||||||
|
|
||||||
export const MESSAGES = {
|
export const MESSAGES = {
|
||||||
|
|
||||||
R_MCU_APP_FW_VERSION: 0x26,//MCU APP FW version.
|
R_MCU_APP_FW_VERSION: 0x26,//MCU APP FW version.
|
||||||
R_GLASSID: 0x15,//MCU APP FW version.
|
R_GLASSID: 0x15,//MCU APP FW version.
|
||||||
// R_DSP_APP_FW_VERSION: 0x21,//DSP APP FW version.
|
// R_DSP_APP_FW_VERSION: 0x21,//DSP APP FW version.
|
||||||
|
|
@ -88,10 +70,16 @@ export const MESSAGES = {
|
||||||
W_ACTIVATION_TIME: 0x2A,//Write activation time
|
W_ACTIVATION_TIME: 0x2A,//Write activation time
|
||||||
W_SLEEP_TIME: 0x1E,//Write unsleep time
|
W_SLEEP_TIME: 0x1E,//Write unsleep time
|
||||||
|
|
||||||
R_IMU_DATA: 0x80,//IMU data
|
// R_IMU_DATA: 0x80,//IMU data
|
||||||
UNKNOWN_40: 0x40,//Unknown
|
// UNKNOWN_40: 0x40,//Unknown
|
||||||
|
|
||||||
W_TOGGLE_IMU: 0x19,
|
R_DISPLAY_MODE: 0x7,//Read display mode
|
||||||
|
W_DISPLAY_MODE: 0x08,//Write display mode
|
||||||
|
|
||||||
|
R_BRIGHTNESS: 0x0,//Read brightness
|
||||||
|
W_BRIGHTNESS: 0x0,//Write brightness
|
||||||
|
|
||||||
|
W_TOGGLE_IMU: 0x19,
|
||||||
W_CANCEL_ACTIVATION: 0x19,
|
W_CANCEL_ACTIVATION: 0x19,
|
||||||
|
|
||||||
// R_IS_NEED_UPGRADE_DSP_FW: 0x49,//Check whether the DSP needs to be upgraded.
|
// R_IS_NEED_UPGRADE_DSP_FW: 0x49,//Check whether the DSP needs to be upgraded.
|
||||||
|
|
@ -111,7 +99,7 @@ export const MESSAGES = {
|
||||||
W_UPDATE_MCU_APP_FW_FINISH: 0x41, //(Implemented in Boot)
|
W_UPDATE_MCU_APP_FW_FINISH: 0x41, //(Implemented in Boot)
|
||||||
W_BOOT_JUMP_TO_APP: 0x42, //(Implemented in Boot)
|
W_BOOT_JUMP_TO_APP: 0x42, //(Implemented in Boot)
|
||||||
W_MCU_APP_JUMP_TO_BOOT: 0x44,
|
W_MCU_APP_JUMP_TO_BOOT: 0x44,
|
||||||
R_DP7911_FW_IS_UPDATE:0x3C,
|
R_DP7911_FW_IS_UPDATE: 0x3C,
|
||||||
W_UPDATE_DP: 0x3D,
|
W_UPDATE_DP: 0x3D,
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -133,7 +121,7 @@ export const MESSAGES = {
|
||||||
P_UKNOWN_HEARTBEAT_2: 0x6c12
|
P_UKNOWN_HEARTBEAT_2: 0x6c12
|
||||||
};
|
};
|
||||||
|
|
||||||
export function keyForHex(hex){
|
export function keyForHex(hex) {
|
||||||
for (let key in MESSAGES) {
|
for (let key in MESSAGES) {
|
||||||
if (MESSAGES[key] == hex) {
|
if (MESSAGES[key] == hex) {
|
||||||
return key;
|
return key;
|
||||||
|
|
@ -143,15 +131,15 @@ export function keyForHex(hex){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function listKnownCommands(){
|
export function listKnownCommands() {
|
||||||
let data = [];
|
let data = [];
|
||||||
Object.keys(MESSAGES).map((key)=>{
|
Object.keys(MESSAGES).map((key) => {
|
||||||
|
|
||||||
|
|
||||||
data.push({
|
data.push({
|
||||||
key,
|
key,
|
||||||
hex:'0x'+MESSAGES[key].toString(16),
|
hex: '0x' + MESSAGES[key].toString(16),
|
||||||
dec:MESSAGES[key]
|
dec: MESSAGES[key]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -278,7 +266,7 @@ function get_status_byte(response) {
|
||||||
window.unparsed = [];
|
window.unparsed = [];
|
||||||
|
|
||||||
// 4-bytes to 32-bit float
|
// 4-bytes to 32-bit float
|
||||||
function four_bytes_to_float(byte_array){
|
function four_bytes_to_float(byte_array) {
|
||||||
var data = byte_array; // [64, 226, 157, 10];
|
var data = byte_array; // [64, 226, 157, 10];
|
||||||
|
|
||||||
// Create a buffer
|
// Create a buffer
|
||||||
|
|
@ -306,11 +294,11 @@ export function parse_rsp(rsp) {
|
||||||
payload: new Uint8Array()
|
payload: new Uint8Array()
|
||||||
};
|
};
|
||||||
|
|
||||||
if(rsp[0] !== HEAD){
|
if (rsp[0] !== HEAD) {
|
||||||
// console.warn('HEAD mismatch', rsp[0]);
|
// console.warn('HEAD mismatch', rsp[0]);
|
||||||
// console.warn([...rsp].map(x => x.toString(16).padStart(2,'0')).join(' '));
|
// console.warn([...rsp].map(x => x.toString(16).padStart(2,'0')).join(' '));
|
||||||
if(window.unparsed.length<1000){
|
if (window.unparsed.length < 1000) {
|
||||||
window.unparsed.push([...rsp].map(x => x.toString(16).padStart(2,'0')).join(','))
|
window.unparsed.push([...rsp].map(x => x.toString(16).padStart(2, '0')).join(','))
|
||||||
|
|
||||||
// extract 16 32-bit,4-byte floats from 64 bytes
|
// extract 16 32-bit,4-byte floats from 64 bytes
|
||||||
// NOPE
|
// NOPE
|
||||||
|
|
@ -408,9 +396,9 @@ export function brightBytes2Int(bright_byte_arr) {
|
||||||
export function bytes2Time(bytes) {
|
export function bytes2Time(bytes) {
|
||||||
let time = '';
|
let time = '';
|
||||||
for (let i = bytes.byteLength - 1; i >= 0; i--) {
|
for (let i = bytes.byteLength - 1; i >= 0; i--) {
|
||||||
if(i > 3){
|
if (i > 3) {
|
||||||
time += bytes[i].toString(2)
|
time += bytes[i].toString(2)
|
||||||
}else{
|
} else {
|
||||||
time += bytes[i].toString(2)
|
time += bytes[i].toString(2)
|
||||||
// time += bytes[i] << (i * 8);
|
// time += bytes[i] << (i * 8);
|
||||||
}
|
}
|
||||||
|
|
@ -418,18 +406,18 @@ export function bytes2Time(bytes) {
|
||||||
return time;
|
return time;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function hex2Decimal(byte){
|
export function hex2Decimal(byte) {
|
||||||
return parseInt(byte, 16);
|
return parseInt(byte, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function time2Bytes(timeStamp){
|
export function time2Bytes(timeStamp) {
|
||||||
let arr = new Uint8Array(8)
|
let arr = new Uint8Array(8)
|
||||||
let len = Math.floor((Number(timeStamp).toString(2).length) / 8)
|
let len = Math.floor((Number(timeStamp).toString(2).length) / 8)
|
||||||
let longN = parseInt(Number(timeStamp).toString(2).substring(0,Number(timeStamp).toString(2).length - 32), 2)
|
let longN = parseInt(Number(timeStamp).toString(2).substring(0, Number(timeStamp).toString(2).length - 32), 2)
|
||||||
for (let i = len; i >= 0; i--) {
|
for (let i = len; i >= 0; i--) {
|
||||||
if(i > 3){
|
if (i > 3) {
|
||||||
arr[i] = ((longN >>> ((i - 4) * 8)) & 0xFF);
|
arr[i] = ((longN >>> ((i - 4) * 8)) & 0xFF);
|
||||||
}else{
|
} else {
|
||||||
arr[i] = ((timeStamp >>> (i * 8)) & 0xFF);
|
arr[i] = ((timeStamp >>> (i * 8)) & 0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue