Skip to content

Commit 35b9eb8

Browse files
committed
🚧 Work in progress
1 parent 5b04585 commit 35b9eb8

File tree

8 files changed

+148
-123
lines changed

8 files changed

+148
-123
lines changed

examples/connect.ts

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,10 @@
1-
// TODO
21
import { serial } from "node-web-serial-ponyfill";
3-
import { ProgramIniConfig, V5SerialDevice, ZerobaseSlotNumber } from "../src";
4-
5-
import fs from 'fs';
6-
7-
function toUint8(b: Buffer): Uint8Array {
8-
let ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
9-
return new Uint8Array(ab);
10-
}
2+
import { V5SerialDevice } from "../src";
113

124
(async function() {
135
let device = new V5SerialDevice(serial);
146

15-
device.autoRefresh = false;
16-
177
await device.connect();
188

19-
// device.brain.activeProgram = 1;
20-
21-
// console.log(device.brain.systemVersion);
22-
23-
// read file
24-
25-
26-
let slot = 2;
27-
// let bin = await readFileFromInternet("./field_skills_1_0_0_0.bin");
28-
let bin = new Uint8Array(toUint8(fs.readFileSync("./slot_8.bin")));
29-
let cold = undefined;
30-
// let bin = new Uint8Array(await readFileFromInternet("./hot.package.bin"));
31-
// let cold = new Uint8Array(await readFileFromInternet("./cold.package.bin"));
32-
33-
// console.log(bin);
34-
35-
36-
let ini = new ProgramIniConfig();
37-
ini.autorun = true;
38-
ini.baseName = "slot_" + slot;
39-
ini.program.name = "Their Program";
40-
ini.program.slot = (slot - 1) as ZerobaseSlotNumber;
41-
ini.program.icon = "USER902x.bmp";
42-
ini.program.description = "My Program Description";
43-
44-
const onProgress = (state: string, current: number, total: number) => {
45-
console.log(state, current, total);
46-
47-
// TODO
48-
};
49-
50-
let isDone = await device.brain.uploadProgram(ini, bin, cold, onProgress);
51-
console.log("done", isDone);
9+
console.log(device.brain.systemVersion);
5210
})();
1.31 MB
Binary file not shown.
1.11 KB
Binary file not shown.

examples/upload.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { serial } from "node-web-serial-ponyfill";
2+
import { ProgramIniConfig, V5SerialDevice, ZerobaseSlotNumber } from "../src";
3+
4+
import fs from 'fs';
5+
6+
function toUint8(b: Buffer): Uint8Array {
7+
let ab = b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
8+
return new Uint8Array(ab);
9+
}
10+
11+
(async function() {
12+
let device = new V5SerialDevice(serial);
13+
14+
await device.connect();
15+
16+
let slot = 2;
17+
let bin = toUint8(fs.readFileSync("./examples/pros-demo-program/hot.package.bin"));
18+
let cold = toUint8(fs.readFileSync("./examples/pros-demo-program/cold.package.bin"));
19+
20+
let ini = new ProgramIniConfig();
21+
ini.autorun = true;
22+
ini.baseName = "slot_" + slot;
23+
ini.program.name = "PROS Demo";
24+
ini.program.slot = (slot - 1) as ZerobaseSlotNumber;
25+
ini.program.icon = "USER902x.bmp";
26+
ini.program.description = "Demo";
27+
28+
const onProgress = (state: string, current: number, total: number) => {
29+
console.log(state, current, total);
30+
};
31+
32+
let isDone = await device.brain.uploadProgram(ini, bin, cold, onProgress);
33+
console.log("done", isDone);
34+
})();

src/VexCRC.ts

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,89 @@
1+
let CRC16TABLE = [
2+
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b,
3+
0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
4+
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
5+
0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
6+
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738,
7+
0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
8+
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,
9+
0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
10+
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
11+
0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
12+
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb,
13+
0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
14+
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2,
15+
0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
16+
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
17+
0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
18+
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827,
19+
0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
20+
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d,
21+
0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
22+
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
23+
0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
24+
];
25+
126
export class CrcGenerator {
227
crc16Table: Uint32Array;
328
crc32Table: Uint32Array;
429
static POLYNOMIAL_CRC32 = 79764919;
530
static POLYNOMIAL_CRC16 = 4129;
631

732
constructor() {
8-
this.crc16Table = new Uint32Array(256);
933
this.crc32Table = new Uint32Array(256);
10-
this.crc16GenTable();
1134
this.crc32GenTable();
1235
}
1336

14-
crc16GenTable() {
15-
let e, t, a;
16-
for (this.crc16Table = new Uint32Array(256),
17-
e = 0; e < 256; e++) {
18-
for (a = e << 8, t = 0; t < 8; t++) {
19-
32768 & a ? a = a << 1 ^ CrcGenerator.POLYNOMIAL_CRC16 : a <<= 1;
20-
}
21-
this.crc16Table[e] = a;
22-
}
23-
}
37+
/**
38+
* Calculate CRC16 for buffer
39+
*/
40+
crc16(buf: Uint8Array, initValue: number) {
41+
const numberOfBytes = buf.byteLength;
42+
let accumulator = initValue;
43+
let i;
44+
let j;
2445

25-
crc16(data: Uint8Array, t: number) {
26-
const len = data.byteLength;
27-
let n: number, r: number, i: number = t;
28-
for (r = 0; r < len; r++) {
29-
n = 255 & (i >>> 8 ^ data[r]);
30-
i = (i << 8 ^ this.crc16Table[n]) >>> 0;
46+
// now calculate CRC16
47+
for (j = 0; j < numberOfBytes; j++) {
48+
i = ((accumulator >>> 8) ^ buf[j]) & 0xFF;
49+
accumulator = ((accumulator << 8) ^ CRC16TABLE[i]) >>> 0;
3150
}
32-
return (65535 & i) >>> 0;
51+
return (accumulator & 0xFFFF) >>> 0;
3352
}
3453

54+
/**
55+
* Generate CRC32 reverse table
56+
*/
3557
crc32GenTable() {
36-
let e, t, a;
37-
for (e = 0; e < 256; e++) {
38-
for (a = e << 24, t = 0; t < 8; t++) {
39-
2147483648 & a ? a = a << 1 ^ CrcGenerator.POLYNOMIAL_CRC32 : a <<= 1;
58+
var i;
59+
var j;
60+
var crc_accumulator;
61+
for (i = 0; i < 256; i++) {
62+
crc_accumulator = i << 24;
63+
for (j = 0; j < 8; j++) {
64+
if (crc_accumulator & 0x80000000)
65+
crc_accumulator = (crc_accumulator << 1) ^ CrcGenerator.POLYNOMIAL_CRC32;
66+
else
67+
crc_accumulator = (crc_accumulator << 1);
4068
}
41-
this.crc32Table[e] = a;
69+
this.crc32Table[i] = crc_accumulator;
4270
}
4371
}
4472

45-
crc32(data: Uint8Array, t: number) {
46-
const a = data.byteLength;
47-
let n, r, i = t;
48-
for (r = 0; r < a; r++) {
49-
n = 255 & (i >>> 24 ^ data[r]);
50-
i = (i << 8 ^ this.crc32Table[n]) >>> 0;
73+
/**
74+
* Calculate CRC32 for buffer
75+
*/
76+
crc32(buf: Uint8Array, initValue: number) {
77+
const numberOfBytes = buf.byteLength;
78+
let crc_accumulator = initValue;
79+
let i;
80+
let j;
81+
82+
// now calculate CRC32
83+
for (j = 0; j < numberOfBytes; j++) {
84+
i = ((crc_accumulator >>> 24) ^ buf[j]) & 0xFF;
85+
crc_accumulator = ((crc_accumulator << 8) ^ this.crc32Table[i]) >>> 0;
5186
}
52-
return (4294967295 & i) >>> 0;
87+
return (crc_accumulator & 0xFFFFFFFF) >>> 0;
5388
}
5489
}

src/VexConnection.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,10 @@ export class VexSerialConnection extends VexEventTarget {
129129
wantedCommandId: rawData instanceof DeviceBoundPacket ? (rawData.constructor as any).COMMAND_ID : undefined,
130130
wantedCommandExId: rawData instanceof DeviceBoundPacket ? (rawData.constructor as any).COMMAND_EXTENDED_ID : undefined
131131
};
132-
this.callbacksQueue.push(cb);logData(data, 100);
132+
this.callbacksQueue.push(cb);
133133

134134
try {
135-
this.writer.write(data).then(() => { });
135+
this.writer.write(data).then(() => { logData(data, 100); });
136136
} catch (error) {
137137
this.callbacksQueue.splice(this.callbacksQueue.indexOf(cb), 1);
138138
done(AckType.WRITE_ERROR);
@@ -496,6 +496,8 @@ export class V5SerialConnection extends VexSerialConnection {
496496
}
497497

498498
function logData(data: Uint8Array, limitedSize: number) {
499+
if (data === undefined) return;
500+
499501
limitedSize || (limitedSize = data.length);
500502
let a = "";
501503
for (let n = 0; n < data.length && n < limitedSize; n++)

src/VexDevice.ts

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -904,9 +904,6 @@ export class V5SerialDevice extends VexSerialDevice {
904904
}
905905

906906
async refresh() {
907-
// let matchStatus = await this.connection?.getMatchStatus();
908-
// console.log(matchStatus);
909-
910907
let ssPacket = await this.connection?.getSystemStatus();
911908
if (!ssPacket) {
912909
this.state.brain.isAvailable = false;
@@ -929,50 +926,47 @@ export class V5SerialDevice extends VexSerialDevice {
929926

930927
this.state.brain.uniqueId = ssPacket.uniqueId;
931928

932-
// let sfPacket = await this.connection?.getSystemFlags();
933-
// if (!sfPacket) return false;
934-
935-
// let flags5 = sfPacket.flags; // Math.pow(2, 32 - i);
936-
// this.state.radio.isRadioData = (flags5 & Math.pow(2, 32 - 12)) !== 0;
937-
// this.state.brain.button.isDoublePressed = (flags5 & Math.pow(2, 32 - 14)) !== 0;
938-
// this.state.brain.battery.isCharging = (flags5 & Math.pow(2, 32 - 15)) !== 0;
939-
// this.state.brain.button.isPressed = (flags5 & Math.pow(2, 32 - 17)) !== 0;
940-
// this.state.radio.isVexNet = (flags5 & Math.pow(2, 32 - 18)) !== 0;
941-
// this.state.controllers[1].isAvailable = (flags5 & Math.pow(2, 32 - 19)) !== 0;
942-
// this.state.radio.isConnected = (flags5 & Math.pow(2, 32 - 22)) !== 0;
943-
// this.state.radio.isAvailable = (flags5 & Math.pow(2, 32 - 23)) !== 0;
944-
// this.state.brain.battery.batteryPercent = sfPacket.battery || 0;
945-
// this.state.controllers[0].isAvailable = this.state.radio.isConnected || this.state.controllers[0].isCharging;
946-
// this.state.controllers[0].battery = sfPacket.controllerBatteryPercent || 0;
947-
// this.state.controllers[1].battery = sfPacket.partnerControllerBatteryPercent || 0;
948-
// this.state.brain.activeProgram = sfPacket.currentProgram;
949-
// this.state.brain.isAvailable = !this.isV5Controller || this.state.radio.isConnected;
950-
951-
// let rdPacket = await this.connection?.getRadioStatus();
952-
// if (!rdPacket) return false;
953-
954-
// this.state.radio.channel = rdPacket.channel;
955-
// this.state.radio.latency = rdPacket.timeslot;
956-
// this.state.radio.signalQuality = rdPacket.quality;
957-
// this.state.radio.signalStrength = rdPacket.strength;
958-
959-
// let dsPacket = await this.connection?.getDeviceStatus();
960-
// if (!dsPacket) return false;
961-
962-
// let missingPorts = this.state.devices.map((d) => d?.port).filter((p) => p !== undefined);
963-
964-
// for (let i = 0; i < dsPacket.devices.length; i++) {
965-
// let device = dsPacket.devices[i];
966-
// this.state.devices[device.port] = device;
967-
968-
// // remove device port from missing ports
969-
// missingPorts = missingPorts.filter((p) => p !== device.port);
970-
// }
971-
972-
// missingPorts.forEach((port) => delete this.state.devices[port]);
973-
974-
// console.log(this.state);
929+
let sfPacket = await this.connection?.getSystemFlags();
930+
if (!sfPacket) return false;
931+
932+
let flags5 = sfPacket.flags; // Math.pow(2, 32 - i);
933+
this.state.radio.isRadioData = (flags5 & Math.pow(2, 32 - 12)) !== 0;
934+
this.state.brain.button.isDoublePressed = (flags5 & Math.pow(2, 32 - 14)) !== 0;
935+
this.state.brain.battery.isCharging = (flags5 & Math.pow(2, 32 - 15)) !== 0;
936+
this.state.brain.button.isPressed = (flags5 & Math.pow(2, 32 - 17)) !== 0;
937+
this.state.radio.isVexNet = (flags5 & Math.pow(2, 32 - 18)) !== 0;
938+
this.state.controllers[1].isAvailable = (flags5 & Math.pow(2, 32 - 19)) !== 0;
939+
this.state.radio.isConnected = (flags5 & Math.pow(2, 32 - 22)) !== 0;
940+
this.state.radio.isAvailable = (flags5 & Math.pow(2, 32 - 23)) !== 0;
941+
this.state.brain.battery.batteryPercent = sfPacket.battery || 0;
942+
this.state.controllers[0].isAvailable = this.state.radio.isConnected || this.state.controllers[0].isCharging;
943+
this.state.controllers[0].battery = sfPacket.controllerBatteryPercent || 0;
944+
this.state.controllers[1].battery = sfPacket.partnerControllerBatteryPercent || 0;
945+
this.state.brain.activeProgram = sfPacket.currentProgram;
946+
this.state.brain.isAvailable = !this.isV5Controller || this.state.radio.isConnected;
947+
948+
let rdPacket = await this.connection?.getRadioStatus();
949+
if (!rdPacket) return false;
950+
951+
this.state.radio.channel = rdPacket.channel;
952+
this.state.radio.latency = rdPacket.timeslot;
953+
this.state.radio.signalQuality = rdPacket.quality;
954+
this.state.radio.signalStrength = rdPacket.strength;
955+
956+
let dsPacket = await this.connection?.getDeviceStatus();
957+
if (!dsPacket) return false;
958+
959+
let missingPorts = this.state.devices.map((d) => d?.port).filter((p) => p !== undefined);
960+
961+
for (let i = 0; i < dsPacket.devices.length; i++) {
962+
let device = dsPacket.devices[i];
963+
this.state.devices[device.port] = device;
964+
965+
// remove device port from missing ports
966+
missingPorts = missingPorts.filter((p) => p !== device.port);
967+
}
975968

969+
missingPorts.forEach((port) => delete this.state.devices[port]);
976970

977971
return true;
978972
}

src/VexFirmwareVersion.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export class VexFirmwareVersion {
5353
static allZero() {
5454
return new VexFirmwareVersion(0, 0, 0, 0);
5555
}
56+
5657
/**
5758
* Take a a string of MAJOR_MINOR_BUILD_BETA and converts it to a
5859
* VexFirmwareVersion instance
@@ -92,6 +93,7 @@ export class VexFirmwareVersion {
9293
toInternalString() {
9394
return `${this.toUserString()}.b${this.beta}`;
9495
}
96+
9597
/**
9698
* compares this version to the provided version.
9799
* * if this < b: negative

0 commit comments

Comments
 (0)