/// /// /// namespace pxsim { export class EV3Board extends CoreBoard { view: SVGSVGElement; outputState: EV3OutputState; analogState: EV3AnalogState; uartState: EV3UArtState; motorState: EV3MotorState; screenState: ScreenState; audioState: AudioState; remoteState: RemoteState; inputNodes: SensorNode[] = []; brickNode: BrickNode; outputNodes: MotorNode[] = []; public motorMap: pxt.Map = { 0x01: 0, 0x02: 1, 0x04: 2, 0x08: 3 } constructor() { super() this.bus.setNotify(DAL.DEVICE_ID_NOTIFY, DAL.DEVICE_ID_NOTIFY_ONE); this.brickNode = new BrickNode(); this.outputState = new EV3OutputState(); this.analogState = new EV3AnalogState(); this.uartState = new EV3UArtState(); this.motorState = new EV3MotorState(); this.screenState = new ScreenState(["#97b5a6", "#000000"], visuals.SCREEN_WIDTH, visuals.SCREEN_HEIGHT); this.audioState = new AudioState(); this.remoteState = new RemoteState(); } receiveMessage(msg: SimulatorMessage) { if (!runtime || runtime.dead) return; switch (msg.type || "") { case "eventbus": { let ev = msg; this.bus.queue(ev.id, ev.eventid, ev.value); break; } case "serial": { let data = (msg).data || ""; // TODO break; } } } initAsync(msg: SimulatorRunMessage): Promise { super.initAsync(msg); const options = (msg.options || {}) as pxt.RuntimeOptions; const boardDef = msg.boardDefinition; const cmpsList = msg.parts; const cmpDefs = msg.partDefinitions || {}; const fnArgs = msg.fnArgs; const opts: visuals.BoardHostOpts = { state: this, boardDef: boardDef, partsList: cmpsList, partDefs: cmpDefs, fnArgs: fnArgs, maxWidth: "100%", maxHeight: "100%", }; const viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView({ visual: boardDef.visual }), opts); document.body.innerHTML = ""; // clear children document.body.appendChild(this.view = viewHost.getView() as SVGSVGElement); this.inputNodes = []; this.outputNodes = []; return Promise.resolve(); } screenshot(): string { return svg.toDataUri(new XMLSerializer().serializeToString(this.view)); } getBrickNode() { return this.brickNode; } motorUsed(ports: number, large: boolean): boolean { for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) { const p = 1 << i; if (ports & p) { const motorPort = this.motorMap[p]; const outputNode = this.outputNodes[motorPort]; if (!outputNode) { this.outputNodes[motorPort] = new MotorNode(motorPort, large); continue; } if (outputNode && outputNode.isLarge() != large) return false; } } return true; } getMotor(port: number, large?: boolean): MotorNode[] { const r = []; for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) { const p = 1 << i; if (port & p) { const motorPort = this.motorMap[p]; const outputNode = this.outputNodes[motorPort]; if (outputNode) r.push(outputNode); } } return r; } getMotors() { return this.outputNodes; } hasSensor(port: number) { return !!this.inputNodes[port]; } getSensor(port: number, type: number): SensorNode { if (!this.inputNodes[port]) { switch (type) { case DAL.DEVICE_TYPE_GYRO: this.inputNodes[port] = new GyroSensorNode(port); break; case DAL.DEVICE_TYPE_COLOR: this.inputNodes[port] = new ColorSensorNode(port); break; case DAL.DEVICE_TYPE_TOUCH: this.inputNodes[port] = new TouchSensorNode(port); break; case DAL.DEVICE_TYPE_ULTRASONIC: this.inputNodes[port] = new UltrasonicSensorNode(port); break; case DAL.DEVICE_TYPE_IR: this.inputNodes[port] = new InfraredSensorNode(port); break; } } return this.inputNodes[port]; } getInputNodes() { return this.inputNodes; } } export function initRuntimeWithDalBoard() { U.assert(!runtime.board); let b = new EV3Board(); runtime.board = b; runtime.postError = (e) => { // TODO runtime.updateDisplay(); console.log('runtime error: ' + e); } } export function ev3board(): EV3Board { return runtime.board as EV3Board; } if (!pxsim.initCurrentRuntime) { pxsim.initCurrentRuntime = initRuntimeWithDalBoard; } }