@depz/sensor-sdk 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/README.md +13 -5
  2. package/dist/dataset.d.ts.map +1 -1
  3. package/dist/dataset.js +66 -2
  4. package/dist/dataset.js.map +1 -1
  5. package/dist/device/device.d.ts +6 -0
  6. package/dist/device/device.d.ts.map +1 -1
  7. package/dist/device/device.js +29 -6
  8. package/dist/device/device.js.map +1 -1
  9. package/dist/discovery.d.ts.map +1 -1
  10. package/dist/discovery.js +25 -2
  11. package/dist/discovery.js.map +1 -1
  12. package/dist/index.d.ts +21 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +16 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/protocol/bno055.d.ts +101 -0
  17. package/dist/protocol/bno055.d.ts.map +1 -0
  18. package/dist/protocol/bno055.js +105 -0
  19. package/dist/protocol/bno055.js.map +1 -0
  20. package/dist/protocol/identity.d.ts +1 -1
  21. package/dist/protocol/identity.d.ts.map +1 -1
  22. package/dist/protocol/identity.js +6 -0
  23. package/dist/protocol/identity.js.map +1 -1
  24. package/dist/protocol/vl53l7.d.ts +77 -0
  25. package/dist/protocol/vl53l7.d.ts.map +1 -0
  26. package/dist/protocol/vl53l7.js +99 -0
  27. package/dist/protocol/vl53l7.js.map +1 -0
  28. package/dist/protocol/vl53lx.d.ts +72 -0
  29. package/dist/protocol/vl53lx.d.ts.map +1 -0
  30. package/dist/protocol/vl53lx.js +87 -0
  31. package/dist/protocol/vl53lx.js.map +1 -0
  32. package/dist/sensors/bno055/bno055.d.ts +207 -0
  33. package/dist/sensors/bno055/bno055.d.ts.map +1 -0
  34. package/dist/sensors/bno055/bno055.js +547 -0
  35. package/dist/sensors/bno055/bno055.js.map +1 -0
  36. package/dist/sensors/bno055/regs.d.ts +271 -0
  37. package/dist/sensors/bno055/regs.d.ts.map +1 -0
  38. package/dist/sensors/bno055/regs.js +366 -0
  39. package/dist/sensors/bno055/regs.js.map +1 -0
  40. package/dist/sensors/bno086/bno086.d.ts +15 -0
  41. package/dist/sensors/bno086/bno086.d.ts.map +1 -1
  42. package/dist/sensors/bno086/bno086.js +43 -1
  43. package/dist/sensors/bno086/bno086.js.map +1 -1
  44. package/dist/sensors/bno086/sh2.d.ts.map +1 -1
  45. package/dist/sensors/bno086/sh2.js +5 -2
  46. package/dist/sensors/bno086/sh2.js.map +1 -1
  47. package/dist/sensors/reg-bridge.d.ts +35 -0
  48. package/dist/sensors/reg-bridge.d.ts.map +1 -0
  49. package/dist/sensors/reg-bridge.js +44 -0
  50. package/dist/sensors/reg-bridge.js.map +1 -0
  51. package/dist/sensors/vl53l4/vl53l4.d.ts.map +1 -1
  52. package/dist/sensors/vl53l4/vl53l4.js +18 -30
  53. package/dist/sensors/vl53l4/vl53l4.js.map +1 -1
  54. package/dist/sensors/vl53l7/vl53l7.d.ts +97 -0
  55. package/dist/sensors/vl53l7/vl53l7.d.ts.map +1 -0
  56. package/dist/sensors/vl53l7/vl53l7.js +138 -0
  57. package/dist/sensors/vl53l7/vl53l7.js.map +1 -0
  58. package/dist/sensors/vl53l8/assets/index.d.ts +5 -1
  59. package/dist/sensors/vl53l8/assets/index.d.ts.map +1 -1
  60. package/dist/sensors/vl53l8/assets/index.js +7 -1
  61. package/dist/sensors/vl53l8/assets/index.js.map +1 -1
  62. package/dist/sensors/vl53l8/assets/l7ch.d.ts +12 -0
  63. package/dist/sensors/vl53l8/assets/l7ch.d.ts.map +1 -0
  64. package/dist/sensors/vl53l8/assets/l7ch.js +18 -0
  65. package/dist/sensors/vl53l8/assets/l7ch.js.map +1 -0
  66. package/dist/sensors/vl53l8/assets/l7cx.d.ts +14 -0
  67. package/dist/sensors/vl53l8/assets/l7cx.d.ts.map +1 -0
  68. package/dist/sensors/vl53l8/assets/l7cx.js +20 -0
  69. package/dist/sensors/vl53l8/assets/l7cx.js.map +1 -0
  70. package/dist/sensors/vl53l8/cnh.d.ts +4 -3
  71. package/dist/sensors/vl53l8/cnh.d.ts.map +1 -1
  72. package/dist/sensors/vl53l8/cnh.js +4 -3
  73. package/dist/sensors/vl53l8/cnh.js.map +1 -1
  74. package/dist/sensors/vl53l8/uld.d.ts +50 -9
  75. package/dist/sensors/vl53l8/uld.d.ts.map +1 -1
  76. package/dist/sensors/vl53l8/uld.js +241 -35
  77. package/dist/sensors/vl53l8/uld.js.map +1 -1
  78. package/dist/sensors/vl53l8/vl53l8.d.ts +8 -3
  79. package/dist/sensors/vl53l8/vl53l8.d.ts.map +1 -1
  80. package/dist/sensors/vl53l8/vl53l8.js +41 -39
  81. package/dist/sensors/vl53l8/vl53l8.js.map +1 -1
  82. package/dist/sensors/vl53lx/decode.d.ts +70 -0
  83. package/dist/sensors/vl53lx/decode.d.ts.map +1 -0
  84. package/dist/sensors/vl53lx/decode.js +108 -0
  85. package/dist/sensors/vl53lx/decode.js.map +1 -0
  86. package/dist/sensors/vl53lx/uld/arith.d.ts +23 -0
  87. package/dist/sensors/vl53lx/uld/arith.d.ts.map +1 -0
  88. package/dist/sensors/vl53lx/uld/arith.js +42 -0
  89. package/dist/sensors/vl53lx/uld/arith.js.map +1 -0
  90. package/dist/sensors/vl53lx/uld/bare/core.d.ts +345 -0
  91. package/dist/sensors/vl53lx/uld/bare/core.d.ts.map +1 -0
  92. package/dist/sensors/vl53lx/uld/bare/core.js +1085 -0
  93. package/dist/sensors/vl53lx/uld/bare/core.js.map +1 -0
  94. package/dist/sensors/vl53lx/uld/bare/driver.d.ts +91 -0
  95. package/dist/sensors/vl53lx/uld/bare/driver.d.ts.map +1 -0
  96. package/dist/sensors/vl53lx/uld/bare/driver.js +206 -0
  97. package/dist/sensors/vl53lx/uld/bare/driver.js.map +1 -0
  98. package/dist/sensors/vl53lx/uld/bare/hist.d.ts +180 -0
  99. package/dist/sensors/vl53lx/uld/bare/hist.d.ts.map +1 -0
  100. package/dist/sensors/vl53lx/uld/bare/hist.js +949 -0
  101. package/dist/sensors/vl53lx/uld/bare/hist.js.map +1 -0
  102. package/dist/sensors/vl53lx/uld/bare/image.d.ts +53 -0
  103. package/dist/sensors/vl53lx/uld/bare/image.d.ts.map +1 -0
  104. package/dist/sensors/vl53lx/uld/bare/image.js +108 -0
  105. package/dist/sensors/vl53lx/uld/bare/image.js.map +1 -0
  106. package/dist/sensors/vl53lx/uld/bare/imath.d.ts +39 -0
  107. package/dist/sensors/vl53lx/uld/bare/imath.d.ts.map +1 -0
  108. package/dist/sensors/vl53lx/uld/bare/imath.js +99 -0
  109. package/dist/sensors/vl53lx/uld/bare/imath.js.map +1 -0
  110. package/dist/sensors/vl53lx/uld/bare/index.d.ts +22 -0
  111. package/dist/sensors/vl53lx/uld/bare/index.d.ts.map +1 -0
  112. package/dist/sensors/vl53lx/uld/bare/index.js +22 -0
  113. package/dist/sensors/vl53lx/uld/bare/index.js.map +1 -0
  114. package/dist/sensors/vl53lx/uld/bare/nvm.d.ts +85 -0
  115. package/dist/sensors/vl53lx/uld/bare/nvm.d.ts.map +1 -0
  116. package/dist/sensors/vl53lx/uld/bare/nvm.js +148 -0
  117. package/dist/sensors/vl53lx/uld/bare/nvm.js.map +1 -0
  118. package/dist/sensors/vl53lx/uld/bare/regs.d.ts +54 -0
  119. package/dist/sensors/vl53lx/uld/bare/regs.d.ts.map +1 -0
  120. package/dist/sensors/vl53lx/uld/bare/regs.js +496 -0
  121. package/dist/sensors/vl53lx/uld/bare/regs.js.map +1 -0
  122. package/dist/sensors/vl53lx/uld/bare/tuning.d.ts +15 -0
  123. package/dist/sensors/vl53lx/uld/bare/tuning.d.ts.map +1 -0
  124. package/dist/sensors/vl53lx/uld/bare/tuning.js +303 -0
  125. package/dist/sensors/vl53lx/uld/bare/tuning.js.map +1 -0
  126. package/dist/sensors/vl53lx/uld/base.d.ts +129 -0
  127. package/dist/sensors/vl53lx/uld/base.d.ts.map +1 -0
  128. package/dist/sensors/vl53lx/uld/base.js +166 -0
  129. package/dist/sensors/vl53lx/uld/base.js.map +1 -0
  130. package/dist/sensors/vl53lx/uld/l0x.d.ts +306 -0
  131. package/dist/sensors/vl53lx/uld/l0x.d.ts.map +1 -0
  132. package/dist/sensors/vl53lx/uld/l0x.js +1492 -0
  133. package/dist/sensors/vl53lx/uld/l0x.js.map +1 -0
  134. package/dist/sensors/vl53lx/uld/l1.d.ts +69 -0
  135. package/dist/sensors/vl53lx/uld/l1.d.ts.map +1 -0
  136. package/dist/sensors/vl53lx/uld/l1.js +262 -0
  137. package/dist/sensors/vl53lx/uld/l1.js.map +1 -0
  138. package/dist/sensors/vl53lx/uld/l3.d.ts +25 -0
  139. package/dist/sensors/vl53lx/uld/l3.d.ts.map +1 -0
  140. package/dist/sensors/vl53lx/uld/l3.js +51 -0
  141. package/dist/sensors/vl53lx/uld/l3.js.map +1 -0
  142. package/dist/sensors/vl53lx/uld/l4.d.ts +22 -0
  143. package/dist/sensors/vl53lx/uld/l4.d.ts.map +1 -0
  144. package/dist/sensors/vl53lx/uld/l4.js +99 -0
  145. package/dist/sensors/vl53lx/uld/l4.js.map +1 -0
  146. package/dist/sensors/vl53lx/uld/link.d.ts +42 -0
  147. package/dist/sensors/vl53lx/uld/link.d.ts.map +1 -0
  148. package/dist/sensors/vl53lx/uld/link.js +28 -0
  149. package/dist/sensors/vl53lx/uld/link.js.map +1 -0
  150. package/dist/sensors/vl53lx/uld/registry.d.ts +68 -0
  151. package/dist/sensors/vl53lx/uld/registry.d.ts.map +1 -0
  152. package/dist/sensors/vl53lx/uld/registry.js +139 -0
  153. package/dist/sensors/vl53lx/uld/registry.js.map +1 -0
  154. package/dist/sensors/vl53lx/uld/vl53l1-die.d.ts +172 -0
  155. package/dist/sensors/vl53lx/uld/vl53l1-die.d.ts.map +1 -0
  156. package/dist/sensors/vl53lx/uld/vl53l1-die.js +431 -0
  157. package/dist/sensors/vl53lx/uld/vl53l1-die.js.map +1 -0
  158. package/dist/sensors/vl53lx/vl53lx.d.ts +323 -0
  159. package/dist/sensors/vl53lx/vl53lx.d.ts.map +1 -0
  160. package/dist/sensors/vl53lx/vl53lx.js +688 -0
  161. package/dist/sensors/vl53lx/vl53lx.js.map +1 -0
  162. package/dist/transport/webserial.d.ts +4 -0
  163. package/dist/transport/webserial.d.ts.map +1 -1
  164. package/dist/transport/webserial.js +58 -12
  165. package/dist/transport/webserial.js.map +1 -1
  166. package/package.json +9 -2
@@ -16,9 +16,31 @@
16
16
  // downloaded sensor FW (and hence its checksum at 0x812FFC) and the NVM/config
17
17
  // blobs differ. 'cx' = VL53L8CX ULD 2.1.0; 'ch' = VL53L7CH/VL53L8CH (VL53LMZ)
18
18
  // ULD 2.0.16 — used to try running CH firmware on VL53L8CX silicon.
19
+ //
20
+ // The I2C branch of the family (VL53L5CX / VL53L7CX / VL53L7CH, contract 11)
21
+ // adds 'l7cx' = VL53L5CX/VL53L7CX ULD 2.0.1 and 'l7ch' = VL53LMZ ULD 2.0.16
22
+ // with the VL53L7 default configuration (its firmware is the 'ch' blob).
23
+ // null = the driver publishes no checksum and skips the step (ULD 2.0.1).
19
24
  export const FW_CHECKSUM = {
20
25
  cx: 0xcadf7caf,
21
26
  ch: 0x0c0b6c9e,
27
+ l7cx: null,
28
+ l7ch: 0x0c0b6c9e,
29
+ };
30
+ /** Variants that run on the I2C L5/L7 silicon (different boot sequence). */
31
+ export const I2C_VARIANTS = ["l7cx", "l7ch"];
32
+ export const SI_REVISION_CUT11 = 0x01; // VL53L5CX / VL53L7CX, first cut
33
+ export const SI_REVISION_CUT12 = 0x02; // VL53L5CX / VL53L7CX / VL53L7CH
34
+ export const SI_REVISION_L8 = 0x0c; // VL53L8CX / VL53L8CH
35
+ /** byte[1] = module_type, byte[6] = laser safety. */
36
+ export const DCI_FW_FLAGS = 0xe0c4;
37
+ export const MODULE_TYPE_MZ = 0; // VL53L5CX
38
+ export const MODULE_TYPE_MZEVO = 1; // VL53L7CX / VL53L7CH
39
+ export const MODULE_TYPE_MZPLUS = 2; // VL53L8
40
+ export const MODULE_TYPE_NAMES = {
41
+ [MODULE_TYPE_MZ]: "MZ",
42
+ [MODULE_TYPE_MZEVO]: "MZEVO",
43
+ [MODULE_TYPE_MZPLUS]: "MZPlus",
22
44
  };
23
45
  export const RESOLUTION_4X4 = 16;
24
46
  export const RESOLUTION_8X8 = 64;
@@ -133,6 +155,32 @@ function fromHexConst(hex) {
133
155
  export const GET_XTALK_CMD = fromHexConst("540000409fd800c09fe401409ff800409ffc0404a0fc0100a10c0100a11c00c0a1280902a2480040a24c0081a2540081a25c0081a2640081a26c0084a28c00820000000f07020044");
134
156
  // VL53L8CX_CALIBRATE_XTALK config table (vl53l8cx_plugin_xtalk.h, BSD-3).
135
157
  export const CALIBRATE_XTALK = fromHexConst("545000800004080800000404ad3000800301060300000100ad38010001e0014000100010010001000000000154580040041a0200545c01400001005100000fa00fa003e802801f400000050054700080032003200000000854780100011b0021003300000200000104010802548801400000000000000000000000000000000000000800ad48010001f40000030600100808080800000008ad6001000000008000000000201f01f400001d0aad70008008001f4000000001ad78008000a0032000010190ad80004000002800ad8400800000320003200000ad8c00800258ff380000000cad94010000019000fffffc000000040000000100ada400c00480061a0080058000000106adb000c00480061a1900058000000190adbc044000000000000000000012002500000006000000050000000500000006000000040000000f0000005a00000000000000090b0c0b0b030311050101010100000000000d0000ae00010400000004000000080000000a0000000c0000000d0000000e000000080000000800000010000000100000002000000020000000060000050a02000c0800000000ae400040000000ffae44004000100401ae48004000001000ae4c004000000001ae500140000000140400280003206c000000000000000000ae64004000000001aed8010000c805dc00000ccd0104000000012601b5500282a3e8a3b8a438a428a648a448a788a748ac10a79099bc99b49afc9abc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5a002820088030000820082040404080080040109020908040400800401040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5f0004000040000b39c01004000051e021b087c8000120100010800b6c000c0000060000000200000000000aea8004000000405aeac00800100010000020000aeb4004000000000aeb800810000000000000000aec000810000000000000000aec800810801010800000008aed000810108080800000001b5f400800000000000000000b5fc00800000000000000000b604004000000000b608004400000000000000000000000000000000b618004400000000000000000000000000000000b628004400000000000000000000000000000000b638004400000000000000000000000000000000b648010000000000000000000000000000000000b658010000000000000000000000000000000000b6680100000000000000000000000000000000005470008000000000000000020000000f000103d4");
158
+ // ── L5/L7 xtalk calibration (contract 11 §4) ──────────────────────────────────
159
+ // Verified byte-for-byte (compiled from the C headers) against ST ULD 2.0.1
160
+ // (VL53L7CX/L5CX, the source of the l7cx blobs) and VL53LMZ 2.0.16 (VL53L7CH,
161
+ // the source of the ch/l7ch blobs). Every ST version programs this dedicated
162
+ // 17-block output list for the calibration run, not the ranging list.
163
+ export const XTALK_CAL_OUTPUT = [
164
+ 0x0000000d, 0x54000040, 0x9fd800c0, 0x9fe40140, 0x9ff80040, 0x9ffc0404, 0xa0fc0100,
165
+ 0xa10c0100, 0xa11c00c0, 0xa1280902, 0xa2480040, 0xa24c0081, 0xa2540081, 0xa25c0081,
166
+ 0xa2640081, 0xa26c0084, 0xa28c0082,
167
+ ];
168
+ export const XTALK_CAL_OUTPUT_ENABLE = [0x0001ffff, 0, 0, 0xc0000000];
169
+ // VL53LMZ_CALIBRATE_XTALK, ULD 2.0.16 (VL53L7CH), FW_NBTAR_XTALK = 2 (BSD-3).
170
+ export const CALIBRATE_XTALK_LMZ = fromHexConst("545000800004080800000404ad3000800301060300000100ad38010001e0014000100010010001000000000154580040041a0200545c01400001005100000fa00fa003e802801f400000050054700080032003200000000854780100011b0021003300000200000104010802548801400000000000000000000000000000000000000800ad48010001f40000030600100808080800000008ad6001000000008000000000201f01f400001d0aad70008008001f4000000001ad78008000a0032000010190ad80004000002800ad8400800000320003200000ad8c00800258ff380000000cad94010000019000fffffc000000040000000100ada400c00480061a0080058000000106adb000c00480061a1900058000000190adbc044000000000000000000012002500000006000000050000000500000006000000040000000f0000005a00000000000000090b0c0b0b030311050101010100000000000d0000ae00010400000004000000080000000a0000000c0000000d0000000e000000080000000800000010000000100000002000000020000000060000050a02000c0800000000ae400040000000ffae44004000100401ae48004000001000ae4c004000000001ae500140000000140400280003206c000000000000000000ae64004000000001aed8010000c805dc00000ccd0104000000012601b5500282a3e8a3b8a438a428a648a448a788a748ac10a79099bc99b49afc9abc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5a002820088030000820082040404080080040109020908040400800401040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5f0004000040000b39c01004000051e021b087c8000120100010800b6c000c0000060000000200000000000aea8004000000405aeac00800100010000020000aeb4004000000000aeb800810000000000000000aec000810000000000000000aec800810801010800000008aed000810108080800000001b5f400800000000000000000b5fc00800000000000000000b604004000000000b608004400000000000000000000000000000000b618004400000000000000000000000000000000b628004400000000000000000000000000000000b638004400000000000000000000000000000000b648010000000000000000000000000000000000b658010000000000000000000000000000000000b6680100000000000000000000000000000000005470008000000000000000020000000f000103d4");
171
+ // VL53L7CX_CALIBRATE_XTALK, ULD 2.0.1 (VL53L5CX/VL53L7CX), FW_NBTAR_XTALK = 2
172
+ // (BSD-3). Differs from the LMZ table in bytes 693 and 697 only.
173
+ export const CALIBRATE_XTALK_L7CX = fromHexConst("545000800004080800000404ad3000800301060300000100ad38010001e0014000100010010001000000000154580040041a0200545c01400001005100000fa00fa003e802801f400000050054700080032003200000000854780100011b0021003300000200000104010802548801400000000000000000000000000000000000000800ad48010001f40000030600100808080800000008ad6001000000008000000000201f01f400001d0aad70008008001f4000000001ad78008000a0032000010190ad80004000002800ad8400800000320003200000ad8c00800258ff380000000cad94010000019000fffffc000000040000000100ada400c00480061a0080058000000106adb000c00480061a1900058000000190adbc044000000000000000000012002500000006000000050000000500000006000000040000000f0000005a00000000000000090b0c0b0b030311050101010100000000000d0000ae00010400000004000000080000000a0000000c0000000d0000000e000000080000000800000010000000100000002000000020000000060000050a02000c0800000000ae400040000000ffae44004000100401ae48004000001000ae4c004000000001ae500140000000140400280003206c000000000000000000ae64004000000001aed8010000c805dc00000ccd0104000000012601b5500282a3e8a3b8a438a428a648a448a788a748ac10a79099bc99b49afc9abc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5a002820088030000820082040404080080040109020908040400800401040100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5f0004000040000b39c01004000051e021b087c8001120100000800b6c000c0000060000000200000000000aea8004000000405aeac00800100010000020000aeb4004000000000aeb800810000000000000000aec000810000000000000000aec800810801010800000008aed000810108080800000001b5f400800000000000000000b5fc00800000000000000000b604004000000000b608004400000000000000000000000000000000b618004400000000000000000000000000000000b628004400000000000000000000000000000000b638004400000000000000000000000000000000b648010000000000000000000000000000000000b658010000000000000000000000000000000000b6680100000000000000000000000000000000005470008000000000000000020000000f000103d4");
174
+ // The table must match the sensor firmware: the VL53L8CH runs the VL53LMZ blob,
175
+ // and with the VL53L8CX table that firmware silently skips the calibration
176
+ // (measured 2026-09-25: 0.7 s, xtalk buffer unchanged; with the LMZ table it
177
+ // runs 2.6 s and answers). 'cx' falls back to CALIBRATE_XTALK — 1000 B against
178
+ // 984 B in every ST 2.x header we have, unsettled (contract 04 §7).
179
+ const CALIBRATE_XTALK_BY_VARIANT = {
180
+ l7cx: CALIBRATE_XTALK_L7CX,
181
+ l7ch: CALIBRATE_XTALK_LMZ,
182
+ ch: CALIBRATE_XTALK_LMZ,
183
+ };
136
184
  export const NB_TARGET_PER_ZONE = 1;
137
185
  const STATUS_NAMES = {
138
186
  [STATUS_TIMEOUT_ERROR]: "TIMEOUT",
@@ -186,6 +234,9 @@ function packU32ArrayLE(values) {
186
234
  function hex4(n) {
187
235
  return n.toString(16).toUpperCase().padStart(4, "0");
188
236
  }
237
+ function hex2(n) {
238
+ return n.toString(16).toUpperCase().padStart(2, "0");
239
+ }
189
240
  function hex8(n) {
190
241
  return (n >>> 0).toString(16).toUpperCase().padStart(8, "0");
191
242
  }
@@ -332,6 +383,8 @@ export function packDetectionThresholds(thresholds) {
332
383
  export class VL53L8CX {
333
384
  p;
334
385
  variant;
386
+ /** True for the I2C L5/L7 variants (the non-L8 branch of vl53lmz_init). */
387
+ i2c;
335
388
  fwChecksum;
336
389
  firmware;
337
390
  defaultCfg;
@@ -343,32 +396,45 @@ export class VL53L8CX {
343
396
  dataReadSize = 0;
344
397
  /** { fw, host } when the FW disagrees with the api.c formula. */
345
398
  frameSizeMismatch = null;
399
+ /** Last calibrateXtalk(): nothing to calibrate (ST XTALK_FAILED). */
400
+ xtalkCalibrationFailed = false;
346
401
  /** [idx, type, size] of the blocks in the last parsed frame. */
347
402
  lastBlocks = [];
348
403
  /** Whether the motion-indicator output block is configured. */
349
404
  motionPresent = false;
405
+ /** Silicon ids cached by isAlive(). */
406
+ deviceId = null;
407
+ revisionId = null;
408
+ /** I2C variants: 0 MZ (L5) / 1 MZEVO (L7), read after init(). */
409
+ moduleType = null;
410
+ /** Zones the last startRanging() used (the L5/L7 parser trims to it). */
411
+ resolution = null;
350
412
  outputEnableW3;
351
413
  frameTail;
352
414
  footerIdOff;
353
415
  constructor(platform, assets, variant = "cx") {
416
+ if (!(variant in FW_CHECKSUM))
417
+ throw new Error(`unknown variant ${String(variant)}`);
354
418
  this.p = platform;
355
419
  this.variant = variant;
420
+ this.i2c = I2C_VARIANTS.includes(variant);
356
421
  this.fwChecksum = FW_CHECKSUM[variant];
357
422
  // start_ranging output config differs slightly by FW variant:
358
423
  // cx (ULD 2.1.0): OUTPUT_ENABLES word[3]=0xC0000000, frame tail +32
359
424
  // ch (VL53LMZ 2.0.16): OUTPUT_ENABLES word[3]=0, frame tail +24
425
+ // l7cx (ULD 2.0.1): OUTPUT_ENABLES word[3]=0xC0000000, frame tail +24
426
+ // l7ch = ch
360
427
  // footerIdOff: where the footer id sits relative to the frame end
361
- // (cx 2.1.0 = size-12; ch 2.0.16 = size-4).
362
- if (variant === "ch") {
363
- this.outputEnableW3 = 0x00000000;
364
- this.frameTail = 24;
365
- this.footerIdOff = 4;
366
- }
367
- else {
368
- this.outputEnableW3 = 0xc0000000;
428
+ // (cx 2.1.0 = size-12; the 2.0.x drivers = size-4).
429
+ this.outputEnableW3 = variant === "ch" || variant === "l7ch" ? 0x00000000 : 0xc0000000;
430
+ if (variant === "cx") {
369
431
  this.frameTail = 32;
370
432
  this.footerIdOff = 12;
371
433
  }
434
+ else {
435
+ this.frameTail = 24;
436
+ this.footerIdOff = 4;
437
+ }
372
438
  this.firmware = assets.firmware;
373
439
  this.defaultCfg = assets.defaultCfg;
374
440
  this.defaultXtalk = assets.defaultXtalk;
@@ -544,9 +610,24 @@ export class VL53L8CX {
544
610
  await this.pollForAnswer(4, 1, UI_CMD_STATUS, 0xff, 0x03, "xtalk data");
545
611
  }
546
612
  // ---------------- public API ----------------
547
- /** Returns [deviceId, revisionId]; alive when (0xF0, 0x0C). */
613
+ /**
614
+ * Returns [deviceId, revisionId] and caches them; alive when (0xF0, 0x0C)
615
+ * on L8, revision 0x02 (or 0x01 with deviceId 0xF0) on L5/L7.
616
+ */
548
617
  async isAlive() {
549
- return readDeviceRevisionId(this.p);
618
+ const ids = await readDeviceRevisionId(this.p);
619
+ [this.deviceId, this.revisionId] = ids;
620
+ return ids;
621
+ }
622
+ /**
623
+ * I2C variants only: refuse to boot an L5/L7 blob on anything but L5/L7
624
+ * silicon (vl53lmz_is_alive()).
625
+ */
626
+ async checkI2cSilicon() {
627
+ const [deviceId, revisionId] = await this.isAlive();
628
+ if (!(revisionId === SI_REVISION_CUT12 || (deviceId === 0xf0 && revisionId === SI_REVISION_CUT11))) {
629
+ throw new Vl53l8cxError(STATUS_ERROR, `not a VL53L5/L7 sensor: device_id=0x${hex2(deviceId)} revision_id=0x${hex2(revisionId)}`);
630
+ }
550
631
  }
551
632
  /**
552
633
  * vl53l8cx_init(): boot the sensor MCU, download the 84 KB sensor
@@ -560,6 +641,10 @@ export class VL53L8CX {
560
641
  };
561
642
  const wr = (addr, value) => this.wrByte(addr, value);
562
643
  const rd = (addr) => this.rdByte(addr);
644
+ const i2c = this.i2c; // L5/L7 branch of vl53lmz_init(); L8 path unchanged
645
+ this.moduleType = null;
646
+ if (i2c)
647
+ await this.checkI2cSilicon();
563
648
  // SW reboot sequence
564
649
  note("SW reboot...");
565
650
  await wr(0x7fff, 0x00);
@@ -588,9 +673,16 @@ export class VL53L8CX {
588
673
  await wr(0x000e, 0x01);
589
674
  await wr(0x7fff, 0x02);
590
675
  // Enable FW access
591
- await wr(0x7fff, 0x01);
592
- await wr(0x06, 0x01);
593
- await this.pollForAnswer(1, 0, 0x21, 0xff, 0x04, "fw access");
676
+ if (i2c) {
677
+ await wr(0x03, 0x0d);
678
+ await wr(0x7fff, 0x01);
679
+ await this.pollForAnswer(1, 0, 0x21, 0x10, 0x10, "fw access");
680
+ }
681
+ else {
682
+ await wr(0x7fff, 0x01);
683
+ await wr(0x06, 0x01);
684
+ await this.pollForAnswer(1, 0, 0x21, 0xff, 0x04, "fw access");
685
+ }
594
686
  await wr(0x7fff, 0x00);
595
687
  // Enable host access to GO1
596
688
  await rd(0x7fff);
@@ -614,8 +706,14 @@ export class VL53L8CX {
614
706
  // Wake up MCU
615
707
  await wr(0x7fff, 0x00);
616
708
  await rd(0x7fff);
709
+ if (i2c)
710
+ await wr(0x0c, 0x00);
617
711
  await wr(0x7fff, 0x01);
618
- // Download FW into VL53L8CX
712
+ if (i2c) {
713
+ await wr(0x20, 0x07);
714
+ await wr(0x20, 0x06);
715
+ }
716
+ // Download FW into the sensor
619
717
  note("Downloading sensor FW (84 KB)... bank 1/3");
620
718
  await wr(0x7fff, 0x09);
621
719
  await this.p.wrMulti(0, this.firmware.subarray(0, 0x8000));
@@ -627,9 +725,17 @@ export class VL53L8CX {
627
725
  await this.p.wrMulti(0, this.firmware.subarray(0x10000, 0x15000));
628
726
  await wr(0x7fff, 0x01);
629
727
  // Check if FW correctly downloaded
630
- await wr(0x7fff, 0x01);
631
- await wr(0x06, 0x03);
632
- await this.p.sleepMs(5);
728
+ if (i2c) {
729
+ await wr(0x7fff, 0x02);
730
+ await wr(0x03, 0x0d);
731
+ await wr(0x7fff, 0x01);
732
+ await this.pollForAnswer(1, 0, 0x21, 0x10, 0x10, "fw downloaded");
733
+ }
734
+ else {
735
+ await wr(0x7fff, 0x01);
736
+ await wr(0x06, 0x03);
737
+ await this.p.sleepMs(5);
738
+ }
633
739
  await wr(0x7fff, 0x00);
634
740
  await rd(0x7fff);
635
741
  await wr(0x0c, 0x01);
@@ -648,12 +754,15 @@ export class VL53L8CX {
648
754
  await wr(0x7fff, 0x02);
649
755
  // Firmware checksum (0x812FFC & 0xFFFF); value depends on the FW variant
650
756
  // (see FW_CHECKSUM). cx = ULD 2.1.0 FW; ch = VL53LMZ ULD 2.0.16 FW.
651
- const crcBuf = swapBuffer(await this.p.rdMulti(0x2ffc, 4));
652
- const crc = dvOf(crcBuf).getUint32(0, true);
653
- if (crc !== this.fwChecksum) {
654
- throw new Vl53l8cxError(STATUS_FW_CHECKSUM_FAIL, `crc=0x${hex8(crc)} (expected 0x${hex8(this.fwChecksum)} for ${this.variant})`);
757
+ // The L5/L7 ULD 2.0.1 (l7cx) publishes no checksum and skips the step.
758
+ if (this.fwChecksum !== null) {
759
+ const crcBuf = swapBuffer(await this.p.rdMulti(0x2ffc, 4));
760
+ const crc = dvOf(crcBuf).getUint32(0, true);
761
+ if (crc !== this.fwChecksum) {
762
+ throw new Vl53l8cxError(STATUS_FW_CHECKSUM_FAIL, `crc=0x${hex8(crc)} (expected 0x${hex8(this.fwChecksum)} for ${this.variant})`);
763
+ }
764
+ note("Sensor FW checksum OK");
655
765
  }
656
- note("Sensor FW checksum OK");
657
766
  // Get offset NVM data
658
767
  note("Reading NVM offset data...");
659
768
  await this.p.wrMulti(0x2fd8, this.getNvmCmd);
@@ -672,7 +781,15 @@ export class VL53L8CX {
672
781
  const pipeCtrl = Uint8Array.of(NB_TARGET_PER_ZONE, 0x00, 0x01, 0x00);
673
782
  await this.dciWriteData(DCI_PIPE_CONTROL, pipeCtrl);
674
783
  await this.dciWriteData(DCI_SINGLE_RANGE, packU32ArrayLE([0x01]));
675
- note("Sensor init done");
784
+ if (i2c) {
785
+ // Readable only once the sensor FW runs; tells L5 (MZ) from L7 (MZEVO),
786
+ // which share a blob and a board.
787
+ this.moduleType = (await this.dciReadData(DCI_FW_FLAGS, 8))[1];
788
+ note(`Sensor init done (module type ${MODULE_TYPE_NAMES[this.moduleType] ?? this.moduleType})`);
789
+ }
790
+ else {
791
+ note("Sensor init done");
792
+ }
676
793
  }
677
794
  async getResolution() {
678
795
  const buf = await this.dciReadData(DCI_ZONE_CONFIG, 8);
@@ -828,7 +945,18 @@ export class VL53L8CX {
828
945
  const [bhType, bhSizeIn, bhIdx] = bhFields(output[i]);
829
946
  let bhSize = bhSizeIn;
830
947
  if (bhType >= 0x1 && bhType < 0x0d) {
831
- if (bhIdx >= 0x54d0 && bhIdx < 0x54d0 + 960) {
948
+ if (this.i2c) {
949
+ // vl53lmz_start_ranging (2.0.16), as verified on L5/L7 hardware:
950
+ // per-target blocks above 0x6C90 keep their 64-entry size even in
951
+ // 4x4 (parseFrame trims them).
952
+ if (bhIdx >= 0x54d0 && bhIdx < 0x5890) {
953
+ bhSize = resolution;
954
+ }
955
+ else if (bhIdx < 0x6c90) {
956
+ bhSize = resolution * NB_TARGET_PER_ZONE;
957
+ }
958
+ }
959
+ else if (bhIdx >= 0x54d0 && bhIdx < 0x54d0 + 960) {
832
960
  bhSize = resolution;
833
961
  }
834
962
  else if (bhIdx === CNH_DATA_IDX) {
@@ -846,6 +974,7 @@ export class VL53L8CX {
846
974
  this.dataReadSize += 4;
847
975
  }
848
976
  this.dataReadSize += this.frameTail;
977
+ this.resolution = resolution;
849
978
  await this.dciWriteData(DCI_OUTPUT_LIST, packU32ArrayLE(output));
850
979
  const headerConfig = packU32ArrayLE([this.dataReadSize, output.length + 1]);
851
980
  await this.dciWriteData(DCI_OUTPUT_CONFIG, headerConfig);
@@ -1015,6 +1144,21 @@ export class VL53L8CX {
1015
1144
  }
1016
1145
  i += msize + 4;
1017
1146
  }
1147
+ // L5/L7: the per-target blocks carry 64 entries even in 4x4 (see
1148
+ // startRanging); the sensor fills the first `resolution` and pads the
1149
+ // rest with zeros. Trim to the zones that exist.
1150
+ if (this.i2c && this.resolution) {
1151
+ const n = this.resolution;
1152
+ results.ambientPerSpad = results.ambientPerSpad.slice(0, n);
1153
+ results.nbSpadsEnabled = results.nbSpadsEnabled.slice(0, n);
1154
+ results.nbTargetDetected = results.nbTargetDetected.slice(0, n);
1155
+ const nt = n * NB_TARGET_PER_ZONE;
1156
+ results.distanceMm = results.distanceMm.slice(0, nt);
1157
+ results.targetStatus = results.targetStatus.slice(0, nt);
1158
+ results.signalPerSpad = results.signalPerSpad.slice(0, nt);
1159
+ results.rangeSigmaMm = results.rangeSigmaMm.slice(0, nt);
1160
+ results.reflectance = results.reflectance.slice(0, nt);
1161
+ }
1018
1162
  // Convert to real format (fixed-point scaling, per ST GetRangingData).
1019
1163
  results.distanceMm = results.distanceMm.map((d) => Math.floor(d / 4));
1020
1164
  results.rangeSigmaMm = results.rangeSigmaMm.map((s) => s / 128.0);
@@ -1094,7 +1238,13 @@ export class VL53L8CX {
1094
1238
  mode = POWER_MODE_WAKEUP;
1095
1239
  }
1096
1240
  else if (tmp === 0x02) {
1097
- mode = (await this.rdByte(0x000f)) === 0x43 ? POWER_MODE_DEEP_SLEEP : POWER_MODE_SLEEP;
1241
+ // ULD 2.0.1 (l7cx) has no deep sleep and never reads 0x000F.
1242
+ if (this.variant === "l7cx") {
1243
+ mode = POWER_MODE_SLEEP;
1244
+ }
1245
+ else {
1246
+ mode = (await this.rdByte(0x000f)) === 0x43 ? POWER_MODE_DEEP_SLEEP : POWER_MODE_SLEEP;
1247
+ }
1098
1248
  }
1099
1249
  else {
1100
1250
  await this.wrByte(0x7fff, 0x02);
@@ -1108,10 +1258,22 @@ export class VL53L8CX {
1108
1258
  * from DEEP_SLEEP re-runs init() (the FW blob is lost).
1109
1259
  */
1110
1260
  async setPowerMode(powerMode) {
1261
+ if (this.variant === "l7cx" &&
1262
+ powerMode !== POWER_MODE_SLEEP &&
1263
+ powerMode !== POWER_MODE_WAKEUP) {
1264
+ // vl53l7cx_set_power_mode (ULD 2.0.1): SLEEP / WAKEUP only.
1265
+ throw new Vl53l8cxError(STATUS_INVALID_PARAM, "set_power_mode: VL53L5CX/L7CX have no deep sleep");
1266
+ }
1111
1267
  const current = await this.getPowerMode();
1112
1268
  if (powerMode === current)
1113
1269
  return;
1114
- if (powerMode === POWER_MODE_WAKEUP) {
1270
+ if (powerMode === POWER_MODE_WAKEUP && this.variant === "l7cx") {
1271
+ await this.wrByte(0x7fff, 0x00);
1272
+ await this.wrByte(0x09, 0x04);
1273
+ await this.pollForAnswer(1, 0, 0x06, 0x01, 1, "wakeup");
1274
+ await this.wrByte(0x7fff, 0x02);
1275
+ }
1276
+ else if (powerMode === POWER_MODE_WAKEUP) {
1115
1277
  await this.wrByte(0x7fff, 0x00);
1116
1278
  await this.wrByte(0x09, 0x04);
1117
1279
  const stored = await this.rdByte(0x000f);
@@ -1232,6 +1394,10 @@ export class VL53L8CX {
1232
1394
  await this.dciWriteData(DCI_DET_THRESH_START, start);
1233
1395
  }
1234
1396
  async setDetectionThresholdsAutoStop(autoStop) {
1397
+ if (this.variant === "l7cx") {
1398
+ // Not in the VL53L5CX/L7CX ULD 2.0.1 thresholds plugin.
1399
+ throw new Vl53l8cxError(STATUS_INVALID_PARAM, "detection-threshold auto-stop: not in the L5CX/L7CX ULD");
1400
+ }
1235
1401
  await this.dciReplaceData(DCI_PIPE_CONTROL, 4, Uint8Array.of(autoStop ? 1 : 0), 0x03);
1236
1402
  }
1237
1403
  // ---------------- motion indicator (plugin) ----------------
@@ -1317,12 +1483,44 @@ export class VL53L8CX {
1317
1483
  return dataReadSize;
1318
1484
  }
1319
1485
  /**
1320
- * vl53l8cx_calibrate_xtalk: run on-device crosstalk calibration.
1321
- *
1322
- * NOTE: ported from ST ULD source but NOT verified against live hardware in
1323
- * this SDK — the get/set caldata-xtalk buffer path IS the tested save/restore
1324
- * route. Saves & restores resolution/frequency/int-time/sharpener/target-
1325
- * order/xtalk-margin/ranging-mode around the run.
1486
+ * _vlxxx_program_output_config() of the ST xtalk plugin (every version):
1487
+ * the dedicated 17-block calibration output list, sized with the classic
1488
+ * 0x54D0+960 rule, 24-byte tail. Used by every variant.
1489
+ */
1490
+ async programXtalkOutputConfig(resolution) {
1491
+ const output = [...XTALK_CAL_OUTPUT];
1492
+ let dataReadSize = 0;
1493
+ for (let i = 0; i < output.length; i++) {
1494
+ if (output[i] === 0 ||
1495
+ !((XTALK_CAL_OUTPUT_ENABLE[Math.floor(i / 32)] & (1 << i % 32)) >>> 0)) {
1496
+ continue;
1497
+ }
1498
+ const [bhType, bhSizeIn, bhIdx] = bhFields(output[i]);
1499
+ let bhSize = bhSizeIn;
1500
+ if (bhType >= 0x1 && bhType < 0x0d) {
1501
+ bhSize = bhIdx >= 0x54d0 && bhIdx < 0x54d0 + 960 ? resolution : resolution * NB_TARGET_PER_ZONE;
1502
+ output[i] = bhSetSize(output[i], bhSize);
1503
+ dataReadSize += bhType * bhSize;
1504
+ }
1505
+ else {
1506
+ dataReadSize += bhSize;
1507
+ }
1508
+ dataReadSize += 4;
1509
+ }
1510
+ dataReadSize += 24;
1511
+ await this.dciWriteData(DCI_OUTPUT_LIST, packU32ArrayLE(output));
1512
+ await this.dciWriteData(DCI_OUTPUT_CONFIG, packU32ArrayLE([dataReadSize, output.length + 1]));
1513
+ await this.dciWriteData(DCI_OUTPUT_ENABLES, packU32ArrayLE([...XTALK_CAL_OUTPUT_ENABLE]));
1514
+ return dataReadSize;
1515
+ }
1516
+ /**
1517
+ * vl53l8cx_calibrate_xtalk: run on-device crosstalk calibration. As every ST
1518
+ * version: the firmware's own calibration table, then the dedicated 17-block
1519
+ * calibration output list. Verified on a VL53L8CH (and L5CX / L7CH) without
1520
+ * cover glass, where the firmware correctly answers XTALK_FAILED
1521
+ * ("coverglass too good"); a successful run needs glass. Saves & restores
1522
+ * resolution/frequency/int-time/sharpener/target-order/xtalk-margin/
1523
+ * ranging-mode around the run.
1326
1524
  */
1327
1525
  async calibrateXtalk(reflectancePercent, nbSamples, distanceMm) {
1328
1526
  if (!(reflectancePercent >= 1 && reflectancePercent <= 99)) {
@@ -1346,7 +1544,9 @@ export class VL53L8CX {
1346
1544
  rangingMode: await this.getRangingMode(),
1347
1545
  };
1348
1546
  await this.setResolution(RESOLUTION_8X8);
1349
- await this.p.wrMulti(0x2c28, CALIBRATE_XTALK);
1547
+ // L5/L7: the ST table of the matching ULD (verified against the C headers);
1548
+ // L8 keeps its own table (see CALIBRATE_XTALK).
1549
+ await this.p.wrMulti(0x2c28, CALIBRATE_XTALK_BY_VARIANT[this.variant] ?? CALIBRATE_XTALK);
1350
1550
  await this.pollForAnswer(4, 1, UI_CMD_STATUS, 0xff, 0x03, "calib cmd");
1351
1551
  const refl = reflectancePercent * 16;
1352
1552
  const dist = distanceMm * 4;
@@ -1358,15 +1558,21 @@ export class VL53L8CX {
1358
1558
  await this.dciReplaceData(DCI_CAL_CFG, 8, u16(dist), 0x00);
1359
1559
  await this.dciReplaceData(DCI_CAL_CFG, 8, u16(refl), 0x02);
1360
1560
  await this.dciReplaceData(DCI_CAL_CFG, 8, Uint8Array.of(nbSamples), 0x04);
1361
- await this.programOutputConfig(RESOLUTION_8X8);
1561
+ // Every ST version programs the calibration output list here, not the
1562
+ // ranging one.
1563
+ await this.programXtalkOutputConfig(RESOLUTION_8X8);
1362
1564
  await this.p.wrMulti(UI_CMD_END - 3, cmd);
1363
1565
  await this.pollForAnswer(4, 1, UI_CMD_STATUS, 0xff, 0x03, "calib start");
1364
1566
  let timeout = 0;
1567
+ this.xtalkCalibrationFailed = false;
1365
1568
  for (;;) {
1366
1569
  const buf = await this.p.rdMulti(0x0, 4);
1367
1570
  if (buf[0] !== STATUS_ERROR) {
1368
1571
  if (buf[2] >= 0x7f && ((buf[3] & 0x80) >> 7) === 1) {
1369
- this.xtalkData = this.defaultXtalk; // XTALK_FAILED
1572
+ // ST: "Coverglass too good for Xtalk calibration" (XTALK_FAILED);
1573
+ // the buffer read back below is what the FW keeps.
1574
+ this.xtalkData = this.defaultXtalk;
1575
+ this.xtalkCalibrationFailed = true;
1370
1576
  }
1371
1577
  break;
1372
1578
  }