Compare commits

...

9 Commits

Author SHA1 Message Date
jake downs e0cd593338 listEndpoints etc 2024-02-18 20:25:30 -05:00
jake downs 33f8f61a14 display mode 2024-02-15 13:14:54 -05:00
jake downs a6a714f92b Merge branch 'main' into imu-kickoff 2024-02-13 16:36:30 -05:00
jake downs bdcf723ae9 update readme 2024-02-13 16:36:09 -05:00
jake downs 424403e130 Merge branch 'main' into imu-kickoff 2024-02-09 17:06:50 -05:00
jake downs cc725fe357 copy/paste 2024-02-09 17:06:40 -05:00
jake downs e11cc6b0b0 Merge branch 'imu-kickoff' of github.com:jakedowns/xreal-webxr into imu-kickoff
# Conflicts:
#	js_air/glasses.js
2024-02-09 16:03:41 -05:00
jake downs f204abebe3 mode switch 2024-02-08 22:08:00 -05:00
jake downs b0c27a160b stubbing polling 2024-02-08 21:54:48 -05:00
7 changed files with 319 additions and 231 deletions

View File

@ -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/)

View File

@ -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() {

View File

@ -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);
} }

View File

@ -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)
} }

View File

@ -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 || {};

View File

@ -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;

View File

@ -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);
} }
} }