new part definitions (#247)
* working on new part definitions * draft of new part definitions * updates comments * starting new allocator * starting from the old allocator * alloc internals renaming * alloc minor renaming * alloc internal renaming * progress on new parts definition * progress on new part defs allocator * refactors BBLoc; progress on new allocator * more progress on new allocator * finishing new allocator * deleting old allocator * moves new allocator and part definitions * porting to new part definitions * refactors instructions for new definitions * debugging new allocator * fixes ground and power wire colros * fixing new part definition bugs * fixes wire end offsets; fixes NeoPixel placement * fixes colorGroup issue * fixes led matrix wiring * naming tweaks * fixes instructions regressions * typo
This commit is contained in:
committed by
Peli de Halleux
parent
d8fc11a688
commit
c63e2c85f1
@ -2,8 +2,8 @@ namespace pxsim.visuals {
|
||||
export interface BoardHostOpts {
|
||||
state: DalBoard,
|
||||
boardDef: BoardDefinition,
|
||||
cmpsList?: string[],
|
||||
cmpDefs: Map<PartDefinition>,
|
||||
partsList?: string[],
|
||||
partDefs: Map<PartDefinition>,
|
||||
fnArgs: any,
|
||||
forceBreadboard?: boolean,
|
||||
maxWidth?: string,
|
||||
@ -11,13 +11,15 @@ namespace pxsim.visuals {
|
||||
wireframe?: boolean
|
||||
}
|
||||
export class BoardHost {
|
||||
private components: IBoardComponent<any>[] = [];
|
||||
private parts: IBoardPart<any>[] = [];
|
||||
private wireFactory: WireFactory;
|
||||
private breadboard: Breadboard;
|
||||
private fromBBCoord: (xy: Coord) => Coord;
|
||||
private fromMBCoord: (xy: Coord) => Coord;
|
||||
private boardView: BoardView;
|
||||
private view: SVGSVGElement;
|
||||
private partGroup: SVGGElement;
|
||||
private partOverGroup: SVGGElement;
|
||||
private style: SVGStyleElement;
|
||||
private defs: SVGDefsElement;
|
||||
private state: DalBoard;
|
||||
@ -26,7 +28,7 @@ namespace pxsim.visuals {
|
||||
constructor(opts: BoardHostOpts) {
|
||||
this.state = opts.state;
|
||||
let onboardCmps = opts.boardDef.onboardComponents || [];
|
||||
let activeComponents = (opts.cmpsList || []).filter(c => onboardCmps.indexOf(c) < 0);
|
||||
let activeComponents = (opts.partsList || []).filter(c => onboardCmps.indexOf(c) < 0);
|
||||
activeComponents.sort();
|
||||
this.useCrocClips = opts.boardDef.useCrocClips;
|
||||
|
||||
@ -68,6 +70,8 @@ namespace pxsim.visuals {
|
||||
this.fromMBCoord = composition.toHostCoord1;
|
||||
this.fromBBCoord = composition.toHostCoord2;
|
||||
let pinDist = composition.scaleUnit;
|
||||
this.partGroup = over;
|
||||
this.partOverGroup = <SVGGElement>svg.child(this.view, "g");
|
||||
|
||||
this.style = <SVGStyleElement>svg.child(this.view, "style", {});
|
||||
this.defs = <SVGDefsElement>svg.child(this.view, "defs", {});
|
||||
@ -76,16 +80,18 @@ namespace pxsim.visuals {
|
||||
|
||||
let allocRes = allocateDefinitions({
|
||||
boardDef: opts.boardDef,
|
||||
cmpDefs: opts.cmpDefs,
|
||||
partDefs: opts.partDefs,
|
||||
fnArgs: opts.fnArgs,
|
||||
getBBCoord: this.breadboard.getCoord.bind(this.breadboard),
|
||||
cmpList: activeComponents,
|
||||
partsList: activeComponents,
|
||||
});
|
||||
|
||||
this.addAll(allocRes);
|
||||
} else {
|
||||
let el = this.boardView.getView().el;
|
||||
this.view = el;
|
||||
this.partGroup = <SVGGElement>svg.child(this.view, "g");
|
||||
this.partOverGroup = <SVGGElement>svg.child(this.view, "g");
|
||||
if (opts.maxWidth)
|
||||
svg.hydrate(this.view, { width: opts.maxWidth });
|
||||
if (opts.maxHeight)
|
||||
@ -99,7 +105,7 @@ namespace pxsim.visuals {
|
||||
this.boardView.highlightPin(pinNm);
|
||||
}
|
||||
|
||||
public highlightBreadboardPin(rowCol: BBRowCol) {
|
||||
public highlightBreadboardPin(rowCol: BBLoc) {
|
||||
this.breadboard.highlightLoc(rowCol);
|
||||
}
|
||||
|
||||
@ -120,10 +126,10 @@ namespace pxsim.visuals {
|
||||
}
|
||||
|
||||
private updateState() {
|
||||
this.components.forEach(c => c.updateState());
|
||||
this.parts.forEach(c => c.updateState());
|
||||
}
|
||||
|
||||
private getBBCoord(rowCol: BBRowCol) {
|
||||
private getBBCoord(rowCol: BBLoc) {
|
||||
let bbCoord = this.breadboard.getCoord(rowCol);
|
||||
return this.fromBBCoord(bbCoord);
|
||||
}
|
||||
@ -134,7 +140,7 @@ namespace pxsim.visuals {
|
||||
public getLocCoord(loc: Loc): Coord {
|
||||
let coord: Coord;
|
||||
if (loc.type === "breadboard") {
|
||||
let rowCol = (<BBLoc>loc).rowCol;
|
||||
let rowCol = (<BBLoc>loc);
|
||||
coord = this.getBBCoord(rowCol);
|
||||
} else {
|
||||
let pinNm = (<BoardLoc>loc).pin;
|
||||
@ -147,47 +153,62 @@ namespace pxsim.visuals {
|
||||
return coord;
|
||||
}
|
||||
|
||||
public addComponent(cmpDesc: CmpInst): IBoardComponent<any> {
|
||||
let cmp: IBoardComponent<any> = null;
|
||||
public addPart(partInst: PartInst): IBoardPart<any> {
|
||||
let part: IBoardPart<any> = null;
|
||||
let colOffset = 0;
|
||||
if (typeof cmpDesc.visual === "string") {
|
||||
let builtinVisual = cmpDesc.visual as string;
|
||||
let cnstr = builtinComponentSimVisual[builtinVisual];
|
||||
let stateFn = builtinComponentSimState[builtinVisual];
|
||||
cmp = cnstr();
|
||||
cmp.init(this.state.bus, stateFn(this.state), this.view, cmpDesc.microbitPins, cmpDesc.otherArgs);
|
||||
if (partInst.simulationBehavior) {
|
||||
//TODO: seperate simulation behavior from builtin visual
|
||||
let builtinBehavior = partInst.simulationBehavior;
|
||||
let cnstr = builtinComponentSimVisual[builtinBehavior];
|
||||
let stateFn = builtinComponentSimState[builtinBehavior];
|
||||
part = cnstr();
|
||||
part.init(this.state.bus, stateFn(this.state), this.view, partInst.params);
|
||||
} else {
|
||||
let vis = cmpDesc.visual as PartVisualDefinition;
|
||||
cmp = new GenericPart(vis);
|
||||
colOffset = vis.extraColumnOffset || 0;
|
||||
let vis = partInst.visual as PartVisualDefinition;
|
||||
part = new GenericPart(vis);
|
||||
}
|
||||
this.components.push(cmp);
|
||||
this.view.appendChild(cmp.element);
|
||||
if (cmp.defs)
|
||||
cmp.defs.forEach(d => this.defs.appendChild(d));
|
||||
this.style.textContent += cmp.style || "";
|
||||
let rowCol = <BBRowCol>[`${cmpDesc.breadboardStartRow}`, `${colOffset + cmpDesc.breadboardStartColumn}`];
|
||||
this.parts.push(part);
|
||||
this.partGroup.appendChild(part.element);
|
||||
if (part.overElement)
|
||||
this.partOverGroup.appendChild(part.overElement);
|
||||
if (part.defs)
|
||||
part.defs.forEach(d => this.defs.appendChild(d));
|
||||
this.style.textContent += part.style || "";
|
||||
let colIdx = partInst.startColumnIdx;
|
||||
let rowIdx = partInst.startRowIdx;
|
||||
let row = getRowName(rowIdx);
|
||||
let col = getColumnName(colIdx);
|
||||
let xOffset = partInst.bbFit.xOffset / partInst.visual.pinDistance;
|
||||
let yOffset = partInst.bbFit.yOffset / partInst.visual.pinDistance;
|
||||
let rowCol = <BBLoc>{
|
||||
type: "breadboard",
|
||||
row: row,
|
||||
col: col,
|
||||
xOffset: xOffset,
|
||||
yOffset: yOffset
|
||||
};
|
||||
let coord = this.getBBCoord(rowCol);
|
||||
cmp.moveToCoord(coord);
|
||||
part.moveToCoord(coord);
|
||||
let getCmpClass = (type: string) => `sim-${type}-cmp`;
|
||||
let cls = getCmpClass(name);
|
||||
svg.addClass(cmp.element, cls);
|
||||
svg.addClass(cmp.element, "sim-cmp");
|
||||
cmp.updateTheme();
|
||||
cmp.updateState();
|
||||
return cmp;
|
||||
let cls = getCmpClass(partInst.name);
|
||||
svg.addClass(part.element, cls);
|
||||
svg.addClass(part.element, "sim-cmp");
|
||||
part.updateTheme();
|
||||
part.updateState();
|
||||
return part;
|
||||
}
|
||||
public addWire(inst: WireInst): Wire {
|
||||
return this.wireFactory.addWire(inst.start, inst.end, inst.color, this.useCrocClips);
|
||||
}
|
||||
public addAll(basicWiresAndCmpsAndWires: AllocatorResult) {
|
||||
let {powerWires, components} = basicWiresAndCmpsAndWires;
|
||||
powerWires.forEach(w => this.addWire(w));
|
||||
components.forEach((cAndWs, idx) => {
|
||||
let {component, wires} = cAndWs;
|
||||
wires.forEach(w => this.addWire(w));
|
||||
this.addComponent(component);
|
||||
});
|
||||
public addAll(allocRes: AllocatorResult) {
|
||||
allocRes.partsAndWires.forEach(pAndWs => {
|
||||
let part = pAndWs.part;
|
||||
if (part)
|
||||
this.addPart(part)
|
||||
let wires = pAndWs.wires;
|
||||
if (wires)
|
||||
wires.forEach(w => this.addWire(w));
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -107,10 +107,10 @@ namespace pxsim.visuals {
|
||||
}
|
||||
`
|
||||
// Pin rows and coluns
|
||||
const MID_ROWS = 10;
|
||||
export const BREADBOARD_MID_ROWS = 10;
|
||||
export const BREADBOARD_MID_COLS = 30;
|
||||
const MID_ROW_GAPS = [4, 4];
|
||||
const MID_ROW_AND_GAPS = MID_ROWS + MID_ROW_GAPS.length;
|
||||
const MID_COLS = 30;
|
||||
const MID_ROW_AND_GAPS = BREADBOARD_MID_ROWS + MID_ROW_GAPS.length;
|
||||
const BAR_ROWS = 2;
|
||||
const BAR_COLS = 25;
|
||||
const POWER_ROWS = BAR_ROWS * 2;
|
||||
@ -118,14 +118,14 @@ namespace pxsim.visuals {
|
||||
const BAR_COL_GAPS = [4, 9, 14, 19];
|
||||
const BAR_COL_AND_GAPS = BAR_COLS + BAR_COL_GAPS.length;
|
||||
// Essential dimensions
|
||||
const WIDTH = PIN_DIST * (MID_COLS + 3);
|
||||
const WIDTH = PIN_DIST * (BREADBOARD_MID_COLS + 3);
|
||||
const HEIGHT = PIN_DIST * (MID_ROW_AND_GAPS + POWER_ROWS + 5.5);
|
||||
const MID_RATIO = 2.0 / 3.0;
|
||||
const BAR_RATIO = (1.0 - MID_RATIO) * 0.5;
|
||||
const MID_HEIGHT = HEIGHT * MID_RATIO;
|
||||
const BAR_HEIGHT = HEIGHT * BAR_RATIO;
|
||||
// Pin grids
|
||||
const MID_GRID_WIDTH = (MID_COLS - 1) * PIN_DIST;
|
||||
const MID_GRID_WIDTH = (BREADBOARD_MID_COLS - 1) * PIN_DIST;
|
||||
const MID_GRID_HEIGHT = (MID_ROW_AND_GAPS - 1) * PIN_DIST;
|
||||
const MID_GRID_X = (WIDTH - MID_GRID_WIDTH) / 2.0;
|
||||
const MID_GRID_Y = BAR_HEIGHT + (MID_HEIGHT - MID_GRID_HEIGHT) / 2.0;
|
||||
@ -152,6 +152,10 @@ namespace pxsim.visuals {
|
||||
const SMALL_CHANNEL_HEIGHT = PIN_DIST * 0.05;
|
||||
// Background
|
||||
const BACKGROUND_ROUNDING = PIN_DIST * 0.3;
|
||||
// Row and column helpers
|
||||
const alphabet = "abcdefghij".split("").reverse();
|
||||
export function getColumnName(colIdx: number): string { return `${colIdx + 1}` };
|
||||
export function getRowName(rowIdx: number): string { return alphabet[rowIdx] };
|
||||
|
||||
export interface GridPin {
|
||||
el: SVGElement,
|
||||
@ -321,12 +325,14 @@ namespace pxsim.visuals {
|
||||
return null;
|
||||
return pin;
|
||||
}
|
||||
public getCoord(rowCol: BBRowCol): Coord {
|
||||
let [row, col] = rowCol;
|
||||
public getCoord(rowCol: BBLoc): Coord {
|
||||
let {row, col, xOffset, yOffset} = rowCol;
|
||||
let pin = this.getPin(row, col);
|
||||
if (!pin)
|
||||
return null;
|
||||
return [pin.cx, pin.cy];
|
||||
let xOff = (xOffset || 0) * PIN_DIST;
|
||||
let yOff = (yOffset || 0) * PIN_DIST;
|
||||
return [pin.cx + xOff, pin.cy + yOff];
|
||||
}
|
||||
|
||||
public getPinDist() {
|
||||
@ -371,14 +377,11 @@ namespace pxsim.visuals {
|
||||
mkChannel(BAR_HEIGHT + MID_HEIGHT, SMALL_CHANNEL_HEIGHT);
|
||||
|
||||
//-----pins
|
||||
const getMidTopOrBot = (rowIdx: number) => rowIdx < MID_ROWS / 2.0 ? "b" : "t";
|
||||
const getMidTopOrBot = (rowIdx: number) => rowIdx < BREADBOARD_MID_ROWS / 2.0 ? "b" : "t";
|
||||
const getBarTopOrBot = (colIdx: number) => colIdx < POWER_COLS / 2.0 ? "b" : "t";
|
||||
const alphabet = "abcdefghij".split("").reverse();
|
||||
const getColName = (colIdx: number) => `${colIdx + 1}`;
|
||||
const getMidRowName = (rowIdx: number) => alphabet[rowIdx];
|
||||
const getMidGroupName = (rowIdx: number, colIdx: number) => {
|
||||
let botOrTop = getMidTopOrBot(rowIdx);
|
||||
let colNm = getColName(colIdx);
|
||||
let colNm = getColumnName(colIdx);
|
||||
return `${botOrTop}${colNm}`;
|
||||
};
|
||||
const getBarRowName = (rowIdx: number) => rowIdx === 0 ? "-" : "+";
|
||||
@ -392,13 +395,13 @@ namespace pxsim.visuals {
|
||||
let midGridRes = mkGrid({
|
||||
xOffset: MID_GRID_X,
|
||||
yOffset: MID_GRID_Y,
|
||||
rowCount: MID_ROWS,
|
||||
colCount: MID_COLS,
|
||||
rowCount: BREADBOARD_MID_ROWS,
|
||||
colCount: BREADBOARD_MID_COLS,
|
||||
pinDist: PIN_DIST,
|
||||
mkPin: mkBBPin,
|
||||
mkHoverPin: mkBBHoverPin,
|
||||
getRowName: getMidRowName,
|
||||
getColName: getColName,
|
||||
getRowName: getRowName,
|
||||
getColName: getColumnName,
|
||||
getGroupName: getMidGroupName,
|
||||
rowIdxsWithGap: MID_ROW_GAPS,
|
||||
});
|
||||
@ -415,7 +418,7 @@ namespace pxsim.visuals {
|
||||
mkPin: mkBBPin,
|
||||
mkHoverPin: mkBBHoverPin,
|
||||
getRowName: getBarRowName,
|
||||
getColName: getColName,
|
||||
getColName: getColumnName,
|
||||
getGroupName: getBarGroupName,
|
||||
colIdxsWithGap: BAR_COL_GAPS,
|
||||
});
|
||||
@ -433,7 +436,7 @@ namespace pxsim.visuals {
|
||||
mkPin: mkBBPin,
|
||||
mkHoverPin: mkBBHoverPin,
|
||||
getRowName: getBarRowName,
|
||||
getColName: getColName,
|
||||
getColName: getColumnName,
|
||||
getGroupName: getBarGroupName,
|
||||
colIdxsWithGap: BAR_COL_GAPS.map(g => g + BAR_COLS),
|
||||
});
|
||||
@ -460,39 +463,39 @@ namespace pxsim.visuals {
|
||||
const mkBBLabelAtPin = (row: string, col: string, xOffset: number, yOffset: number, txt: string, group?: string): GridLabel => {
|
||||
let size = PIN_LBL_SIZE;
|
||||
let rotation = LBL_ROTATION;
|
||||
let loc = this.getCoord([row, col]);
|
||||
let loc = this.getCoord({type: "breadboard", row: row, col: col});
|
||||
let [cx, cy] = loc;
|
||||
let t = mkBBLabel(cx + xOffset, cy + yOffset, size, rotation, txt, group);
|
||||
return t;
|
||||
}
|
||||
|
||||
//columns
|
||||
for (let colIdx = 0; colIdx < MID_COLS; colIdx++) {
|
||||
let colNm = getColName(colIdx);
|
||||
for (let colIdx = 0; colIdx < BREADBOARD_MID_COLS; colIdx++) {
|
||||
let colNm = getColumnName(colIdx);
|
||||
//top
|
||||
let rowTIdx = 0;
|
||||
let rowTNm = getMidRowName(rowTIdx);
|
||||
let rowTNm = getRowName(rowTIdx);
|
||||
let groupT = getMidGroupName(rowTIdx, colIdx);
|
||||
let lblT = mkBBLabelAtPin(rowTNm, colNm, 0, -PIN_DIST, colNm, groupT);
|
||||
this.allLabels.push(lblT);
|
||||
//bottom
|
||||
let rowBIdx = MID_ROWS - 1;
|
||||
let rowBNm = getMidRowName(rowBIdx);
|
||||
let rowBIdx = BREADBOARD_MID_ROWS - 1;
|
||||
let rowBNm = getRowName(rowBIdx);
|
||||
let groupB = getMidGroupName(rowBIdx, colIdx);
|
||||
let lblB = mkBBLabelAtPin(rowBNm, colNm, 0, +PIN_DIST, colNm, groupB);
|
||||
this.allLabels.push(lblB);
|
||||
}
|
||||
//rows
|
||||
for (let rowIdx = 0; rowIdx < MID_ROWS; rowIdx++) {
|
||||
let rowNm = getMidRowName(rowIdx);
|
||||
for (let rowIdx = 0; rowIdx < BREADBOARD_MID_ROWS; rowIdx++) {
|
||||
let rowNm = getRowName(rowIdx);
|
||||
//top
|
||||
let colTIdx = 0;
|
||||
let colTNm = getColName(colTIdx);
|
||||
let colTNm = getColumnName(colTIdx);
|
||||
let lblT = mkBBLabelAtPin(rowNm, colTNm, -PIN_DIST, 0, rowNm);
|
||||
this.allLabels.push(lblT);
|
||||
//top
|
||||
let colBIdx = MID_COLS - 1;
|
||||
let colBNm = getColName(colBIdx);
|
||||
let colBIdx = BREADBOARD_MID_COLS - 1;
|
||||
let colBNm = getColumnName(colBIdx);
|
||||
let lblB = mkBBLabelAtPin(rowNm, colBNm, +PIN_DIST, 0, rowNm);
|
||||
this.allLabels.push(lblB);
|
||||
}
|
||||
@ -635,8 +638,8 @@ namespace pxsim.visuals {
|
||||
return {el: this.bb, y: 0, x: 0, w: WIDTH, h: HEIGHT};
|
||||
}
|
||||
|
||||
public highlightLoc(rowCol: BBRowCol) {
|
||||
let [row, col] = rowCol;
|
||||
public highlightLoc(rowCol: BBLoc) {
|
||||
let {row, col} = rowCol;
|
||||
let pin = this.rowColToPin[row][col];
|
||||
let {cx, cy} = pin;
|
||||
let lbls = this.rowColToLbls[row][col];
|
||||
|
@ -92,7 +92,7 @@ namespace pxsim.visuals {
|
||||
pointer-events:none;
|
||||
}
|
||||
`;
|
||||
export class ButtonPairView implements IBoardComponent<ButtonPairState> {
|
||||
export class ButtonPairView implements IBoardPart<ButtonPairState> {
|
||||
public element: SVGElement;
|
||||
public defs: SVGElement[];
|
||||
public style = BUTTON_PAIR_STYLE;
|
||||
|
@ -5,13 +5,13 @@ namespace pxsim.visuals {
|
||||
image: partVisual.image,
|
||||
width: partVisual.width,
|
||||
height: partVisual.height,
|
||||
imageUnitDist: partVisual.pinDist,
|
||||
imageUnitDist: partVisual.pinDistance,
|
||||
targetUnitDist: PIN_DIST
|
||||
});
|
||||
return imgAndSize;
|
||||
}
|
||||
|
||||
export class GenericPart implements IBoardComponent<any> {
|
||||
export class GenericPart implements IBoardPart<any> {
|
||||
public style: string = "";
|
||||
public element: SVGElement;
|
||||
defs: SVGElement[] = [];
|
||||
@ -19,11 +19,6 @@ namespace pxsim.visuals {
|
||||
constructor(partVisual: PartVisualDefinition) {
|
||||
let imgAndSize = mkGenericPartSVG(partVisual);
|
||||
let img = imgAndSize.el;
|
||||
let scaleFn = mkScaleFn(partVisual.pinDist, PIN_DIST);
|
||||
let [pinX, pinY] = partVisual.firstPin;
|
||||
let left = -scaleFn(pinX);
|
||||
let top = -scaleFn(pinY);
|
||||
translateEl(img, [left, top]); // So that 0,0 is on the first pin
|
||||
this.element = svg.elt("g");
|
||||
this.element.appendChild(img);
|
||||
}
|
||||
@ -33,7 +28,7 @@ namespace pxsim.visuals {
|
||||
}
|
||||
|
||||
//unused
|
||||
init(bus: EventBus, state: any, svgEl: SVGSVGElement, gpioPins: string[], otherArgs: string[]): void { }
|
||||
init(bus: EventBus, state: any, svgEl: SVGSVGElement): void { }
|
||||
updateState(): void { }
|
||||
updateTheme(): void { }
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ namespace pxsim.visuals {
|
||||
}
|
||||
`
|
||||
|
||||
export class LedMatrixView implements IBoardComponent<LedMatrixState> {
|
||||
export class LedMatrixView implements IBoardPart<LedMatrixState> {
|
||||
private background: SVGElement;
|
||||
private ledsOuter: SVGElement[];
|
||||
private leds: SVGElement[];
|
||||
|
@ -107,13 +107,12 @@ namespace pxsim.visuals {
|
||||
public cy: number;
|
||||
|
||||
constructor(xy: Coord = [0, 0]) {
|
||||
let circle = <SVGElement>svg.elt("rect");
|
||||
let el = <SVGElement>svg.elt("rect");
|
||||
let r = PIXEL_RADIUS;
|
||||
let [cx, cy] = xy;
|
||||
let y = cy - r;
|
||||
let x = 0;
|
||||
svg.hydrate(circle, { x: "-50%", y: y, width: "100%", height: r*2, class: "sim-neopixel" });
|
||||
this.el = circle;
|
||||
svg.hydrate(el, { x: "-50%", y: y, width: "100%", height: r * 2, class: "sim-neopixel" });
|
||||
this.el = el;
|
||||
this.cy = cy;
|
||||
}
|
||||
|
||||
@ -192,9 +191,15 @@ namespace pxsim.visuals {
|
||||
}
|
||||
};
|
||||
|
||||
function gpioPinToPinNumber(gpioPin: string): number {
|
||||
let pinNumStr = gpioPin.split("P")[1];
|
||||
let pinNum = Number(pinNumStr) + 7 /*MICROBIT_ID_IO_P0; TODO: don't hardcode this, import enums.d.ts*/;
|
||||
function digitalPinToPinNumber(gpioPin: string): number {
|
||||
const MICROBIT_ID_IO_P0 = 7; //TODO: don't hardcode this, import enums.d.ts
|
||||
if (gpioPin == "*") {
|
||||
return MICROBIT_ID_IO_P0;
|
||||
}
|
||||
let pinSplit = gpioPin.split("DigitalPin.P");
|
||||
U.assert(pinSplit.length === 2, "Unknown format for pin (for NeoPixel): " + gpioPin);
|
||||
let pinNumStr = pinSplit[1];
|
||||
let pinNum = Number(pinNumStr) + MICROBIT_ID_IO_P0;
|
||||
return pinNum
|
||||
}
|
||||
function parseNeoPixelMode(modeStr: string): NeoPixelMode {
|
||||
@ -214,7 +219,7 @@ namespace pxsim.visuals {
|
||||
return mode;
|
||||
}
|
||||
|
||||
export class NeoPixelView implements IBoardComponent<NeoPixelState> {
|
||||
export class NeoPixelView implements IBoardPart<NeoPixelState> {
|
||||
public style: string = `
|
||||
.sim-neopixel-canvas {
|
||||
}
|
||||
@ -232,6 +237,7 @@ namespace pxsim.visuals {
|
||||
}
|
||||
`;
|
||||
public element: SVGElement;
|
||||
public overElement: SVGElement;
|
||||
public defs: SVGElement[];
|
||||
private state: NeoPixelState;
|
||||
private canvas: NeoPixelCanvas;
|
||||
@ -241,22 +247,24 @@ namespace pxsim.visuals {
|
||||
private pin: number;
|
||||
private mode: NeoPixelMode;
|
||||
|
||||
public init(bus: EventBus, state: NeoPixelState, svgEl: SVGSVGElement, gpioPins: string[], otherArgs: string[]): void {
|
||||
U.assert(otherArgs.length === 1, "NeoPixels assumes a RGB vs RGBW mode is passed to it");
|
||||
let modeStr = otherArgs[0];
|
||||
public init(bus: EventBus, state: NeoPixelState, svgEl: SVGSVGElement, otherParams: Map<string>): void {
|
||||
U.assert(!!otherParams["mode"], "NeoPixels assumes a RGB vs RGBW mode is passed to it");
|
||||
U.assert(!!otherParams["pin"], "NeoPixels assumes a pin is passed to it");
|
||||
let modeStr = otherParams["mode"];
|
||||
this.mode = parseNeoPixelMode(modeStr);
|
||||
this.state = state;
|
||||
this.stripGroup = <SVGGElement>svg.elt("g");
|
||||
this.element = this.stripGroup;
|
||||
let pinStr = gpioPins[0];
|
||||
this.pin = gpioPinToPinNumber(pinStr);
|
||||
let pinStr = otherParams["pin"];
|
||||
this.pin = digitalPinToPinNumber(pinStr);
|
||||
this.lastLocation = [0, 0];
|
||||
let part = mkNeoPixelPart();
|
||||
this.part = part;
|
||||
this.stripGroup.appendChild(part.el);
|
||||
let canvas = new NeoPixelCanvas(this.pin);
|
||||
this.canvas = canvas;
|
||||
let canvasG = svg.child(this.stripGroup, "g", { class: "sim-neopixel-canvas-parent" });
|
||||
let canvasG = svg.elt("g", { class: "sim-neopixel-canvas-parent" });
|
||||
this.overElement = canvasG;
|
||||
canvasG.appendChild(canvas.canvas);
|
||||
this.updateStripLoc();
|
||||
}
|
||||
@ -268,6 +276,7 @@ namespace pxsim.visuals {
|
||||
}
|
||||
private updateStripLoc() {
|
||||
let [x, y] = this.lastLocation;
|
||||
U.assert(typeof x === "number" && typeof y === "number", "invalid x,y for NeoPixel strip");
|
||||
this.canvas.setLoc([x + CANVAS_LEFT, y + CANVAS_TOP]);
|
||||
svg.hydrate(this.part.el, { transform: `translate(${x} ${y})` }); //TODO: update part's l,h, etc.
|
||||
}
|
||||
|
@ -455,7 +455,7 @@ namespace pxsim.visuals {
|
||||
let wireEls: Wire;
|
||||
if (withCrocs && end.type == "dalboard") {
|
||||
let boardPin = (<BoardLoc>end).pin;
|
||||
if (boardPin == "P0" || boardPin == "P1" || boardPin == "P0" || boardPin == "GND" || boardPin == "+3v3" ) {
|
||||
if (boardPin == "P0" || boardPin == "P1" || boardPin == "P2" || boardPin == "GND" || boardPin == "+3v3" ) {
|
||||
//HACK
|
||||
wireEls = this.drawWireWithCrocs(startLoc, endLoc, color);
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user