Skip to content

Commit

Permalink
do stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
fchorney committed Apr 7, 2024
1 parent d887f52 commit 8e34efd
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 20 deletions.
4 changes: 2 additions & 2 deletions sdk/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export class SMXConfig {
* TODO: Make this private again later, and maybe make a function called
* "write_to_stage" or something? Depends on how we want to handle writing/reading
*/
encode(): DataView {
return smx_config_t.encode(this.config, true);
encode(): Array<number> {
return Array.from(new Uint8Array(smx_config_t.encode(this.config, true).buffer));
}
}
42 changes: 28 additions & 14 deletions sdk/smx.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Bacon from "baconjs";
import { collatePackets, type DataPacket } from "./state-machines/collate-packets";
import { collatePackets, type AckPacket, type DataPacket } from "./state-machines/collate-packets";
import { API_COMMAND, char2byte } from "./api";
import { SMXConfig, type Decoded } from "./commands/config";
import { SMXDeviceInfo } from "./commands/data_info";
Expand All @@ -18,6 +18,8 @@ class SMXEvents {
public readonly inputState$;
/** read from this to see all reports sent by the stage in response to a command */
public readonly otherReports$: Bacon.EventStream<Uint8Array>;
/** read from this to see if we've received an ACK */
public readonly ackReports$: Bacon.EventStream<boolean>;
/** push to this to write commands to the stage */
public readonly output$: Bacon.Bus<number[]>;
/** this is everything pushed to `output$` but properly throttled/timed to the device's ack responses */
Expand All @@ -39,9 +41,8 @@ class SMXEvents {
.filter((d) => d.byteLength !== 0)
.withStateMachine({ currentPacket: new Uint8Array() }, collatePackets);

this.otherReports$ = (report$.filter((e) => e.type === "data") as Bacon.EventStream<DataPacket>).map(
(e) => e.payload,
);
this.otherReports$ = (report$.filter((e) => e.type === "data") as Bacon.EventStream<DataPacket>).map((e) => e.payload);
this.ackReports$ = (report$.filter((e) => e.type === "ack") as Bacon.EventStream<AckPacket>).map((e) => e.type === "ack");

const finishedCommand$ = report$
.filter((e) => e.type === "host_cmd_finished")
Expand Down Expand Up @@ -127,21 +128,38 @@ export class SMXStage {

/**
* TODO: To Implement:
*
*
* WRITE_CONFIG_V5
* FACTORY_RESET
* SET_LIGHT_STRIP
* FORCE_RECALIBRATION
*
*
* Stretch Goal:
* SET_PANEL_TEST_MODE
*
*
* Double Stretch Goal:
* GET_CONFIG (old firmware)
* WRITE_CONFIG (old_firmware)
* SET_SERIAL_NUMBERS
*/

writeConfig(): Promise<void> | undefined {
if (!this.info || !this.config) {
return;
}

const encoded_config = this.config.encode();

const command = this.info.firmware_version < 5 ? API_COMMAND.WRITE_CONFIG : API_COMMAND.WRITE_CONFIG_V5;
const cmd = [command, encoded_config.length].concat(encoded_config);

this.events.output$.push([command, encoded_config.length].concat(encoded_config));

return this.events.ackReports$
.map((e) => void e)
.firstToPromise();
}

updateDeviceInfo(): Promise<SMXDeviceInfo> {
this.events.output$.push([API_COMMAND.GET_DEVICE_INFO]);
return this.deviceInfo$.firstToPromise();
Expand Down Expand Up @@ -180,8 +198,8 @@ export class SMXStage {
// Right now I just want to confirm that decoding and encoding gives us back the same data
const encoded_config = this.config.encode();
if (encoded_config) {
const buf = new Uint8Array(encoded_config.buffer);
this.debug && console.log("Config Encodes Correctly: ", data.slice(2, -1).toString() === buf.toString());
this.debug &&
console.log("Config Encodes Correctly: ", data.slice(2, -1).toString() === encoded_config.toString());
}
this.debug && console.log("Got Config: ", this.config);

Expand All @@ -191,11 +209,7 @@ export class SMXStage {
private handleTestData(data: Uint8Array): SMXSensorTestData | undefined {
if (!this.config) return;

this.test = new SMXSensorTestData(
Array.from(data),
this.test_mode,
this.config.config.flags.PlatformFlags_FSR,
);
this.test = new SMXSensorTestData(Array.from(data), this.test_mode, this.config.config.flags.PlatformFlags_FSR);

this.debug && console.log("Got Test: ", this.test);

Expand Down
21 changes: 17 additions & 4 deletions sdk/state-machines/collate-packets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import {
PACKET_PREAMBLE_SIZE,
} from "../packet";

const ACK_PACKET = 0x7;

interface PacketHandlingState {
currentPacket: Uint8Array;
}

export type DataPacket = { type: "data"; payload: Uint8Array };
export type Packet = { type: "host_cmd_finished" } | DataPacket;
export type AckPacket = { type: "ack" };
export type Packet = { type: "host_cmd_finished" } | DataPacket | AckPacket;

/**
* Gets called when a packet is received, returns a tuple of new state and an array of
Expand Down Expand Up @@ -53,9 +56,15 @@ export const collatePackets: StateF<DataView, PacketHandlingState, Packet> = (st
}

// The data exists after the first 2 bytes
const dataBody = data.slice(2, 2 + byte_len);
const dataBody = data.slice(PACKET_PREAMBLE_SIZE, PACKET_PREAMBLE_SIZE + byte_len);

/**
* If packet starts with `ACK_PACKET`, the `byte_len` is 0, and the whole array is just 0,
* then this is an ack packet.
*/
const isAck = (cmd & ACK_PACKET) === ACK_PACKET && byte_len === 0 && dataBody.byteLength === 0;

if ((cmd & PACKET_FLAG_START_OF_COMMAND) === PACKET_FLAG_START_OF_COMMAND && state.currentPacket.length > 0) {
if (cmd & PACKET_FLAG_START_OF_COMMAND && state.currentPacket.length > 0) {
/**
* When we get a start packet, the read buffer should already be empty. If it isn't,
* we got a command that didn't end with an END_OF_COMMAND packet and something is wrong.
Expand Down Expand Up @@ -85,7 +94,11 @@ export const collatePackets: StateF<DataView, PacketHandlingState, Packet> = (st

if ((cmd & PACKET_FLAG_END_OF_COMMAND) === PACKET_FLAG_END_OF_COMMAND) {
newState = { currentPacket: new Uint8Array(0) };
eventsToPass.push({ type: "data", payload: nextPacket });
if (isAck) {
eventsToPass.push({ type: "ack" });
} else {
eventsToPass.push({ type: "data", payload: nextPacket });
}
}

return [newState, eventsToPass.map((e) => new Bacon.Next(e))];
Expand Down
1 change: 1 addition & 0 deletions ui/pad-coms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@ type FunctionKeys<T extends object> = keyof {
/** anything here will appear in the debug UI to dispatch at will */
export const DEBUG_COMMANDS: Record<string, FunctionKeys<SMXStage>> = {
requestConfig: "updateConfig",
writeConfig: "writeConfig",
requestTestData: "updateTestData",
};
1 change: 1 addition & 0 deletions ui/stage/stage-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { timez } from "./util";
const UI_UPDATE_RATE = 50;

function useInputState(stage: SMXStage | undefined) {
const readTestData = useAtomValue(displayTestData$);
const [panelStates, setPanelStates] = useState<Array<boolean> | null>();
useEffect(() => {
return stage?.inputState$.throttle(UI_UPDATE_RATE).onValue(setPanelStates);
Expand Down

0 comments on commit 8e34efd

Please sign in to comment.