diff --git a/src/activities/activities.txt b/src/activities/activities.txt --- a/src/activities/activities.txt +++ b/src/activities/activities.txt @@ -9,6 +9,7 @@ align4 align4-2players alphabet-sequence +analog_electricity babymatch babyshapes baby_wordprocessor @@ -121,8 +122,8 @@ numbers-odd-even paintings penalty -piano_composition photo_hunter +piano_composition planegame play_piano play_rhythm diff --git a/src/activities/analog_electricity/ActivityInfo.qml b/src/activities/analog_electricity/ActivityInfo.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/ActivityInfo.qml @@ -0,0 +1,40 @@ +/* GCompris - ActivityInfo.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import GCompris 1.0 + +ActivityInfo { + name: "analog_electricity/Analog_electricity.qml" + difficulty: 1 + icon: "analog_electricity/analog_electricity.svg" + author: "Deepak Kumar <deepakdk2431@gmail.com>" + demo: true + //: Activity title + title: qsTr("Analog electricity") + //: Help title + description: qsTr("Create and simulate an electric schema.") + //intro: "put here in comment the text for the intro voice" + //: Help goal + goal: qsTr("Freely create an electric schema with a real time simulation of it.") + //: Help prerequisite + prerequisite: qsTr("Requires some basic understanding of the concept of electricity.") + //: Help manual + manual: qsTr("Drag electrical components from the selector and drop them in the working area. Create wires by clicking on a connection spot, dragging the mouse to the next connection spot, and letting go. You can also move components by dragging them. You can delete wires by clicking on them. To delete a component, select the deletion tool on top of the component selector. You can click on the switch to open and close it. You can change the rheostat value by dragging its wiper. In order to simulate what happens when a bulb is blown, you can blown it by right-clicking on it. The simulation is updated in real time by any user action.") + credit: "" + section: "experimental" + createdInVersion: 9000 +} diff --git a/src/activities/analog_electricity/Analog_electricity.qml b/src/activities/analog_electricity/Analog_electricity.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/Analog_electricity.qml @@ -0,0 +1,408 @@ +/* GCompris - Analog_Electricity.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 + +import "../../core" +import "analog_electricity.js" as Activity + +ActivityBase { + id: activity + + onStart: focus = true + onStop: {} + + property string mode: "tutorial" + property bool isTutorialMode: mode == "tutorial" ? true : false + + pageComponent: Image { + id: background + anchors.fill: parent + source: Activity.url + "texture02.png" + fillMode: Image.Tile + signal start + signal stop + + property bool hori: background.width >= background.height + + Component.onCompleted: { + dialogActivityConfig.getInitialConfiguration() + activity.start.connect(start) + activity.stop.connect(stop) + } + + Keys.onPressed: { + if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && okButton.enabled) { + Activity.checkAnswer() + } + if (event.key === Qt.Key_Plus) { + Activity.zoomIn() + } + if (event.key === Qt.Key_Minus) { + Activity.zoomOut() + } + if (event.key === Qt.Key_Right) { + playArea.x -= 200; + } + if (event.key === Qt.Key_Left) { + playArea.x += 200 + } + if (event.key === Qt.Key_Up) { + playArea.y += 200 + } + if (event.key === Qt.Key_Down) { + playArea.y -= 200 + } + if (playArea.x >= mousePan.drag.maximumX) { + playArea.x = mousePan.drag.maximumX + } + if (playArea.y >= mousePan.drag.maximumY) { + playArea.y = mousePan.drag.maximumY + } + if (playArea.x <= mousePan.drag.minimumX) { + playArea.x = mousePan.drag.minimumX + } + if (playArea.y <= mousePan.drag.minimumY) { + playArea.y = mousePan.drag.minimumY + } + } + + onHoriChanged: { + if (hori == true) { + playArea.x += items.toolsMargin + playArea.y -= items.toolsMargin + } else { + playArea.x -= items.toolsMargin + playArea.y += items.toolsMargin + } + } + + // Add here the QML items you need to access in javascript + QtObject { + id: items + property Item main: activity.main + property alias playArea: playArea + property alias mousePan: mousePan + property alias bar: bar + property alias bonus: bonus + property alias availablePieces: availablePieces + property alias toolTip: toolTip + property alias infoTxt: infoTxt + property alias dataset: dataset + property alias tutorialDataset: tutorialDataset + property alias infoImage: infoImage + property bool isTutorialMode: activity.isTutorialMode + property alias tutorialInstruction: tutorialInstruction + property real toolsMargin: 90 * ApplicationInfo.ratio + property real zoomLvl: 0.25 + } + + Loader { + id: dataset + asynchronous: false + } + + Dataset { + id: tutorialDataset + } + + IntroMessage { + id: tutorialInstruction + intro: [] + textContainerWidth: background.hori ? parent.width - inputComponentsContainer.width - items.toolsMargin : 0.9 * background.width + textContainerHeight: background.hori ? 0.5 * parent.height : parent.height - inputComponentsContainer.height - (bar.height * 2) - items.toolsMargin + anchors { + fill: undefined + top: background.hori ? parent.top : inputComponentsContainer.bottom + topMargin: 10 + right: parent.right + rightMargin: 5 + left: background.hori ? inputComponentsContainer.right : parent.left + leftMargin: 5 + } + z: 5 + } + + onStart: { Activity.start(items) } + onStop: { Activity.stop() } + + Rectangle { + id: visibleArea + color: "#00000000" + width: background.hori ? background.width - items.toolsMargin - 10 : background.width - 10 + height: background.hori ? background.height - bar.height - items.toolsMargin - 10 : background.height - bar.height - 10 + anchors { + fill: undefined + top: background.hori ? parent.top : inputComponentsContainer.bottom + topMargin: 5 + right: parent.right + rightMargin: 5 + left: background.hori ? inputComponentsContainer.right : parent.left + leftMargin: 5 + bottom: bar.top + bottomMargin: 20 + } + z: 6 + + GCText { + id: infoTxt + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: 2 + } + fontSizeMode: Text.Fit + minimumPixelSize: 10 + font.pixelSize: 150 + color: "white" + horizontalAlignment: Text.AlignHLeft + width: mediumSize + height: mediumSize + wrapMode: TextEdit.WordWrap + visible: false + z: 4 + } + + Rectangle { + id: infoTxtContainer + anchors.fill: parent + opacity: 1 + radius: 10 + color: "#373737" + border.width: 2 + border.color: "#F2F2F2" + visible: infoTxt.visible + MouseArea { + anchors.fill: parent + onClicked: infoTxt.visible = false + } + z: 3 + } + + Image { + id: infoImage + property bool imgVisible: false + height: source == "" ? 0 : parent.height * 0.3 - 10 + width: source == "" ? 0 : parent.width - 10 + fillMode: Image.PreserveAspectFit + visible: infoTxt.visible && imgVisible + anchors { + top: infoTxt.bottom + horizontalCenter: infoTxtContainer.horizontalCenter + } + z: 5 + } + } + + Rectangle { + id: playArea + color: "#10000000" + x: background.hori ? items.toolsMargin : 0 + y: background.hori ? 0 : items.toolsMargin + width: background.hori ? + background.width * 4 - items.toolsMargin : background.width * 4 + height: background.hori ? + background.height * 4 - (bar.height * 1.1) : + background.height * 4 - (bar.height * 1.1) - items.toolsMargin + + PinchArea { + id: pinchZoom + anchors.fill: parent + onPinchFinished: { + if (pinch.scale < 1) { + Activity.zoomOut() + } + if (pinch.scale > 1) { + Activity.zoomIn() + } + } + MouseArea { + id: mousePan + anchors.fill: parent + scrollGestureEnabled: false //needed for pinchZoom + drag.target: playArea + drag.axis: Drag.XandYAxis + drag.minimumX: - playArea.width * items.zoomLvl + drag.maximumX: background.hori ? items.toolsMargin : 0 + drag.minimumY: - playArea.height * items.zoomLvl + drag.maximumY: background.hori ? 0 : items.toolsMargin + onClicked: { + Activity.deselect() + availablePieces.hideToolbar() + } + } + } + } + + Rectangle { + id: inputComponentsContainer + width: background.hori ? + items.toolsMargin : + background.width + height: background.hori ? + background.height : + items.toolsMargin + color: "#4A3823" + anchors.left: parent.left + Image { + anchors.fill: parent + anchors.rightMargin: background.hori ? 3 * ApplicationInfo.ratio : 0 + anchors.bottomMargin: background.hori ? 0 : 3 * ApplicationInfo.ratio + source: Activity.url + "texture01.png" + fillMode: Image.Tile + ListWidget { + id: availablePieces + hori: background.hori + } + } + z: 10 + } + + Rectangle { + id: toolTip + anchors { + bottom: bar.top + bottomMargin: 10 + left: inputComponentsContainer.left + leftMargin: 5 + } + width: toolTipTxt.width + 10 + height: toolTipTxt.height + 5 + color: "#373737" + opacity: 1 + radius: 10 + z: 100 + border.width: 2 + border.color: "#F2F2F2" + property alias text: toolTipTxt.text + Behavior on opacity { NumberAnimation { duration: 120 } } + + function show(newText) { + if(newText) { + text = newText + opacity = 1 + } else { + opacity = 0 + } + } + + GCText { + id: toolTipTxt + anchors.centerIn: parent + fontSize: regularSize + color: "white" + horizontalAlignment: Text.AlignHCenter + wrapMode: TextEdit.WordWrap + } + } + + DialogActivityConfig { + id: dialogActivityConfig + currentActivity: activity + content: Component { + Item { + property alias modesComboBox: modesComboBox + + property var availableModes: [ + { "text": qsTr("Tutorial Mode"), "value": "tutorial" }, + { "text": qsTr("Free Mode"), "value": "free" }, + ] + + Flow { + id: flow + spacing: 5 + width: dialogActivityConfig.width + GCComboBox { + id: modesComboBox + model: availableModes + background: dialogActivityConfig + label: qsTr("Select your Mode") + } + } + } + } + + onClose: home(); + + onLoadData: { + if(dataToSave && dataToSave["modes"]) { + activity.mode = dataToSave["modes"]; + } + } + + onSaveData: { + var newMode = dialogActivityConfig.configItem.availableModes[dialogActivityConfig.configItem.modesComboBox.currentIndex].value; + if (newMode !== activity.mode) { + activity.mode = newMode; + dataToSave = {"modes": activity.mode}; + Activity.reset() + } + } + + function setDefaultValues() { + for(var i = 0 ; i < dialogActivityConfig.configItem.availableModes.length; i ++) { + if(dialogActivityConfig.configItem.availableModes[i].value === activity.mode) { + dialogActivityConfig.configItem.modesComboBox.currentIndex = i; + break; + } + } + } + } + + DialogHelp { + id: dialogHelp + onClose: home() + } + + BarButton { + id: okButton + visible: activity.isTutorialMode + anchors { + bottom: bar.top + right: parent.right + rightMargin: 10 * ApplicationInfo.ratio + bottomMargin: height * 0.5 + } + source: "qrc:/gcompris/src/core/resource/bar_ok.svg" + sourceSize.width: 60 * ApplicationInfo.ratio + enabled: !tutorialInstruction.visible + onClicked: Activity.checkAnswer() + } + + Bar { + id: bar + content: BarEnumContent { value: help | home | ( activity.isTutorialMode ? level : 0) | reload | config} + onHelpClicked: {displayDialog(dialogHelp)} + onPreviousLevelClicked: Activity.previousLevel() + onNextLevelClicked: Activity.nextLevel() + onHomeClicked: activity.home() + onReloadClicked: Activity.reset() + onConfigClicked: { + dialogActivityConfig.active = true + dialogActivityConfig.setDefaultValues() + displayDialog(dialogActivityConfig) + } + } + + Bonus { + id: bonus + Component.onCompleted: win.connect(Activity.nextLevel) + } + } + +} diff --git a/src/activities/analog_electricity/Battery.qml b/src/activities/analog_electricity/Battery.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/Battery.qml @@ -0,0 +1,47 @@ +/* GCompris - Battery.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 +import "analog_electricity.js" as Activity + +ElectricalComponent { + id: digitalLight + terminalSize: 0.1 + noOfNodes: 2 + property var positionY: [1.07, 0.005] + + information: qsTr("") + + + property alias nodes: nodes + + Repeater { + id: nodes + model: 2 + delegate: node + Component { + id: node + TerminalPoint { + posX: 0.65 + posY: positionY[index] + type: "In" + } + } + } + +} diff --git a/src/activities/analog_electricity/Bulb.qml b/src/activities/analog_electricity/Bulb.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/Bulb.qml @@ -0,0 +1,47 @@ +/* GCompris - Bulb.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 +import "analog_electricity.js" as Activity + +ElectricalComponent { + id: digitalLight + terminalSize: 0.1 + noOfNodes: 2 + property var positionX: [0.8, 0.2] + + information: qsTr("A light bulb is a device that produces light from electricity.") + + + property alias nodes: nodes + + Repeater { + id: nodes + model: 2 + delegate: node + Component { + id: node + TerminalPoint { + posX: positionX[index] + posY: 1.0 + type: "Out" + } + } + } + +} diff --git a/src/activities/analog_electricity/CMakeLists.txt b/src/activities/analog_electricity/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/CMakeLists.txt @@ -0,0 +1 @@ +GCOMPRIS_ADD_RCC(activities/analog_electricity *.qml *.svg *.js resource/*) diff --git a/src/activities/analog_electricity/Dataset.qml b/src/activities/analog_electricity/Dataset.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/Dataset.qml @@ -0,0 +1,51 @@ +/* GCompris - Dataset.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . +*/ +import QtQuick 2.6 + +QtObject { + property var bulb: { + 'imageName': 'bulb1.png', + 'componentSource': 'Bulb.qml', + 'width': 0.4, + 'height': 0.4, + 'toolTipText': qsTr("Bulb") + } + property var battery: { + 'imageName': 'battery.png', + 'componentSource': 'Battery.qml', + 'width': 0.4, + 'height': 0.4, + 'toolTipText': qsTr("Battery") + } + // List of all components + property var componentList: [bulb, battery] + // tutorial levels + property var tutorialLevels: [ + // level 1 + { + inputComponentList: [battery, bulb], + playAreaComponentList: [battery], + playAreaComponentPositionX: [0.4], + playAreaComponentPositionY: [0.3], + introMessage: [ + qsTr("The bulb will glow when both of its terminal is connected to the battery.") + ] + } + ] + +} diff --git a/src/activities/analog_electricity/DragListItem.qml b/src/activities/analog_electricity/DragListItem.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/DragListItem.qml @@ -0,0 +1,132 @@ +/* GCompris - DragListItem.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 +import "analog_electricity.js" as Activity + +Item { + id: item + + width: tile.width + height: tile.height + + property string source: componentSrc + property string imageName: imgName + property string toolTipTxt: toolTipText + property double imageWidth: imgWidth + property double imageHeight: imgHeight + property double heightInColumn + property double widthInColumn + property double tileWidth + property double tileHeight + property bool selected: false + + signal pressed + + Rectangle { + id: tile + width: tileWidth + height: tileHeight + color: (parent.selected && tileImage.parent == tile) ? "#33FF294D" : "transparent" + border.color: (parent.selected && tileImage.parent == tile) ? "white" : "transparent" + border.width: 3 + radius: 2 + + property double xCenter: tile.x + tile.width / 2 + property double yCenter: tile.y + tile.height / 2 + property bool selected: false + + Image { + anchors.centerIn: parent + width: widthInColumn + height: heightInColumn + fillMode: Image.PreserveAspectFit + source: Activity.url + imgName + } + + Image { + id: tileImage + anchors.centerIn: parent + width: smallWidth + height: smallHeight + fillMode: Image.PreserveAspectFit + source: Activity.url + imgName + mipmap: true + antialiasing: true + + property double smallWidth: widthInColumn + property double smallHeight: heightInColumn + property double fullWidth: imgWidth * playArea.width + property double fullHeight: imgHeight * playArea.height + property QtObject tileImageParent + property bool small: true + + function toSmall() { + width = smallWidth + height = smallHeight + small = true + } + + function toFull() { + width = fullWidth * Activity.currentZoom + height = fullHeight * Activity.currentZoom + small = false + } + + MultiPointTouchArea { + id: mouseArea + touchPoints: [ TouchPoint { id: point1 } ] + property real startX + property real startY + property bool pressedOnce + + anchors.fill: parent + + onPressed: { + tileImage.anchors.centerIn = undefined + startX = point1.x + startY = point1.y + tileImage.toFull() + toolTip.show(toolTipText) + pressedOnce = true + item.selected = true + } + + onUpdated: { + var moveX = point1.x - startX + var moveY = point1.y - startY + parent.x = parent.x + moveX + parent.y = parent.y + moveY + } + + onReleased: { + if (pressedOnce) { + pressedOnce = false + item.selected = false + var coord = playArea.mapFromItem(tileImage.parent, parent.x, parent.y) + if(coord.x > 0 && ((playArea.width/Activity.currentZoom) - coord.x > tileImage.fullWidth)) + Activity.createComponent(coord.x, coord.y, index) + tileImage.anchors.centerIn = tile + tileImage.toSmall() + toolTip.show("") + } + } + } + } + } +} diff --git a/src/activities/analog_electricity/ElectricalComponent.qml b/src/activities/analog_electricity/ElectricalComponent.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/ElectricalComponent.qml @@ -0,0 +1,133 @@ +/* GCompris - ElectricalComponent.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 + +import "analog_electricity.js" as Activity + +Image { + id: electricalComponent + property double posX + property double posY + property double imgWidth + property double imgHeight + property string imgSrc + property string information + property string toolTipTxt + property int index + property int noOfNodes + property int rotationAngle: 0 + property int initialAngle: 0 + property int startingAngle: 0 + property double terminalSize + property bool destructible + + property alias rotateComponent: rotateComponent + + x: posX * parent.width + y: posY * parent.height + width: imgWidth * parent.width + height: imgHeight * parent.height + fillMode: Image.PreserveAspectFit + + source: Activity.url + imgSrc + z: 2 + mipmap: true + antialiasing: true + + onPaintedWidthChanged: { + updateDragConstraints() + } + + + PropertyAnimation { + id: rotateComponent + target: electricalComponent + property: "rotation" + from: initialAngle; to: initialAngle + rotationAngle + duration: 1 + onStarted:{ Activity.animationInProgress = true } + onStopped: { + initialAngle = initialAngle + rotationAngle + Activity.updateWires(index) + if(initialAngle == startingAngle + rotationAngle * 45) { + if(initialAngle == 360 || initialAngle == -360) + initialAngle = 0 + startingAngle = initialAngle + Activity.animationInProgress = false + updateDragConstraints() + } + else + rotateComponent.start() + } + easing.type: Easing.InOutQuad + } + + function updateDragConstraints() { + if(initialAngle == 0 || initialAngle == 180 || initialAngle == 360 || initialAngle == -360 + || initialAngle == -180) { + mouseArea.drag.minimumX = (electricalComponent.paintedWidth - electricalComponent.width)/2 + mouseArea.drag.minimumY = (electricalComponent.paintedHeight - electricalComponent.height)/2 + + mouseArea.drag.maximumX = electricalComponent.parent.width - + (electricalComponent.width + electricalComponent.paintedWidth)/2 + mouseArea.drag.maximumY = electricalComponent.parent.height - + (electricalComponent.height + electricalComponent.paintedHeight)/2 + } + else { + mouseArea.drag.minimumX = (electricalComponent.paintedHeight - electricalComponent.width)/2 + mouseArea.drag.minimumY = (electricalComponent.paintedWidth - electricalComponent.height)/2 + + mouseArea.drag.maximumX = electricalComponent.parent.width - + (electricalComponent.width + electricalComponent.paintedHeight)/2 + mouseArea.drag.maximumY = electricalComponent.parent.height - + (electricalComponent.height + electricalComponent.paintedWidth)/2 + } + } + + + MouseArea { + id: mouseArea + width: parent.paintedWidth + height: parent.paintedHeight + anchors.centerIn: parent + drag.target: electricalComponent + onPressed: { + Activity.updateToolTip(toolTipTxt) + Activity.componentSelected(index) + } + onClicked: { + if(Activity.toolDelete || Activity.toolDeleteSticky) { + if (destructible) { + Activity.removeComponent(index) + } else { + Activity.deselect() + } + } + } + onReleased: { + parent.posX = parent.x / parent.parent.width + parent.posY = parent.y / parent.parent.height + Activity.updateToolTip("") + } + + onPositionChanged: { + updateDragConstraints() + } + } +} diff --git a/src/activities/analog_electricity/ListWidget.qml b/src/activities/analog_electricity/ListWidget.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/ListWidget.qml @@ -0,0 +1,417 @@ +/* GCompris - ListWidget.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 +import "../../core" +import "analog_electricity.js" as Activity + +Item { + id: listWidget + anchors.fill: parent + anchors.topMargin: 5 * ApplicationInfo.ratio + anchors.leftMargin: 5 * ApplicationInfo.ratio + z: 10 + + property bool hori + property alias model: mymodel + property alias view: view + property alias repeater: repeater + property alias toolDelete: toolDelete + property alias rotateLeft: rotateLeft + property alias rotateRight: rotateRight + property alias info: info + property alias zoomInBtn: zoomInBtn + property alias zoomOutBtn: zoomOutBtn + + signal hideToolbar + onHideToolbar: toolButton.showToolBar = false + + property int minIconWidth: listWidget.hori ? Math.min((background.width - 1.5*view.width) / 6, 100) : Math.min((background.height - 1.5*bar.height - view.height) / 6, 100) + + ListModel { + id: mymodel + } + + Grid { + id: view + width: listWidget.hori ? inputComponentsContainer.width : 2 * bar.height + height: listWidget.hori ? background.height - 2 * bar.height : bar.height + spacing: 5 + z: 20 + columns: listWidget.hori ? 1 : nbItemsByGroup + 2 + + property int currentDisplayedGroup: 0 + property int setCurrentDisplayedGroup: 0 + property int nbItemsByGroup: + listWidget.hori ? + parent.height / iconSize - 2 : + parent.width / iconSize - 2 + + property int nbDisplayedGroup: Math.ceil(model.count / nbItemsByGroup) + property int iconSize: 80 * ApplicationInfo.ratio + property int previousNavigation: 1 + property int nextNavigation: 1 + + onNbDisplayedGroupChanged: { + view.setCurrentDisplayedGroup = 0 + refreshInputComponentsContainer() + } + + add: Transition { + NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 } + NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 } + } + + move: Transition { + NumberAnimation { properties: "x,y"; duration: 400; easing.type: Easing.OutBounce } + } + + //For setting navigation buttons + function setNextNavigation() { + nextNavigation = 0 + if(currentDisplayedGroup + 1 < nbDisplayedGroup) + nextNavigation = 1 + } + + function setPreviousNavigation() { + previousNavigation = 0 + if(currentDisplayedGroup > 0) + previousNavigation = 1 + } + + function refreshInputComponentsContainer() { + availablePieces.view.currentDisplayedGroup = availablePieces.view.setCurrentDisplayedGroup + availablePieces.view.setNextNavigation() + availablePieces.view.setPreviousNavigation() + } + + Image { + id: toolButton + width: (listWidget.hori ? listWidget.width : listWidget.height) - listWidget.anchors.leftMargin + height: width + sourceSize.width: width + sourceSize.height: height + source: Activity.url + "tools.svg" + fillMode: Image.PreserveAspectFit + + property bool showToolBar: false + + MouseArea { + anchors.fill: parent + onClicked: toolButton.showToolBar = !toolButton.showToolBar + } + + Rectangle { + id: toolsContainer + visible: toolButton.showToolBar + width: listWidget.hori ? (toolDelete.width + tools.spacing) * tools.children.length + tools.spacing * 4 : parent.width + height: listWidget.hori ? parent.width : (toolDelete.height + tools.spacing) * tools.children.length + tools.spacing * 4 + anchors.top: listWidget.hori ? parent.top : parent.bottom + anchors.left: listWidget.hori ? parent.right : parent.left + color: "#2a2a2a" + radius: 4 * ApplicationInfo.ratio + + Flow { + id: tools + width: parent.width + height: parent.height + + property int topMarginAmt: (toolsContainer.height - toolDelete.height) / 2 + property int leftMarginAmt: (toolsContainer.width - toolDelete.width) / 2 + + anchors { + fill: parent + leftMargin: listWidget.hori ? 8 * ApplicationInfo.ratio : tools.leftMarginAmt + topMargin: listWidget.hori ? tools.topMarginAmt : 8 * ApplicationInfo.ratio + } + spacing: 4 * ApplicationInfo.ratio + + Image { + id: toolDelete + state: "notSelected" + width: minIconWidth + height: width + sourceSize.width: width + sourceSize.height: height + source: Activity.url + "deleteOn.svg" + fillMode: Image.PreserveAspectFit + MouseArea { + anchors.fill: parent + onClicked: { + toolDelete.state = (toolDelete.state == "selected") ? "notSelected" : "selected" + Activity.toolDelete = !Activity.toolDelete + Activity.toolDeleteSticky = false + } + onDoubleClicked: { + Activity.toolDeleteSticky = true + Activity.toolDelete = true + toolDelete.state = "selected" + } + } + states: [ + State { + name: "selected" + PropertyChanges { + target: toolDelete + opacity: 1 + } + }, + State { + name: "notSelected" + PropertyChanges { + target: toolDelete + opacity: 0.5 + } + } + ] + } + + Image { + id: info + source: Activity.url + "info.svg" + width: minIconWidth + height: width + sourceSize.width: width + sourceSize.height: height + fillMode: Image.PreserveAspectFit + MouseArea { + anchors.fill: parent + onClicked: { + if(!Activity.animationInProgress && parent.state == "canBeSelected") { + Activity.displayInfo() + hideToolbar() + } + } + } + states: [ + State { + name: "canBeSelected" + PropertyChanges { + target: info + opacity: 1 + } + }, + State { + name: "canNotBeSelected" + PropertyChanges { + target: info + opacity: 0.5 + } + } + ] + } + + Image { + id: rotateLeft + width: minIconWidth + height: width + sourceSize.width: width + sourceSize.height: height + source: Activity.url + "rotate.svg" + fillMode: Image.PreserveAspectFit + state: "CanNotBeSelected" + MouseArea { + anchors.fill: parent + onClicked: { + if(!Activity.animationInProgress && parent.state == "canBeSelected") { + Activity.rotateLeft() + } + } + } + states: [ + State { + name: "canBeSelected" + PropertyChanges { + target: rotateLeft + opacity: 1 + } + }, + State { + name: "canNotBeSelected" + PropertyChanges { + target: rotateLeft + opacity: 0.5 + } + } + ] + } + + Image { + id: rotateRight + width: minIconWidth + height: width + sourceSize.width: width + sourceSize.height: height + source: Activity.url + "rotate.svg" + fillMode: Image.PreserveAspectFit + mirror: true + state: "CanNotBeSelected" + MouseArea { + anchors.fill: parent + onClicked: { + if(!Activity.animationInProgress && parent.state == "canBeSelected") { + Activity.rotateRight() + } + } + } + states: [ + State { + name: "canBeSelected" + PropertyChanges{ + target: rotateRight + opacity: 1 + } + }, + State { + name: "canNotBeSelected" + PropertyChanges { + target: rotateRight + opacity: 0.5 + } + } + ] + } + + Image { + id: zoomInBtn + width: minIconWidth + height: width + sourceSize.width: width + sourceSize.height: height + source: Activity.url + "zoomIn.svg" + fillMode: Image.PreserveAspectFit + + MouseArea { + anchors.fill: parent + onClicked: Activity.zoomIn() + } + states: [ + State { + name: "canZoomIn" + PropertyChanges { + target: zoomInBtn + opacity: 1.0 + } + }, + State { + name: "cannotZoomIn" + PropertyChanges { + target: zoomInBtn + opacity: 0.5 + } + } + ] + } + + Image { + id: zoomOutBtn + width: minIconWidth + height: width + sourceSize.width: width + sourceSize.height: height + source: Activity.url + "zoomOut.svg" + fillMode: Image.PreserveAspectFit + + MouseArea { + anchors.fill: parent + onClicked: Activity.zoomOut() + } + states: [ + State { + name: "canZoomOut" + PropertyChanges { + target: zoomOutBtn + opacity: 1.0 + } + }, + State { + name: "cannotZoomOut" + PropertyChanges { + target: zoomOutBtn + opacity: 0.5 + } + } + ] + } + } + } + } + + Repeater { + id: repeater + property int currentIndex + width: 100 + DragListItem { + id: contactsDelegate + z: 1 + heightInColumn: view.iconSize * 0.75 + widthInColumn: view.iconSize * 0.85 + tileWidth: view.iconSize + tileHeight: view.iconSize * 0.85 + visible: view.currentDisplayedGroup * view.nbItemsByGroup <= index && + index <= (view.currentDisplayedGroup+1) * view.nbItemsByGroup-1 + + onPressed: repeater.currentIndex = index + } + + clip: true + model: mymodel + + onModelChanged: repeater.currentIndex = -1 + } + + Row { + spacing: view.iconSize * 0.20 + Image { + id: previous + opacity: (model.count > view.nbItemsByGroup && + view.previousNavigation != 0 && view.currentDisplayedGroup != 0) ? 1 : 0 + source: "qrc:/gcompris/src/core/resource/bar_previous.svg" + sourceSize.width: view.iconSize * 0.30 + fillMode: Image.PreserveAspectFit + MouseArea { + anchors.fill: parent + onClicked: { + repeater.currentIndex = -1 + if(previous.opacity == 1) { + view.setCurrentDisplayedGroup = view.currentDisplayedGroup - view.previousNavigation + view.refreshInputComponentsContainer() + } + } + } + } + + Image { + id: next + visible: model.count > view.nbItemsByGroup && view.nextNavigation != 0 && view.currentDisplayedGroup < + view.nbDisplayedGroup - 1 + source: "qrc:/gcompris/src/core/resource/bar_next.svg" + sourceSize.width: view.iconSize * 0.30 + fillMode: Image.PreserveAspectFit + MouseArea { + anchors.fill: parent + onClicked: { + repeater.currentIndex = -1 + view.setCurrentDisplayedGroup = view.currentDisplayedGroup + view.nextNavigation + view.refreshInputComponentsContainer() + } + } + } + } + } +} diff --git a/src/activities/digital_electricity/components/TerminalPoint.qml b/src/activities/analog_electricity/TerminalPoint.qml copy from src/activities/digital_electricity/components/TerminalPoint.qml copy to src/activities/analog_electricity/TerminalPoint.qml --- a/src/activities/digital_electricity/components/TerminalPoint.qml +++ b/src/activities/analog_electricity/TerminalPoint.qml @@ -1,37 +1,34 @@ /* GCompris - TerminalPoint.qml * - * Copyright (C) 2016 Pulkit Gupta + * Copyright (C) 2019 Deepak Kumar * - * Authors: - * Bruno Coudoin (GTK+ version) - * Pulkit Gupta (Qt Quick port) + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 -import "../digital_electricity.js" as Activity +import "../../core" +import "analog_electricity.js" as Activity Image { id: terminalPoint property double posX property double posY property double size: parent.terminalSize property bool selected: false - property string type + property string type property int value: 0 property var wires: [] @@ -42,8 +39,9 @@ sourceSize.height: width antialiasing: true - x: (parent.width - parent.paintedWidth) / 2 + posX * parent.paintedWidth - width / 2 - y: (parent.height - parent.paintedHeight) / 2 + posY * parent.paintedHeight - height / 2 + + x: (parent.width - parent.paintedWidth) / 2 + posX * parent.paintedWidth - width + y: (parent.height - parent.paintedHeight) / 2 + posY * parent.paintedHeight - height property double xCenter: terminalPoint.parent.x + terminalPoint.x + width/2 property double yCenter: terminalPoint.parent.y + terminalPoint.y + height/2 @@ -55,7 +53,7 @@ anchors.centerIn: terminalPoint width: terminalPoint.width * 2 height: width - visible: selected + visible: true radius: width / 2 color: "#08D050" z: -1 diff --git a/src/activities/analog_electricity/Wire.qml b/src/activities/analog_electricity/Wire.qml new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/Wire.qml @@ -0,0 +1,47 @@ +/* GCompris - Wire.qml + * + * Copyright (C) 2019 Deepak Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 + +import "analog_electricity.js" as Activity + +Rectangle { + id: wire + + property QtObject from + property QtObject to + property bool destructible + + height: 5 * ApplicationInfo.ratio + color: from.value == 0 ? "#d21818" : "#6ce76c" + radius: height / 2 + transformOrigin: Item.Left + + MouseArea { + id: mouseArea + enabled: destructible + width: parent.width + height: parent.height * 3 + anchors.centerIn: parent + onPressed: { + if(Activity.toolDelete) { + Activity.removeWire(wire) + } + } + } +} diff --git a/src/activities/analog_electricity/analog_electricity.js b/src/activities/analog_electricity/analog_electricity.js new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/analog_electricity.js @@ -0,0 +1,356 @@ +/* GCompris - analog_electricity.js + * + * Copyright (C) 2019 Deepak Kumar + * + * Authors: + * Bruno Coudoin (GTK+ version) + * Pulkit Gupta (Qt Quick port) + * Rudra Nil Basu (Qt Quick port) + * Timothée Giet (mouse drag refactoring) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +.pragma library +.import QtQuick 2.6 as Quick + +var currentLevel = 1 +var numberOfLevel +var items +var url = "qrc:/gcompris/src/activities/analog_electricity/resource/" +var toolDelete +var toolDeleteSticky +var selectedIndex +var animationInProgress +var selectedTerminal +var deletedIndex = [] +var components = [] +var connected = [] +var determiningComponents = [] +var processingAnswer + +var currentZoom +var maxZoom = 0.375 +var minZoom = 0.125 +var defaultZoom = 0.25 +var zoomStep = 0.0625 + +var direction = { + LEFT: -1, + RIGHT: 1, + UP: -2, + DOWN: 2 +} + +var viewPort = { + leftExtreme: 0, + rightExtreme: 1, + topExtreme: 0, + bottomExtreme: 1, + leftEdge: 0, + topEdge: 0 +} + +function start(items_) { + items = items_ + currentLevel = 1 + numberOfLevel = items.tutorialDataset.tutorialLevels.length + initLevel() +} + +function stop() { + for(var i = 0 ; i < components.length ; ++i) { + var j + for(j = 0 ; j < deletedIndex.length ; ++j) { + if(deletedIndex[j] == i) + break + } + if(j == deletedIndex.length) + removeComponent(i) + } +} + +function initLevel() { + items.bar.level = currentLevel + + items.availablePieces.view.currentDisplayedGroup = 0 + items.availablePieces.view.previousNavigation = 1 + items.availablePieces.view.nextNavigation = 1 + deletedIndex = [] + components = [] + connected = [] + animationInProgress = false + toolDelete = false + toolDeleteSticky = false + deselect() + updateToolTip("") + items.availablePieces.hideToolbar() + + currentZoom = defaultZoom + items.availablePieces.zoomInBtn.state = "canZoomIn" + items.availablePieces.zoomOutBtn.state = "canZoomOut" + viewPort.leftEdge = 0 + viewPort.topEdge = 0 + items.playArea.x = items.mousePan.drag.maximumX + items.playArea.y = items.mousePan.drag.maximumY + + if (!items.isTutorialMode) { + items.tutorialInstruction.index = -1 + loadFreeMode() + } else { + // load tutorial levels from dataset + var levelProperties = items.tutorialDataset.tutorialLevels[currentLevel - 1] + + for (var i = 0; i < levelProperties.inputComponentList.length; i++) { + var currentInputComponent = levelProperties.inputComponentList[i] + items.availablePieces.model.append( { + "imgName": currentInputComponent.imageName, + "componentSrc": currentInputComponent.componentSource, + "imgWidth": currentInputComponent.width, + "imgHeight": currentInputComponent.height, + "toolTipText": currentInputComponent.toolTipText + }) + } + + for (var i = 0; i < levelProperties.playAreaComponentList.length; i++) { + var index = components.length + var currentPlayAreaComponent = levelProperties.playAreaComponentList[i] + var staticElectricalComponent = Qt.createComponent("qrc:/gcompris/src/activities/analog_electricity/" + currentPlayAreaComponent.componentSource) + components[index] = staticElectricalComponent.createObject( + items.playArea, { + "index": index, + "posX": levelProperties.playAreaComponentPositionX[i] * currentZoom, + "posY": levelProperties.playAreaComponentPositionY[i] * currentZoom, + "imgSrc": currentPlayAreaComponent.imageName, + "toolTipTxt": currentPlayAreaComponent.toolTipText, + "imgWidth": currentPlayAreaComponent.width * currentZoom, + "imgHeight": currentPlayAreaComponent.height * currentZoom, + "destructible": false + }); + } + + if (levelProperties.introMessage.length != 0) { + items.tutorialInstruction.index = 0 + items.tutorialInstruction.intro = levelProperties.introMessage + } else { + items.tutorialInstruction.index = -1 + } + } +} + +function loadFreeMode() { + + var componentList = items.tutorialDataset.componentList + for (var i = 0; i < componentList.length; i++) { + items.availablePieces.model.append( { + "imgName": componentList[i].imageName, + "componentSrc": componentList[i].componentSource, + "imgWidth": componentList[i].width, + "imgHeight": componentList[i].height, + "toolTipText": componentList[i].toolTipText + }) + } +} + +function checkanswer() +{ + // here the external library needs to be called +} + +function zoomIn() { + var previousZoom = currentZoom + currentZoom += zoomStep + if (currentZoom > maxZoom) + currentZoom = maxZoom + var zoomRatio = currentZoom / previousZoom + updateComponentDimension(zoomRatio) + + if (currentZoom == maxZoom) { + items.availablePieces.zoomInBtn.state = "cannotZoomIn" + } else { + items.availablePieces.zoomInBtn.state = "canZoomIn" + } + items.availablePieces.zoomOutBtn.state = "canZoomOut" + + if (items.zoomLvl < 0.5) { + items.zoomLvl += 0.125 + } +} + +function zoomOut() { + var previousZoom = currentZoom + currentZoom -= zoomStep + if (currentZoom < minZoom) + currentZoom = minZoom + var zoomRatio = currentZoom / previousZoom + updateComponentDimension(zoomRatio) + + if (currentZoom == minZoom) { + items.availablePieces.zoomOutBtn.state = "cannotZoomOut" + } else { + items.availablePieces.zoomOutBtn.state = "canZoomOut" + } + items.availablePieces.zoomInBtn.state = "canZoomIn" + + if (items.zoomLvl > 0) { + items.zoomLvl -= 0.125 + } +} + +function updateComponentDimension(zoomRatio) { + for (var i = 0; i < components.length; i++) { + components[i].posX *= zoomRatio + components[i].posY *= zoomRatio + components[i].imgWidth *= zoomRatio + components[i].imgHeight *= zoomRatio + } +} + +function nextLevel() { + if(numberOfLevel < ++currentLevel) { + currentLevel = 1 + } + reset(); +} + +function previousLevel() { + if(--currentLevel < 1) { + currentLevel = numberOfLevel + } + reset(); +} + +function reset() { + stop() + items.availablePieces.model.clear() + initLevel() +} + +// Creates component from ListWidget to the drawing board area +function createComponent(x, y, componentIndex) { + x = x / items.playArea.width + y = y / items.playArea.height + + var index + if(deletedIndex.length > 0) { + index = deletedIndex[deletedIndex.length - 1] + deletedIndex.pop() + } + else + index = components.length + + var component = items.availablePieces.repeater.itemAt(componentIndex) + var electricComponent = Qt.createComponent("qrc:/gcompris/src/activities/analog_electricity/" + + component.source) + + //console.log("Error loading component:", electricComponent.errorString()) + components[index] = electricComponent.createObject( + items.playArea, { + "index": index, + "posX": x, + "posY": y, + "imgSrc": component.imageName, + "toolTipTxt": component.toolTipTxt, + "imgWidth": component.imageWidth * currentZoom, + "imgHeight": component.imageHeight * currentZoom, + "destructible": true + }); + + toolDeleteSticky = false + deselect() + componentSelected(index) + //updateComponent(index) +} + +/* Creates wire between two terminals. Condition for creation of wire is that an input terminal + * can only be connected to 1 wire, output terminals can be connected by any number of wires, and + * an input terminal can be connected with an output terminal only. 'connected' variable is used + * to make sure that an input is connected by only 1 wire. +*/ +function terminalPointSelected(terminal) { + if(selectedTerminal == -1 || selectedTerminal == terminal) + selectedTerminal = terminal + else if((selectedTerminal.type != terminal.type) && (selectedTerminal.parent != terminal.parent)) { + var inTerminal = terminal.type == "In" ? terminal : selectedTerminal + var outTerminal = terminal.type == "Out" ? terminal : selectedTerminal + if(connected[inTerminal] == undefined || connected[inTerminal] == -1) { + createWire(inTerminal, outTerminal, true) + } + deselect() + } + else { + deselect() + selectedTerminal = terminal + terminal.selected = true + } +} + + +function deselect() { + if(toolDeleteSticky == false) { + toolDelete = false + items.availablePieces.toolDelete.state = "notSelected" + } + items.availablePieces.rotateLeft.state = "canNotBeSelected" + items.availablePieces.rotateRight.state = "canNotBeSelected" + items.availablePieces.info.state = "canNotBeSelected" + items.infoTxt.visible = false + selectedIndex = -1 + selectedTerminal = -1 + for(var i = 0 ; i < components.length ; ++i) { + var component = components[i] + for(var j = 0 ; j < component.noOfInputs ; ++j) + component.inputTerminals.itemAt(j).selected = false + for(var j = 0 ; j < component.noOfOutputs ; ++j) + component.outputTerminals.itemAt(j).selected = false + } +} + + +function componentSelected(index) { + selectedIndex = index + items.availablePieces.rotateLeft.state = "canBeSelected" + items.availablePieces.rotateRight.state = "canBeSelected" + items.availablePieces.info.state = "canBeSelected" +} + +function rotateLeft() { + components[selectedIndex].rotationAngle = -2 + components[selectedIndex].rotateComponent.start() +} + +function rotateRight() { + components[selectedIndex].rotationAngle = 2 + components[selectedIndex].rotateComponent.start() +} + +function displayInfo() { + var component = components[selectedIndex] + var componentTruthTable = component.truthTable + deselect() + items.infoTxt.visible = true + items.infoTxt.text = component.information + + if(component.infoImageSrc != undefined) { + items.infoImage.imgVisible = true + items.infoImage.source = url + component.infoImageSrc + } + else { + items.infoImage.imgVisible = false + items.infoImage.source = "" + } +} + +function updateToolTip(toolTipTxt) { + items.toolTip.show(toolTipTxt) +} diff --git a/src/activities/analog_electricity/analog_electricity.svg b/src/activities/analog_electricity/analog_electricity.svg new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/analog_electricity.svg @@ -0,0 +1,192 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/Makefile.am b/src/activities/analog_electricity/resource/Makefile.am new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/resource/Makefile.am @@ -0,0 +1,43 @@ +imgdir = $(pkgdatadir)/@PACKAGE_DATA_DIR@/electric +img_DATA = \ + battery.png \ + battery_dead.png \ + battery_icon.png \ + bulb1.png \ + bulb10.png \ + bulb11.png \ + bulb2.png \ + bulb3.png \ + bulb4.png \ + bulb5.png \ + bulb6.png \ + bulb7.png \ + bulb8.png \ + bulb9.png \ + bulb_icon.png \ + connect.png \ + connect_icon.png \ + connect_spot.png \ + diode.png \ + diode_icon.png \ + red_led_icon.png \ + red_led_off.png \ + red_led_on.png \ + resistor.png \ + resistor_icon.png \ + resistor_track.png \ + resistor_track_icon.png \ + resistor_wiper.png \ + switch2_icon.png \ + switch2_off.png \ + switch2_on.png \ + switch_click.png \ + switch_icon.png \ + switch_off.png \ + switch_on.png \ + tool-del.png \ + tool-del_on.png \ + tool-select.png \ + tool-select_on.png + +EXTRA_DIST = $(img_DATA) diff --git a/src/activities/analog_electricity/resource/README b/src/activities/analog_electricity/resource/README new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/resource/README @@ -0,0 +1,48 @@ +Copyright: Timothée Giet, 2018 +License: CC-BY-SA 4.0 +Files: +../digital_electricity.svg +7SegmentDisplay.svg +arrowDown.svg +arrowUp.svg +bcdCounter.svg +BCDTo7Segment.svg +BCDTo7SegmentA_on.svg +BCDTo7SegmentB_on.svg +BCDTo7SegmentC_on.svg +BCDTo7SegmentD_on.svg +BCDTo7SegmentE_on.svg +BCDTo7SegmentF_on.svg +BCDTo7SegmentG_on.svg +comparator.svg +deleteOn.svg +DigitalLightOff.svg +DigitalLightOn.svg +empty.svg +gateAnd.svg +gateNand.svg +gateNor.svg +gateNot.svg +gateOr.svg +gateXor.svg +info.svg +one.svg +rotate.svg +sevenSegmentDisplay.svg +sevenSegmentDisplayA.svg +sevenSegmentDisplayB.svg +sevenSegmentDisplayC.svg +sevenSegmentDisplayD.svg +sevenSegmentDisplayE.svg +sevenSegmentDisplayF.svg +sevenSegmentDisplayG.svg +signalGenerator.svg +switchOff.svg +switchOn.svg +texture01.png +texture02.png +tools.svg +tPoint.svg +zero.svg +zoomIn.svg +zoomOut.svg diff --git a/src/activities/analog_electricity/resource/battery.png b/src/activities/analog_electricity/resource/battery.png new file mode 100644 index 0000000000000000000000000000000000000000..7d49cc97f1c3a3bf79bc5f73ef5fe6c106b70b47 GIT binary patch literal 3834 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 B3S002A)1^@s6E@?-T00004b3#c}2nYxW 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 FV1m0lxMBbR literal 0 Hc$@r0068A1^@s6q;fP*00004b3#c}2nYxW zdi2&FCM754(K@-GmQ;0X{sBtU@R5ZV9lTU|Fjxo<*dCX+BU z=dATxBbm8<@1Bn>`|NYZT@r%=zzvKAtHClb1Mqc!&4;79UvTtg9!zHfqB3UWYjnO-4aJ?@EJG{Bsx+~m#~7% zr@RFX}R@H(&5UgeTIq}QAM4nj?OfVP<66wi{Uy*DAVvu~QgnOKl+t)>InJ4># z$YsLk_HbO}j4fh05+Nr?oe=+MVwt@ltDeO85y}c62Gzci7bimG&YP^l?;>6Sc(g|- z=S4120Jd^4R6P3}mFwwd%4?HYZiCu-BI8yh9zYC`%09dq7PDLN5xKw#x6<9*xdkXN zx-163oOpZL^+Hb7+amW&VhIE8AhDiQ$BSe*5ChaYLin%toD~ANA#$6kt|hBNcXe9i zB4U}-{LF9Q4-s!#A!4M+v1Rm0xx)I5NiYY2tDaoPiKH8d076(S+w=182|Om^Nh=VO zSWbzYGekv8aY^Lr36V4Wz9;^6QRE5*#lKq;6XP5TC^lmG?yj84zf7K*#Bv9e*OMH3 zk(36Jem>`7dH%~&@lq#%79j?q1Tod6b%0p>U^Tpq+RCjML}m_*V{2Jx1>Js;K$BSR zfkJw+?H5UM-~)tYnJX{1JQN>G6L3?p2DA(m1cg8=Kw;2&c;Yob3&D8$iul_a*j^F2 z&hI;dDQDyovo%F5S3x#C>Gla_77&tTvP3MqCg-EO@pLV8AB;8l+Dqg-Ybk16LYKoB zgw}2H#W^jKDj+iWYrj`+$8_WATF#32VnPF=n{2u%ii*#p zi$^FpAAIgOME8FpJ`^9HpD@)_92Mjyit2`rf)rW+)`=t)@B=~^03Hq(&zNpH-Aqg| z2ZdmERYq`2G4OBkO}}GNmLbSiUB$IdC=1oay|3@cS!-{)MQdS#mVuUqwGsxXOoRE| zw@C+BOp{pJYaztYk)~!jy^hEYTW`9*$PLw6_=)(_l~5oQg^^YhK6e&sZIb(nP_BUF zS`g6-<$E9`?=pFIBqHV;eBi|k&*3Xp__rN0Bw*tD^_Tw$5BH{vQF}_>1%3(P$v_Q97gW3(Vn=7NGj1}%*L70MwXq{JEtiSA}{!W(@0>D>wq8$Mj| z#~{P9`ZSQB!mhIKxB}=Y)Y}@AdwYT@#X+Qns$IsXA(BWRyX3c^>>e@Bv zr(3tYolPjLIJ2il5zAaHjHn`M48-6~H4~D*WXY%5^5uJBe!p3-UV+oMZuO&(C=kB4 z`SRt{6i49-6`s&V@jY6ca`oyx{L<6&?2;o#E_}XW!{z?-=3QHQ^yvAwEf%(2nsxx_ z)&xZ;r+|*YaAH*?^^h1c*cnX_xxMfLp_{rUy+y(T?+1Z}!>>GYBC@RJk--O`TW zV6XZeJKi-u+j;!>TS<~8jbLmu?%Qv#EZD#QV*8OJZ&z;I_yH|Ys{sSb|572B#BrX7;|B3cSy*o6sc2(RdaI-R^Q+M z{JCf2Zry?yr||XR&`{4V6DQuR(W=$`esktrH-tjV()IJtZ+`LHZ|AEtZTf(MGOodR zCu#EJ;j^}H_cdG{W1LRo#@!maY}wV;0|(w|)VcHB?vp3q{532rPQ=o5n*=FB`BIC7 z!(CcM7T3Ozr`F!ghMhXyO`0rO#I`$kVvIGmT)XDO;Fbd8>t?-s2U0i`!KY)#-kP^} z??t}P$GYv>-CKR)#5qH3WW>sq{w^s~h7Ve_=-Ng_3J*47R)3c zxugi?vK9#kwsQg@jkijWwKsG5@4ug?`{_1ml3mS3ob)=Md~%Pj#t4cj62>%qUb#t= z2Zvt2_MG|4FTQkT42)@=)N3#n%A7s>D_(=y*Q8CGE;&LdJD-aet*auI+*&B^asUV! z{+IaMazh!^evmh>DX6ud3G3EfW=zv}=FID*YSw&2Yf-XBjS#~UF(~FEVcN~~yHS@e zch{ahdxma~!8GC>hr~1NyHSMFJ)w&v5qJoM*ix=ngWB0UcltU?ER1tz@7UqH^3Old z8UGCmq~qw(w;Aj3z3=_~eVA(VdFKfeZY}%of6vqX(Bh=cm@$+ti57{%qk!!B-_drL z1SmrJCZP+Zkh;~=no6uWsC7w|Dy(Mf*7x~3uGsnDffrq!G3i@x-}WwEwQ2~hNwF$b z9#dQt(WK3rFV$$-GMKT?p2v?*G5(>@ehvumW{t;||0b=gB9vVTT_~-AkfN*Pu|1Q> zpfhEfG-2^wd8Gwm(TE#i{j~{QC@mwav0ob1SlbxCb}h34nfk*IetiA5pyi;unf~+7e&6``oGn+s z{zGO@hKnN1mP*&E^@xu)W z>oTmvFhgRkhc%oxU4v^~icn4@bfHuQLU_!Cy%SRj71T5tGK3m2gflRI-@c0j=Fh)I zH$+R*cJSZ;iiP6o=I(xzDR-}F)1qyonCmAO6``EbUH0xGB=cN(W$&c0nyO|$&c@m^ zXU;G_VKul!wQ3=>f_$Hrh1pefo8J|oTuSIdDF}q5_K;9}CxX>k3WX^wUppiJ2@LdJ zcI?=BipF?vKvtomBCNSCxlQHAn>y3WIWFZNDE)|@$CvRKCF&dQGa_r18_*xSS7 zMy)n&?q|=R|M}i0Pb{X*ga3@Oio8u%X5Hm35JGcn?<6oyPM0auYiAP&>nFy#5Z9(? z`A9Msm+&e|rPoZW9dajXUy2sWb|9n|j?l7qLV8S@a)T4V`h_zHgmoQSjx?y$@_$$A z^yx!cpyS%nmaA8N)D>$>R9qWbu_nE>P~2ra5K?u$1lv0?>?h%bjQQ%TD{osQT<>ws zo%<#K_Y^E$`YC&PZ7m39M;53EMIV*Ho8XAdhbBI8k|Yt$`}7HXTLRhj=+P*tdGwef5|T>`!?IWwM^y>zlysZ>T<}1rfbaY5*ZT0%G4Q+uRQug(wtmpK$afa(f1^&HX@e zA(E{;_5v=~`eQG&`w0L-CVJcEez>2QlgXY`N2kGw5+{x@b`QqGHqsmVw+v$z%Q7IO z#zx!R4>zfELb)>Q$c7^p@ff^vqkCM41@3D8* zk(0wel{FlIdIkNwg5G`>B-&_B1nbiv(9~9W{wYT}It=>}cBTj1s_x zf$CZWb~H0}IVe_760;Kae>h?S84&aM3$8{RuFTO)@RG}kqHac?t|#9%p^O4T%6u)4 ztiAEHCfup#h)Lvim5y@ZUxPC(O%1;=%{-gco>20~Iyvo20y&`CGZZusz6cjEIb z6<({us8Mm!)z5v!CQEVyBPVAjrb1jC#bF@f$9}!v(QSb#h^<>9RC|?61 zJ+0`@&sUaPo|PNT?;x+&CsI3BC?kN7hCj;PH%$sH3Abv{ve-MZJg}Hm-Pl}%d~sdQ^Q>G` zz)CKI26|#0FO)vkuK6%F;lY2gX^@U>1$M@H@#WF%7A(kXFhl=fQ``w<0T9yUX9;@K z#&56WBT0BBaS*tN~3>4Rs8Mi|D%bLADJVBb)fG0EZwLM*N zww_nZAHL>3>1cjhpX}D#K;Odd!HxIjbaV&qu`u>w*|K)0#Rbchd6F)3=GT^vpD?pI zSWdV2MFNfO6edE!Mo>ymVEl~r?C)d9UFDN!|NUXmpK8?i)9<)Gj=6$=)4) z{QjGc$Rc~uY4^!)3E-Y13j%otmh0+j{Er(z%BR`{4HQzofUp@I}HTv)PY%O=TP zTq5{BtEXJu<#Y71-nO^Bk>BURd(mwaFM_jgEePZy=me7KDSJC(MxsQCA~I&oNRdd| zbm@eT$&x3RYSpSq^XAQ^S+izRxpHO6l`EGdPMlZ_(eTu0{$K$Y^sE(1`34Oh^3-cf z?Tz0C%9-@Dn~1mPS&fN)^tt(RkGOn+~pFQxZfeO?&nXva~LfakiLU&3fngNqjw0fR`>V zE)<6F(Rgma$)#XE{P08J>l!s`L|U3kl`2IM4eKI2r^Hg@QRD92gSa+i-g?UHiii1_ zie;_!)HqjsG7m_nu3cr|(4kTR6Q3+uvPhAb1(P&sQmI$39)%JGil%(|^0YRQpXF(h zJOZ69jV#d7UGWfORV3S=ikGP_5(?Vtsd1u#$=qd#fUc%k@#4~5_%aS9^7 zLfLIe2qaJ5ywaj|Yw0&&fHXpkk~vEji=RuGGNmxKp+zwZhOrI*mOg#@$j>tXUU1+5 z#d2~J3Ta8B)<_2FS#i!$3`lBN2R=pzEknNi`K1ahNFBJH28|j?>yJN{#t?^*Qqv;Q z?UX4~MjAJ697QnY%9Z=uvOsKfU3^}seEBC;rvDo3{QGM3=nTAo^zPSBCQhC#&0DsV z+Yp(SD3{7HunGG^jL zp?G@r?JKlE1t1VkxGJ9P*|SqLk-{Oxkx|hKrAn1b6^2eP{w z$hrw*k~|1@StC)`eT*1{nNc%jIdc~*5W1@wbLI%G53l)g`}R@`^_3!6D#(fN=7P&2 znf@-&k*&bVR)qD~8X3SMYiR^4z*4;7f+&#kSUqmruAOx2)k`?ZO2J7afr^Go& zCm?xY8H}uju7#D>+OR4V4c(5K%`lc>Ou}sFW5g#BV&s%s-o)C{dhB8+Er zIXQCVh+Ma!YoMi=j`~S|#1pg@>DZT|Sd>C2uCdL4^$)`S6sEx}#?jpj#`lIHC}xaO z2_j=q%hEp!a;1@0zwheG>ljdU{BQH|F8&+SfRha!$od=oCv*{9z++Zph^8=#V6ED; zk&$D^iu=^5j8Ry&r<>vgN6Cm-bzQo2sjObTT2`)HDa)5HXS0*Kwi9_>S`S(lUZ-gB z;!LSonY{s=dFc2=wHUM(>@lIcp=i`K9$K3wD7`ayEXd9lLkS{zHdk>$YvO_Pg(-P209~GmJmp6uhd}3&LX-pog>e zpK#K-mcxdnxr-JF7X_Olc+Jk(MJbSRHMm8K7Sal-Ed@mD^FCaN5tj@_v(qG`xkF%a zXlaIx8YS}?GC1wmnD*Tf=&je|J6AnH0)9lk7(9O_I7-jborAkTH z9zDbZMKW3&KCcFs;fi2Y4Qfl_bBiFXb?es2cd#OiO{O7pqIgtm!9bVgeOee^rvU@j2I!bI_$OW z{n=;I3^7ePe3xrK`Ha3>=inaL3C4mPKo1KeEsJgD-Vg??Ts7uG;A9UEx|_et^C-z1 z!Xb=nJn(nMBQvpDJRJh-jf$??Vn8t!M{7Y(r@J*+RfLg)NS1Cmdk|61(2mSIg9z?u!jd z#=p`Ez}ZG_FvWb_hl!s-@`NlDKNiT0eK$2ty(J7j8Q`+$whRk>(-63FWq9Dgfm|(S z>PxXOD>CXZe9gVdybdju>b@wHD$cx43YvgDKrFByqy`Cctc6PmV@ck;6_hQG#!aFS zhC(1SkmamF&13>n;ua{XaY2x6jI8pSV;ov2S}Rs&mD2$JU`Z@Ye^;znAv0#o;O;)fl~{x^4I8X!RgBMG0PpH>0sk>qdJ}3F zo*Q@$_YuZ*8M9F4qtd!+)hZb`Zk+Hn1;v^PK5tPp=2V;8L0IH_$9Gd+0-|sVB*>GW z%7Ujx2bysd7hR4j5)({TBF4%qn@kFR=KoC?o z768LgV+n)xp-4hNBajeAE0a)y6XHIkWDvnV5W%|2h7B8pf+2IUPlqLV2qloKyWkt} zBiI6pBqR@QVXdf7LOn0#Ffg{1Mqr(X8BRDY3Er#so*pAiLOBZ(zj&L>bC=}L0(ZkYM2SlNn z7K$F0#(W?OowQK&ury`@QRtzCqKBn11&BgFEfhU0jR`;$25X_{VQGv4qA*emMGs43 z2oQzwS}1y08lM4Cn52cGho#XIh=PX}iXN6mA0P_TwNR`Xy3u-+7K$F0#$;=@ZfK$C hu>godd+^rB{{sxq-->RvdBy+$002ovPDHLkV1jZF$QA$q literal 0 Hc$@r0068A1^@s6q;fP*00004b3#c}2nYxW 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 literal 0 Hc$@r0068A1^@s6q;fP*00004b3#c}2nYxW zdq$gGRCodG z!2t~b006=u`=_?Y2doVM000000000000000000000D!Z1Cg4rhc^+2|(82K-#|K5% z!)4v|SruVDlmT`;aC8(znQ@$P6&*#_VVo6@@o}Nt2y%de+y_N&q#*YJj{qx&0;@&?(|TMH z1@g~=QG(9|s{~60vs)g&FL+Jxf?$MTkf85B_$^ZYQHl@tXRKYFdP?)|_nAdKr}(SI zHFOd_=Zs*cV5Fd*a%2B-1Yv{j7x)J+FT<4BR7Az9FfK-i-qZYS{H{C;dA9|FGt45$9;ADH$o4ghLJR^Si=Yf1M<7uOfFiy|C}PYdMaxr@ zYo?wo5M7%JLzdfHe;=P z-ldgftF$5dOoxA#3g%*VP~k-eSVH*1^=luWcNxkOM27AP}XH?fQ>@5M+T5ngc1`ISW3|z9u#;zPzw^hUJ+%SP`PrE zU04Wpu@MPPA{db*zGhPn8F@|LKaUz!t6T@Gp?Y!$%4D)M2%-c%ltzubBon1KThuz- z{Hx6Z@* zS=twc#G6xL&kQzFViX*;7gm`pWrBN@#tvVSK7tGZ$S>!iW`_$Iff~RBn5A7!7Lb<; zWX1#O=K-}Ajyx+8ZEQ?-FHR9b*!Z2ng`$d3q8O2E)5v44uf|=fka_##D~l#F&G&bG1!$bL2XTLBTGh;ECom}Qp1{+1a}7OD=fyP zpe$33k{lNAT7U0XMZ}cJ@&`qP5G&H8qnx)-!zh;_6nelYT{fVHx7d#OG7Iu;5-BV# zn7fZWfl3fhX?{Q&tZgFBh^=r)L@5;XQG^IC%60+Bol8-9x-qmE$E&N;CN5vDAN#kz zStf1TR1oj?r*qz?bxlb&^71(vVdMRH6t;+?6C{{(kXs;sAG_R0?>nPSQEs9lL|{oC zk`~rxWux6;=BC_S&6xM!FMar#XI!7IUR}t?e_6P&=aa0e|~)zqXt{ii?K9~wE* zwLCt)P53@qS*aQ^cC6!NP^}L3-dJ(wni`2L^As`KO7g4#t+ZD&A$Q+@zweg2?y8nwAM@VZ zwzaX_ikC!x;?dam*-X%wb6jdG{EKQJzq7r~Swh85-ZsvqVi;Bdv@a4gSxg1TT z!E48bt!3Nx&GzM#r&vw?LNkTPa;8}es4&e4U449Z!vM?K-mByY>4ezWrx6yQR+yjY^utw##q#z$Ou8jUq|2C}S=Z*S>+T zqr>2luf1mP)w_4&aa&$?9y0Zmg@3iu6=$vFR-{|cMFEA8!bab;Yf&Y; z8g)sWo!2M{a~l3PuNRAm6fYvn_WjFz@p;D_j6%}a*dij!yoDb&@MkH_+3Z6hW|&jV zdZZbp#kN2ksDhf&RU*sniYQSyE&!RB1bs+JWJ&GKcivgucFw0x#TndYVUnebjY4up zd%($@=1|<$id7qDHbsk7(KBjVBN3BgekJUVjwbDNZ51OZZCQ$q-Q4yA%e~BZ+F!Gh zYA!}%Nqfr?2-n?6M0xXam*h%;O90ZDa=kREoqOPb?uV0vH7X{!%?qIOIxLH!F3-aJ zq&3PM6_JO6?1|mrVXnh#j5-`@Hzma_xemJ@Mw~fcPVh6jFv?Io3KXQo-|muxu?Jz1 zh_e227v&xS2$u?msKf?LYWx1|XAQ$&ddU&^XZ)!;Wa+zFnJuW!DWy2Ajh^S#mabes zt%lKLh4@OjC=t7!=$-ScnENmaG5?`x{CWONpt=gXOD^1&|L%;g5>XCb?xMUT0J(Q1 zJiI}jg_YQ=ueqjyg}6Z9k3*H34I)_(9T6BoShVBU3{j6^gfR#~R*SBS*O>HDn)!=9 ztY`APS>!*fqNmkptmkaal4J=~f;b_I?gyix&(csRU0-{-i}K=yYU~=g!x824=xB}# zFn#CFpkdsAG@}XHZmqmBax~RoMAF+-(AzwtI=%Fm{o7qpl}xTFM1IwY(p4KLROeU4 zmU4j;6I*tVtgnO^`JBJpMR{7fXgVBG4tqSRK384kf8v!_%7V`*tBXz0T(Swk4BKJb z#_v9@T(e`cdt>Z+vl`~?l_z5Klh-aWju`!0*K==+1t{Km6-u9plo7l4>>})wuf1fr7s*SWtA@?@xX7x#!Bq ze(-^1&c1!R7sW*8xTq-8b8o$6dwa%=pvx%c5^HGS#Xv)PoU z_1ecPSL#1nu_9pYXhFUbQKX{WES=}!zL#)ix#_msYKA=dq)U2@yY`BZY`S#$NxGTS z3Bi8H{SJqE#;#p?@64KI9P#qYjsbVyU3J9kRRx?yPG~cWyho|bM!_xsVYm%f6b_TG z{lzcpq}Mo_XfC)Fc5Ct~T}r^ZjeL#FXY1A#a{UbFrWpB1@4kKgk3IjqGuZnXvmd2x z*QF?;?7Of=_7sfait^U9X+}1{W}QycQkhkA60ZA_SZ&J`fpju5)6B%Vb%7Nl$2B+H zP|x41-*wm3KlA$Q_AmDC)$K4CGMMDH_kJFZhD##KJBlb#_*?+;_$D~R6=mVEW4UaQ zzpq_e$j6-0Z;mDuMa{-+A(`-6%lC9)Eka__s)a$90*5vm1^Il;Nk57+W9xcD|J!e` z;qNnW&>$bz^2!T>p%@@Wff7-aqcV6CA~Et|i0{#}XX6Xw$6Gm-&jur$fMa){L6J_2 zqFkPmq!sWuiz1|$E*@o}5fpYv5=MQTSaZs9yvz+)+(#2~hoO*)0yQPQA-k$9 zLA;qmZu#r1N>0uiHFj9-)Tz&7;rdDCv2}G}C+0kfQX+{@k>sK*X#$W>QlJm_2H*S0 zBc40%y|*&F=lfIBVamC9no?naB?1Wnmov_ciOFMf%6w#R>gG~*LuXO13io|Xh(nP? zlw?Jai=uoX0C{*L%EP_EtbpFozkk@>7vcFPoP#kUku$t)Dz4&s@fq1nFOySBa_hi> zRonIYjCfS3rTdS=f%iZn%4|iDi=qsXZX-QZgRuS@IjUfzbww1yuB*9F7uV7iWjEzJ zNwU0zi@Q0`#2o>`Z zA1)N4DAAdj+DJFz??3#|!q@)m;>AVXAxR96y%1fla_mLNyB~`HWKw$Px}X30{PPkv z=DxBrbtD^+!{94>^l0P^bvVxtV;iY4^k*3=vMd#V4BOJV?q~FS?^)TPl9|~q!v#ky z;xT#M?{uoWLz1-?WXk4t{;Y`5iAh2ho}>r;h2q!0`&}8=&PK8kxsIe~uU?JaHIm|D ztvi>r8R_H*dMYAx?4wr7!&%HUaH&5BpQ$jaj!mo{G5%JbY&6cf7K|svh8N{nM&h#PLxjsAP=rXMMrNu zqsibWo~VdKBl2}P6qeLWBFf*>P$)aGAi4A9dPS5+1t3?==vbb@q?6smD-$Q0yV{66 zD3Gu9>L;I=yF(K0E0#qPqu@@Z;X5x%FM&@0vc!PwP&a?_=FKd&VebC@x~?=Lk0a$A z4o5j$H5X|~ct)G-SaW^XBvE8JApqgc4b=c#0?E-yxQ#2X#ZbIROY+WXMh-xNPH>yj z*j*E4odD#|9ax=z*M0Z-n9O#iAvqJwr2}GDUqtd8>4!SqzXooZBw3O9Y-B~0#R8C5 zLwvf%!HNnM3vDk=m{8i41|2$Tl#@}32O3905aw2IoPbI8**qjYa>s%yqD&KjjNXTK z1>o*Gb{AZ`8g8S`KXN3Oufa{^k&uLE+jl3x1J38mX+=K`Jh1Rm0P@^!*xK9p&AejNyYE`VZDfk}bFtNe$5C{4qZW_QlFijf zIV<>gr7^o#l%$UA^?7sZR1>4Y(sSps`8cdqagy_DI|4uWn){@Ke6&6}q-+EI5q1x5 zaX=IBFS?;2m4&f?89X@bVe!BRAM{>(7Y!N)5G~lKA zx9N(WeVtd__ZqGkxe)!{iLDQ|5GiWQ7M9w<6PLn~grg)rzr7=}$dOv8et!rS?l}q| zNTpzzQeD0D|BM32x$%};YKOh}qLU{B{2zPg9-CEt#_@ubmOF)(D&<}-g>oshV7XK- zlmab<7LYp%<$_!aMFH_bv6phGAjl>PB%6SPIpf?!B?4+@W|nNp%o3Ab%=XXbGPV(? z+nCJqKKs1i^cN4OZ#QC`zWAOe`Q-Gar-whzx6l2YUbuQyv!BedV?XMglJf7*`0&uKIW}m}AiLv^JFIm= zf?h-u?w*FHyL@fzvVQP+*Bh0a@Z!DZ9u&{u-M0}0@+(*h@o`^?1ytXZ?HsHn*9yz@@$*|Vp$Y}wMBXeN}D{I&ATnfDp!-Lz-P&d>ia z{MPG8>y6*$Pr-EBtFqQSd<@&adVvJ?0NCKcgKfl!5!SV9R|(;^+iue_H8s^{&YUU1 zOrJhoLg5^V1~JLgB(`mPJ^XI8%Cl$R_rJKtzm$Y1t+1@@a-_LT(!M64=5+M@N&LVP z;gf`f1POzqxvw4ETnT2tfC2hEVZsD+o@UILF*k@N+!vX#%xWJ;vxS6kVFc)fuWM4v54V)`TA zCFkI;nMbEkUgKbq=-sD}%`PpqbsIKV0Xa(7&W5$dd1T$*XD3fPFY=ka-Juo}_@3}Q^T?wA6iGEuK?}Dvfx6U5fz1wEZ znPa_r_io}bZomC@Q$K~0+5LNBVxsjQIM60fooW*%PPBgg``)uKo zB{rBF%7plabEt46fIft#9zA-vGFsp*eCt*#E-A6$Sy}p?Cjpjd(n)&z<57kU z8)id?4pnE@e@%HC-)BOaycD^T`}czoSd`feP-WvnN^{^zR5steXp!xB}Xq<4sGBY#fh1#}l>lKDyJim<#EUIh^H|rWV#wHR9HdR#Es&(rm z2678`+{n?}B|ma3>~&mPK+<2-Hl*4x-Aah$^T4;6a6}y8Zj*eYmF0U%1fjqQ8>CsGtWw+mnz5)}^sQ2QNY}5soh7 zrnm%_s-*xgKr7ybAPFR!>G8Y;3+&!it8|mIM~}A7Nl9L>qP&CzRURTYH`m6F9cvp9 z*=Wx73Ty!01Cc1tS-fnSts(c>x_!GnR9R^ZAsg^+R9}Hbqb&vNgJ*D63!z1w)`@r( zM5D0d2?@$&$VpTU&0n-g;f2uQ&QV^n6)&=P?_SH#&zEpO*CGr#&(&OR@*c-F5Lgu1 zLVkmz{_4ji9XVmYS;TI1ruw zZ;pTF|EPw*qAZd9o!dVlL}-9VRpUfsgJ^=4%$;iwJoupPs;W|sLfc+p${RiiP3pQH zIda5~9Xn=EKmD{l_0&^ZcJj=2+;!zW@GQE{U`l05>X6ni1B>qb#OpEe7TPf(+&Iy= z8IQcp%%UQd(EFcw!nQy3koqa3@hFRzERiR1&~a5cJ#yqoi3rii^Kfnb8{ta{w6AY7 z9s-LpONAeW^OI_lPMT*558XWCppwx{X3m^B%1!9JdXr8~m8X!@?qW7{?zPwK!W(bc zi!Z%o&z?GEbLY)dm?8i8ugRC;E0bxdA!nNIp4j*p!tXyfeG|BKb`g$B8Bb8*;o74{Hyh8}<eMOaCe>6gmjwTt8>&%f}39XoNt_ThmB5RUvg36+o52nbdB{1xyC`~(ie zV(14qVSy!+qg-_%WCUU;V**@RQ==ArIzv9b@0OA@?WH*;(GYIraY|W@ba~0HUAyc6 zGo6PS25!Fpe#7f%*LL-N_gN7+%_x4B*^l*gd$-ZSU*HvZ5Yiy92-YFoY;%dMH(_OJ ztU=)J+FFGhwdZNcJK=!xnp(b3K4N>A7S|xK)pT?{D+Ur%CaVQw83jxuC!rssWZC1L zK88#1UHB%{KrPh6VK@pW;3S-d7vUVd4sXGa;ivE(eE0=~u9u-W$ak7rM!0>?(fs(! zUxcHoWy9vpR!FyX8$IW9L*)kD)xcM`C7ghF z;9p=j$p=sao(J9o>j(z^o2e!o!#%IZQMtT=3g|m$&e$vG&)W~rowJivJ8Q^ShLHr* zgK@K+o8ik`cZ`S8P!4B69qIo;2)+m10SoL?IE4^7ZMO+`-DS*nwDbgO;1P1PrjYVkJO3gqy9JZ|OJF{> zLCjeid`cO69RWlVi^|`lM~_+^B{EOM$yRssR9KtdefhCH~{ZJhtnTd0oJ)yQ8HE{xEj8&1U{f$Z3^ zL!xK~?a%U@aj3B$Q3#_T^K009*c+ks-!m3V<)86D*Y)GakLytll31-SBA^g0c}ujyz7hoRtLCjeND0w|cd;aw4)3%()FAz`2I|D*c*BJmd&|_)9 z`-DaE5fnfySP7ViE3x<-QamDf9YXX~?78QjGXx{*>+98mM<{=4obG-LUV!HzBbFj` zgjvy=Sbbm0o8TTP4Ke32DxB+KPx7C3><~ABD2l@HRjq4H_fXXpjB0H~WkpTfWC8}n zFai)j0zrX5kYHgM;9&zO1Uo>Hpn2GngD2ttlDmPEU(CFS_y`md$~NxQOorH{Tcmpn zTs)^c%0^iPq5OuzlwV~+QO>(;v<`z%@R;r-Zz@lO0%s*VeGv+rrtCB!6gZjev?LTb zFS65~P;kvbK4>2Z1coVILLBNRBL zY}FtXICa^oMJRBpvQ>vr;QY&0144n5%T|3tfm6s00000NkvXXu0mjfS3-QN literal 0 Hc$@r0068A1^@s6q;fP*00004b3#c}2nYxW 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 T31+CG00000NkvXXu0mjfDkV0_ literal 0 Hc$@r0068A1^@s6q;fP*00004b3#c}2nYxW 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 literal 0 Hc$@r0068A1^@s6q;fP*00004b3#c}2nYxW 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 JPDHLkV1fi)|E&N3 literal 0 Hc$@r0068A1^@s6q;fP*00004b3#c}2nYxW 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 literal 0 Hc$@r0068A1^@s6q;fP*00004b3#c}2nYxW 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
;%^I14 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 literal 0 Hc$@001ut1^@s6t1CCA00004b3#c}2nYxW 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 literal 0 Hc$@ + + + + + + + + + + + image/svg+xml + + + 2018 + + + Timothée Giet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/connect.png b/src/activities/analog_electricity/resource/connect.png new file mode 100644 index 0000000000000000000000000000000000000000..bc5317758bd11ea64461c8b8ccd0ad3d98bfc22d GIT binary patch literal 1433 zc$@*51!nq*P)Hi@-n%eakl@vhHOJk58n_-4J#PmO`ag3RnND%>J7QjJ%5O$SP1E5{V#@ zNFbF;As&x|zXt{eKrz4HkCv7eR904^WR4B4_y$BqzeyK7F1YfQN(z4pAn~#Da0OSw z=kuYjuMdkBEkZ0711ptGCc%I6U4MT+dU|@$)YOFH;$q03`k!J8Jj=!;`Ww33X`wz> zsa|1H00}<)4(2-ClwvjbaSRR)vP!I$9wS1b5F8E%MP{VNlR#|8IbH6AP&1oUt#CmA z>3Q^B*sE&L)zyVSAixi2jd8((1zDvOw)t&HJpGd{_r6e^P3$EBWMK1WuvXNdt*wpK zLNFNAV`PMSjA(CfSMlY9-4#lo!H>-(6%wWdq@Mc&eeD;bGyD4~dvAs&HDY=;+gV*bw zHAc$n}RT4MiAO~RIgf$VjI;9@9-9QJRY`)Sz~NyXfRBQxMJ&dvBxQPP`z;amgN*9e;ZjX zQtgiEVh1U9T)n8OZOkb~m&;|S6tR@o=wio;)Dkqb>laj1ROA$6Sy`FkVkExvM>&Xp zF!EZ)7}Gu-X1l;!gU+5lOF)c>7+ii-Nf9;!kwT@)k^Y0Qs zqN87XI<=( zZ0E`@;dcQfy!I82H_lMQw$Y@*(Vc$aeJ__Qf)RDTB*6y{qpibdSjDOrM%DI4@wvJp z$VKh};U58HaO-I_`fukVU$9WgoN{gt@FT*Lw?6oV na9NnV#e{HF*e|RpbR7K)Foy8Sls0rz00000NkvXXu0mjf0@$Lb literal 0 Hc$@002D*1^@s6+lz^ z@qfIJ`*1%#htH!Nl!tOrKI$<5utu?So?^F!u>n~NO%O^Kx?R^G%l2mE=48!Bhd;sR zjdN!^W`(c|Nzdx;Y=2Q#zUw8U3-zEr)QkFI2ke1e4Zwr_=}LR7)r90Nlq6Jse}x^| zn^S~`J)b+)oqZWMlrvx;fYB{6O8 z$4q;6op_zVG^ds^&GCiezIm+ji&?B9JBF3-jd~!6un%^^Uf5j+T)EOd@0LIsskkoH z%E7KPO?tjB-}#pib~E)iO+z^_m1#~cMdMl3rCq%G+96)^O^(o+maFs>uP(~sRTtAZ zz-o@oXBD5m)g(OF4g1j!w5JZZlS;dreK`qb-rwg88`OhueLskmZ69d>&S+ib!9Ou= z&PrBQuuC-NBpUVTb^S|Tbzv*KkyT_x8w7{;pj~KRojxy9;b8EZ0=KM%6!ml;p1*d4 z!3q%;+T3JTQ*s=}wmMaReURe|toY{}2HSylqP-FtIDkhZS8Od=bd1>xhpE~2rvq1|Y|^fGX%b4Ay_Iq_F6ywT2j&+m2Ubd3>W)um^6 z@#Q>ztssw=T*>7(3eR(GiE*IeORhXJhZ!0az(E27ALa58VnQ@-s1t9vfKfWl@dd2r z`VrL()(8;UC$93vyT7BilFR9t6^tU|NKYeH=qP4$8ExEO!gKR3st@hzUXFgYF=*hS zz+wugb{`0lS07v6U8jeL#Qxp8N!qprJ2Ncz8Gk2M3eCzd!l-_>iZkC%L-1Qvd$_sc*k0sjuG)pPwIjdwY|IhX)NDIFOv3ovCZru5$j<+0KRB#--{( zpP71_G$kr}SYC>r(|}8D{SCsxj9ZP0?_NL4|Cn4Z8|FX#U(}<2FnM`-!HeKc@G1%k z388?102(}aFy13KH#h3jrw>_LS~j>a?&%*z;R|HB^x=;GlA0b?`FSjB7A!0o)Tj`{ z{3?4vspSk{R`)w~Of z^(J8x5?fxw4KEFAz_O)!%c{P_0 zjpHz!f?|uPn~fbtHgb1&M+hR^8Vtb!0|tKR?($==~W)DrU8NsL5y@t2qOIS zLQqaTTPW8t|B&95m%WK$&4*l@$fgPip9qi1<~9F0#<4QNUnB}^ioXCLj(dNcU+o?R zNJfW+EP{m9KXMY5D@}$V?ok62Was*82`eoniK(#>Vl-GAGYh1#j;@i-3c+sOx~T@M zqm84if64lN-1x8xG9CcXX;P zZdDaN{|CULcM@}r4+~pTh5#Ynu_5qdrg6_0y@Dqs+zZ2?SznW_t!S@5DQ7dke(P3dv4@0LOpyI<^o0lRwz!|JOV|1ehM`>- z64rsu3t6j%buRTi39H|W@#w@G3_&L+C!@gfjy^=S^St8p3A$Dd>+a5%buX{H1%oMc z?oD!b>02)ZktMaaw^tohm+ntWubR60JVLN_!-7_C*zy1MVaO{DrDKfJx%Ycvg@pCl z=Eck;U|mdmM<+KaCT78#>Sjc-YooeXMJ&>yPJ(Cuuyd5oBw#^Um&sJkv(xlK5ZO|5 zb942k3ufkW)(&k?kz4Vm0Sn&sOq^CG0p0zF>upM?=~Yfo&6J?z;@Om7LEBQ+%8@a2 zb}@N}Jc|%SB2YC@j-hW$Q227LY>U>JBrIs=n&Vso6C0w=o{_4}v7U%{SArTAS3{r4 zd6kL6y0c@nZpNAu5?I(rW#k+=g}QX<+M)!X*PHt#sG)I;KK=VrX}ih7f-o}8UH7>J z1`UtRAqThN54hdcO@!TKy&dRb%W7!vrsdLZlZOS}722Gf%#==F%KyDQdLlfAtepbM z+_L^wn5C6HJ@(`X8u0R3kpaD{_t^;vg*-1UM%w&yfhBc0Em}8ub)Mp7`WmuCM}af1 z5OQHq@SGBA=so~X`Z$%9$+^_e6PDEJtuxu&b%*)W%c=mNS^C||8?-4og?+RARawrX zhgJ8}0p%fOR=2A(Nx zlm0WM2A)=KQ{AVP4Lk?mrn=9;8#-a}i(Vm+{X?x1GLM|7!bPhqhk~QT=NBEt>xU@A!>DO9~WB00000 LNkvXXu0mjfAGS*? literal 0 Hc$@002D*1^@s6)0I3bpys2-HIAOkl|24%n);) zxxlE5kgpfy--qOJ5qVxv#tF!{%b7yPj~vE}j0EA4%iP42FQ6$N6$>O!hpQ$!zB-%Ovra4R(g z7ENX zCzuB2kHmy7pP6G7=I4o$#n+3P(z&#A-6A?(e~7j84^I$&Ai}{fU@Y1o>!dWvfv+kI8mDu>$Tsly@jMA3U{IIFCKWWCgU!qvg22y)p zBlXZ5qz-H)?eM##eOFJ~kq=4x_I-Z;4ypZbk=nO~kE@~B{&l2;o}*}6`9(=Ye#jH~ zBJTuoQCVNnf0o5#B@=cAzV6B^tg8EO5MQoeM8EBLU~DO!&ypH`(=J{=*(8iJ-6H;L zggN~GIo~ggpE`to;&TD9>cLHcZ zfc|P+=_04ZjCDOvTI6lg2b;K=C#6ut1KSX zOmsw2`SRJ~*n2BnC&Xo;9r=jj=lYQBq{H~ROW*@kzN&Do19hTahqNesB$dS@Fk%)9 zV`$3~N*TPZ%+w-vWSr?jLQ@7~FetD_@)D6!8tO*<(gg^NlEtHvvA~-9=7^Mwb;~Lf zi>|!HrY!i7V?D2s+f4x;9KtH$31c2Zj8(cUUnCDuY^r^mDSoyGlVuIYP@BLyn@Spd zNLeI3`CetL8)y4P(gl21si_Y(BY4)LeY1^H-2mVPexxT~Ki=SX$iEivJ(VVI_XwEn z=qJ7qSY{F(z>Ac{p5!Ii{rXZ$yvxPU9YP?_V4Ut?VXH^Uf)~f7=(7O!V$OwJexp2x ze)JP^%7T{>M@ePj7dKAyDzSY5N=p{D3|VlSdYsfWP!|1FusUr&_oNwF6B;bW714{ikbs z^kdS$|BUn>8tvnZ)4OrE!nqt{AoHS51x2*=adQG?MYza4LgSl<-IVLBHlx8uGSYiT z(-HeurM<#bzJA7x?OkiPpwXelo)5h??xwPYUHpv+vE+jSI}^O3Q5YZIZwtb)_V26a zV#K|)vha;T0@yZ5F;kLplV$waCU6P4_rkMD)?n}=1PuuNJ02XS$L+0TjwZ2!+Wtf^8)xXuRkTuVBVHBg3|FcQ^j|!Ri2XbcRP1% z10VpzFmMH?V*in7C?kqUFT`_&7jPY?kOi{HB8x1t$O2hpkwq3+3m}UuvdAKfti1d~ zUjF4xDdMIyuayzk%4r9Wu!DapEPhHZEc$k5ExFxktFQ(1RaoB}E}-uX`;zrj^d;+j xBR$LejkNl{m*v;NW5}GWUgB|o#GD(xXfD7 + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 2018 + + + + + Timothée Giet + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/diode.png b/src/activities/analog_electricity/resource/diode.png new file mode 100644 index 0000000000000000000000000000000000000000..46b943ccfafdff24973c1bf974ae3750a5b27896 GIT binary patch literal 1034 zc$@(W1oiugP)^EkWoeFN~~6A|df&LD?1vvNamS zqNx`y+#p$P4V^QP%-uxLMfTE-kQYHnM0+WIJzMd}ndj{JdtNRc;fqJk^WnkYho8Um zxYGgvvIl*=g;J&^Yin!&Kul0! zIk`-9phDZ5GVi|lKz;4Y&)P-pnM@{$LOdSNEzWE`>Hq|K#0=x?Zm*c1J3e65^Az2>DJfAvou=P(FDS-814fDZdtatgVuSSglr~ke!_! zAwDmA?ficKQz(;iMy*y~$t(n?bT$c(P#vjYq#CQn2_^1 zD1Yg}f4a(91AM;GE?S7om?R+tn{ZWblN5gNhA_Ne32F*-^eAT z^wl$*uDC#5@q|Z(*GmM074qvRdi?K^i2>XdiVBHDB19qR0LjO`PK%J3SRu8?*wtuR*y4t{000~a1^@s6DaAsi00004b3#c}2nYxW zdjewu|*r3Vj7JK#TacPrBN^RrbO^c&|cUUYHOR1nEl>;U3VF0LnfWKx{_V+fnR1b znUiIooHKKR13Q2Vm5{K>#SQB`m;X*}M@PrCp`oFSTcXiu%%T2U6xjvH#ZEYY{OV0p z&I||Tea)U5uJ7#Zlw)IKuIcINajH)OOPC89^9fJ^oOs3L?zJ8apWwtkgAI3jxDkTE zAS%qx&fUcnRKkzb$z|7teTpd zd+O@ySnQnrWhKuYiIB-sAmA5#^0LlDZOfGEYiny!LDMwH`bZ?QNo5TER0yNves=YR z$>t~!G~k`CDb_cnalMD_C^Tk<%-S36T6@?KpBz-%lXsS<_MOG{p z!wIj~yTVmgB9ZuQdU~2l%JI`Fb{^7gVW#BZQdw~=4h|}<4sC613%%cX1+Nb7^p9qE?RXlC{A$6$EV5_IMhqy(=Hxm-RHq@*lpA|Gw; zQ3&C1-r<KyC2EtQ7aygXUX+Gm=MA> z+F!4kmw$^b_v&~w3gkZns${cS7NWhqeRGMMW)0X23|h(mRU)?9>fyo_Nj7JXmMWo8 zh=piuY}`}gCaMG90QDuCYY6ZFT)Zmj?oR?Bt=W|Y@4bEU6E@f+(Z zG$aVSQV9F!n_4`y+~&bz&ym!etvuf`?j7dxATUkycOXlVTX5ieKvr@d+o%`zEGuVv zO)13OYler1mG-RW=H`XoCk=$%R)-iBOv|krhn_XCIDbX5C7M7=#T&PJXH5Y!ZnEN3 zD0NE(AMZ6Wd=!W$VRLt!%ac<5DW`tVngFOuS^uvQjP5sCwM<~~#DN6kKjp9~tE@?Y zsvE- + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 2018 + + + + + Timothée Giet + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/red_led_icon.png b/src/activities/analog_electricity/resource/red_led_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..891a7530d16e6cd774270fad8bdbbbaba4d6e544 GIT binary patch literal 2888 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 literal 0 Hc$@D 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 P00000NkvXXu0mjfSHtV3 literal 0 Hc$@X1^@s6$6kv|00004b3#c}2nYxW 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 literal 0 Hc$@0018d1^@s6uTd}y00004b3#c}2nYxW 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 Sg#PUS0000&B}&sB^I7aT|L;0@4%0gIp*8RwTw zlVT7vQ;BWzEhcH+`!a9dn<13a71)<&+%WDLQwH5KQ{>_~^WS}fVsXYTgZ?vchzA8B zmtZ{jKP8jNc{-gQXR}#1m&-kE6XZZHdEY6pxkgHcUYuSsj+CF1H*XzNe-NMyGt2CxNt$Z5f2M?Scjs4 zPHlU!Nf4BZMOQQ~T(}_I2nFb + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 2018 + + + + + Timothée Giet + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/signalGenerator.svg b/src/activities/analog_electricity/resource/signalGenerator.svg new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/resource/signalGenerator.svg @@ -0,0 +1,165 @@ + + + + + + + + + + + + image/svg+xml + + + 2018 + + + Timothée Giet + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/switch2_icon.png b/src/activities/analog_electricity/resource/switch2_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8ced7ae8204ec042596c18cbdc059f8a781f2c22 GIT binary patch literal 2681 zc$@)w3WoKGP)001fo1^@s6`{t$<00004b3#c}2nYxW zd@vy-JtHIW491^QTHSrJu9hF-S zL=K}M2NW?T!2qH_0(eACGMTZHG)J@dvdgl&?DF2P-~aZlvzk?oT@?DA`OF)4*#CR) zxBvg|9ixLqMnXI^f);21bi+-^0e={h84Fi{n8)4Sxk;l&8STw?_;6M%5_~^Y3-&(H zd_TXg+w0d$Y3EKc#m7tO=usJ^rpj%Wlq6^4v2kUaHc4I&3^dQ&G8j_v0__MlH%=2B zEvAeN1(lSjsI=7n*tjU1Av#**h5cc_8h8wbOqKyfOrNf$%uEGUR;mWv!GqG5o_b0z z%&uUtH6E}WvZ2TZr{N&H29x1uc@yaHk|iBfU9Em7ii_Ld5SAh=09!KL(b4f+Y{|}e zNCPjplNg{gk&$Zp=%bE@;=>O+wuFRq3J0|m`kHA_0>w}P^jzdT?fzQ_WLerA@k#9| zX^E~(UaqU`lQLa}JpGGf%C`!)s{NmN%3wM^N5}85od~Av1ghA$v4d)BH4ju(rKa3m zB_$@xC?P>gd-g~uCPqx}zAK^FSScMkB%`!6Ih#53@y8Dw?{A@@=3@O0`jU+fjt)A@ zS>W}AmoZIwOk744(gwQR-bA0OnyA?(A9jDNSaoQ%TG&TDIDx}-nuaJaYlhdG*H&krD|$y?4;&qfU{@S?AC#uG)~?&2M$Q7yj(?1 zP5&Fau1*s^Wr}%r%!Qt^7=7s{Z0T1^gY_x0G|36d7g=hhHuV*{+F?%>R4Gdmr${Vs zbE1Ia=FL-^mQX=~lJ@PBu#>bqwrmRvm6V(;x40V4fcwP_4gv4#?#e}^tyQtY+^d*M zB%jlbj^4UXpZACrKc5Q4Z2YnQV~tq)-#H*J1HBazqG2cWuuL93+9(w339y!_a1F?B zrk{Z=H*1Ar3h8}uGy2pm`a)xNlWu9)QmUnT^NJ^<(%Km+h z&dY1)f`auaR!H_eR;c&swAeiUw1v~UgkyDh8hGzv!@9qWjFb*^k+`?t7G*A3q7rs~ z1*~NQen~C1w0O&s&MbY7aNrMCMb)w@I%_HjW(E7qE}ot53^{lZz>OwK>sw*6K23XAmcm@6e`)#lr)_^yRf)Q|U zTpoaOl2>vq_+U^|<3$tMK*8iet8z?}>; z_X@^+ga-w^^h;VAvy5Mzu!eu*NMyf69E#vy-1;It8RAb^Vr*;`WJ5Ka#Alt@(t@bx zJ2SP}JvQ;9KPE}0Et<}nEgSDPwg+G@(3pv1y4fSoALGN-;R!4Hg?)G4pTo5Nq5cL( zCr4g*Ss4dTa3^U%Oz^T0KIPx3T($ljSKoD!ztnZvCKtOJ_z!gF`9JJ@`De4ubF?SF zscdt5Z+_{`Ifh(E0@;u^b}_~x!p zt!VDECP9tv0xK9l=TCF^-|tw;uSt51-+wEXk|inK+4|%6z3Q z{sLd4uiiCAPOMH_sEARa-`@BF~$ckgt@y-)mx;%qt1>1KsmdE3TQCN20VEY>w zG$Drd5_aHax^mM}yxi5u*P$S+fJNG3c2d2TuPxw8b!FUH-C2&!R$=+|XjAcK-gAtn zxygPDelV!=4PJlHl(|!g9q^-&smSCOMlIr5k=)$ecyDiSqea2y!l20+Ah%&|l%>jk z=!M$TvX`3>Fu_!)i4!LpcJ10FO-@c0EnBus?d0Ud3q9+-!P2uf05PxZew81nqU30D zxh!=KYv`;;K`yuY&>9|h;>2e5;>C+KiHV7#l$4Y^wr$%c8;6H_;rK3tKRnVn!)NRc z8&@CNQnJPF1!DzD{3(g%zVRH5_8U!pK@-V0(3cf}MvfZUy?OIy1uKp zxGxjbiH_ z7hZUwBPl7#^f#HAnc{+i0%>t^vAm?Dq|egR)8#8xtkB?xWWADy<#68wz&U&C!1 zd<7Ta0IY&hV40_(6^LB{w{PDr>#1O@`LA8Owtdl}MVjE?VBM@)v$XN?@#56fR8eVZ zsl2YPPSqc^wY7J_z7&|rM&bRNFAR#fLL6}H*Id4QxtbNFud1r56qhbtQroJbp~2+h z#fvJo^o7}*34@C$N=0jHYe#Rjw6yf-+_`f~Hulu1Q}x1oEe{x!Sr45+VPRpNM~@zT zVDrz<&o|AiYuB!6%-9Kk^2sOdYV18E4M9OcI`a*!J+T{L%qpYMJ14`C%$v{& z9JB-3b9o*)azwmx~ z@eoi`lOqv45WF$*FfFF3tk`=OSPoWr`aVwUyzGd$E4#Q0&&+3>kstf}?fdL|yzjI8 zuZHl21&|2&Pz7WrGPnSHVF|Q`#t_08R)7wup8N@Z&=?3GxBT5r;|#)zoGH56AB%hIEssn zjnEWqHWujT5FWC4xVlC^6&cEn#htG@R0wfQ*flWpt5Krp-=C4w2 z(RIozt|LXpI7O#bH6?{@(QcItm^QFPNK7e2fXzid5U;ZKQ-bs+-7Gf6jc3G3OrRtw zH-2p*l4h!0TDnvU$vFmYU^7t##LHf86mH<#bVvInd<_pbJP+{7>MSN{{*?2akV5LbY&*~kAKG3@U?k#quOiVqT3H~LK5kqj2rxEt@&e}lota+V*Z9eu!$hX`w)J! ziAW4jym#rI_Gh}wjrK4BygEujgY(b%I#cbV1JYx3T%Li&1TTlvDMN`KYSL?NuiRNM zX8G76VSiHvvEU3=9crN9nDNyn+1<29!v9)>B{`oc+&Z~E5PD56_<+?$CQ!hHfKq;g z)+$c3MH29CUvUwjg%GgHhz0WS_R#U0vv$1sZR*-o+|wL_R$x^z7KnxJ4O81fVpjbc zBkR<=bA`bn=U}j!u!kI==B=7nuKR0)w7wcMDt*4vy^Fh!pQFR89V+}s`*V?ArUJ$fkWU-ySojx&@uo4`hrtpJNFdf3oU=s8Ir>8w3E(PL7S(LR{Vd;dd zy}w@S+QyX|jtp_bj$HUwF&f(F*PWlaP|>noOK}l!5xRgF9UvRXLdqc*!fHGHj({qC zBMc6GL(7}A*x%QhwdZg{FS`;g@7(9na8m*E;Y&z>0wBiMtj>>-8GDaSimxU9Z}%(} z8l?!Pf{VD=(QEeqW|jDW)Hw&|N9T8QH5>(EJc(m6 zH)-yhym^Yo*~Phf!w5;|Jr5t{82%oY6?iXofD)g{zKZ?Q)z@PbAAI|vhU-VdGnBz7 zs4-f=8X-BBavx?vO%VsN>?!K%Xp(tsEr=kt(cYEq8SF}bDdNZeES-o1nS=vRj)!Ro^f=0Z6T<3gBz6=e)Q zxwd2-i4&Mahh%*3;ML;``Po4QHWU7E2S|UG7kzcP+?b?rN#RNLBrap{@W$W5IYVdF z{9T4Ltk8~Avf_I>DnCevW!&46|Eni)jfuYn#MNBo&}`0Qo@7^A%6sioDO{>;KsxU3zJmJnF=S{S9yIT=AGyGis| zejX9ey&7!11mj=`c*8ZIwq9*@youvK(ZIf;&hZ%+Z)`jE>R936VX_4LSxhr!{Ic@fXqY-=V3F$)* zkO+#DT&ElA+jJ-2&~DM~e14kvsq8bhPYGWal!6PGbSz;7Xo1+sd7}!$OZG{)F)HJs z>Mq^Wh-J`SgE~x6l2GXmX-oT-!W^>@Og7Gt3dHOk?R7y33xzqO3LduZQ)WQ}(7Y;s zT7>uS`EgHSeu)B;%p}MIV!cPZmu$-omDbcDES?e-59mRGKC}bo*aE&* z_ybHTb`TE4tZc2zr)-`o+>N#3)fP9@Bg!tU3I93I2R!faP<$glh+*j|D7( zQXs|~w6MZ(VKO%gylLfY2PGJFoFEB^*|oLPeG?O?RP(x@m67oF*+T3I6mXg0U=;?X#v}Tn5DHPO2wm+Ab>9fMWQj2!*tOUkGl>|aLkcFiMjqv-Z zF!0zs<+jJ6vS>Oc<%(tkomMoQM8ye;l^xbbNrP{%k#`^1UATMs=TcY?(c(tqzq2uC zliqjpPQ@;X$EW>-)eY0YEU*JkN@LuFyqT@$2~7hxs1i3Q26F7-s9lk^Qh^PRgf}}} z$!rMewYW@as<5Yf<$U3lFIu=s#x4J(V4rrs-goEHl;w)Ho!Sa38+HSFfH+;?Do`US zg$(eoX%4Z3bfDJlTI;s{vt1fb2?{O|G$t-xtWFJ9@=d|l(dGRvWgZheioF($E?9YW zmEMy%ccAyOaRum5p&@h-0@hGd++jS-0e=IS4t>GqRf>1S{388TC+MV%OAU>UE2fD; zfv%o5{JBZiZ9v6v$ezFmFq&)@YDK@$VaXlJ5Y7@B^<05*U8uet!ixaW*#tWd?ZBv# z0^~W>vzRAdu4*D7mPA0Al^jr#Lnjgb&&;`l=Zx_dXMgF z_;-B>rR=)k4J2ZeX+_#-(Fkaq;j~(|H09WBhH5vve+x4~6&)B8GmIamky9 zzRHcoN1eQ!=6UM>()ESst2us(g!2XNkW&;dl(O~Sne*O)OD&?ah|ORNMxAmXK4jq! zdWa$X0~a0Fy}!P_I$FOJ4WR;1UQQV2L`T7y`lMvJA-XEj!(Al~CY&{RC(H zAa`j;8a!i2(d*bD{N)Gh7BAF|LZKy?bk+hfy(+K%J`tEmLgsfbOf`Co48|mj^W9lS7p3h z=6y^<aNpsDe7+#sZ#;zE5Cf+n04%^PV+(6R3)DoOfIBp&n#q3|#6S*| l0~v@6u0tfOg7#q6`48Szy6SFSIm7?}002ovPDHLkV1k5KSDpX> literal 0 Hc$@ + + + + + + + + + + + image/svg+xml + + + 2018 + + + Timothée Giet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/switchOn.svg b/src/activities/analog_electricity/resource/switchOn.svg new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/resource/switchOn.svg @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2018 + + + Timothée Giet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/switch_click.png b/src/activities/analog_electricity/resource/switch_click.png new file mode 100644 index 0000000000000000000000000000000000000000..c65efb7c3f555557a1655af892872cd7dec7023f GIT binary patch literal 833 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 c + + + + + + + + + image/svg+xml + + + 2018 + + + Timothée Giet + + + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/texture01.png b/src/activities/analog_electricity/resource/texture01.png new file mode 100644 index 0000000000000000000000000000000000000000..161457a68ba5dd236ba471daa4c3e046c9d0b60c GIT binary patch literal 94218 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МpZLzPLfK{8EL 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 O0000i7)fDj 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
hA^-aVf938LEb$%Z4%Mv)v< zhHHIh2V!Ht-UXsOJ`E=weRT{r!>9NE>A|Y-W?G1+&L^SfP z43N1X^|?7BjU9j+(1W)wg$64a9LD+h0hp<;opE|v=%$l8>(>kOQ6L#$LgpOl==y8c zjO`3#dxwNGV^Z;z7kz^DOapiT_@%jqnvaxu8g|sjdZ1cc0r6Thh>hb!)C_PoWj~4V z?o%?EX*rw$lwrp$e0f?*You6g)N(Et6T8AJ@|$%Wh?$6qLm|!ssjZ{a_!T}zO!1Jr zz3-w7T@qk;O{9D8`9T!}n{WL8m-QTT>0;)&AH%MP9E^Pa_}(GWD0{ncaen#zjcVbN z&pK8QKH&iuOJ?99o1u?!M{|zDnD+Jpm^F?D760ITGxkP{%mtqi!jQuuN&6MFw(RrO~PFkHU3o0;&>s`rTkrjP5~r6ia*DkokNnBDX<$SZBCZ zl?=AMQ4v0=MI-1~DjRGMS;tjYTCt%=<-pKR!{LL8V7$Bd8%TM8ewq0t5a=s+#wZMi zLkgP>X?(3l^|=N#_{_>eJS;rYRopPV^juGa!NYo7xQoQ&Sm_Ztnp+xQzV+V3C9Y`% zb&?To8DX-(Ims9@9!N#=ZGt!_25yqY%fN_xKLnzGvGzD8AOvZ#Qn0wnU!K;fqka%4 zOuj?h$gRZ8ST~}W&&e^#$H%K1PUWlzzSROqNs%kE7&|AW-o%_F|umPrDn ze5@_>e0f|;>0003x9}H8VnwBsaSCZ3Upany!**B!sN?!QJiM}Gc=YE#RzzgdP{sa;4+Q$JxS zh7u5alTm_r{b(m%QV$t7i2l-F|C?VY&K?{Cj&DE5C5>J92|YC?w{U`}pUkFg9SjUF z$q~#$`O>GRg*c#m)@ujRU1o%M!yeWEV};|$l9*(n*+jArHQY7H!ftXr9#j5N8ijl9 zx~J9hbUHmhZQ}AB+3pLCzeB^JCLjA_d<__k|b_)JiC(e^Q6w&97naqB2K-v zR1yZu(#*-3jHfVXv=e;v$0VrI8hSiLNz;>!D;9;*2MMa=Vi2dR{EFw6!Nr2%)A68@Hoe4GK7UK}rj4e8f zy^X23Xh!sv0uPBQ?9HN1n0`Zo?Np8iAel;q4~1n%@%jF-gT(B!ly+fdJ2Y;YgdERA z&C&=dJW%EGO{*%-??fd1=fC`2;x)IpR{lNQ6$t4%05vqUHxnac z$5`U%p~{cCJs#E!H#QI#I;62*SJP#NdY}q&XvX8?`IMl%t8z!~%5=)2;zSUr?PL;V zhKXOmUN|1a32eKMFXJUU$6+QO`kM|6IyP02qPLIjVNhhKFsRx%(#2mej$nYkh(>&s zbs;00wvDqvCpYh7cfzOux0Tb|Vr~Wr?ERrkNyIjB*Y{C2XaO7Wa9<6h?quvT1}-J- zY4>~3-RfF1sAz`7`6!;w7L^WOSd(~|AIH|38M?9MD%-wl3#!O_q@tpg`72+ZWo0+9 zpw5W&8Kw!zUVhh5DBlv8w^=QjpETGN;v(=lfi`!w-L7~!V;f=YvtUl1@tB3w?tBU3 z_w5en^a;g%k8h`P^C8(2bk_=)TnBVo4P)H3MuzEx4kKOWBXz7zpNJ=CLen3_xq#eF+ISzP9o(h#j22n zO0~55J;wSvrl(8maDX*Vo4hpDs)|Cf`uBhIt2PG)%+H=yv^&fimwqw+8gwNA?~=zejkO$ zC}Sae>j7QrkEJX00P<^`IM0q+(ez1*j$H*Mz35q*YajX^Vihrevya+w9j^ybNXEMp zP+kZp7AN@A<{sBXb2^i%IP`0hIs?y~000I5Nkl$^R!-c zhUh#k=kZCty>5T@8Z*dqU zBnn5%gy})s(7x<6!t$hD#W6AbT9JlUd3)}k8ESZF_GDDo374EWP=95IDWoRfeQ)8A z608(|g4hI$o*1RUd;&alvtGres1%ZrIbFtqWE30M&CqDGOxu%LMDg(w+e+aOXS4tK zr~e|u-J{ruA3;n88QmOQ5k1VuDju(|&j9;@;Kk)+g$C2d3~0T~FkQJCq{0j! zkyK834)GSzTK&xEdwkXybcD{aR_&E@mYgx_1W$PAL|Jaz+TjZI6$Km+W=*)`3FK1{cLi zFMGqi%A3bYU^I-!LP0nvj+Lz^Tp*4BD#h`Q+kL`R;@9fjZx1Kleun(s%Ouj}7%}#= zcn6vq9Q4Ve`|I;s`or*JPh&0q;cN7wS!M|n4_IKqM}yIX(` z=reO59tAQ|N1rLSqWyttY;?-cn7Puah_Y?RW%4J-(;pIht)nkJAPci*hVs=PHNRHae7Yfcn{6~I8QN* z%e;p{8xIWgW>v?76ebbjGa43(wv+tTic-}xZE)`cN62b5e>2God2h!G9j{GX`Pi*&l}SaR*Sol?jyTNn4#!hmgQzSld@i!RzthDm5t1ydGK)RIk?#) zq9iv@+`Ma+C-~CM_(K?5eC!Ofzg*fUd~Mfk?`}5BE#%E6Nea1MrWp3#KSZNJ0FSc7 zm>~0#NrU8hLa<~eO=l-$cRYRBtiEse4^m8SHNpqF_$hghRjeM4j9p?8YK(Kd(C?al zAo@oI6je%^jqubdeBk_nYqT>O5FttD|J)KoKi6YDFwrrNbi6-Z8}-aM=NRO*(3Bjd z*4pM^Pxw;2$>6t|?vZ4QLF_P5+9maEVBnlS-JAMCCa-bDYlFDm-irOZsaDdu&BVV z7biVYSxhCF4$>TJZ=e(i(Ae^RAa>$aX=BA43B=_x8Ug~m>~>vZLO_=CaPo3u#1^mU a?f(PJ@rg1Sb0l< literal 0 Hc$@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 2018 + + + + + Timothée Giet + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/zoomIn.svg b/src/activities/analog_electricity/resource/zoomIn.svg new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/resource/zoomIn.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 2018 + + + + + Timothée Giet + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/resource/zoomOut.svg b/src/activities/analog_electricity/resource/zoomOut.svg new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/resource/zoomOut.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 2018 + + + + + Timothée Giet + + + + + + + + + + + + + + + + + diff --git a/src/activities/analog_electricity/simulation.js b/src/activities/analog_electricity/simulation.js new file mode 100644 --- /dev/null +++ b/src/activities/analog_electricity/simulation.js @@ -0,0 +1,6196 @@ +/* eslint-disable */ + +////////////////////////////////////////////////////////////////////////////// +// +// Circuit simulator +// +////////////////////////////////////////////////////////////////////////////// + +// Copyright (C) 2011 Massachusetts Institute of Technology + + +// create a circuit for simulation using "new cktsim.Circuit()" + +// for modified nodal analysis (MNA) stamps see +// http://www.analog-electronics.eu/analog-electronics/modified-nodal-analysis/modified-nodal-analysis.xhtml + +var cktsim = (function() { + /////////////////////////////////////////////////////////////////////////////// + // + // Circuit + // + ////////////////////////////////////////////////////////////////////////////// + + // types of "nodes" in the linear system + var T_VOLTAGE = 0; + var T_CURRENT = 1; + + var v_newt_lim = 0.3; // Voltage limited Newton great for Mos/diodes + var v_abstol = 1e-6; // Absolute voltage error tolerance + var i_abstol = 1e-12; // Absolute current error tolerance + var eps = 1.0e-12; // A very small number compared to one. + var dc_max_iters = 1000; // max iterations before giving up + var max_tran_iters = 20; // max iterations before giving up + var time_step_increase_factor = 2.0; // How much can lte let timestep grow. + var lte_step_decrease_factor = 8; // Limit lte one-iter timestep shrink. + var nr_step_decrease_factor = 4; // Newton failure timestep shrink. + var reltol = 0.0001; // Relative tol to max observed value + var lterel = 10; // LTE/Newton tolerance ratio (> 10!) + var res_check_abs = Math.sqrt(i_abstol); // Loose Newton residue check + var res_check_rel = Math.sqrt(reltol); // Loose Newton residue check + + function Circuit() { + this.node_map = []; + this.ntypes = []; + this.initial_conditions = []; + this.devices = []; + this.device_map = []; + this.voltage_sources = []; + this.current_sources = []; + this.finalized = false; + this.diddc = false; + this.node_index = -1; + this.periods = 1 + } + + // index of ground node + Circuit.prototype.gnd_node = function() { + return -1; + } + + // allocate a new node index + Circuit.prototype.node = function(name,ntype,ic) { + this.node_index += 1; + if (name) this.node_map[name] = this.node_index; + this.ntypes.push(ntype); + this.initial_conditions.push(ic); + return this.node_index; + } + + // call to finalize the circuit in preparation for simulation + Circuit.prototype.finalize = function() { + if (!this.finalized) { + this.finalized = true; + this.N = this.node_index + 1; // number of nodes + + // give each device a chance to finalize itself + for (var i = this.devices.length - 1; i >= 0; --i) + this.devices[i].finalize(this); + + // set up augmented matrix and various temp vectors + this.matrix = mat_make(this.N, this.N+1); + this.Gl = mat_make(this.N, this.N); // Matrix for linear conductances + this.G = mat_make(this.N, this.N); // Complete conductance matrix + this.C = mat_make(this.N, this.N); // Matrix for linear L's and C's + + this.soln_max = new Array(this.N); // max abs value seen for each unknown + this.abstol = new Array(this.N); + this.solution = new Array(this.N); + this.rhs = new Array(this.N); + for (var i = this.N - 1; i >= 0; --i) { + this.soln_max[i] = 0.0; + this.abstol[i] = this.ntypes[i] == T_VOLTAGE ? v_abstol : i_abstol; + this.solution[i] = 0.0; + this.rhs[i] = 0.0; + } + + // Load up the linear elements once and for all + for (var i = this.devices.length - 1; i >= 0; --i) { + this.devices[i].load_linear(this) + } + + // Check for voltage source loops. + var n_vsrc = this.voltage_sources.length; + if (n_vsrc > 0) { // At least one voltage source + var GV = mat_make(n_vsrc, this.N); // Loop check + for (var i = n_vsrc - 1; i >= 0; --i) { + var branch = this.voltage_sources[i].branch; + for (var j = this.N - 1; j >= 0; j--) + GV[i][j] = this.Gl[branch][j]; + } + var rGV = mat_rank(GV); + if (rGV < n_vsrc) { + alert('Warning!!! Circuit has a voltage source loop or a source or current probe shorted by a wire, please remove the source or the wire causing the short.'); + alert('Warning!!! Simulator might produce meaningless results or no result with illegal circuits.'); + return false; + } + } + } + return true; + } + + // load circuit from JSON netlist (see schematic.js) + Circuit.prototype.load_netlist = function(netlist) { + // set up mapping for all ground connections + for (var i = netlist.length - 1; i >= 0; --i) { + var component = netlist[i]; + var type = component[0]; + if (type == 'g') { + var connections = component[3]; + this.node_map[connections[0]] = this.gnd_node(); + } + } + + // process each component in the JSON netlist (see schematic.js for format) + var found_ground = false; + for (var i = netlist.length - 1; i >= 0; --i) { + var component = netlist[i]; + var type = component[0]; + + // ignore wires, ground connections, scope probes and view info + if (type == 'view' || type == 'w' || type == 'g' || type == 's' || type == 'L') { + continue; + } + + var properties = component[2]; + var name = properties['name']; + if (name==undefined || name=='') + name = '_' + properties['_json_'].toString(); + + // convert node names to circuit indicies + var connections = component[3]; + for (var j = connections.length - 1; j >= 0; --j) { + var node = connections[j]; + var index = this.node_map[node]; + if (index == undefined) index = this.node(node,T_VOLTAGE); + else if (index == this.gnd_node()) found_ground = true; + connections[j] = index; + } + + // process the component + if (type == 'r') // resistor + this.r(connections[0],connections[1],properties['r'],name); + else if (type == 'd') // diode + this.d(connections[0],connections[1],properties['area'],properties['type'],name); + else if (type == 'c') // capacitor + this.c(connections[0],connections[1],properties['c'],name); + else if (type == 'l') // inductor + this.l(connections[0],connections[1],properties['l'],name); + else if (type == 'v') // voltage source + this.v(connections[0],connections[1],properties['value'],name); + else if (type == 'i') // current source + this.i(connections[0],connections[1],properties['value'],name); + else if (type == 'o') // op amp + this.opamp(connections[0],connections[1],connections[2],connections[3],properties['A'],name); + else if (type == 'n') // n fet + this.n(connections[0],connections[1],connections[2],properties['W/L'],name); + else if (type == 'p') // p fet + this.p(connections[0],connections[1],connections[2],properties['W/L'],name); + else if (type == 'a') // current probe == 0-volt voltage source + this.v(connections[0],connections[1],'0',name); + } + + if (!found_ground) { // No ground on schematic + alert('Please make at least one connection to ground (inverted T symbol)'); + return false; + } + return true; + } + + // if converges: updates this.solution, this.soln_max, returns iter count + // otherwise: return undefined and set this.problem_node + // Load should compute -f and df/dx (note the sign pattern!) + Circuit.prototype.find_solution = function(load,maxiters) { + var soln = this.solution; + var rhs = this.rhs; + var d_sol = []; + var abssum_compare; + var converged,abssum_old=0, abssum_rhs; + var use_limiting = false; + var down_count = 0; + var thresh; + + // iteratively solve until values convere or iteration limit exceeded + for (var iter = 0; iter < maxiters; iter++) { + // set up equations + load(this,soln,rhs); + + // Compute norm of rhs, assume variables of v type go with eqns of i type + abssum_rhs = 0; + for (var i = this.N - 1; i >= 0; --i) + if (this.ntypes[i] == T_VOLTAGE) + abssum_rhs += Math.abs(rhs[i]); + + if ((iter > 0) && (use_limiting == false) && (abssum_old < abssum_rhs)) { + // Old rhsnorm was better, undo last iter and turn on limiting + for (var i = this.N - 1; i >= 0; --i) + soln[i] -= d_sol[i]; + iter -= 1; + use_limiting = true; + } + else { // Compute the Newton delta + d_sol = mat_solve_rq(this.matrix,rhs); + + // If norm going down for ten iters, stop limiting + if (abssum_rhs < abssum_old) + down_count += 1; + else + down_count = 0; + if (down_count > 10) { + use_limiting = false; + down_count = 0; + } + + // Update norm of rhs + abssum_old = abssum_rhs; + } + + // Update the worst case abssum for comparison. + if ((iter == 0) || (abssum_rhs > abssum_compare)) + abssum_compare = abssum_rhs; + + // Check residue convergence, but loosely, and give up + // on last iteration + if ( (iter < (maxiters - 1)) && + (abssum_rhs > (res_check_abs+res_check_rel*abssum_compare))) + converged = false; + else converged = true; + + + // Update solution and check delta convergence + for (var i = this.N - 1; i >= 0; --i) { + // Simple voltage step limiting to encourage Newton convergence + if (use_limiting) { + if (this.ntypes[i] == T_VOLTAGE) { + d_sol[i] = (d_sol[i] > v_newt_lim) ? v_newt_lim : d_sol[i]; + d_sol[i] = (d_sol[i] < -v_newt_lim) ? -v_newt_lim : d_sol[i]; + } + } + soln[i] += d_sol[i]; + thresh = this.abstol[i] + reltol*this.soln_max[i]; + if (Math.abs(d_sol[i]) > thresh) { + converged = false; + this.problem_node = i; + } + } + + if (converged == true) { + for (var i = this.N - 1; i >= 0; --i) + if (Math.abs(soln[i]) > this.soln_max[i]) + this.soln_max[i] = Math.abs(soln[i]); + return iter+1; + } + } + return undefined; + } + + // DC analysis + Circuit.prototype.dc = function() { + // Allocation matrices for linear part, etc. + if (this.finalize() == false) + return undefined; + + // Define -f and df/dx for Newton solver + function load_dc(ckt,soln,rhs) { + // rhs is initialized to -Gl * soln + mat_v_mult(ckt.Gl, soln, rhs, -1.0); + // G matrix is initialized with linear Gl + mat_copy(ckt.Gl,ckt.G); + // Now load up the nonlinear parts of rhs and G + for (var i = ckt.devices.length - 1; i >= 0; --i) + ckt.devices[i].load_dc(ckt,soln,rhs); + // G matrix is copied in to the system matrix + mat_copy(ckt.G,ckt.matrix); + } + + // find the operating point + var iterations = this.find_solution(load_dc,dc_max_iters); + + if (typeof iterations == 'undefined') { + // too many iterations + if (this.current_sources.length > 0) { + alert('Newton Method Failed, do your current sources have a conductive path to ground?'); + } else { + alert('Newton Method Failed, it may be your circuit or it may be our simulator.'); + } + + return undefined + } else { + // Note that a dc solution was computed + this.diddc = true; + // create solution dictionary + var result = []; + // capture node voltages + for (var name in this.node_map) { + var index = this.node_map[name]; + result[name] = (index == -1) ? 0 : this.solution[index]; + } + // capture branch currents from voltage sources + for (var i = this.voltage_sources.length - 1; i >= 0; --i) { + var v = this.voltage_sources[i]; + result['I('+v.name+')'] = this.solution[v.branch]; + } + return result; + } + } + + // Transient analysis (needs work!) + Circuit.prototype.tran = function(ntpts, tstart, tstop, probenames, no_dc) { + + // Define -f and df/dx for Newton solver + function load_tran(ckt,soln,rhs) { + // Crnt is initialized to -Gl * soln + mat_v_mult(ckt.Gl, soln, ckt.c,-1.0); + // G matrix is initialized with linear Gl + mat_copy(ckt.Gl,ckt.G); + // Now load up the nonlinear parts of crnt and G + for (var i = ckt.devices.length - 1; i >= 0; --i) + ckt.devices[i].load_tran(ckt,soln,ckt.c,ckt.time); + // Exploit the fact that storage elements are linear + mat_v_mult(ckt.C, soln, ckt.q, 1.0); + // -rhs = c - dqdt + for (var i = ckt.N-1; i >= 0; --i) { + var dqdt = ckt.alpha0*ckt.q[i] + ckt.alpha1*ckt.oldq[i] + + ckt.alpha2*ckt.old2q[i]; + rhs[i] = ckt.beta0[i]*ckt.c[i] + ckt.beta1[i]*ckt.oldc[i] - dqdt; + } + // matrix = beta0*G + alpha0*C. + mat_scale_add(ckt.G,ckt.C,ckt.beta0,ckt.alpha0,ckt.matrix); + } + + var p = new Array(3); + function interp_coeffs(t, t0, t1, t2) { + // Poly coefficients + var dtt0 = (t - t0); + var dtt1 = (t - t1); + var dtt2 = (t - t2); + var dt0dt1 = (t0 - t1); + var dt0dt2 = (t0 - t2); + var dt1dt2 = (t1 - t2); + p[0] = (dtt1*dtt2)/(dt0dt1 * dt0dt2); + p[1] = (dtt0*dtt2)/(-dt0dt1 * dt1dt2); + p[2] = (dtt0*dtt1)/(dt0dt2 * dt1dt2); + return p; + } + + function pick_step(ckt, step_index) { + var min_shrink_factor = 1.0/lte_step_decrease_factor; + var max_growth_factor = time_step_increase_factor; + var N = ckt.N; + var p = interp_coeffs(ckt.time, ckt.oldt, ckt.old2t, ckt.old3t); + var trapcoeff = 0.5*(ckt.time - ckt.oldt)/(ckt.time - ckt.old3t); + var maxlteratio = 0.0; + for (var i = ckt.N-1; i >= 0; --i) { + if (ckt.ltecheck[i]) { // Check lte on variable + var pred = p[0]*ckt.oldsol[i] + p[1]*ckt.old2sol[i] + p[2]*ckt.old3sol[i]; + var lte = Math.abs((ckt.solution[i] - pred))*trapcoeff; + var lteratio = lte/(lterel*(ckt.abstol[i] + reltol*ckt.soln_max[i])); + maxlteratio = Math.max(maxlteratio, lteratio); + } + } + var new_step; + var lte_step_ratio = 1.0/Math.pow(maxlteratio,1/3); // Cube root because trap + if (lte_step_ratio < 1.0) { // Shrink the timestep to make lte + lte_step_ratio = Math.max(lte_step_ratio,min_shrink_factor); + new_step = (ckt.time - ckt.oldt)*0.75*lte_step_ratio; + new_step = Math.max(new_step, ckt.min_step); + } else { + lte_step_ratio = Math.min(lte_step_ratio, max_growth_factor); + if (lte_step_ratio > 1.2) /* Increase timestep due to lte. */ + new_step = (ckt.time - ckt.oldt) * lte_step_ratio / 1.2; + else + new_step = (ckt.time - ckt.oldt); + new_step = Math.min(new_step, ckt.max_step); + } + return new_step; + } + + // Standard to do a dc analysis before transient + // Otherwise, do the setup also done in dc. + no_dc = false; + if ((this.diddc == false) && (no_dc == false)) { + if (this.dc() == undefined) { // DC failed, realloc mats and vects. + alert('DC failed, trying transient analysis from zero.'); + this.finalized = false; // Reset the finalization. + if (this.finalize() == false) + return undefined; + } + } + else { + if (this.finalize() == false) // Allocate matrices and vectors. + return undefined; + } + + // Tired of typing this, and using "with" generates hate mail. + var N = this.N; + + // build array to hold list of results for each variable + // last entry is for timepoints. + var response = new Array(N + 1); + for (var i = N; i >= 0; --i) response[i] = []; + + // Allocate back vectors for up to a second order method + this.old3sol = new Array(this.N); + this.old3q = new Array(this.N); + this.old2sol = new Array(this.N); + this.old2q = new Array(this.N); + this.oldsol = new Array(this.N); + this.oldq = new Array(this.N); + this.q = new Array(this.N); + this.oldc = new Array(this.N); + this.c = new Array(this.N); + this.alpha0 = 1.0; + this.alpha1 = 0.0; + this.alpha2 = 0.0; + this.beta0 = new Array(this.N); + this.beta1 = new Array(this.N); + + // Mark a set of algebraic variable (don't miss hidden ones!). + this.ar = this.algebraic(this.C); + + // Non-algebraic variables and probe variables get lte + this.ltecheck = new Array(this.N); + for (var i = N; i >= 0; --i) + this.ltecheck[i] = (this.ar[i] == 0); + + for (var name in this.node_map) { + var index = this.node_map[name]; + for (var i = probenames.length; i >= 0; --i) { + if (name == probenames[i]) { + this.ltecheck[index] = true; + break; + } + } + } + + // Check for periodic sources + var period = tstop - tstart; + for (var i = this.voltage_sources.length - 1; i >= 0; --i) { + var per = this.voltage_sources[i].src.period; + if (per > 0) + period = Math.min(period, per); + } + for (var i = this.current_sources.length - 1; i >= 0; --i) { + var per = this.current_sources[i].src.period; + if (per > 0) + period = Math.min(period, per); + } + this.periods = Math.ceil((tstop - tstart)/period); + + this.time = tstart; + // ntpts adjusted by numbers of periods in input + this.max_step = (tstop - tstart)/(this.periods*ntpts); + this.min_step = this.max_step/1e8; + var new_step = this.max_step/1e6; + this.oldt = this.time - new_step; + + // Initialize old crnts, charges, and solutions. + load_tran(this,this.solution,this.rhs) + for (var i = N-1; i >= 0; --i) { + this.old3sol[i] = this.solution[i]; + this.old2sol[i] = this.solution[i]; + this.oldsol[i] = this.solution[i]; + this.old3q[i] = this.q[i]; + this.old2q[i] = this.q[i]; + this.oldq[i] = this.q[i]; + this.oldc[i] = this.c[i]; + } + + var beta0,beta1; + // Start with two pseudo-Euler steps, maximum 50000 steps/period + var max_nsteps = this.periods*50000; + for(var step_index = -3; step_index < max_nsteps; step_index++) { + // Save the just computed solution, and move back q and c. + for (var i = this.N - 1; i >= 0; --i) { + if (step_index >= 0) + response[i].push(this.solution[i]); + this.oldc[i] = this.c[i]; + this.old3sol[i] = this.old2sol[i]; + this.old2sol[i] = this.oldsol[i]; + this.oldsol[i] = this.solution[i]; + this.old3q[i] = this.oldq[i]; + this.old2q[i] = this.oldq[i]; + this.oldq[i] = this.q[i]; + } + + if (step_index < 0) { // Take a prestep using BE + this.old3t = this.old2t - (this.oldt-this.old2t) + this.old2t = this.oldt - (tstart-this.oldt) + this.oldt = tstart - (this.time - this.oldt); + this.time = tstart; + beta0 = 1.0; + beta1 = 0.0; + } else { // Take a regular step + // Save the time, and rotate time wheel + response[this.N].push(this.time); + this.old3t = this.old2t; + this.old2t = this.oldt; + this.oldt = this.time; + // Make sure we come smoothly in to the interval end. + if (this.time >= tstop) break; // We're done. + else if(this.time + new_step > tstop) + this.time = tstop; + else if(this.time + 1.5*new_step > tstop) + this.time += (2/3)*(tstop - this.time); + else + this.time += new_step; + + // Use trap (average old and new crnts. + beta0 = 0.5; + beta1 = 0.5; + } + + // For trap rule, turn off current avging for algebraic eqns + for (var i = this.N - 1; i >= 0; --i) { + this.beta0[i] = beta0 + this.ar[i]*beta1; + this.beta1[i] = (1.0 - this.ar[i])*beta1; + } + + // Loop to find NR converging timestep with okay LTE + while (true) { + // Set the timestep coefficients (alpha2 is for bdf2). + this.alpha0 = 1.0/(this.time - this.oldt); + this.alpha1 = -this.alpha0; + this.alpha2 = 0; + + // If timestep is 1/10,000th of tstop, just use BE. + if ((this.time-this.oldt) < 1.0e-4*tstop) { + for (var i = this.N - 1; i >= 0; --i) { + this.beta0[i] = 1.0; + this.beta1[i] = 0.0; + } + } + // Use Newton to compute the solution. + var iterations = this.find_solution(load_tran,max_tran_iters); + + // If NR succeeds and stepsize is at min, accept and newstep=maxgrowth*minstep. + // Else if Newton Fails, shrink step by a factor and try again + // Else LTE picks new step, if bigger accept current step and go on. + if ((iterations != undefined) && + (step_index <= 0 || (this.time-this.oldt) < (1+reltol)*this.min_step)) { + if (step_index > 0) new_step = time_step_increase_factor*this.min_step; + break; + } else if (iterations == undefined) { // NR nonconvergence, shrink by factor + this.time = this.oldt + + (this.time - this.oldt)/nr_step_decrease_factor; + } else { // Check the LTE and shrink step if needed. + new_step = pick_step(this, step_index); + if (new_step < (1.0 - reltol)*(this.time - this.oldt)) { + this.time = this.oldt + new_step; // Try again + } + else + break; // LTE okay, new_step for next step + } + } + } + + // create solution dictionary + var result = []; + for (var name in this.node_map) { + var index = this.node_map[name]; + result[name] = (index == -1) ? 0 : response[index]; + } + // capture branch currents from voltage sources + for (var i = this.voltage_sources.length - 1; i >= 0; --i) { + var v = this.voltage_sources[i]; + result['I('+v.name+')'] = response[v.branch]; + } + + result['_time_'] = response[this.N]; + return result; + } + + // AC analysis: npts/decade for freqs in range [fstart,fstop] + // result['_frequencies_'] = vector of log10(sample freqs) + // result['xxx'] = vector of dB(response for node xxx) + // NOTE: Normalization removed in schematic.js, jkw. + Circuit.prototype.ac = function(npts,fstart,fstop,source_name) { + + if (this.dc() == undefined) { // DC failed, realloc mats and vects. + return undefined; + } + + var N = this.N; + var G = this.G; + var C = this.C; + + // Complex numbers, we're going to need a bigger boat + var matrixac = mat_make(2*N, (2*N)+1); + + // Get the source used for ac + if (this.device_map[source_name] === undefined) { + alert('AC analysis refers to unknown source ' + source_name); + return 'AC analysis failed, unknown source'; + } + this.device_map[source_name].load_ac(this,this.rhs); + + // build array to hold list of magnitude and phases for each node + // last entry is for frequency values + var response = new Array(2*N + 1); + for (var i = 2*N; i >= 0; --i) response[i] = []; + + // multiplicative frequency increase between freq points + var delta_f = Math.exp(Math.LN10/npts); + + var phase_offset = new Array(N); + for (var i = N-1; i >= 0; --i) phase_offset[i] = 0; + + var f = fstart; + fstop *= 1.0001; // capture that last freq point! + while (f <= fstop) { + var omega = 2 * Math.PI * f; + response[2*N].push(f); // 2*N for magnitude and phase + + // Find complex x+jy that sats Gx-omega*Cy=rhs; omega*Cx+Gy=0 + // Note: solac[0:N-1]=x, solac[N:2N-1]=y + for (var i = N-1; i >= 0; --i) { + // First the rhs, replicated for real and imaginary + matrixac[i][2*N] = this.rhs[i]; + matrixac[i+N][2*N] = 0; + + for (var j = N-1; j >= 0; --j) { + matrixac[i][j] = G[i][j]; + matrixac[i+N][j+N] = G[i][j]; + matrixac[i][j+N] = -omega*C[i][j]; + matrixac[i+N][j] = omega*C[i][j]; + } + } + + // Compute the small signal response + var solac = mat_solve(matrixac); + + // Save magnitude and phase + for (var i = N - 1; i >= 0; --i) { + var mag = Math.sqrt(solac[i]*solac[i] + solac[i+N]*solac[i+N]); + response[i].push(mag); + + // Avoid wrapping phase, add or sub 180 for each jump + var phase = 180*(Math.atan2(solac[i+N],solac[i])/Math.PI); + var phasei = response[i+N]; + var L = phasei.length; + // Look for a one-step jump greater than 90 degrees + if (L > 1) { + var phase_jump = phase + phase_offset[i] - phasei[L-1]; + if (phase_jump > 90) { + phase_offset[i] -= 360; + } else if (phase_jump < -90) { + phase_offset[i] += 360; + } + } + response[i+N].push(phase + phase_offset[i]); + } + f *= delta_f; // increment frequency + } + + // create solution dictionary + var result = []; + for (var name in this.node_map) { + var index = this.node_map[name]; + result[name] = (index == -1) ? 0 : response[index]; + result[name+'_phase'] = (index == -1) ? 0 : response[index+N]; + } + result['_frequencies_'] = response[2*N]; + return result; + } + + // Helper for adding devices to a circuit, warns on duplicate device names. + Circuit.prototype.add_device = function(d,name) { + // Add device to list of devices and to device map + this.devices.push(d); + d.name = name; + if (name) { + if (this.device_map[name] === undefined) + this.device_map[name] = d; + else { + alert('Warning: two circuit elements share the same name ' + name); + this.device_map[name] = d; + } + } + return d; + } + + Circuit.prototype.r = function(n1,n2,v,name) { + // try to convert string value into numeric value, barf if we can't + if ((typeof v) == 'string') { + v = parse_number(v,undefined); + if (v === undefined) return undefined; + } + + if (v != 0) { + var d = new Resistor(n1,n2,v); + return this.add_device(d, name); + } else return this.v(n1,n2,'0',name); // zero resistance == 0V voltage source + } + + Circuit.prototype.d = function(n1,n2,area,type,name) { + // try to convert string value into numeric value, barf if we can't + if ((typeof area) == 'string') { + area = parse_number(area,undefined); + if (area === undefined) return undefined; + } + + if (area != 0) { + var d = new Diode(n1,n2,area,type); + return this.add_device(d, name); + } // zero area diodes discarded. + } + + Circuit.prototype.c = function(n1,n2,v,name) { + // try to convert string value into numeric value, barf if we can't + if ((typeof v) == 'string') { + v = parse_number(v,undefined); + if (v === undefined) return undefined; + } + var d = new Capacitor(n1,n2,v); + return this.add_device(d, name); + } + + Circuit.prototype.l = function(n1,n2,v,name) { + // try to convert string value into numeric value, barf if we can't + if ((typeof v) == 'string') { + v = parse_number(v,undefined); + if (v === undefined) return undefined; + } + var branch = this.node(undefined,T_CURRENT); + var d = new Inductor(n1,n2,branch,v); + return this.add_device(d, name); + } + + Circuit.prototype.v = function(n1,n2,v,name) { + var branch = this.node(undefined,T_CURRENT); + var d = new VSource(n1,n2,branch,v); + this.voltage_sources.push(d); + return this.add_device(d, name); + } + + Circuit.prototype.i = function(n1,n2,v,name) { + var d = new ISource(n1,n2,v); + this.current_sources.push(d); + return this.add_device(d, name); + } + + Circuit.prototype.opamp = function(np,nn,no,ng,A,name) { + var ratio; + // try to convert string value into numeric value, barf if we can't + if ((typeof A) == 'string') { + ratio = parse_number(A,undefined); + if (A === undefined) return undefined; + } + var branch = this.node(undefined,T_CURRENT); + var d = new Opamp(np,nn,no,ng,branch,A,name); + return this.add_device(d, name); + } + + Circuit.prototype.n = function(d,g,s, ratio, name) { + // try to convert string value into numeric value, barf if we can't + if ((typeof ratio) == 'string') { + ratio = parse_number(ratio,undefined); + if (ratio === undefined) return undefined; + } + var d = new Fet(d,g,s,ratio,name,'n'); + return this.add_device(d, name); + } + + Circuit.prototype.p = function(d,g,s, ratio, name) { + // try to convert string value into numeric value, barf if we can't + if ((typeof ratio) == 'string') { + ratio = parse_number(ratio,undefined); + if (ratio === undefined) return undefined; + } + var d = new Fet(d,g,s,ratio,name,'p'); + return this.add_device(d, name); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Support for creating conductance and capacitance matrices associated with + // modified nodal analysis (unknowns are node voltages and inductor and voltage + // source currents). + // The linearized circuit is written as + // C d/dt x = G x + rhs + // x - vector of node voltages and element currents + // rhs - vector of source values + // C - Matrix whose values are capacitances and inductances, has many zero rows. + // G - Matrix whose values are conductances and +-1's. + // + //////////////////////////////////////////////////////////////////////////////// + + // add val component between two nodes to matrix M + // Index of -1 refers to ground node + Circuit.prototype.add_two_terminal = function(i,j,g,M) { + if (i >= 0) { + M[i][i] += g; + if (j >= 0) { + M[i][j] -= g; + M[j][i] -= g; + M[j][j] += g; + } + } else if (j >= 0) + M[j][j] += g; + } + + // add val component between two nodes to matrix M + // Index of -1 refers to ground node + Circuit.prototype.get_two_terminal = function(i,j,x) { + var xi_minus_xj = 0; + if (i >= 0) xi_minus_xj = x[i]; + if (j >= 0) xi_minus_xj -= x[j]; + return xi_minus_xj + } + + Circuit.prototype.add_conductance_l = function(i,j,g) { + this.add_two_terminal(i,j,g, this.Gl) + } + + Circuit.prototype.add_conductance = function(i,j,g) { + this.add_two_terminal(i,j,g, this.G) + } + + Circuit.prototype.add_capacitance = function(i,j,c) { + this.add_two_terminal(i,j,c,this.C) + } + + // add individual conductance to Gl matrix + Circuit.prototype.add_to_Gl = function(i,j,g) { + if (i >=0 && j >= 0) + this.Gl[i][j] += g; + } + + // add individual conductance to Gl matrix + Circuit.prototype.add_to_G = function(i,j,g) { + if (i >=0 && j >= 0) + this.G[i][j] += g; + } + + // add individual capacitance to C matrix + Circuit.prototype.add_to_C = function(i,j,c) { + if (i >=0 && j >= 0) + this.C[i][j] += c; + } + + // add source info to rhs + Circuit.prototype.add_to_rhs = function(i,v,rhs) { + if (i >= 0) rhs[i] += v; + } + + + /////////////////////////////////////////////////////////////////////////////// + // + // Generic matrix support - making, copying, factoring, rank, etc + // Note, Matrices are stored using nested javascript arrays. + //////////////////////////////////////////////////////////////////////////////// + + // Allocate an NxM matrix + function mat_make(N,M) { + var mat = new Array(N); + for (var i = N - 1; i >= 0; --i) { + mat[i] = new Array(M); + for (var j = M - 1; j >= 0; --j) { + mat[i][j] = 0.0; + } + } + return mat; + } + + // Form b = scale*Mx + function mat_v_mult(M,x,b,scale) { + var n = M.length; + var m = M[0].length; + + if (n != b.length || m != x.length) + throw 'Rows of M mismatched to b or cols mismatch to x.'; + + for (var i = 0; i < n; i++) { + var temp = 0; + for (var j = 0; j < m; j++) temp += M[i][j]*x[j]; + b[i] = scale*temp; // Recall the neg in the name + } + } + + // C = scalea*A + scaleb*B, scalea, scaleb eithers numbers or arrays (row scaling) + function mat_scale_add(A, B, scalea, scaleb, C) { + var n = A.length; + var m = A[0].length; + + if (n > B.length || m > B[0].length) + throw 'Row or columns of A to large for B'; + if (n > C.length || m > C[0].length) + throw 'Row or columns of A to large for C'; + if ((typeof scalea == 'number') && (typeof scaleb == 'number')) + for (var i = 0; i < n; i++) + for (var j = 0; j < m; j++) + C[i][j] = scalea*A[i][j] + scaleb*B[i][j]; + else if ((typeof scaleb == 'number') && (scalea instanceof Array)) + for (var i = 0; i < n; i++) + for (var j = 0; j < m; j++) + C[i][j] = scalea[i]*A[i][j] + scaleb*B[i][j]; + else if ((typeof scaleb instanceof Array) && (scalea instanceof Array)) + for (var i = 0; i < n; i++) + for (var j = 0; j < m; j++) + C[i][j] = scalea[i]*A[i][j] + scaleb[i]*B[i][j]; + else + throw 'scalea and scaleb must be scalars or Arrays'; + } + + // Returns a vector of ones and zeros, ones denote algebraic + // variables (rows that can be removed without changing rank(M). + Circuit.prototype.algebraic = function(M) { + var Nr = M.length + var Mc = mat_make(Nr, Nr); + mat_copy(M,Mc); + var R = mat_rank(Mc); + + var one_if_alg = new Array(Nr); + for (var row = 0; row < Nr; row++) { // psuedo gnd row small + for (var col = Nr - 1; col >= 0; --col) + Mc[row][col] = 0; + if (mat_rank(Mc) == R) // Zeroing row left rank unchanged + one_if_alg[row] = 1; + else { // Zeroing row changed rank, put back + for (var col = Nr - 1; col >= 0; --col) + Mc[row][col] = M[row][col]; + one_if_alg[row] = 0; + } + } + return one_if_alg; + } + + // Copy A -> using the bounds of A + function mat_copy(src,dest) { + var n = src.length; + var m = src[0].length; + if (n > dest.length || m > dest[0].length) + throw 'Rows or cols > rows or cols of dest'; + + for (var i = 0; i < n; i++) + for (var j = 0; j < m; j++) + dest[i][j] = src[i][j]; + } + // Copy and transpose A -> using the bounds of A + function mat_copy_transposed(src,dest) { + var n = src.length; + var m = src[0].length; + if (n > dest[0].length || m > dest.length) + throw 'Rows or cols > cols or rows of dest'; + + for (var i = 0; i < n; i++) + for (var j = 0; j < m; j++) + dest[j][i] = src[i][j]; + } + + + // Uses GE to determine rank. + function mat_rank(Mo) { + var Nr = Mo.length; // Number of rows + var Nc = Mo[0].length; // Number of columns + var temp,i,j; + // Make a copy to avoid overwriting + var M = mat_make(Nr, Nc); + mat_copy(Mo,M); + + // Find matrix maximum entry + var max_abs_entry = 0; + for(var row = Nr-1; row >= 0; --row) { + for(var col = Nr-1; col >= 0; --col) { + if (Math.abs(M[row][col]) > max_abs_entry) + max_abs_entry = Math.abs(M[row][col]); + } + } + + // Gaussian elimination to find rank + var the_rank = 0; + var start_col = 0; + for (var row = 0; row < Nr; row++) { + // Search for first nonzero column in the remaining rows. + for (var col = start_col; col < Nc; col++) { + var max_v = Math.abs(M[row][col]); + var max_row = row; + for (var i = row + 1; i < Nr; i++) { + temp = Math.abs(M[i][col]); + if (temp > max_v) { max_v = temp; max_row = i; } + } + // if max_v non_zero, column is nonzero, eliminate in subsequent rows + if (Math.abs(max_v) > eps*max_abs_entry) { + start_col = col+1; + the_rank += 1; + // Swap rows to get max in M[row][col] + temp = M[row]; + M[row] = M[max_row]; + M[max_row] = temp; + + // now eliminate this column for all subsequent rows + for (var i = row + 1; i < Nr; i++) { + temp = M[i][col]/M[row][col]; // multiplier for current row + if (temp != 0) // subtract + for (var j = col; j < Nc; j++) M[i][j] -= M[row][j]*temp; + } + // Now move on to the next row + break; + } + } + } + + return the_rank; + } + + // Solve Mx=b and return vector x using R^TQ^T factorization. + // Multiplication by R^T implicit, should be null-space free soln. + // M should have the extra column! + // Almost everything is in-lined for speed, sigh. + function mat_solve_rq(M, rhs) { + var scale; + var Nr = M.length; // Number of rows + var Nc = M[0].length; // Number of columns + + // Copy the rhs in to the last column of M if one is given. + if (rhs != null) { + for (var row = Nr - 1; row >= 0; --row) + M[row][Nc-1] = rhs[row]; + } + + var mat_scale = 0; // Sets the scale for comparison to zero. + var max_nonzero_row = Nr-1; // Assumes M nonsingular. + for (var row = 0; row < Nr; row++) { + // Find largest row with largest 2-norm + var max_row = row; + var maxsumsq = 0; + for (var rowp = row; rowp < Nr; rowp++) { + var Mr = M[rowp]; + var sumsq = 0; + for (var col = Nc-2; col >= 0; --col) // Last col=rhs + sumsq += Mr[col]*Mr[col]; + if ((row == rowp) || (sumsq > maxsumsq)) { + max_row = rowp; + maxsumsq = sumsq; + } + } + if (max_row > row) { // Swap rows if not max row + var temp = M[row]; + M[row] = M[max_row]; + M[max_row] = temp; + } + + // Calculate row norm, save if this is first (largest) + var row_norm = Math.sqrt(maxsumsq); + if (row == 0) mat_scale = row_norm; + + // Check for all zero rows + if (row_norm > mat_scale*eps) + scale = 1.0/row_norm; + else { + max_nonzero_row = row - 1; // Rest will be nullspace of M + break; + } + + // Nonzero row, eliminate from rows below + var Mr = M[row]; + for (var col = Nc-1; col >= 0; --col) // Scale rhs also + Mr[col] *= scale; + for (var rowp = row + 1; rowp < Nr; rowp++) { // Update. + var Mrp = M[rowp]; + var inner = 0; + for (var col = Nc-2; col >= 0; --col) // Project + inner += Mr[col]*Mrp[col]; + for (var col = Nc-1; col >= 0; --col) // Ortho (rhs also) + Mrp[col] -= inner *Mr[col]; + } + } + + // Last Column of M has inv(R^T)*rhs. Scale rows of Q to get x. + var x = new Array(Nc-1); + for (var col = Nc-2; col >= 0; --col) + x[col] = 0; + for (var row = max_nonzero_row; row >= 0; --row) { + Mr = M[row]; + for (var col = Nc-2; col >= 0; --col) { + x[col] += Mr[col]*Mr[Nc-1]; + } + } + + return x; + } + + // solve Mx=b and return vector x given augmented matrix M = [A | b] + // Uses Gaussian elimination with partial pivoting + function mat_solve(M,rhs) { + var N = M.length; // augmented matrix M has N rows, N+1 columns + var temp,i,j; + + // Copy the rhs in to the last column of M if one is given. + if (rhs != null) { + for (var row = 0; row < N ; row++) + M[row][N] = rhs[row]; + } + + // gaussian elimination + for (var col = 0; col < N ; col++) { + // find pivot: largest abs(v) in this column of remaining rows + var max_v = Math.abs(M[col][col]); + var max_col = col; + for (i = col + 1; i < N; i++) { + temp = Math.abs(M[i][col]); + if (temp > max_v) { max_v = temp; max_col = i; } + } + + // if no value found, generate a small conductance to gnd + // otherwise swap current row with pivot row + if (max_v == 0) M[col][col] = eps; + else { + temp = M[col]; + M[col] = M[max_col]; + M[max_col] = temp; + } + + // now eliminate this column for all subsequent rows + for (i = col + 1; i < N; i++) { + temp = M[i][col]/M[col][col]; // multiplier we'll use for current row + if (temp != 0) + // subtract current row from row we're working on + // remember to process b too! + for (j = col; j <= N; j++) M[i][j] -= M[col][j]*temp; + } + } + + // matrix is now upper triangular, so solve for elements of x starting + // with the last row + var x = new Array(N); + for (i = N-1; i >= 0; --i) { + temp = M[i][N]; // grab b[i] from augmented matrix as RHS + // subtract LHS term from RHS using known x values + for (j = N-1; j > i; --j) temp -= M[i][j]*x[j]; + // now compute new x value + x[i] = temp/M[i][i]; + } + + return x; + } + + // test solution code, expect x = [2,3,-1] + //M = [[2,1,-1,8],[-3,-1,2,-11],[-2,1,2,-3]]; + //x = mat_solve(M); + //y = 1; // so we have place to set a breakpoint :) + + /////////////////////////////////////////////////////////////////////////////// + // + // Device base class + // + //////////////////////////////////////////////////////////////////////////////// + + function Device() { + } + + // complete initial set up of device + Device.prototype.finalize = function() { + } + + // Load the linear elements in to Gl and C + Device.prototype.load_linear = function(ckt) { + } + + // load linear system equations for dc analysis + // (inductors shorted and capacitors opened) + Device.prototype.load_dc = function(ckt,soln,rhs) { + } + + // load linear system equations for tran analysis + Device.prototype.load_tran = function(ckt,soln) { + } + + // load linear system equations for ac analysis: + // current sources open, voltage sources shorted + // linear models at operating point for everyone else + Device.prototype.load_ac = function(ckt,rhs) { + } + + // return time of next breakpoint for the device + Device.prototype.breakpoint = function(time) { + return undefined; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Parse numbers in engineering notation + // + /////////////////////////////////////////////////////////////////////////////// + + // convert first character of argument into an integer + function ord(ch) { + return ch.charCodeAt(0); + } + + // convert string argument to a number, accepting usual notations + // (hex, octal, binary, decimal, floating point) plus engineering + // scale factors (eg, 1k = 1000.0 = 1e3). + // return default if argument couldn't be interpreted as a number + function parse_number(s,default_v) { + var slen = s.length; + var multiplier = 1; + var result = 0; + var index = 0; + + // skip leading whitespace + while (index < slen && s.charAt(index) <= ' ') index += 1; + if (index == slen) return default_v; + + // check for leading sign + if (s.charAt(index) == '-') { + multiplier = -1; + index += 1; + } else if (s.charAt(index) == '+') + index += 1; + var start = index; // remember where digits start + + // if leading digit is 0, check for hex, octal or binary notation + if (index >= slen) return default_v; + else if (s.charAt(index) == '0') { + index += 1; + if (index >= slen) return 0; + if (s.charAt(index) == 'x' || s.charAt(index) == 'X') { // hex + while (true) { + index += 1; + if (index >= slen) break; + if (s.charAt(index) >= '0' && s.charAt(index) <= '9') + result = result*16 + ord(s.charAt(index)) - ord('0'); + else if (s.charAt(index) >= 'A' && s.charAt(index) <= 'F') + result = result*16 + ord(s.charAt(index)) - ord('A') + 10; + else if (s.charAt(index) >= 'a' && s.charAt(index) <= 'f') + result = result*16 + ord(s.charAt(index)) - ord('a') + 10; + else break; + } + return result*multiplier; + } else if (s.charAt(index) == 'b' || s.charAt(index) == 'B') { // binary + while (true) { + index += 1; + if (index >= slen) break; + if (s.charAt(index) >= '0' && s.charAt(index) <= '1') + result = result*2 + ord(s.charAt(index)) - ord('0'); + else break; + } + return result*multiplier; + } else if (s.charAt(index) != '.') { // octal + while (true) { + if (s.charAt(index) >= '0' && s.charAt(index) <= '7') + result = result*8 + ord(s.charAt(index)) - ord('0'); + else break; + index += 1; + if (index >= slen) break; + } + return result*multiplier; + } + } + // read decimal integer or floating-point number + while (true) { + if (s.charAt(index) >= '0' && s.charAt(index) <= '9') + result = result*10 + ord(s.charAt(index)) - ord('0'); + else break; + index += 1; + if (index >= slen) break; + } + + // fractional part? + if (index < slen && s.charAt(index) == '.') { + while (true) { + index += 1; + if (index >= slen) break; + if (s.charAt(index) >= '0' && s.charAt(index) <= '9') { + result = result*10 + ord(s.charAt(index)) - ord('0'); + multiplier *= 0.1; + } else break; + } + } + + // if we haven't seen any digits yet, don't check + // for exponents or scale factors + if (index == start) return default_v; + + // type of multiplier determines type of result: + // multiplier is a float if we've seen digits past + // a decimal point, otherwise it's an int or long. + // Up to this point result is an int or long. + result *= multiplier; + + // now check for exponent or engineering scale factor. If there + // is one, result will be a float. + if (index < slen) { + var scale = s.charAt(index); + index += 1; + if (scale == 'e' || scale == 'E') { + var exponent = 0; + multiplier = 10.0; + if (index < slen) { + if (s.charAt(index) == '+') index += 1; + else if (s.charAt(index) == '-') { + index += 1; + multiplier = 0.1; + } + } + while (index < slen) { + if (s.charAt(index) >= '0' && s.charAt(index) <= '9') { + exponent = exponent*10 + ord(s.charAt(index)) - ord('0'); + index += 1; + } else break; + } + while (exponent > 0) { + exponent -= 1; + result *= multiplier; + } + } else if (scale == 't' || scale == 'T') result *= 1e12; + else if (scale == 'g' || scale == 'G') result *= 1e9; + else if (scale == 'M') result *= 1e6; + else if (scale == 'k' || scale == 'K') result *= 1e3; + else if (scale == 'm') result *= 1e-3; + else if (scale == 'u' || scale == 'U') result *= 1e-6; + else if (scale == 'n' || scale == 'N') result *= 1e-9; + else if (scale == 'p' || scale == 'P') result *= 1e-12; + else if (scale == 'f' || scale == 'F') result *= 1e-15; + } + // ignore any remaining chars, eg, 1kohms returns 1000 + return result; + } + + Circuit.prototype.parse_number = parse_number; // make it easy to call from outside + + /////////////////////////////////////////////////////////////////////////////// + // + // Sources + // + /////////////////////////////////////////////////////////////////////////////// + + // argument is a string describing the source's value (see comments for details) + // source types: dc,step,square,triangle,sin,pulse,pwl,pwl_repeating + + // returns an object with the following attributes: + // fun -- name of source function + // args -- list of argument values + // value(t) -- compute source value at time t + // inflection_point(t) -- compute time after t when a time point is needed + // dc -- value at time 0 + // period -- repeat period for periodic sources (0 if not periodic) + + function parse_source(v) { + // generic parser: parse v as either or (,...) + var src = {}; + src.period = 0; // Default not periodic + src.value = function(t) { return 0; } // overridden below + src.inflection_point = function(t) { return undefined; }; // may be overridden below + + // see if there's a "(" in the description + var index = v.indexOf('('); + var ch; + if (index >= 0) { + src.fun = v.slice(0,index); // function name is before the "(" + src.args = []; // we'll push argument values onto this list + var end = v.indexOf(')',index); + if (end == -1) end = v.length; + + index += 1; // start parsing right after "(" + while (index < end) { + // figure out where next argument value starts + ch = v.charAt(index); + if (ch <= ' ') { index++; continue; } + // and where it ends + var arg_end = v.indexOf(',',index); + if (arg_end == -1) arg_end = end; + // parse and save result in our list of arg values + src.args.push(parse_number(v.slice(index,arg_end),undefined)); + index = arg_end + 1; + } + } else { + src.fun = 'dc'; + src.args = [parse_number(v,0)]; + } + + // post-processing for constant sources + // dc(v) + if (src.fun == 'dc') { + var v = arg_value(src.args,0,0); + src.args = [v]; + src.value = function(t) { return v; } // closure + } + + // post-processing for impulse sources + // impulse(height,width) + else if (src.fun == 'impulse') { + var h = arg_value(src.args,0,1); // default height: 1 + var w = Math.abs(arg_value(src.args,2,1e-9)); // default width: 1ns + src.args = [h,w]; // remember any defaulted values + pwl_source(src,[0,0,w/2,h,w,0],false); + } + + // post-processing for step sources + // step(v_init,v_plateau,t_delay,t_rise) + else if (src.fun == 'step') { + var v1 = arg_value(src.args,0,0); // default init value: 0V + var v2 = arg_value(src.args,1,1); // default plateau value: 1V + var td = Math.max(0,arg_value(src.args,2,0)); // time step starts + var tr = Math.abs(arg_value(src.args,3,1e-9)); // default rise time: 1ns + src.args = [v1,v2,td,tr]; // remember any defaulted values + pwl_source(src,[td,v1,td+tr,v2],false); + } + + // post-processing for square wave + // square(v_init,v_plateau,freq,duty_cycle) + else if (src.fun == 'square') { + var v1 = arg_value(src.args,0,0); // default init value: 0V + var v2 = arg_value(src.args,1,1); // default plateau value: 1V + var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1Hz + var duty_cycle = Math.min(100,Math.abs(arg_value(src.args,3,50))); // default duty cycle: 0.5 + src.args = [v1,v2,freq,duty_cycle]; // remember any defaulted values + + var per = freq == 0 ? Infinity : 1/freq; + var t_change = 0.01 * per; // rise and fall time + var t_pw = .01 * duty_cycle * 0.98 * per; // fraction of cycle minus rise and fall time + pwl_source(src,[0,v1,t_change,v2,t_change+t_pw, + v2,t_change+t_pw+t_change,v1,per,v1],true); + } + + // post-processing for triangle + // triangle(v_init,v_plateua,t_period) + else if (src.fun == 'triangle') { + var v1 = arg_value(src.args,0,0); // default init value: 0V + var v2 = arg_value(src.args,1,1); // default plateau value: 1V + var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1s + src.args = [v1,v2,freq]; // remember any defaulted values + + var per = freq == 0 ? Infinity : 1/freq; + pwl_source(src,[0,v1,per/2,v2,per,v1],true); + } + + // post-processing for pwl and pwlr sources + // pwl[r](t1,v1,t2,v2,...) + else if (src.fun == 'pwl' || src.fun == 'pwl_repeating') { + pwl_source(src,src.args,src.fun == 'pwl_repeating'); + } + + // post-processing for pulsed sources + // pulse(v_init,v_plateau,t_delay,t_rise,t_fall,t_width,t_period) + else if (src.fun == 'pulse') { + var v1 = arg_value(src.args,0,0); // default init value: 0V + var v2 = arg_value(src.args,1,1); // default plateau value: 1V + var td = Math.max(0,arg_value(src.args,2,0)); // time pulse starts + var tr = Math.abs(arg_value(src.args,3,1e-9)); // default rise time: 1ns + var tf = Math.abs(arg_value(src.args,4,1e-9)); // default rise time: 1ns + var pw = Math.abs(arg_value(src.args,5,1e9)); // default pulse width: "infinite" + var per = Math.abs(arg_value(src.args,6,1e9)); // default period: "infinite" + src.args = [v1,v2,td,tr,tf,pw,per]; + + var t1 = td; // time when v1 -> v2 transition starts + var t2 = t1 + tr; // time when v1 -> v2 transition ends + var t3 = t2 + pw; // time when v2 -> v1 transition starts + var t4 = t3 + tf; // time when v2 -> v1 transition ends + + pwl_source(src,[t1,v1, t2,v2, t3,v2, t4,v1, per,v1],true); + } + + // post-processing for sinusoidal sources + // sin(v_offset,v_amplitude,freq_hz,t_delay,phase_offset_degrees) + else if (src.fun == 'sin') { + var voffset = arg_value(src.args,0,0); // default offset voltage: 0V + var va = arg_value(src.args,1,1); // default amplitude: -1V to 1V + var freq = Math.abs(arg_value(src.args,2,1)); // default frequency: 1Hz + src.period = 1.0/freq; + + var td = Math.max(0,arg_value(src.args,3,0)); // default time delay: 0sec + var phase = arg_value(src.args,4,0); // default phase offset: 0 degrees + src.args = [voffset,va,freq,td,phase]; + + phase /= 360.0; + + // return value of source at time t + src.value = function(t) { // closure + if (t < td) return voffset + va*Math.sin(2*Math.PI*phase); + else return voffset + va*Math.sin(2*Math.PI*(freq*(t - td) + phase)); + } + + // return time of next inflection point after time t + src.inflection_point = function(t) { // closure + if (t < td) return td; + else return undefined; + } + } + + // object has all the necessary info to compute the source value and inflection points + src.dc = src.value(0); // DC value is value at time 0 + return src; + } + + function pwl_source(src,tv_pairs,repeat) { + var nvals = tv_pairs.length; + if (repeat) + src.period = tv_pairs[nvals-2]; // Repeat period of source + if (nvals % 2 == 1) npts -= 1; // make sure it's even! + + if (nvals <= 2) { + // handle degenerate case + src.value = function(t) { return nvals == 2 ? tv_pairs[1] : 0; } + src.inflection_point = function(t) { return undefined; } + } else { + src.value = function(t) { // closure + if (repeat) + // make time periodic if values are to be repeated + t = Math.fmod(t,tv_pairs[nvals-2]); + var last_t = tv_pairs[0]; + var last_v = tv_pairs[1]; + if (t > last_t) { + var next_t,next_v; + for (var i = 2; i < nvals; i += 2) { + next_t = tv_pairs[i]; + next_v = tv_pairs[i+1]; + if (next_t > last_t) // defend against bogus tv pairs + if (t < next_t) + return last_v + (next_v - last_v)*(t - last_t)/(next_t - last_t); + last_t = next_t; + last_v = next_v; + } + } + return last_v; + } + src.inflection_point = function(t) { // closure + if (repeat) + // make time periodic if values are to be repeated + t = Math.fmod(t,tv_pairs[nvals-2]); + for (var i = 0; i < nvals; i += 2) { + var next_t = tv_pairs[i]; + if (t < next_t) return next_t; + } + return undefined; + } + } + } + + // helper function: return args[index] if present, else default_v + function arg_value(args,index,default_v) { + if (index < args.length) { + var result = args[index]; + if (result === undefined) result = default_v; + return result; + } else return default_v; + } + + // we need fmod in the Math library! + Math.fmod = function(numerator,denominator) { + var quotient = Math.floor(numerator/denominator); + return numerator - quotient*denominator; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Sources + // + /////////////////////////////////////////////////////////////////////////////// + + function VSource(npos,nneg,branch,v) { + Device.call(this); + this.src = parse_source(v); + this.npos = npos; + this.nneg = nneg; + this.branch = branch; + } + VSource.prototype = new Device(); + VSource.prototype.constructor = VSource; + + // load linear part for source evaluation + VSource.prototype.load_linear = function(ckt) { + // MNA stamp for independent voltage source + ckt.add_to_Gl(this.branch,this.npos,1.0); + ckt.add_to_Gl(this.branch,this.nneg,-1.0); + ckt.add_to_Gl(this.npos,this.branch,1.0); + ckt.add_to_Gl(this.nneg,this.branch,-1.0); + } + + // Source voltage added to b. + VSource.prototype.load_dc = function(ckt,soln,rhs) { + ckt.add_to_rhs(this.branch,this.src.dc,rhs); + } + + // Load time-dependent value for voltage source for tran + VSource.prototype.load_tran = function(ckt,soln,rhs,time) { + ckt.add_to_rhs(this.branch,this.src.value(time),rhs); + } + + // return time of next breakpoint for the device + VSource.prototype.breakpoint = function(time) { + return this.src.inflection_point(time); + } + + // small signal model ac value + VSource.prototype.load_ac = function(ckt,rhs) { + ckt.add_to_rhs(this.branch,1.0,rhs); + } + + function ISource(npos,nneg,v) { + Device.call(this); + this.src = parse_source(v); + this.npos = npos; + this.nneg = nneg; + } + ISource.prototype = new Device(); + ISource.prototype.constructor = ISource; + + ISource.prototype.load_linear = function(ckt) { + // Current source is open when off, no linear contribution + } + + // load linear system equations for dc analysis + ISource.prototype.load_dc = function(ckt,soln,rhs) { + var is = this.src.dc; + + // MNA stamp for independent current source + ckt.add_to_rhs(this.npos,-is,rhs); // current flow into npos + ckt.add_to_rhs(this.nneg,is,rhs); // and out of nneg + } + + // load linear system equations for tran analysis (just like DC) + ISource.prototype.load_tran = function(ckt,soln,rhs,time) { + var is = this.src.value(time); + + // MNA stamp for independent current source + ckt.add_to_rhs(this.npos,-is,rhs); // current flow into npos + ckt.add_to_rhs(this.nneg,is,rhs); // and out of nneg + } + + // return time of next breakpoint for the device + ISource.prototype.breakpoint = function(time) { + return this.src.inflection_point(time); + } + + // small signal model: open circuit + ISource.prototype.load_ac = function(ckt,rhs) { + // MNA stamp for independent current source + ckt.add_to_rhs(this.npos,-1.0,rhs); // current flow into npos + ckt.add_to_rhs(this.nneg,1.0,rhs); // and out of nneg + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Resistor + // + /////////////////////////////////////////////////////////////////////////////// + + function Resistor(n1,n2,v) { + Device.call(this); + this.n1 = n1; + this.n2 = n2; + this.g = 1.0/v; + } + Resistor.prototype = new Device(); + Resistor.prototype.constructor = Resistor; + + Resistor.prototype.load_linear = function(ckt) { + // MNA stamp for admittance g + ckt.add_conductance_l(this.n1,this.n2,this.g); + } + + Resistor.prototype.load_dc = function(ckt) { + // Nothing to see here, move along. + } + + Resistor.prototype.load_tran = function(ckt,soln) { + } + + Resistor.prototype.load_ac = function(ckt) { + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Diode + // + /////////////////////////////////////////////////////////////////////////////// + + function Diode(n1,n2,v,type) { + Device.call(this); + this.anode = n1; + this.cathode = n2; + this.area = v; + this.type = type; // 'normal' or 'ideal' + this.is = 1.0e-14; + this.ais = this.area * this.is; + this.vt = (type == 'normal') ? 25.8e-3 : 0.1e-3; // 26mv or .1mv + this.exp_arg_max = 50; // less than single precision max. + this.exp_max = Math.exp(this.exp_arg_max); + } + Diode.prototype = new Device(); + Diode.prototype.constructor = Diode; + + Diode.prototype.load_linear = function(ckt) { + // Diode is not linear, has no linear piece. + } + + Diode.prototype.load_dc = function(ckt,soln,rhs) { + var vd = ckt.get_two_terminal(this.anode, this.cathode, soln); + var exp_arg = vd / this.vt; + var temp1, temp2; + // Estimate exponential with a quadratic if arg too big. + var abs_exp_arg = Math.abs(exp_arg); + var d_arg = abs_exp_arg - this.exp_arg_max; + if (d_arg > 0) { + var quad = 1 + d_arg + 0.5*d_arg*d_arg; + temp1 = this.exp_max * quad; + temp2 = this.exp_max * (1 + d_arg); + } else { + temp1 = Math.exp(abs_exp_arg); + temp2 = temp1; + } + if (exp_arg < 0) { // Use exp(-x) = 1.0/exp(x) + temp1 = 1.0/temp1; + temp2 = (temp1*temp2)*temp1; + } + var id = this.ais * (temp1 - 1); + var gd = this.ais * (temp2 / this.vt); + + // MNA stamp for independent current source + ckt.add_to_rhs(this.anode,-id,rhs); // current flows into anode + ckt.add_to_rhs(this.cathode,id,rhs); // and out of cathode + ckt.add_conductance(this.anode,this.cathode,gd); + } + + Diode.prototype.load_tran = function(ckt,soln,rhs,time) { + this.load_dc(ckt,soln,rhs); + } + + Diode.prototype.load_ac = function(ckt) { + } + + + /////////////////////////////////////////////////////////////////////////////// + // + // Capacitor + // + /////////////////////////////////////////////////////////////////////////////// + + function Capacitor(n1,n2,v) { + Device.call(this); + this.n1 = n1; + this.n2 = n2; + this.value = v; + } + Capacitor.prototype = new Device(); + Capacitor.prototype.constructor = Capacitor; + + Capacitor.prototype.load_linear = function(ckt) { + // MNA stamp for capacitance matrix + ckt.add_capacitance(this.n1,this.n2,this.value); + } + + Capacitor.prototype.load_dc = function(ckt,soln,rhs) { + } + + Capacitor.prototype.load_ac = function(ckt) { + } + + Capacitor.prototype.load_tran = function(ckt) { + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Inductor + // + /////////////////////////////////////////////////////////////////////////////// + + function Inductor(n1,n2,branch,v) { + Device.call(this); + this.n1 = n1; + this.n2 = n2; + this.branch = branch; + this.value = v; + } + Inductor.prototype = new Device(); + Inductor.prototype.constructor = Inductor; + + Inductor.prototype.load_linear = function(ckt) { + // MNA stamp for inductor linear part + // L on diag of C because L di/dt = v(n1) - v(n2) + ckt.add_to_Gl(this.n1,this.branch,1); + ckt.add_to_Gl(this.n2,this.branch,-1); + ckt.add_to_Gl(this.branch,this.n1,-1); + ckt.add_to_Gl(this.branch,this.n2,1); + ckt.add_to_C(this.branch,this.branch,this.value) + } + + Inductor.prototype.load_dc = function(ckt,soln,rhs) { + // Inductor is a short at dc, so is linear. + } + + Inductor.prototype.load_ac = function(ckt) { + } + + Inductor.prototype.load_tran = function(ckt) { + } + + + /////////////////////////////////////////////////////////////////////////////// + // + // Simple Voltage-Controlled Voltage Source Op Amp model + // + /////////////////////////////////////////////////////////////////////////////// + + function Opamp(np,nn,no,ng,branch,A,name) { + Device.call(this); + this.np = np; + this.nn = nn; + this.no = no; + this.ng = ng; + this.branch = branch; + this.gain = A; + this.name = name; + } + + Opamp.prototype = new Device(); + Opamp.prototype.constructor = Opamp; + Opamp.prototype.load_linear = function(ckt) { + // MNA stamp for VCVS: 1/A(v(no) - v(ng)) - (v(np)-v(nn))) = 0. + var invA = 1.0/this.gain; + ckt.add_to_Gl(this.no,this.branch,1); + ckt.add_to_Gl(this.ng,this.branch,-1); + ckt.add_to_Gl(this.branch,this.no,invA); + ckt.add_to_Gl(this.branch,this.ng,-invA); + ckt.add_to_Gl(this.branch,this.np,-1); + ckt.add_to_Gl(this.branch,this.nn,1); + } + + Opamp.prototype.load_dc = function(ckt,soln,rhs) { + // Op-amp is linear. + } + + Opamp.prototype.load_ac = function(ckt) { + } + + Opamp.prototype.load_tran = function(ckt) { + } + + + /////////////////////////////////////////////////////////////////////////////// + // + // Simplified MOS FET with no bulk connection and no body effect. + // + /////////////////////////////////////////////////////////////////////////////// + + function Fet(d,g,s,ratio,name,type) { + Device.call(this); + this.d = d; + this.g = g; + this.s = s; + this.name = name; + this.ratio = ratio; + if (type != 'n' && type != 'p') + { throw 'fet type is not n or p'; + } + this.type_sign = (type == 'n') ? 1 : -1; + this.vt = 0.5; + this.kp = 20e-6; + this.beta = this.kp * this.ratio; + this.lambda = 0.05; + } + Fet.prototype = new Device(); + Fet.prototype.constructor = Fet; + + Fet.prototype.load_linear = function(ckt) { + // FET's are nonlinear, just like javascript progammers + } + + Fet.prototype.load_dc = function(ckt,soln,rhs) { + var vds = this.type_sign * ckt.get_two_terminal(this.d, this.s, soln); + if (vds < 0) { // Drain and source have swapped roles + var temp = this.d; + this.d = this.s; + this.s = temp; + vds = this.type_sign * ckt.get_two_terminal(this.d, this.s, soln); + } + var vgs = this.type_sign * ckt.get_two_terminal(this.g, this.s, soln); + var vgst = vgs - this.vt; + var gmgs,ids,gds; + if (vgst > 0.0 ) { // vgst < 0, transistor off, no subthreshold here. + if (vgst < vds) { /* Saturation. */ + gmgs = this.beta * (1 + (this.lambda * vds)) * vgst; + ids = this.type_sign * 0.5 * gmgs * vgst; + gds = 0.5 * this.beta * vgst * vgst * this.lambda; + } else { /* Linear region */ + gmgs = this.beta * (1 + this.lambda * vds); + ids = this.type_sign * gmgs * vds * (vgst - 0.50 * vds); + gds = gmgs * (vgst - vds) + this.beta * this.lambda * vds * (vgst - 0.5 * vds); + gmgs *= vds; + } + ckt.add_to_rhs(this.d,-ids,rhs); // current flows into the drain + ckt.add_to_rhs(this.s, ids,rhs); // and out the source + ckt.add_conductance(this.d,this.s,gds); + ckt.add_to_G(this.s,this.s, gmgs); + ckt.add_to_G(this.d,this.s,-gmgs); + ckt.add_to_G(this.d,this.g, gmgs); + ckt.add_to_G(this.s,this.g,-gmgs); + } + } + + Fet.prototype.load_tran = function(ckt,soln,rhs) { + this.load_dc(ckt,soln,rhs); + } + + Fet.prototype.load_ac = function(ckt) { + } + + + /////////////////////////////////////////////////////////////////////////////// + // + // Module definition + // + /////////////////////////////////////////////////////////////////////////////// + var module = { + 'Circuit': Circuit, + 'parse_number': parse_number, + 'parse_source': parse_source + } + return module; + }()); + +///////////////////////////////////////////////////////////////////////////// +// +// Simple schematic capture +// +//////////////////////////////////////////////////////////////////////////////// + +// Copyright (C) 2011 Massachusetts Institute of Technology + +// add schematics to a document with +// +// +// +// other attributes you can add to the input tag: +// width -- width in pixels of diagram +// height -- height in pixels of diagram +// parts -- comma-separated list of parts for parts bin (see parts_map), +// parts="" disables editing of diagram + +// JSON schematic representation: +// sch := [part, part, ...] +// part := [type, coords, properties, connections] +// type := string (see parts_map) +// coords := [number, ...] // (x,y,rot) or (x1,y1,x2,y2) +// properties := {name: value, ...} +// connections := [node, ...] // one per connection point in canoncial order +// node := string +// need a netlist? just use the part's type, properites and connections + +// TO DO: +// - wire labels? +// - zoom/scroll canvas +// - rotate multiple objects around their center of mass +// - rubber band wires when moving components + +// set up each schematic entry widget +function update_schematics() { + // set up each schematic on the page + var schematics = $('.schematic'); + for (var i = 0; i < schematics.length; ++i) + if (schematics[i].getAttribute("loaded") != "true") { + try { + new schematic.Schematic(schematics[i]); + } catch (err) { + var msgdiv = document.createElement('div'); + msgdiv.style.border = 'thick solid #FF0000'; + msgdiv.style.margins = '20px'; + msgdiv.style.padding = '20px'; + var msg = document.createTextNode('Sorry, there a browser error in starting the schematic tool. The tool is known to be compatible with the latest versions of Firefox and Chrome, which we recommend you use.'); + msgdiv.appendChild(msg); + schematics[i].parentNode.insertBefore(msgdiv,schematics[i]); + } + schematics[i].setAttribute("loaded","true"); + } +} +window.update_schematics = update_schematics; + +schematic = (function() { + var background_style = 'rgb(220,220,220)'; + var element_style = 'rgb(255,255,255)'; + var thumb_style = 'rgb(128,128,128)'; + var normal_style = 'rgb(0,0,0)'; // default drawing color + var component_style = 'rgb(64,64,255)'; // color for unselected components + var selected_style = 'rgb(64,255,64)'; // highlight color for selected components + var grid_style = "rgb(128,128,128)"; + var annotation_style = 'rgb(255,64,64)'; // color for diagram annotations + var property_size = 5; // point size for Component property text + var annotation_size = 6; // point size for diagram annotations + + var parts_map = { + 'g': [Ground, 'Ground connection'], + 'L': [Label, 'Node label'], + 'v': [VSource, 'Voltage source'], + 'i': [ISource, 'Current source'], + 'r': [Resistor, 'Resistor'], + 'c': [Capacitor, 'Capacitor'], + 'l': [Inductor, 'Inductor'], + 'o': [OpAmp, 'Op Amp'], + 'd': [Diode, 'Diode'], + 'n': [NFet, 'NFet'], + 'p': [PFet, 'PFet'], + 's': [Probe, 'Voltage Probe'], + 'a': [Ammeter, 'Current Probe'] + }; + + // global clipboard + if (typeof sch_clipboard == 'undefined') + sch_clipboard = []; + + /////////////////////////////////////////////////////////////////////////////// + // + // Schematic = diagram + parts bin + status area + // + //////////////////////////////////////////////////////////////////////////////// + + // setup a schematic by populating the
with the appropriate children + function Schematic(input) { + // set up diagram viewing parameters + this.show_grid = true; + this.grid = 8; + this.scale = 2; + this.origin_x = input.getAttribute("origin_x"); + if (this.origin_x == undefined) this.origin_x = 0; + this.origin_y = input.getAttribute("origin_y"); + if (this.origin_y == undefined) this.origin_y = 0; + this.cursor_x = 0; + this.cursor_y = 0; + this.window_list = []; // list of pop-up windows in increasing z order + + // use user-supplied list of parts if supplied + // else just populate parts bin with all the parts + this.edits_allowed = true; + var parts = input.getAttribute('parts'); + if (parts == undefined || parts == 'None') { + parts = []; + for (var p in parts_map) parts.push(p); + } else if (parts == '') { + this.edits_allowed = false; + parts = []; + } else parts = parts.split(','); + + // now add the parts to the parts bin + this.parts_bin = []; + for (var i = 0; i < parts.length; i++) { + var part = new Part(this); + var pm = parts_map[parts[i]]; + part.set_component(new pm[0](0,0,0),pm[1]); + this.parts_bin.push(part); + } + + // use user-supplied list of analyses, otherwise provide them all + // analyses="" means no analyses + var analyses = input.getAttribute('analyses'); + if (analyses == undefined || analyses == 'None') + analyses = ['dc','ac','tran']; + else if (analyses == '') analyses = []; + else analyses = analyses.split(','); + + if (parts.length == 0 && analyses.length == 0) this.diagram_only = true; + else this.diagram_only = false; + + // see what we need to submit. Expecting attribute of the form + // submit_analyses="{'tran':[[node_name,t1,t2,t3],...], + // 'ac':[[node_name,f1,f2,...],...]}" + var submit = input.getAttribute('submit_analyses'); + if (submit && submit.indexOf('{') != -1) + this.submit_analyses = JSON.parse(submit); + else + this.submit_analyses = undefined; + + // toolbar + this.tools = []; + this.toolbar = []; + + /* DISABLE HELP BUTTON (target URL not consistent with multicourse hierarchy) -- SJSU + if (!this.diagram_only) { + this.tools['help'] = this.add_tool(help_icon,'Help: display help page',this.help); + this.enable_tool('help',true); + this.toolbar.push(null); // spacer + } + END DISABLE HELP BUTTON -- SJSU */ + + if (this.edits_allowed) { + this.tools['grid'] = this.add_tool(grid_icon,'Grid: toggle grid display',this.toggle_grid); + this.enable_tool('grid',true); + this.tools['cut'] = this.add_tool(cut_icon,'Cut: move selected components from diagram to the clipboard',this.cut); + this.tools['copy'] = this.add_tool(copy_icon,'Copy: copy selected components into the clipboard',this.copy); + this.tools['paste'] = this.add_tool(paste_icon,'Paste: copy clipboard into the diagram',this.paste); + this.toolbar.push(null); // spacer + } + + // simulation interface if cktsim.js is loaded + if (typeof cktsim != 'undefined') { + if (analyses.indexOf('dc') != -1) { + this.tools['dc'] = this.add_tool('DC','DC Analysis',this.dc_analysis); + this.enable_tool('dc',true); + this.dc_max_iters = '1000'; // default values dc solution + } + + if (analyses.indexOf('ac') != -1) { + this.tools['ac'] = this.add_tool('AC','AC Small-Signal Analysis',this.setup_ac_analysis); + this.enable_tool('ac',true); + this.ac_npts = '50'; // default values for AC Analysis + this.ac_fstart = '10'; + this.ac_fstop = '1G'; + this.ac_source_name = undefined; + } + + if (analyses.indexOf('tran') != -1) { + this.tools['tran'] = this.add_tool('TRAN','Transient Analysis',this.transient_analysis); + this.enable_tool('tran',true); + this.tran_npts = '100'; // default values for transient analysis + this.tran_tstop = '1'; + } + } + + // set up diagram canvas + this.canvas = document.createElement('canvas'); + this.width = input.getAttribute('width'); + this.width = parseInt(this.width == undefined ? '400' : this.width); + this.canvas.width = this.width; + this.height = input.getAttribute('height'); + this.height = parseInt(this.height == undefined ? '300' : this.height); + this.canvas.height = this.height; + + this.sctl_r = 16; // scrolling control parameters + this.sctl_x = this.sctl_r + 8; // upper left + this.sctl_y = this.sctl_r + 8; + this.zctl_left = this.sctl_x - 8; + this.zctl_top = this.sctl_y + this.sctl_r + 8; + + // repaint simply draws this buffer and then adds selected elements on top + this.bg_image = document.createElement('canvas'); + this.bg_image.width = this.width; + this.bg_image.height = this.height; + + if (!this.diagram_only) { + this.canvas.tabIndex = 0; // so we get keystrokes + this.canvas.style.borderStyle = 'solid'; + this.canvas.style.borderWidth = '1px'; + this.canvas.style.borderColor = grid_style; + this.canvas.style.outline = 'none'; + } + + this.canvas.schematic = this; + if (this.edits_allowed) { + this.canvas.addEventListener('mousemove',schematic_mouse_move,false); + this.canvas.addEventListener('mouseover',schematic_mouse_enter,false); + this.canvas.addEventListener('mouseout',schematic_mouse_leave,false); + this.canvas.addEventListener('mousedown',schematic_mouse_down,false); + this.canvas.addEventListener('mouseup',schematic_mouse_up,false); + this.canvas.addEventListener('mousewheel',schematic_mouse_wheel,false); + this.canvas.addEventListener('DOMMouseScroll',schematic_mouse_wheel,false); // for FF + this.canvas.addEventListener('dblclick',schematic_double_click,false); + this.canvas.addEventListener('keydown',schematic_key_down,false); + this.canvas.addEventListener('keyup',schematic_key_up,false); + } + + // set up message area + if (!this.diagram_only) { + this.status_div = document.createElement('div'); + this.status = document.createTextNode(''); + this.status_div.appendChild(this.status); + this.status_div.style.height = status_height + 'px'; + } else this.status_div = undefined; + + this.connection_points = []; // location string => list of cp's + this.components = []; + this.dragging = false; + this.select_rect = undefined; + this.wire = undefined; + this.operating_point = undefined; // result from DC analysis + this.dc_results = undefined; // saved analysis results for submission + this.ac_results = undefined; // saved analysis results for submission + this.transient_results = undefined; // saved analysis results for submission + + // state of modifier keys + this.ctrlKey = false; + this.shiftKey = false; + this.altKey = false; + this.cmdKey = false; + + // make sure other code can find us! + input.schematic = this; + this.input = input; + + // set up DOM -- use nested tables to do the layout + var table,tr,td; + table = document.createElement('table'); + table.rules = 'none'; + if (!this.diagram_only) { + table.frame = 'box'; + table.style.borderStyle = 'solid'; + table.style.borderWidth = '2px'; + table.style.borderColor = normal_style; + table.style.backgroundColor = background_style; + } + + // add tools to DOM + if (this.toolbar.length > 0) { + tr = document.createElement('tr'); + table.appendChild(tr); + td = document.createElement('td'); + td.style.verticalAlign = 'top'; + td.colSpan = 2; + tr.appendChild(td); + for (var i = 0; i < this.toolbar.length; ++i) { + var tool = this.toolbar[i]; + if (tool != null) td.appendChild(tool); + } + } + + // add canvas and parts bin to DOM + tr = document.createElement('tr'); + table.appendChild(tr); + + td = document.createElement('td'); + tr.appendChild(td); + var wrapper = document.createElement('div'); // for inserting pop-up windows + td.appendChild(wrapper); + wrapper.style.position = 'relative'; // so we can position subwindows + wrapper.appendChild(this.canvas); + + td = document.createElement('td'); + td.style.verticalAlign = 'top'; + tr.appendChild(td); + var parts_table = document.createElement('table'); + td.appendChild(parts_table); + parts_table.rules = 'none'; + parts_table.frame = 'void'; + parts_table.cellPadding = '0'; + parts_table.cellSpacing = '0'; + + // fill in parts_table + var parts_per_column = Math.floor(this.height / (part_h + 5)); // mysterious extra padding + for (var i = 0; i < parts_per_column; ++i) { + tr = document.createElement('tr'); + parts_table.appendChild(tr); + for (var j = i; j < this.parts_bin.length; j += parts_per_column) { + td = document.createElement('td'); + tr.appendChild(td); + td.appendChild(this.parts_bin[j].canvas); + } + } + + if (this.status_div != undefined) { + tr = document.createElement('tr'); + table.appendChild(tr); + td = document.createElement('td'); + tr.appendChild(td); + td.colSpan = 2; + td.appendChild(this.status_div); + } + + // add to dom + // avoid Chrome bug that changes to text cursor whenever + // drag starts. Just do this in schematic tool... + var toplevel = document.createElement('div'); + toplevel.onselectstart = function(){ return false; }; + toplevel.appendChild(table); + this.input.parentNode.insertBefore(toplevel,this.input.nextSibling); + + // process initial contents of diagram + this.load_schematic(this.input.getAttribute('value'), + this.input.getAttribute('initial_value')); + + // start by centering diagram on the screen + this.zoomall(); + } + + var part_w = 42; // size of a parts bin compartment + var part_h = 42; + var status_height = 18; + + Schematic.prototype.add_component = function(new_c) { + this.components.push(new_c); + // create undoable edit record here + } + + Schematic.prototype.remove_component = function(c) { + var index = this.components.indexOf(c); + if (index != -1) this.components.splice(index,1); + } + + Schematic.prototype.find_connections = function(cp) { + return this.connection_points[cp.location]; + } + + Schematic.prototype.add_connection_point = function(cp) { + var cplist = this.connection_points[cp.location]; + if (cplist) cplist.push(cp); + else { + cplist = [cp]; + this.connection_points[cp.location] = cplist; + } + + return cplist; + } + + Schematic.prototype.remove_connection_point = function(cp,old_location) { + // remove cp from list at old location + var cplist = this.connection_points[old_location]; + if (cplist) { + var index = cplist.indexOf(cp); + if (index != -1) { + cplist.splice(index,1); + // if no more connections at this location, remove + // entry from array to keep our search time short + if (cplist.length == 0) + delete this.connection_points[old_location]; + } + } + } + + Schematic.prototype.update_connection_point = function(cp,old_location) { + this.remove_connection_point(cp,old_location); + return this.add_connection_point(cp); + } + + Schematic.prototype.add_wire = function(x1,y1,x2,y2) { + var new_wire = new Wire(x1,y1,x2,y2); + new_wire.add(this); + new_wire.move_end(); + return new_wire; + } + + Schematic.prototype.split_wire = function(w,cp) { + // remove bisected wire + w.remove(); + + // add two new wires with connection point cp in the middle + this.add_wire(w.x,w.y,cp.x,cp.y); + this.add_wire(w.x+w.dx,w.y+w.dy,cp.x,cp.y); + } + + // see if connection points of component c split any wires + Schematic.prototype.check_wires = function(c) { + for (var i = 0; i < this.components.length; i++) { + var cc = this.components[i]; + if (cc != c) { // don't check a component against itself + // only wires will return non-null from a bisect call + var cp = cc.bisect(c); + if (cp) { + // cc is a wire bisected by connection point cp + this.split_wire(cc,cp); + this.redraw_background(); + } + } + } + } + + // see if there are any existing connection points that bisect wire w + Schematic.prototype.check_connection_points = function(w) { + for (var locn in this.connection_points) { + var cplist = this.connection_points[locn]; + if (cplist && w.bisect_cp(cplist[0])) { + this.split_wire(w,cplist[0]); + this.redraw_background(); + + // stop here, new wires introduced by split will do their own checks + return; + } + } + } + + // merge collinear wires sharing an end point + Schematic.prototype.clean_up_wires = function() { + for (var locn in this.connection_points) { + var cplist = this.connection_points[locn]; + if (cplist && cplist.length == 2) { + // found a connection with just two connections, see if they're wires + var c1 = cplist[0].parent; + var c2 = cplist[1].parent; + if (c1.type == 'w' && c2.type == 'w') { + var e1 = c1.other_end(cplist[0]); + var e2 = c2.other_end(cplist[1]); + var e3 = cplist[0]; // point shared by the two wires + if (collinear(e1,e2,e3)) { + c1.remove(); + c2.remove(); + this.add_wire(e1.x,e1.y,e2.x,e2.y); + } + } + } + } + } + + Schematic.prototype.unselect_all = function(which) { + this.operating_point = undefined; // remove annotations + for (var i = this.components.length - 1; i >= 0; --i) + if (i != which) this.components[i].set_select(false); + } + + Schematic.prototype.drag_begin = function() { + // let components know they're about to move + for (var i = this.components.length - 1; i >= 0; --i) { + var component = this.components[i]; + if (component.selected) component.move_begin(); + } + + // remember where drag started + this.drag_x = this.cursor_x; + this.drag_y = this.cursor_y; + this.dragging = true; + } + + Schematic.prototype.drag_end = function() { + // let components know they're done moving + for (var i = this.components.length - 1; i >= 0; --i) { + var component = this.components[i]; + if (component.selected) component.move_end(); + } + this.dragging = false; + this.clean_up_wires(); + this.redraw_background(); + } + + Schematic.prototype.help = function() { + window.open('/static/handouts/schematic_tutorial.pdf'); + } + + // zoom diagram around given coords + Schematic.prototype.rescale = function(nscale,cx,cy) { + if (cx == undefined) { + // use current center point if no point has been specified + cx = this.origin_x + this.width/(2*this.scale); + cy = this.origin_y + this.height/(2*this.scale); + } + + this.origin_x += cx*(this.scale - nscale); + this.origin_y += cy*(this.scale - nscale); + this.scale = nscale; + this.redraw_background(); + } + + Schematic.prototype.toggle_grid = function() { + this.show_grid = !this.show_grid; + this.redraw_background(); + } + + var zoom_factor = 1.25; // scaling is some power of zoom_factor + var zoom_min = 0.5; + var zoom_max = 4.0; + var origin_min = -200; // in grids + var origin_max = 200; + + Schematic.prototype.zoomin = function() { + var nscale = this.scale * zoom_factor; + if (nscale < zoom_max) { + // keep center of view unchanged + this.origin_x += (this.width/2)*(1.0/this.scale - 1.0/nscale); + this.origin_y += (this.height/2)*(1.0/this.scale - 1.0/nscale); + this.scale = nscale; + this.redraw_background(); + } + } + + Schematic.prototype.zoomout = function() { + var nscale = this.scale / zoom_factor; + if (nscale > zoom_min) { + // keep center of view unchanged + this.origin_x += (this.width/2)*(1.0/this.scale - 1.0/nscale); + this.origin_y += (this.height/2)*(1.0/this.scale - 1.0/nscale); + this.scale = nscale; + this.redraw_background(); + } + } + + Schematic.prototype.zoomall = function() { + // w,h for schematic including a 25% margin on all sides + var sch_w = 1.5*(this.bbox[2] - this.bbox[0]); + var sch_h = 1.5*(this.bbox[3] - this.bbox[1]); + + if (sch_w == 0 && sch_h == 0) { + this.origin_x = 0; + this.origin_y = 0; + this.scale = 2; + } else { + // compute scales that would make schematic fit, choose smallest + var scale_x = this.width/sch_w; + var scale_y = this.height/sch_h; + this.scale = Math.pow(zoom_factor,Math.ceil(Math.log(Math.min(scale_x,scale_y))/Math.log(zoom_factor))); + if (this.scale < zoom_min) this.scale = zoom_min; + else if (this.scale > zoom_max) this.scale = zoom_max; + + // center the schematic + this.origin_x = (this.bbox[2] + this.bbox[0])/2 - this.width/(2*this.scale); + this.origin_y = (this.bbox[3] + this.bbox[1])/2 - this.height/(2*this.scale); + } + + this.redraw_background(); + } + + Schematic.prototype.cut = function() { + // clear previous contents + sch_clipboard = []; + + // look for selected components, move them to clipboard. + for (var i = this.components.length - 1; i >=0; --i) { + var c = this.components[i]; + if (c.selected) { + c.remove(); + sch_clipboard.push(c); + } + } + + // update diagram view + this.redraw(); + } + + Schematic.prototype.copy = function() { + // clear previous contents + sch_clipboard = []; + + // look for selected components, copy them to clipboard. + for (var i = this.components.length - 1; i >=0; --i) { + var c = this.components[i]; + if (c.selected) + sch_clipboard.push(c.clone(c.x,c.y)); + } + } + + Schematic.prototype.paste = function() { + // compute left,top of bounding box for origins of + // components in the clipboard + var left = undefined; + var top = undefined; + for (var i = sch_clipboard.length - 1; i >= 0; --i) { + var c = sch_clipboard[i]; + left = left ? Math.min(left,c.x) : c.x; + top = top ? Math.min(top,c.y) : c.y; + } + + this.message('cursor '+this.cursor_x+','+this.cursor_y); + + // clear current selections + this.unselect_all(-1); + this.redraw_background(); // so we see any components that got unselected + + // make clones of components on the clipboard, positioning + // them relative to the cursor + for (var i = sch_clipboard.length - 1; i >= 0; --i) { + var c = sch_clipboard[i]; + var new_c = c.clone(this.cursor_x + (c.x - left),this.cursor_y + (c.y - top)); + new_c.set_select(true); + new_c.add(this); + } + + this.redraw(); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Netlist and Simulation interface + // + //////////////////////////////////////////////////////////////////////////////// + + // load diagram from JSON representation + Schematic.prototype.load_schematic = function(value,initial_value) { + // use default value if no schematic info in value + if (value == undefined || value.indexOf('[') == -1) + value = initial_value; + if (value && value.indexOf('[') != -1) { + // convert string value into data structure + var json = JSON.parse(value); + + // top level is a list of components + for (var i = json.length - 1; i >= 0; --i) { + var c = json[i]; + if (c[0] == 'view') { + this.ac_fstart = c[5]; + this.ac_fstop = c[6]; + this.ac_source_name = c[7]; + this.tran_npts = c[8]; + this.tran_tstop = c[9]; + this.dc_max_iters = c[10]; + } else if (c[0] == 'w') { + // wire + this.add_wire(c[1][0],c[1][1],c[1][2],c[1][3]); + } else if (c[0] == 'dc') { + this.dc_results = c[1]; + } else if (c[0] == 'transient') { + this.transient_results = c[1]; + } else if (c[0] == 'ac') { + this.ac_results = c[1]; + } else { + // ordinary component + // c := [type, coords, properties, connections] + var type = c[0]; + var coords = c[1]; + var properties = c[2]; + + var part = new parts_map[type][0](coords[0],coords[1],coords[2]); + for (var name in properties) + part.properties[name] = properties[name]; + + part.add(this); + } + } + } + + this.redraw_background(); + } + + // label all the nodes in the circuit + Schematic.prototype.label_connection_points = function() { + // start by clearing all the connection point labels + for (var i = this.components.length - 1; i >=0; --i) + this.components[i].clear_labels(); + + // components are in charge of labeling their unlabeled connections. + // labels given to connection points will propagate to coincident connection + // points and across Wires. + + // let special components like GND label their connection(s) + for (var i = this.components.length - 1; i >=0; --i) + this.components[i].add_default_labels(); + + // now have components generate labels for unlabeled connections + this.next_label = 0; + for (var i = this.components.length - 1; i >=0; --i) + this.components[i].label_connections(); + } + + Schematic.prototype.get_next_label = function() { + // generate next label in sequence + this.next_label += 1; + return this.next_label.toString(); + } + + // propagate label to coincident connection points + Schematic.prototype.propagate_label = function(label,location) { + var cplist = this.connection_points[location]; + for (var i = cplist.length - 1; i >= 0; --i) + cplist[i].propagate_label(label); + } + + // update the value field of our corresponding input field with JSON + // representation of schematic + Schematic.prototype.update_value = function() { + // label connection points + this.label_connection_points(); + + // build JSON data structure, convert to string value for + // input field + this.input.value = JSON.stringify(this.json_with_analyses()); + } + + Schematic.prototype.json = function() { + var json = []; + + // output all the components/wires in the diagram + var n = this.components.length; + for (var i = 0; i < n; i++) + json.push(this.components[i].json(i)); + + // capture the current view parameters + json.push(['view',this.origin_x,this.origin_y,this.scale, + this.ac_npts,this.ac_fstart,this.ac_fstop, + this.ac_source_name,this.tran_npts,this.tran_tstop, + this.dc_max_iters]); + + return json; + } + + Schematic.prototype.json_with_analyses = function() { + var json = this.json(); + + if (this.dc_results != undefined) json.push(['dc',this.dc_results]); + if (this.ac_results != undefined) json.push(['ac',this.ac_results]); + if (this.transient_results != undefined) json.push(['transient',this.transient_results]); + + return json; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Simulation interface + // + //////////////////////////////////////////////////////////////////////////////// + + Schematic.prototype.extract_circuit = function() { + // give all the circuit nodes a name, extract netlist + this.label_connection_points(); + var netlist = this.json(); + + // since we've done the heavy lifting, update input field value + // so user can grab diagram if they want + this.input.value = JSON.stringify(netlist); + + // create a circuit from the netlist + var ckt = new cktsim.Circuit(); + if (ckt.load_netlist(netlist)) + return ckt; + else + return null; + } + + Schematic.prototype.dc_analysis = function() { + // remove any previous annotations + this.unselect_all(-1); + this.redraw_background(); + + var ckt = this.extract_circuit(); + if (ckt === null) return; + + // run the analysis + this.operating_point = ckt.dc(); + + if (this.operating_point != undefined) { + // save a copy of the results for submission + this.dc_results = {}; + for (var i in this.operating_point) this.dc_results[i] = this.operating_point[i]; + + // display results on diagram + this.redraw(); + } + } + + // return a list of [color,node_label,offset,type] for each probe in the diagram + // type == 'voltage' or 'current' + Schematic.prototype.find_probes = function() { + var result = []; + var result = []; + for (var i = this.components.length - 1; i >= 0; --i) { + var c = this.components[i]; + var info = c.probe_info(); + if (info != undefined) result.push(c.probe_info()); + } + return result; + } + + // use a dialog to get AC analysis parameters + Schematic.prototype.setup_ac_analysis = function() { + this.unselect_all(-1); + this.redraw_background(); + + var npts_lbl = 'Number of points/decade'; + var fstart_lbl = 'Starting frequency (Hz)'; + var fstop_lbl = 'Ending frequency (Hz)'; + var source_name_lbl = 'Name of V or I source for ac' + + if (this.find_probes().length == 0) { + alert("AC Analysis: there are no voltage probes in the diagram!"); + return; + } + + var fields = []; + fields[fstart_lbl] = build_input('text',10,this.ac_fstart); + fields[fstop_lbl] = build_input('text',10,this.ac_fstop); + fields[source_name_lbl] = build_input('text',10,this.ac_source_name); + + var content = build_table(fields); + content.fields = fields; + content.sch = this; + + this.dialog('AC Analysis',content,function(content) { + var sch = content.sch; + + // retrieve parameters, remember for next time + sch.ac_fstart = content.fields[fstart_lbl].value; + sch.ac_fstop = content.fields[fstop_lbl].value; + sch.ac_source_name = content.fields[source_name_lbl].value; + + sch.ac_analysis(cktsim.parse_number(sch.ac_npts), + cktsim.parse_number(sch.ac_fstart), + cktsim.parse_number(sch.ac_fstop), + sch.ac_source_name); + }); + } + + Schematic.prototype.ac_analysis = function(npts,fstart,fstop,ac_source_name) { + var ckt = this.extract_circuit(); + if (ckt === null) return; + var results = ckt.ac(npts,fstart,fstop,ac_source_name); + + if (typeof results == 'string') + this.message(results); + else { + var x_values = results['_frequencies_']; + + // x axis will be a log scale + for (var i = x_values.length - 1; i >= 0; --i) + x_values[i] = Math.log(x_values[i])/Math.LN10; + + if (this.submit_analyses != undefined) { + var submit = this.submit_analyses['ac']; + if (submit != undefined) { + // save a copy of the results for submission + this.ac_results = {}; + + // save requested values for each requested node + for (var j = 0; j < submit.length; j++) { + var flist = submit[j]; // [node_name,f1,f2,...] + var node = flist[0]; + var values = results[node]; + var fvlist = []; + // for each requested freq, interpolate response value + for (var k = 1; k < flist.length; k++) { + var f = flist[k]; + var v = interpolate(f,x_values,values); + // convert to dB + fvlist.push([f,v == undefined ? 'undefined' : 20.0 * Math.log(v)/Math.LN10]); + } + // save results as list of [f,response] paris + this.ac_results[node] = fvlist; + } + } + } + + // set up plot values for each node with a probe + var y_values = []; // list of [color, result_array] + var z_values = []; // list of [color, result_array] + var probes = this.find_probes(); + var probe_maxv = []; + var probe_color = []; + + // Check for probe with near zero transfer function and warn + for (var i = probes.length - 1; i >= 0; --i) { + if (probes[i][3] != 'voltage') continue; + probe_color[i] = probes[i][0]; + var label = probes[i][1]; + var v = results[label]; + probe_maxv[i] = array_max(v); // magnitudes always > 0 + } + + var all_max = array_max(probe_maxv); + if (all_max < 1.0e-16) { + alert('Zero ac response, -infinity on DB scale.'); + } else { + for (var i = probes.length - 1; i >= 0; --i) { + if (probes[i][3] != 'voltage') continue; + if ((probe_maxv[i] / all_max) < 1.0e-10) { + alert('Near zero ac response, remove ' + probe_color[i] + ' probe'); + return; + } + } + } + + for (var i = probes.length - 1; i >= 0; --i) { + if (probes[i][3] != 'voltage') continue; + var color = probes[i][0]; + var label = probes[i][1]; + var offset = cktsim.parse_number(probes[i][2]); + var v = results[label]; + // convert values into dB relative to source amplitude + var v_max = 1; + for (var j = v.length - 1; j >= 0; --j) + // convert each value to dB relative to max + v[j] = 20.0 * Math.log(v[j]/v_max)/Math.LN10; + y_values.push([color,offset,v]); + + var v = results[label+'_phase']; + z_values.push([color,0,v]); + } + + // graph the result and display in a window + var graph2 = this.graph(x_values,'log(Frequency in Hz)',z_values,'degrees'); + this.window('AC Analysis - Phase',graph2); + var graph1 = this.graph(x_values,'log(Frequency in Hz)',y_values,'dB'); + this.window('AC Analysis - Magnitude',graph1,50); + } + } + + Schematic.prototype.transient_analysis = function() { + this.unselect_all(-1); + this.redraw_background(); + + var npts_lbl = 'Minimum number of timepoints'; + var tstop_lbl = 'Stop Time (seconds)'; + var probes = this.find_probes(); + if (probes.length == 0) { + alert("Transient Analysis: there are no probes in the diagram!"); + return; + } + + var fields = []; + fields[tstop_lbl] = build_input('text',10,this.tran_tstop); + + var content = build_table(fields); + content.fields = fields; + content.sch = this; + + this.dialog('Transient Analysis',content,function(content) { + var sch = content.sch; + var ckt = sch.extract_circuit(); + if (ckt === null) return; + + // retrieve parameters, remember for next time + sch.tran_tstop = content.fields[tstop_lbl].value; + + // gather a list of nodes that are being probed. These + // will be added to the list of nodes checked during the + // LTE calculations in transient analysis + var probe_list = sch.find_probes(); + var probe_names = new Array(probe_list.length); + for (var i = probe_list.length - 1; i >= 0; --i) + probe_names[i] = probe_list[i][1]; + + // run the analysis + var results = ckt.tran(ckt.parse_number(sch.tran_npts), 0, + ckt.parse_number(sch.tran_tstop), probe_names, false); + + if (typeof results == 'string') + sch.message(results); + else { + if (sch.submit_analyses != undefined) { + var submit = sch.submit_analyses['tran']; + if (submit != undefined) { + // save a copy of the results for submission + sch.transient_results = {}; + var times = results['_time_']; + + // save requested values for each requested node + for (var j = 0; j < submit.length; j++) { + var tlist = submit[j]; // [node_name,t1,t2,...] + var node = tlist[0]; + var values = results[node]; + var tvlist = []; + // for each requested time, interpolate waveform value + for (var k = 1; k < tlist.length; k++) { + var t = tlist[k]; + var v = interpolate(t,times,values); + tvlist.push([t,v == undefined ? 'undefined' : v]); + } + // save results as list of [t,value] pairs + sch.transient_results[node] = tvlist; + } + } + } + + var x_values = results['_time_']; + var x_legend = 'Time'; + + // set up plot values for each node with a probe + var v_values = []; // voltage values: list of [color, result_array] + var i_values = []; // current values: list of [color, result_array] + var probes = sch.find_probes(); + + for (var i = probes.length - 1; i >= 0; --i) { + var color = probes[i][0]; + var label = probes[i][1]; + var offset = cktsim.parse_number(probes[i][2]); + var v = results[label]; + if (v == undefined) { + alert('The ' + color + ' probe is connected to node ' + '"' + label + '"' + ' which is not an actual circuit node'); + } else if (probes[i][3] == 'voltage') { + if (color == 'x-axis') { + x_values = v; + x_legend = 'Voltage'; + } else v_values.push([color,offset,v]); + } else { + if (color == 'x-axis') { + x_values = v; + x_legend = 'Current'; + } else i_values.push([color,offset,v]); + } + } + + // graph the result and display in a window + var graph = sch.graph(x_values,x_legend,v_values,'Voltage',i_values,'Current'); + sch.window('Results of Transient Analysis',graph); + } + }) + } + + // t is the time at which we want a value + // times is a list of timepoints from the simulation + function interpolate(t,times,values) { + if (values == undefined) return undefined; + + for (var i = 0; i < times.length; i++) + if (t < times[i]) { + // t falls between times[i-1] and times[i] + var t1 = (i == 0) ? times[0] : times[i-1]; + var t2 = times[i]; + + if (t2 == undefined) return undefined; + + var v1 = (i == 0) ? values[0] : values[i-1]; + var v2 = values[i]; + var v = v1; + if (t != t1) v += (t - t1)*(v2 - v1)/(t2 - t1); + return v; + } + } + + // external interface for setting the property value of a named component + Schematic.prototype.set_property = function(component_name,property,value) { + this.unselect_all(-1); + + for (var i = this.components.length - 1; i >= 0; --i) { + var component = this.components[i]; + if (component.properties['name'] == component_name) { + component.properties[property] = value.toString(); + break; + } + } + + this.redraw_background(); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Drawing support -- deals with scaling and scrolling of diagrama + // + //////////////////////////////////////////////////////////////////////////////// + + // here to redraw background image containing static portions of the schematic. + // Also redraws dynamic portion. + Schematic.prototype.redraw_background = function() { + var c = this.bg_image.getContext('2d'); + + c.lineCap = 'round'; + + // paint background color + c.fillStyle = element_style; + c.fillRect(0,0,this.width,this.height); + + if (!this.diagram_only && this.show_grid) { + // grid + c.strokeStyle = grid_style; + var first_x = this.origin_x; + var last_x = first_x + this.width/this.scale; + var first_y = this.origin_y; + var last_y = first_y + this.height/this.scale; + + for (var i = this.grid*Math.ceil(first_x/this.grid); i < last_x; i += this.grid) + this.draw_line(c,i,first_y,i,last_y,0.1); + + for (var i = this.grid*Math.ceil(first_y/this.grid); i < last_y; i += this.grid) + this.draw_line(c,first_x,i,last_x,i,0.1); + } + + // unselected components + var min_x = Infinity; // compute bounding box for diagram + var max_x = -Infinity; + var min_y = Infinity; + var max_y = -Infinity; + for (var i = this.components.length - 1; i >= 0; --i) { + var component = this.components[i]; + if (!component.selected) { + component.draw(c); + min_x = Math.min(component.bbox[0],min_x); + max_x = Math.max(component.bbox[2],max_x); + min_y = Math.min(component.bbox[1],min_y); + max_y = Math.max(component.bbox[3],max_y); + } + } + this.unsel_bbox = [min_x,min_y,max_x,max_y]; + this.redraw(); // background changed, redraw on screen + } + + // redraw what user sees = static image + dynamic parts + Schematic.prototype.redraw = function() { + var c = this.canvas.getContext('2d'); + + // put static image in the background + c.drawImage(this.bg_image, 0, 0); + + // selected components + var min_x = this.unsel_bbox[0]; // compute bounding box for diagram + var max_x = this.unsel_bbox[2]; + var min_y = this.unsel_bbox[1]; + var max_y = this.unsel_bbox[3]; + var selections = false; + for (var i = this.components.length - 1; i >= 0; --i) { + var component = this.components[i]; + if (component.selected) { + component.draw(c); + selections = true; + min_x = Math.min(component.bbox[0],min_x); + max_x = Math.max(component.bbox[2],max_x); + min_y = Math.min(component.bbox[1],min_y); + max_y = Math.max(component.bbox[3],max_y); + } + } + if (min_x == Infinity) this.bbox = [0,0,0,0]; + else this.bbox = [min_x,min_y,max_x,max_y]; + this.enable_tool('cut',selections); + this.enable_tool('copy',selections); + this.enable_tool('paste',sch_clipboard.length > 0); + + // connection points: draw one at each location + for (var location in this.connection_points) { + var cplist = this.connection_points[location]; + cplist[0].draw(c,cplist.length); + } + + // draw new wire + if (this.wire) { + var r = this.wire; + c.strokeStyle = selected_style; + this.draw_line(c,r[0],r[1],r[2],r[3],1); + } + + // draw selection rectangle + if (this.select_rect) { + var r = this.select_rect; + c.lineWidth = 1; + c.strokeStyle = selected_style; + c.beginPath(); + c.moveTo(r[0],r[1]); + c.lineTo(r[0],r[3]); + c.lineTo(r[2],r[3]); + c.lineTo(r[2],r[1]); + c.lineTo(r[0],r[1]); + c.stroke(); + } + + // display operating point results + if (this.operating_point) { + if (typeof this.operating_point == 'string') + this.message(this.operating_point); + else { + // make a copy of the operating_point info so we can mess with it + var temp = []; + for (var i in this.operating_point) temp[i] = this.operating_point[i]; + + // run through connection points displaying (once) the voltage + // for each electrical node + for (var location in this.connection_points) + (this.connection_points[location])[0].display_voltage(c,temp); + + // let components display branch current info if available + for (var i = this.components.length - 1; i >= 0; --i) + this.components[i].display_current(c,temp) + } + } + + // add scrolling/zooming control + if (!this.diagram_only) { + var r = this.sctl_r; + var x = this.sctl_x; + var y = this.sctl_y; + + // circle with border + c.fillStyle = element_style; + c.beginPath(); + c.arc(x,y,r,0,2*Math.PI); + c.fill(); + + c.strokeStyle = grid_style; + c.lineWidth = 0.5; + c.beginPath(); + c.arc(x,y,r,0,2*Math.PI); + c.stroke(); + + // direction markers for scroll + c.lineWidth = 3; + c.beginPath(); + + c.moveTo(x + 4,y - r + 8); // north + c.lineTo(x,y - r + 4); + c.lineTo(x - 4,y - r + 8); + + c.moveTo(x + r - 8,y + 4); // east + c.lineTo(x + r - 4,y); + c.lineTo(x + r - 8,y - 4); + + c.moveTo(x + 4,y + r - 8); // south + c.lineTo(x,y + r - 4); + c.lineTo(x - 4,y + r - 8); + + c.moveTo(x - r + 8,y + 4); // west + c.lineTo(x - r + 4,y); + c.lineTo(x - r + 8,y - 4); + + c.stroke(); + + // zoom control + x = this.zctl_left; + y = this.zctl_top; + c.lineWidth = 0.5; + c.fillStyle = element_style; // background + c.fillRect(x,y,16,48); + c.strokeStyle = grid_style; // border + c.strokeRect(x,y,16,48); + c.lineWidth = 1.0; + c.beginPath(); + // zoom in label + c.moveTo(x+4,y+8); c.lineTo(x+12,y+8); c.moveTo(x+8,y+4); c.lineTo(x+8,y+12); + // zoom out label + c.moveTo(x+4,y+24); c.lineTo(x+12,y+24); + // surround label + c.strokeRect(x+4,y+36,8,8); + c.stroke(); + } + } + + // draws a cross cursor + Schematic.prototype.cross_cursor = function(c,x,y) { + this.draw_line(c,x-this.grid,y,x+this.grid,y,1); + this.draw_line(c,x,y-this.grid,x,y+this.grid,1); + } + + Schematic.prototype.moveTo = function(c,x,y) { + c.moveTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); + } + + Schematic.prototype.lineTo = function(c,x,y) { + c.lineTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); + } + + Schematic.prototype.draw_line = function(c,x1,y1,x2,y2,width) { + c.lineWidth = width*this.scale; + c.beginPath(); + c.moveTo((x1 - this.origin_x) * this.scale,(y1 - this.origin_y) * this.scale); + c.lineTo((x2 - this.origin_x) * this.scale,(y2 - this.origin_y) * this.scale); + c.stroke(); + } + + Schematic.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians,anticlockwise,width,filled) { + c.lineWidth = width*this.scale; + c.beginPath(); + c.arc((x - this.origin_x)*this.scale,(y - this.origin_y)*this.scale,radius*this.scale, + start_radians,end_radians,anticlockwise); + if (filled) c.fill(); + else c.stroke(); + } + + Schematic.prototype.draw_text = function(c,text,x,y,size) { + c.font = size*this.scale+'pt sans-serif' + c.fillText(text,(x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); + } + + // add method to canvas to compute relative coords for event + try { + if (HTMLCanvasElement) + HTMLCanvasElement.prototype.relMouseCoords = function(event){ + // run up the DOM tree to figure out coords for top,left of canvas + var totalOffsetX = 0; + var totalOffsetY = 0; + var currentElement = this; + do { + totalOffsetX += currentElement.offsetLeft; + totalOffsetY += currentElement.offsetTop; + } + while (currentElement = currentElement.offsetParent); + + // now compute relative position of click within the canvas + this.mouse_x = event.pageX - totalOffsetX; + this.mouse_y = event.pageY - totalOffsetY; + this.page_x = event.pageX; + this.page_y = event.pageY; + } + } + catch (err) { // ignore + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Event handling + // + //////////////////////////////////////////////////////////////////////////////// + + // process keystrokes, consuming those that are meaningful to us + function schematic_key_down(event) { + if (!event) event = window.event; + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + var code = event.keyCode; + + // keep track of modifier key state + if (code == 16) sch.shiftKey = true; + else if (code == 17) sch.ctrlKey = true; + else if (code == 18) sch.altKey = true; + else if (code == 91) sch.cmdKey = true; + + // backspace or delete: delete selected components + else if (code == 8 || code == 46) { + // delete selected components + for (var i = sch.components.length - 1; i >= 0; --i) { + var component = sch.components[i]; + if (component.selected) component.remove(); + } + sch.clean_up_wires(); + sch.redraw_background(); + event.preventDefault(); + return false; + } + + // cmd/ctrl x: cut + else if ((sch.ctrlKey || sch.cmdKey) && code == 88) { + sch.cut(); + event.preventDefault(); + return false; + } + + // cmd/ctrl c: copy + else if ((sch.ctrlKey || sch.cmdKey) && code == 67) { + sch.copy(); + event.preventDefault(); + return false; + } + + // cmd/ctrl v: paste + else if ((sch.ctrlKey || sch.cmdKey) && code == 86) { + sch.paste(); + event.preventDefault(); + return false; + } + + // 'r': rotate component + else if (!sch.ctrlKey && !sch.altKey && !sch.cmdKey && code == 82) { + // rotate + for (var i = sch.components.length - 1; i >= 0; --i) { + var component = sch.components[i]; + if (component.selected) { + component.rotate(1); + sch.check_wires(component); + } + } + sch.clean_up_wires(); + sch.redraw_background(); + event.preventDefault(); + return false; + } + + else return true; + + // consume keystroke + sch.redraw(); + event.preventDefault(); + return false; + } + + function schematic_key_up(event) { + if (!event) event = window.event; + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + var code = event.keyCode; + + if (code == 16) sch.shiftKey = false; + else if (code == 17) sch.ctrlKey = false; + else if (code == 18) sch.altKey = false; + else if (code == 91) sch.cmdKey = false; + } + + function schematic_mouse_enter(event) { + if (!event) event = window.event; + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + + // see if user has selected a new part + if (sch.new_part) { + // grab incoming part, turn off selection of parts bin + var part = sch.new_part; + sch.new_part = undefined; + part.select(false); + + // unselect everything else in the schematic, add part and select it + sch.unselect_all(-1); + sch.redraw_background(); // so we see any components that got unselected + + // make a clone of the component in the parts bin + part = part.component.clone(sch.cursor_x,sch.cursor_y); + part.add(sch); // add it to schematic + part.set_select(true); + + // and start dragging it + sch.drag_begin(); + } + + sch.drawCursor = true; + sch.redraw(); + sch.canvas.focus(); // capture key strokes + return false; + } + + function schematic_mouse_leave(event) { + if (!event) event = window.event; + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + sch.drawCursor = false; + sch.redraw(); + return false; + } + + function schematic_mouse_down(event) { + if (!event) event = window.event; + else event.preventDefault(); + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + + // determine where event happened in schematic coordinates + sch.canvas.relMouseCoords(event); + + var mx = sch.canvas.mouse_x; + var my = sch.canvas.mouse_y; + var sx = mx - sch.sctl_x; + var sy = my - sch.sctl_y; + var zx = mx - sch.zctl_left; + var zy = my - sch.zctl_top; + if (sx*sx + sy*sy <= sch.sctl_r*sch.sctl_r) { // click in scrolling control + // click on scrolling control, check which quadrant + if (Math.abs(sy) > Math.abs(sx)) { // N or S + var delta = this.height / 8; + if (sy > 0) delta = -delta; + var temp = sch.origin_y - delta; + if (temp > origin_min*sch.grid && temp < origin_max*sch.grid) sch.origin_y = temp; + } else { // E or W + var delta = this.width / 8; + if (sx < 0) delta = -delta; + var temp = sch.origin_x + delta; + if (temp > origin_min*sch.grid && temp < origin_max*sch.grid) sch.origin_x = temp; + } + } else if (zx >= 0 && zx < 16 && zy >= 0 && zy < 48) { // click in zoom control + if (zy < 16) sch.zoomin(); + else if (zy < 32) sch.zoomout(); + else sch.zoomall(); + } else { + var x = mx/sch.scale + sch.origin_x; + var y = my/sch.scale + sch.origin_y; + sch.cursor_x = Math.round(x/sch.grid) * sch.grid; + sch.cursor_y = Math.round(y/sch.grid) * sch.grid; + + // is mouse over a connection point? If so, start dragging a wire + var cplist = sch.connection_points[sch.cursor_x + ',' + sch.cursor_y]; + if (cplist && !event.shiftKey) { + sch.unselect_all(-1); + sch.wire = [sch.cursor_x,sch.cursor_y,sch.cursor_x,sch.cursor_y]; + } else { + // give all components a shot at processing the selection event + var which = -1; + for (var i = sch.components.length - 1; i >= 0; --i) + if (sch.components[i].select(x,y,event.shiftKey)) { + if (sch.components[i].selected) { + sch.drag_begin(); + which = i; // keep track of component we found + } + break; + } + // did we just click on a previously selected component? + var reselect = which!=-1 && sch.components[which].was_previously_selected; + + if (!event.shiftKey) { + // if shift key isn't pressed and we didn't click on component + // that was already selected, unselect everyone except component + // we just clicked on + if (!reselect) sch.unselect_all(which); + + // if there's nothing to drag, set up a selection rectangle + if (!sch.dragging) sch.select_rect = [sch.canvas.mouse_x,sch.canvas.mouse_y, + sch.canvas.mouse_x,sch.canvas.mouse_y]; + } + } + } + + sch.redraw_background(); + return false; + } + + function schematic_mouse_move(event) { + if (!event) event = window.event; + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + + sch.canvas.relMouseCoords(event); + var x = sch.canvas.mouse_x/sch.scale + sch.origin_x; + var y = sch.canvas.mouse_y/sch.scale + sch.origin_y; + sch.cursor_x = Math.round(x/sch.grid) * sch.grid; + sch.cursor_y = Math.round(y/sch.grid) * sch.grid; + + if (sch.wire) { + // update new wire end point + sch.wire[2] = sch.cursor_x; + sch.wire[3] = sch.cursor_y; + } else if (sch.dragging) { + // see how far we moved + var dx = sch.cursor_x - sch.drag_x; + var dy = sch.cursor_y - sch.drag_y; + if (dx != 0 || dy != 0) { + // update position for next time + sch.drag_x = sch.cursor_x; + sch.drag_y = sch.cursor_y; + + // give all components a shot at processing the event + for (var i = sch.components.length - 1; i >= 0; --i) { + var component = sch.components[i]; + if (component.selected) component.move(dx,dy); + } + } + } else if (sch.select_rect) { + // update moving corner of selection rectangle + sch.select_rect[2] = sch.canvas.mouse_x; + sch.select_rect[3] = sch.canvas.mouse_y; + } + + // just redraw dynamic components + sch.redraw(); + + return false; + } + + function schematic_mouse_up(event) { + if (!event) event = window.event; + else event.preventDefault(); + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + + // drawing a new wire + if (sch.wire) { + var r = sch.wire; + sch.wire = undefined; + + if (r[0]!=r[2] || r[1]!=r[3]) { + // insert wire component + sch.add_wire(r[0],r[1],r[2],r[3]); + sch.clean_up_wires(); + sch.redraw_background(); + } else sch.redraw(); + } + + // dragging + if (sch.dragging) sch.drag_end(); + + // selection rectangle + if (sch.select_rect) { + var r = sch.select_rect; + + // if select_rect is a point, we've already dealt with selection + // in mouse_down handler + if (r[0]!=r[2] || r[1]!=r[3]) { + // convert to schematic coordinates + var s = [r[0]/sch.scale + sch.origin_x, r[1]/sch.scale + sch.origin_y, + r[2]/sch.scale + sch.origin_x, r[3]/sch.scale + sch.origin_y]; + canonicalize(s); + + if (!event.shiftKey) sch.unselect_all(); + + // select components that intersect selection rectangle + for (var i = sch.components.length - 1; i >= 0; --i) + sch.components[i].select_rect(s,event.shiftKey); + } + + sch.select_rect = undefined; + sch.redraw_background(); + } + return false; + } + + function schematic_mouse_wheel(event) { + if (!event) event = window.event; + else event.preventDefault(); + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + + var delta = 0; + if (event.wheelDelta) delta = event.wheelDelta; + else if (event.detail) delta = -event.detail; + + if (delta) { + var nscale = (delta > 0) ? sch.scale*zoom_factor : sch.scale/zoom_factor; + + if (nscale > zoom_min && nscale < zoom_max) { + // zoom around current mouse position + sch.canvas.relMouseCoords(event); + var s = 1.0/sch.scale - 1.0/nscale; + sch.origin_x += sch.canvas.mouse_x*s; + sch.origin_y += sch.canvas.mouse_y*s; + sch.scale = nscale; + sch.redraw_background(); + } + } + } + + function schematic_double_click(event) { + if (!event) event = window.event; + else event.preventDefault(); + var sch = (window.event) ? event.srcElement.schematic : event.target.schematic; + + // determine where event happened in schematic coordinates + sch.canvas.relMouseCoords(event); + var x = sch.canvas.mouse_x/sch.scale + sch.origin_x; + var y = sch.canvas.mouse_y/sch.scale + sch.origin_y; + sch.cursor_x = Math.round(x/sch.grid) * sch.grid; + sch.cursor_y = Math.round(y/sch.grid) * sch.grid; + + // see if we double-clicked a component. If so, edit it's properties + for (var i = sch.components.length - 1; i >= 0; --i) + if (sch.components[i].edit_properties(x,y)) + break; + + return false; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Status message and dialogs + // + //////////////////////////////////////////////////////////////////////////////// + + Schematic.prototype.message = function(message) { + this.status.nodeValue = message; + } + + Schematic.prototype.append_message = function(message) { + this.status.nodeValue += ' / '+message; + } + + // set up a dialog with specified title, content and two buttons at + // the bottom: OK and Cancel. If Cancel is clicked, dialog goes away + // and we're done. If OK is clicked, dialog goes away and the + // callback function is called with the content as an argument (so + // that the values of any fields can be captured). + Schematic.prototype.dialog = function(title,content,callback) { + // create the div for the top level of the dialog, add to DOM + var dialog = document.createElement('div'); + dialog.sch = this; + dialog.content = content; + dialog.callback = callback; + + // look for property input fields in the content and give + // them a keypress listener that interprets ENTER as + // clicking OK. + var plist = content.getElementsByClassName('property'); + for (var i = plist.length - 1; i >= 0; --i) { + var field = plist[i]; + field.dialog = dialog; // help event handler find us... + field.addEventListener('keypress',dialog_check_for_ENTER,false); + } + + // div to hold the content + var body = document.createElement('div'); + content.style.marginBotton = '5px'; + body.appendChild(content); + body.style.padding = '5px'; + dialog.appendChild(body); + + var ok_button = document.createElement('span'); + ok_button.appendChild(document.createTextNode('OK')); + ok_button.dialog = dialog; // for the handler to use + ok_button.addEventListener('click',dialog_okay,false); + ok_button.style.display = 'inline'; + ok_button.style.border = '1px solid'; + ok_button.style.padding = '5px'; + ok_button.style.margin = '10px'; + + var cancel_button = document.createElement('span'); + cancel_button.appendChild(document.createTextNode('Cancel')); + cancel_button.dialog = dialog; // for the handler to use + cancel_button.addEventListener('click',dialog_cancel,false); + cancel_button.style.display = 'inline'; + cancel_button.style.border = '1px solid'; + cancel_button.style.padding = '5px'; + cancel_button.style.margin = '10px'; + + // div to hold the two buttons + var buttons = document.createElement('div'); + buttons.style.textAlign = 'center'; + buttons.appendChild(ok_button); + buttons.appendChild(cancel_button); + buttons.style.padding = '5px'; + buttons.style.margin = '10px'; + dialog.appendChild(buttons); + + // put into an overlay window + this.window(title,dialog); + } + + function dialog_cancel(event) { + if (!event) event = window.event; + var dialog = (window.event) ? event.srcElement.dialog : event.target.dialog; + + window_close(dialog.win); + } + + function dialog_okay(event) { + if (!event) event = window.event; + var dialog = (window.event) ? event.srcElement.dialog : event.target.dialog; + + window_close(dialog.win); + + if (dialog.callback) dialog.callback(dialog.content); + } + + // callback for keypress in input fields: if user typed ENTER, act + // like they clicked OK button. + function dialog_check_for_ENTER(event) { + var key = (window.event) ? window.event.keyCode : event.keyCode; + if (key == 13) dialog_okay(event); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Draggable, resizeable, closeable window + // + //////////////////////////////////////////////////////////////////////////////// + + // build a 2-column HTML table from an associative array (keys as text in + // column 1, values in column 2). + function build_table(a) { + var tbl = document.createElement('table'); + + // build a row for each element in associative array + for (var i in a) { + var label = document.createTextNode(i + ': '); + var col1 = document.createElement('td'); + col1.appendChild(label); + var col2 = document.createElement('td'); + col2.appendChild(a[i]); + var row = document.createElement('tr'); + row.appendChild(col1); + row.appendChild(col2); + row.style.verticalAlign = 'center'; + tbl.appendChild(row); + } + + return tbl; + } + + function build_input(type,size,value) { + var input = document.createElement('input'); + input.type = type; + input.size = size; + input.className = 'property'; // make this easier to find later + if (value == undefined) input.value = ''; + else input.value = value.toString(); + return input; + } + + // build a select widget using the strings found in the options array + function build_select(options,selected) { + var select = document.createElement('select'); + for (var i = 0; i < options.length; i++) { + var option = document.createElement('option'); + option.text = options[i]; + select.add(option); + if (options[i] == selected) select.selectedIndex = i; + } + return select; + } + + Schematic.prototype.window = function(title,content,offset) { + // create the div for the top level of the window + var win = document.createElement('div'); + win.sch = this; + win.content = content; + win.drag_x = undefined; + win.draw_y = undefined; + + // div to hold the title + var head = document.createElement('div'); + head.style.backgroundColor = 'black'; + head.style.color = 'white'; + head.style.textAlign = 'center'; + head.style.padding = '5px'; + head.appendChild(document.createTextNode(title)); + head.win = win; + win.head = head; + + var close_button = new Image(); + close_button.src = close_icon; + close_button.style.cssFloat = 'right'; + close_button.addEventListener('click',window_close_button,false); + close_button.win = win; + head.appendChild(close_button); + + win.appendChild(head); + + // capture mouse events in title bar + head.addEventListener('mousedown',window_mouse_down,false); + + // div to hold the content + //var body = document.createElement('div'); + //body.appendChild(content); + win.appendChild(content); + content.win = win; // so content can contact us + + // compute location relative to canvas + if (offset == undefined) offset = 0; + win.left = this.canvas.mouse_x + offset; + win.top = this.canvas.mouse_y + offset; + + // add to DOM + win.style.background = 'white'; + win.style.position = 'absolute'; + win.style.left = win.left + 'px'; + win.style.top = win.top + 'px'; + win.style.border = '2px solid'; + + this.canvas.parentNode.insertBefore(win,this.canvas); + bring_to_front(win,true); + } + + // adjust zIndex of pop-up window so that it is in front + function bring_to_front(win,insert) { + var wlist = win.sch.window_list; + var i = wlist.indexOf(win); + + // remove from current position (if any) in window list + if (i != -1) wlist.splice(i,1); + + // if requested, add to end of window list + if (insert) wlist.push(win); + + // adjust all zIndex values + for (i = 0; i < wlist.length; i += 1) + wlist[i].style.zIndex = 1000 + i; + } + + // close the window + function window_close(win) { + // remove the window from the top-level div of the schematic + win.parentNode.removeChild(win); + + // remove from list of pop-up windows + bring_to_front(win,false); + } + + function window_close_button(event) { + if (!event) event = window.event; + var src = (window.event) ? event.srcElement : event.target; + window_close(src.win); + } + + // capture mouse events in title bar of window + function window_mouse_down(event) { + if (!event) event = window.event; + var src = (window.event) ? event.srcElement : event.target; + var win = src.win; + + bring_to_front(win,true); + + // add handlers to document so we capture them no matter what + document.addEventListener('mousemove',window_mouse_move,false); + document.addEventListener('mouseup',window_mouse_up,false); + document.tracking_window = win; + + // remember where mouse is so we can compute dx,dy during drag + win.drag_x = event.pageX; + win.drag_y = event.pageY; + + return false; + } + + function window_mouse_up(event) { + var win = document.tracking_window; + + // show's over folks... + document.removeEventListener('mousemove',window_mouse_move,false); + document.removeEventListener('mouseup',window_mouse_up,false); + document.tracking_window = undefined; + win.drag_x = undefined; + win.drag_y = undefined; + return true; // consume event + } + + function window_mouse_move(event) { + var win = document.tracking_window; + + if (win.drag_x) { + var dx = event.pageX - win.drag_x; + var dy = event.pageY - win.drag_y; + + // move the window + win.left += dx; + win.top += dy; + win.style.left = win.left + 'px'; + win.style.top = win.top + 'px'; + + // update reference point + win.drag_x += dx; + win.drag_y += dy; + + return true; // consume event + } + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Toolbar + // + //////////////////////////////////////////////////////////////////////////////// + + Schematic.prototype.add_tool = function(icon,tip,callback) { + var tool, child, label, hidden; + + tool = document.createElement('button'); + child = document.createElement('img'); + label = document.createElement('span'); + hidden = document.createElement('span'); + + tool.style.backgroundImage = 'none'; + tool.setAttribute('title', tip); + label.innerHTML = tip; + label.classList.add('sr'); + hidden.setAttribute('aria-hidden', 'true'); + + if (icon.search('data:image') != -1) { + child.setAttribute('src', icon); + child.setAttribute('alt', ''); + tool.appendChild(child); + } else { + tool.style.font = 'small-caps small sans-serif'; + hidden.innerHTML = icon; + tool.appendChild(hidden); + tool.appendChild(label); + } + + // decorate tool + tool.style.height = '32px'; + tool.style.width = 'auto'; + tool.style.verticalAlign = 'top'; + + // set up event processing + tool.addEventListener('mouseover',tool_enter,false); + tool.addEventListener('mouseout',tool_leave,false); + tool.addEventListener('click',tool_click,false); + + // add to toolbar + tool.sch = this; + tool.tip = tip; + tool.callback = callback; + this.toolbar.push(tool); + + tool.enabled = false; + + return tool; + } + + Schematic.prototype.enable_tool = function(tname,which) { + var tool = this.tools[tname]; + + if (tool != undefined) { + tool.removeAttribute('disabled'); + tool.enabled = which; + + // if disabling tool, remove border and tip + if (!which) { + tool.sch.message(''); + tool.setAttribute('disabled', 'true'); + } + } + } + + // highlight tool button by turning on border, changing background + function tool_enter(event) { + if (!event) event = window.event; + var tool = event.target; + if (event.target.tagName.toLowerCase() == 'img' || event.target.tagName.toLowerCase() == 'span') { + tool = event.target.parentNode; + } + if (tool.enabled) { + tool.sch.message(tool.tip); + } + event.stopPropagation(); + } + + // unhighlight tool button by turning off border, reverting to normal background + function tool_leave(event) { + if (!event) event = window.event; + var tool = event.target; + if (event.target.tagName.toLowerCase() == 'img' || event.target.tagName.toLowerCase() == 'span') { + tool = event.target.parentNode; + } + if (tool.enabled) { + tool.sch.message(''); + } + event.stopPropagation(); + } + + // handle click on a tool + function tool_click(event) { + if (!event) event = window.event; + var tool = event.target; + if (event.target.tagName.toLowerCase() == 'img' || event.target.tagName.toLowerCase() == 'span') { + tool = event.target.parentNode; + } + if (tool.enabled) { + tool.sch.canvas.relMouseCoords(event); // so we can position pop-up window correctly + tool.callback.call(tool.sch); + } + event.stopPropagation(); + } + + var help_icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABgFBMVEUARMwAZsz///8AM5kGqP+s1/8AeuARp/8AZ803qPsAXNYAdNwAZcxZuv9auf99xv8AdNoEd9uTzP8AYsgAivQTl/cAj/V9xf8Ad90AeN5PtP8AUMoAj/oRiOgprf84qfwAb9UAifAAdtwAf+UAgOYActgAk/oAie8cqP8AbtQAXtkXof8AatBNuP8AbdMAgukXcOEAXdcAlP0AhuwJmv0prv8YceGCyP8AbtUAZd8elvMAZcsAW9Ucpv8AjfM3sP8AiO4AWdNOuP8AddsPgeIAhOoAbdT///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABH5RCxAAAASHRSTlP//////////////////////////////////////////////////////////////////////////////////////////////wCc7PJgAAAAAWJLR0R/SL9x5QAAAAlwSFlzAAAASAAAAEgARslrPgAAAAl2cEFnAAAAEAAAABAAXMatwwAAAK5JREFUGNM1zwcOwjAMBVAHQ9PFbIG27L333pve/0bEBr5kyf9JkWIIKYLDK3CNcZgUiE0QFIuuu89kBIHIDy5TUOmXSknBsFxDRAXMJ4FIZOeqA41lxQVB+w/1L9RyO+B+fLwJ7q/OOUfd9FvDkQJDmyyuoLqWGtsVBq3RnAHcUlXbNgSEWPY8n570dH2F6h94Sqe3BAdd7xKEKKVTACg4UuL3OMQoB/F3LRGF1w/Arhm2Q9w2ZQAAACV0RVh0Y3JlYXRlLWRhdGUAMjAwOC0xMC0yM1QxMTo1ODozNiswODowMKkTWd4AAAAldEVYdG1vZGlmeS1kYXRlADIwMDgtMTAtMjNUMTE6NTk6NTArMDg6MDC833hpAAAAAElFTkSuQmCC'; + + var cut_icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QocFh0xaEFkXgAAArRJREFUOMuFk11Ik1EYx59z3nevr9vUfaXbbPgVaHjRVRB0YZRJV0XeZCIRaGmWWKhpgZAElaV9gYgQlBjoEPRKkCS6DAK1MG0zNvJj7zZ1m+51X+92zttNzmFa5+78/w8//s/znIMg5TzrfXIOAN7zPO9tunm7dI/Xz7LspTvNrbpUHadeGIYZu9XYrI1Go8t9/a87Uz0Fq7hw5nS55sWrnk8HAggh/E+HHdfV1lcQQo7t6E97HpeZc82m7ZCIKKUnDgRgjENLS7+AT0tDsVisdCcFy7JThYWF4HF7KKXU8a8EFTabDVZdK6iutr44kUic6nnePVBSUqJAgMHhdAAAWA8E3G299xljvLy4aAc+jUeSJB3X6/TXZAqwvrFGAWCiraXj4YEAAABKaeXCjwV5bc0DjTeaVPFEHIliEObm5iQA6Npb/xegraVjGmM8ZF+00WBwC2s0GhDcgizL8ru2lo7p/wL+pJianZnGTqcD0jkeMt8ORhBCb/arRXuFMaOxl1B6Pb65qSblZTIz+REVGHNAIHQLITRQ6fG07wsYM5k6437/g6MmEyQoRd6tTdkX3h5mZVRVkJ3D8BxHJVkG5/o6KLKyrla63UPJFsbN5hrJ5+sqNhrpwsrKVDASlgJBEdfEaU2UIzqWwTQQEhOO1dUPR/R6EvP5BsfN5t2XOmowCPNFRWSEYe4DAMxYLCGrUpnY8UcYhnzJNQcBAIYxbv+Wn09GDQZhd4ixmF6SJFJFyKMJleqlgmV5hLE9OWmOm1Hz6arJjIy+y5R2gyxTIMSwC+A4Qa1UMl/z8mImna5pXhC8iszMK8mPpNU2fHe5Ng4fOtQwa7HECKUYMA4AADAAANVarc/l95/0SxIbAJA5tfrsRUFI7twqiu7q7GyPNxDI8YfDGl8k4lOoVOetouj+DaDzOgfcNME8AAAAAElFTkSuQmCC'; + + var copy_icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAd0lEQVQ4y9WTsQ7AIAhE7wj//69dHKWLJqSlFOtUFpXA8SAIbBrHaR9yAAA6L2bvGiRvPtltQa+OqMrFPCo1jFhoRytBmXgqUCH5GUEkWCbova8TeBORfBNJVpYIrbVJdwDjY5hjJfk4vFnAzMDxiEqmo/fJAHACspMyA7UYnWgAAAAASUVORK5CYII='; + + var paste_icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAABZElEQVQ4y6WSMUsDMRiGn6RteoJSENS5oCdFR3+D0MHBciA4uujiVrq0o1NBcBEEFycXRzcnf4GDINTiL7BTr9LeJdfGoaX0ei21+MFHAsn7fG9eAjOqXCwoz/NKgAWs53mlcrGgZt0VE3s7fdhsfgHguttztTHA5+0ZjUaDzdM7HEeRy60C0G7/EASa78cLXNelcPkw1qYnkVprfN/n+6aEUgqlFFJKjDForclms2itYzZigH6/Tz6fp9PpAFC8fp3h/J2rw42P2ksLADkNMMbgOA6O4wzfZW2sAWovrb3janUn4cAYgzGGRWWtRQjRPKpUdmOAKIrGgCiK5gKEGGb/XK9/JhwEQUC32yUMw7nTJ0ExQK/Xw/d9BoPBeMqiigHCMEQIQSqV+pM4AbCAXEKcAGAtKSn/AYCE/UVZpIEVYA1ASkkmkxl/mqfzg5ExG1tP7t8AtoAOwDqwP4pgmd4H1n8B+QWeF/d+HLAAAAAASUVORK5CYII='; + + var close_icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACOUlEQVR42m2TzWtTQRTF30ysxE9E0VZKaapBa1OJxtRAW7XVGOrCKijFIEqXbgQFwf/BTReia7GUuBEUF5Y2YiMKKn6iKEqRom1DtAsjStGaGX9v3iQ+Y4Z35t6ZOfe8uXdmhFPVDqRSktYvpBzAxphaBQpKqSdalTLYO7fHxnWZL/zBfclkWAbksBBip7cmHEGvDd3raFlVUoOj2Wz+H4H9vT0RGQhMMLHGkxaienduuJV6p0ql5PjdiRlD2rurO0jwM9zWWnG1dPhyWql9ht3T1XmKwEtAaLNVMUT3AFyBsAz7g9lBbBc4+zcb54joTnQIKeRDZjrcvyNQxG9A5Bd2NwIZ+Gn8e2AxmHNFbTbXRWc8FoRcJLjObtDtbjB3DLtALZbws3l8d/0aOOzLZlYktkfX4eS9epuiehlqZ+TRi5cny8zEtuhVVo/7eabW8a2RFdivwlbPbu079uDT129yZYEd7W17oNzCXe4rdFHE2lrd0SRosbX5TXAK5EAd5NPYi9gF0AtGwSIrcN9IRTeFLxB8zp7RPAExMAUxAw7h3wRpdh+SQjzHBm0KZ4xA+8aWRgivzLU16TvuLZsB8UqyjvMYNDOu98rgfEQ8UklmS6hpQCs9ghuwdShfSKF9Ezb/n5x939upT7mKwOamRogqjchlhit9R+XbhGlfeGgn3k/Pjv33mNwWXl8f4sWdJ+Yow9W+JTetYSkDQ5P5wuear7HcNjSs5Upqd60ZLAXfwPSHwpyu5v4BhpTicEl0i9QAAAAASUVORK5CYII='; + + var grid_icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAMklEQVQ4y2NkYGD4z0ABYGFgYGD4/x/VDEZGRqLFmCixnYGBYRAYwMgwGoijgTgsAhEAq84fH/l+ELYAAAAASUVORK5CYII='; + + /////////////////////////////////////////////////////////////////////////////// + // + // Graphing + // + /////////////////////////////////////////////////////////////////////////////// + + // add dashed lines! + // from http://davidowens.wordpress.com/2010/09/07/html-5-canvas-and-dashed-lines/ + try { + if (CanvasRenderingContext2D) + CanvasRenderingContext2D.prototype.dashedLineTo = function(fromX, fromY, toX, toY, pattern) { + // Our growth rate for our line can be one of the following: + // (+,+), (+,-), (-,+), (-,-) + // Because of this, our algorithm needs to understand if the x-coord and + // y-coord should be getting smaller or larger and properly cap the values + // based on (x,y). + var lt = function (a, b) { return a <= b; }; + var gt = function (a, b) { return a >= b; }; + var capmin = function (a, b) { return Math.min(a, b); }; + var capmax = function (a, b) { return Math.max(a, b); }; + var checkX = { thereYet: gt, cap: capmin }; + var checkY = { thereYet: gt, cap: capmin }; + + if (fromY - toY > 0) { + checkY.thereYet = lt; + checkY.cap = capmax; + } + if (fromX - toX > 0) { + checkX.thereYet = lt; + checkX.cap = capmax; + } + + this.moveTo(fromX, fromY); + var offsetX = fromX; + var offsetY = fromY; + var idx = 0, dash = true; + while (!(checkX.thereYet(offsetX, toX) && checkY.thereYet(offsetY, toY))) { + var ang = Math.atan2(toY - fromY, toX - fromX); + var len = pattern[idx]; + + offsetX = checkX.cap(toX, offsetX + (Math.cos(ang) * len)); + offsetY = checkY.cap(toY, offsetY + (Math.sin(ang) * len)); + + if (dash) this.lineTo(offsetX, offsetY); + else this.moveTo(offsetX, offsetY); + + idx = (idx + 1) % pattern.length; + dash = !dash; + } + }; + } + catch (err) { //noop + } + // given a range of values, return a new range [vmin',vmax'] where the limits + // have been chosen "nicely". Taken from matplotlib.ticker.LinearLocator + function view_limits(vmin,vmax) { + // deal with degenerate case... + if (vmin == vmax) { + if (vmin == 0) { vmin = -0.5; vmax = 0.5; } + else { + vmin = vmin > 0 ? 0.9*vmin : 1.1*vmin; + vmax = vmax > 0 ? 1.1*vmax : 0.9*vmax; + } + } + + var log_range = Math.log(vmax - vmin)/Math.LN10; + var exponent = Math.floor(log_range); + //if (log_range - exponent < 0.5) exponent -= 1; + var scale = Math.pow(10,-exponent); + vmin = Math.floor(scale*vmin)/scale; + vmax = Math.ceil(scale*vmax)/scale; + + return [vmin,vmax,1.0/scale]; + } + + function engineering_notation(n,nplaces,trim) { + if (n == 0) return '0'; + if (n == undefined) return 'undefined'; + if (trim == undefined) trim = true; + + var sign = n < 0 ? -1 : 1; + var log10 = Math.log(sign*n)/Math.LN10; + var exp = Math.floor(log10/3); // powers of 1000 + var mantissa = sign*Math.pow(10,log10 - 3*exp); + + // keep specified number of places following decimal point + var mstring = (mantissa + sign*0.5*Math.pow(10,-nplaces)).toString(); + var mlen = mstring.length; + var endindex = mstring.indexOf('.'); + if (endindex != -1) { + if (nplaces > 0) { + endindex += nplaces + 1; + if (endindex > mlen) endindex = mlen; + if (trim) { + while (mstring.charAt(endindex-1) == '0') endindex -= 1; + if (mstring.charAt(endindex-1) == '.') endindex -= 1; + } + } + if (endindex < mlen) + mstring = mstring.substring(0,endindex); + } + + switch(exp) { + case -5: return mstring+"f"; + case -4: return mstring+"p"; + case -3: return mstring+"n"; + case -2: return mstring+"u"; + case -1: return mstring+"m"; + case 0: return mstring; + case 1: return mstring+"K"; + case 2: return mstring+"M"; + case 3: return mstring+"G"; + } + + // don't have a good suffix, so just print the number + return n.toString(); + } + + var grid_pattern = [1,2]; + var cursor_pattern = [5,5]; + + // x_values is an array of x coordinates for each of the plots + // y_values is an array of [color, value_array], one entry for each plot on left vertical axis + // z_values is an array of [color, value_array], one entry for each plot on right vertical axis + Schematic.prototype.graph = function(x_values,x_legend,y_values,y_legend,z_values,z_legend) { + var pwidth = 400; // dimensions of actual plot + var pheight = 300; // dimensions of actual plot + var left_margin = (y_values != undefined && y_values.length > 0) ? 55 : 25; + var top_margin = 25; + var right_margin = (z_values != undefined && z_values.length > 0) ? 55 : 25; + var bottom_margin = 45; + var tick_length = 5; + + var w = pwidth + left_margin + right_margin; + var h = pheight + top_margin + bottom_margin; + + var canvas = document.createElement('canvas'); + canvas.width = w; + canvas.height = h; + + // the graph itself will be drawn here and this image will be copied + // onto canvas, where it can be overlayed with mouse cursors, etc. + var bg_image = document.createElement('canvas'); + bg_image.width = w; + bg_image.height = h; + canvas.bg_image = bg_image; // so we can find it during event handling + + // start by painting an opaque background + var c = bg_image.getContext('2d'); + c.fillStyle = background_style; + c.fillRect(0,0,w,h); + c.fillStyle = element_style; + c.fillRect(left_margin,top_margin,pwidth,pheight); + + // figure out scaling for plots + var x_min = array_min(x_values); + var x_max = array_max(x_values); + var x_limits = view_limits(x_min,x_max); + x_min = x_limits[0]; + x_max = x_limits[1]; + var x_scale = pwidth/(x_max - x_min); + + function plot_x(x) { + return (x - x_min)*x_scale + left_margin; + } + + // draw x grid + c.strokeStyle = grid_style; + c.lineWidth = 1; + c.fillStyle = normal_style; + c.font = '10pt sans-serif'; + c.textAlign = 'center'; + c.textBaseline = 'top'; + var end = top_margin + pheight; + for (var x = x_min; x <= x_max; x += x_limits[2]) { + var temp = plot_x(x) + 0.5; // keep lines crisp! + + // grid line + c.beginPath(); + if (x == x_min) { + c.moveTo(temp,top_margin); + c.lineTo(temp,end); + } else + c.dashedLineTo(temp,top_margin,temp,end,grid_pattern); + c.stroke(); + + // tick mark + c.beginPath(); + c.moveTo(temp,end); + c.lineTo(temp,end + tick_length); + c.stroke(); + c.fillText(engineering_notation(x,2),temp,end + tick_length); + } + + if (y_values != undefined && y_values.length > 0) { + var y_min = Infinity; + var y_max = -Infinity; + var plot; + for (plot = y_values.length - 1; plot >= 0; --plot) { + var values = y_values[plot][2]; + if (values == undefined) continue; // no data points + var offset = y_values[plot][1]; + var temp = array_min(values) + offset; + if (temp < y_min) y_min = temp; + temp = array_max(values) + offset; + if (temp > y_max) y_max = temp; + } + var y_limits = view_limits(y_min,y_max); + y_min = y_limits[0]; + y_max = y_limits[1]; + var y_scale = pheight/(y_max - y_min); + + function plot_y(y) { + return (y_max - y)*y_scale + top_margin; + } + + // draw y grid + c.textAlign = 'right'; + c.textBaseline = 'middle'; + for (var y = y_min; y <= y_max; y += y_limits[2]) { + if (Math.abs(y/y_max) < 0.001) y = 0.0; // Just 3 digits + var temp = plot_y(y) + 0.5; // keep lines crisp! + + // grid line + c.beginPath(); + if (y == y_min) { + c.moveTo(left_margin,temp); + c.lineTo(left_margin + pwidth,temp); + } else + c.dashedLineTo(left_margin,temp,left_margin + pwidth,temp,grid_pattern); + c.stroke(); + + // tick mark + c.beginPath(); + c.moveTo(left_margin - tick_length,temp); + c.lineTo(left_margin,temp); + c.stroke(); + c.fillText(engineering_notation(y,2),left_margin - tick_length -2,temp); + } + + // now draw each plot + var x,y; + var nx,ny; + c.lineWidth = 3; + c.lineCap = 'round'; + for (plot = y_values.length - 1; plot >= 0; --plot) { + var color = probe_colors_rgb[y_values[plot][0]]; + if (color == undefined) continue; // no plot color (== x-axis) + c.strokeStyle = color; + var values = y_values[plot][2]; + if (values == undefined) continue; // no data points + var offset = y_values[plot][1]; + + x = plot_x(x_values[0]); + y = plot_y(values[0] + offset); + c.beginPath(); + c.moveTo(x,y); + for (var i = 1; i < x_values.length; i++) { + nx = plot_x(x_values[i]); + ny = plot_y(values[i] + offset); + c.lineTo(nx,ny); + x = nx; + y = ny; + if (i % 100 == 99) { + // too many lineTo's cause canvas to break + c.stroke(); + c.beginPath(); + c.moveTo(x,y); + } + } + c.stroke(); + } + } + + if (z_values != undefined && z_values.length > 0) { + var z_min = Infinity; + var z_max = -Infinity; + for (plot = z_values.length - 1; plot >= 0; --plot) { + var values = z_values[plot][2]; + if (values == undefined) continue; // no data points + var offset = z_values[plot][1]; + var temp = array_min(values) + offset; + if (temp < z_min) z_min = temp; + temp = array_max(values) + offset; + if (temp > z_max) z_max = temp; + } + var z_limits = view_limits(z_min,z_max); + z_min = z_limits[0]; + z_max = z_limits[1]; + var z_scale = pheight/(z_max - z_min); + + function plot_z(z) { + return (z_max - z)*z_scale + top_margin; + } + + // draw z ticks + c.textAlign = 'left'; + c.textBaseline = 'middle'; + c.lineWidth = 1; + c.strokeStyle = normal_style; + var tick_length_half = Math.floor(tick_length/2); + var tick_delta = tick_length - tick_length_half; + for (var z = z_min; z <= z_max; z += z_limits[2]) { + if (Math.abs(z/z_max) < 0.001) z = 0.0; // Just 3 digits + var temp = plot_z(z) + 0.5; // keep lines crisp! + + // tick mark + c.beginPath(); + c.moveTo(left_margin + pwidth - tick_length_half,temp); + c.lineTo(left_margin + pwidth + tick_delta,temp); + c.stroke(); + c.fillText(engineering_notation(z,2),left_margin + pwidth + tick_length + 2,temp); + } + + var z; + var nz; + c.lineWidth = 3; + for (plot = z_values.length - 1; plot >= 0; --plot) { + var color = probe_colors_rgb[z_values[plot][0]]; + if (color == undefined) continue; // no plot color (== x-axis) + c.strokeStyle = color; + var values = z_values[plot][2]; + if (values == undefined) continue; // no data points + var offset = z_values[plot][1]; + + x = plot_x(x_values[0]); + z = plot_z(values[0] + offset); + c.beginPath(); + c.moveTo(x,z); + for (var i = 1; i < x_values.length; i++) { + nx = plot_x(x_values[i]); + nz = plot_z(values[i] + offset); + c.lineTo(nx,nz); + x = nx; + z = nz; + if (i % 100 == 99) { + // too many lineTo's cause canvas to break + c.stroke(); + c.beginPath(); + c.moveTo(x,z); + } + } + c.stroke(); + } + } + + // draw legends + c.font = '12pt sans-serif'; + c.textAlign = 'center'; + c.textBaseline = 'bottom'; + c.fillText(x_legend,left_margin + pwidth/2,h - 5); + + if (y_values != undefined && y_values.length > 0) { + c.textBaseline = 'top'; + c.save(); + c.translate(5 ,top_margin + pheight/2); + c.rotate(-Math.PI/2); + c.fillText(y_legend,0,0); + c.restore(); + } + + if (z_values != undefined && z_values.length > 0) { + c.textBaseline = 'bottom'; + c.save(); + c.translate(w-5 ,top_margin + pheight/2); + c.rotate(-Math.PI/2); + c.fillText(z_legend,0,0); + c.restore(); + } + + // save info need for interactions with the graph + canvas.x_values = x_values; + canvas.y_values = y_values; + canvas.z_values = z_values; + canvas.x_legend = x_legend; + canvas.y_legend = y_legend; + canvas.z_legend = y_legend; + canvas.x_min = x_min; + canvas.x_scale = x_scale; + canvas.y_min = y_min; + canvas.y_scale = y_scale; + canvas.z_min = z_min; + canvas.z_scale = z_scale; + canvas.left_margin = left_margin; + canvas.top_margin = top_margin; + canvas.pwidth = pwidth; + canvas.pheight = pheight; + canvas.tick_length = tick_length; + + canvas.cursor1_x = undefined; + canvas.cursor2_x = undefined; + canvas.sch = this; + + // do something useful when user mouses over graph + canvas.addEventListener('mousemove',graph_mouse_move,false); + + // return our masterpiece + redraw_plot(canvas); + return canvas; + } + + function array_max(a) { + var max = -Infinity; + for (var i = a.length - 1; i >= 0; --i) + if (a[i] > max) max = a[i]; + return max; + } + + function array_min(a) { + var min = Infinity; + for (var i = a.length - 1; i >= 0; --i) + if (a[i] < min) min = a[i]; + return min; + } + + function plot_cursor(c,graph,cursor_x,left_margin) { + // draw dashed vertical marker that follows mouse + var x = graph.left_margin + cursor_x; + var end_y = graph.top_margin + graph.pheight + graph.tick_length; + c.strokeStyle = grid_style; + c.lineWidth = 1; + c.beginPath(); + c.dashedLineTo(x,graph.top_margin,x,end_y,cursor_pattern); + c.stroke(); + + // add x label at bottom of marker + var graph_x = cursor_x/graph.x_scale + graph.x_min; + c.font = '10pt sans-serif'; + c.textAlign = 'center'; + c.textBaseline = 'top'; + c.fillStyle = background_style; + c.fillText('\u2588\u2588\u2588\u2588\u2588',x,end_y); + c.fillStyle = normal_style; + c.fillText(engineering_notation(graph_x,3,false),x,end_y); + + // compute which points marker is between + var x_values = graph.x_values; + var len = x_values.length; + var index = 0; + while (index < len && graph_x >= x_values[index]) index += 1; + var x1 = (index == 0) ? x_values[0] : x_values[index-1]; + var x2 = x_values[index]; + + if (x2 != undefined) { + // for each plot, interpolate and output value at intersection with marker + c.textAlign = 'left'; + var tx = graph.left_margin + left_margin; + var ty = graph.top_margin; + if (graph.y_values != undefined) { + for (var plot = 0; plot < graph.y_values.length; plot++) { + var values = graph.y_values[plot][2]; + var color = probe_colors_rgb[graph.y_values[plot][0]]; + if (values == undefined || color == undefined) continue; // no data points or x-axis + + // interpolate signal value at graph_x using values[index-1] and values[index] + var y1 = (index == 0) ? values[0] : values[index-1]; + var y2 = values[index]; + var y = y1; + if (graph_x != x1) y += (graph_x - x1)*(y2 - y1)/(x2 - x1); + + // annotate plot with value of signal at marker + c.fillStyle = element_style; + c.fillText('\u2588\u2588\u2588\u2588\u2588',tx-3,ty); + c.fillStyle = color; + c.fillText(engineering_notation(y,3,false),tx,ty); + ty += 14; + } + } + + c.textAlign = 'right'; + if (graph.z_values != undefined) { + var tx = graph.left_margin + graph.pwidth - left_margin; + var ty = graph.top_margin; + for (var plot = 0; plot < graph.z_values.length; plot++) { + var values = graph.z_values[plot][2]; + var color = probe_colors_rgb[graph.z_values[plot][0]]; + if (values == undefined || color == undefined) continue; // no data points or x-axis + + // interpolate signal value at graph_x using values[index-1] and values[index] + var z1 = (index == 0) ? values[0]: values[index-1]; + var z2 = values[index]; + var z = z1; + if (graph_x != x1) z += (graph_x - x1)*(z2 - z1)/(x2 - x1); + + // annotate plot with value of signal at marker + c.fillStyle = element_style; + c.fillText('\u2588\u2588\u2588\u2588\u2588',tx+3,ty); + c.fillStyle = color; + c.fillText(engineering_notation(z,3,false),tx,ty); + ty += 14; + } + } + } + } + + function redraw_plot(graph) { + var c = graph.getContext('2d'); + c.drawImage(graph.bg_image,0,0); + + if (graph.cursor1_x != undefined) plot_cursor(c,graph,graph.cursor1_x,4); + if (graph.cursor2_x != undefined) plot_cursor(c,graph,graph.cursor2_x,30); + + /* + if (graph.cursor1_x != undefined) { + // draw dashed vertical marker that follows mouse + var x = graph.left_margin + graph.cursor1_x; + var end_y = graph.top_margin + graph.pheight + graph.tick_length; + c.strokeStyle = grid_style; + c.lineWidth = 1; + c.beginPath(); + c.dashedLineTo(x,graph.top_margin,x,end_y,cursor_pattern); + c.stroke(); + + // add x label at bottom of marker + var graph_x = graph.cursor1_x/graph.x_scale + graph.x_min; + c.font = '10pt sans-serif'; + c.textAlign = 'center'; + c.textBaseline = 'top'; + c.fillStyle = background_style; + c.fillText('\u2588\u2588\u2588\u2588\u2588',x,end_y); + c.fillStyle = normal_style; + c.fillText(engineering_notation(graph_x,3,false),x,end_y); + + // compute which points marker is between + var x_values = graph.x_values; + var len = x_values.length; + var index = 0; + while (index < len && graph_x >= x_values[index]) index += 1; + var x1 = (index == 0) ? x_values[0] : x_values[index-1]; + var x2 = x_values[index]; + + if (x2 != undefined) { + // for each plot, interpolate and output value at intersection with marker + c.textAlign = 'left'; + var tx = graph.left_margin + 4; + var ty = graph.top_margin; + for (var plot = 0; plot < graph.y_values.length; plot++) { + var values = graph.y_values[plot][1]; + + // interpolate signal value at graph_x using values[index-1] and values[index] + var y1 = (index == 0) ? values[0] : values[index-1]; + var y2 = values[index]; + var y = y1; + if (graph_x != x1) y += (graph_x - x1)*(y2 - y1)/(x2 - x1); + + // annotate plot with value of signal at marker + c.fillStyle = element_style; + c.fillText('\u2588\u2588\u2588\u2588\u2588',tx-3,ty); + c.fillStyle = probe_colors_rgb[graph.y_values[plot][0]]; + c.fillText(engineering_notation(y,3,false),tx,ty); + ty += 14; + } + } + } + */ + } + + function graph_mouse_move(event) { + if (!event) event = window.event; + var g = (window.event) ? event.srcElement : event.target; + + g.relMouseCoords(event); + // not sure yet where the 3,-3 offset correction comes from (borders? padding?) + var gx = g.mouse_x - g.left_margin - 3; + var gy = g.pheight - (g.mouse_y - g.top_margin) + 3; + if (gx >= 0 && gx <= g.pwidth && gy >=0 && gy <= g.pheight) { + //g.sch.message('button: '+event.button+', which: '+event.which); + g.cursor1_x = gx; + } else { + g.cursor1_x = undefined; + g.cursor2_x = undefined; + } + + redraw_plot(g); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Parts bin + // + //////////////////////////////////////////////////////////////////////////////// + + // one instance will be created for each part in the parts bin + function Part(sch) { + this.sch = sch; + this.component = undefined; + this.selected = false; + + // set up canvas + this.canvas = document.createElement('canvas'); + this.canvas.style.borderStyle = 'solid'; + this.canvas.style.borderWidth = '1px'; + this.canvas.style.borderColor = background_style; + //this.canvas.style.position = 'absolute'; + this.canvas.style.cursor = 'default'; + this.canvas.height = part_w; + this.canvas.width = part_h; + this.canvas.part = this; + + this.canvas.addEventListener('mouseover',part_enter,false); + this.canvas.addEventListener('mouseout',part_leave,false); + this.canvas.addEventListener('mousedown',part_mouse_down,false); + this.canvas.addEventListener('mouseup',part_mouse_up,false); + + // make the part "clickable" by registering a dummy click handler + // this should make things work on the iPad + this.canvas.addEventListener('click',function(){},false); + } + + Part.prototype.set_location = function(left,top) { + this.canvas.style.left = left + 'px'; + this.canvas.style.top = top + 'px'; + } + + Part.prototype.right = function() { + return this.canvas.offsetLeft + this.canvas.offsetWidth; + } + + Part.prototype.bottom = function() { + return this.canvas.offsetTop + this.canvas.offsetHeight; + } + + Part.prototype.set_component = function(component,tip) { + component.sch = this; + this.component = component; + this.tip = tip; + + // figure out scaling and centering of parts icon + var b = component.bounding_box; + var dx = b[2] - b[0]; + var dy = b[3] - b[1]; + this.scale = 0.8; //Math.min(part_w/(1.2*dx),part_h/(1.2*dy)); + this.origin_x = b[0] + dx/2.0 - part_w/(2.0*this.scale); + this.origin_y = b[1] + dy/2.0 - part_h/(2.0*this.scale); + + this.redraw(); + } + + Part.prototype.redraw = function(part) { + var c = this.canvas.getContext('2d'); + + // paint background color + c.fillStyle = this.selected ? selected_style : background_style; + c.fillRect(0,0,part_w,part_h); + + if (this.component) this.component.draw(c); + } + + Part.prototype.select = function(which) { + this.selected = which; + this.redraw(); + } + + Part.prototype.update_connection_point = function(cp,old_location) { + // no connection points in the parts bin + } + + Part.prototype.moveTo = function(c,x,y) { + c.moveTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); + } + + Part.prototype.lineTo = function(c,x,y) { + c.lineTo((x - this.origin_x) * this.scale,(y - this.origin_y) * this.scale); + } + + Part.prototype.draw_line = function(c,x1,y1,x2,y2,width) { + c.lineWidth = width*this.scale; + c.beginPath(); + c.moveTo((x1 - this.origin_x) * this.scale,(y1 - this.origin_y) * this.scale); + c.lineTo((x2 - this.origin_x) * this.scale,(y2 - this.origin_y) * this.scale); + c.stroke(); + } + + Part.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians,anticlockwise,width,filled) { + c.lineWidth = width*this.scale; + c.beginPath(); + c.arc((x - this.origin_x)*this.scale,(y - this.origin_y)*this.scale,radius*this.scale, + start_radians,end_radians,anticlockwise); + if (filled) c.fill(); + else c.stroke(); + } + + Part.prototype.draw_text = function(c,text,x,y,size) { + // no text displayed for the parts icon + } + + function part_enter(event) { + if (!event) event = window.event; + var canvas = (window.event) ? event.srcElement : event.target; + var part = canvas.part; + + // avoid Chrome bug that changes to text cursor whenever + // drag starts. We'll restore the default handler at + // the appropriate point so behavior in other parts of + // the document are unaffected. + //part.sch.saved_onselectstart = document.onselectstart; + //document.onselectstart = function () { return false; }; + + canvas.style.borderColor = normal_style; + part.sch.message(part.tip+': drag onto diagram to insert'); + return false; + } + + function part_leave(event) { + if (!event) event = window.event; + var canvas = (window.event) ? event.srcElement : event.target; + var part = canvas.part; + + if (typeof part.sch.new_part == 'undefined') { + // leaving with no part selected? revert handler + //document.onselectstart = part.sch.saved_onselectstart; + } + + canvas.style.borderColor = background_style; + part.sch.message(''); + return false; + } + + function part_mouse_down(event) { + if (!event) event = window.event; + var part = (window.event) ? event.srcElement.part : event.target.part; + + part.select(true); + part.sch.new_part = part; + return false; + } + + function part_mouse_up(event) { + if (!event) event = window.event; + var part = (window.event) ? event.srcElement.part : event.target.part; + + part.select(false); + part.sch.new_part = undefined; + return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Rectangle helper functions + // + //////////////////////////////////////////////////////////////////////////////// + + // rect is an array of the form [left,top,right,bottom] + + // ensure left < right, top < bottom + function canonicalize(r) { + var temp; + + // canonicalize bounding box + if (r[0] > r[2]) { + temp = r[0]; + r[0] = r[2]; + r[2] = temp; + } + if (r[1] > r[3]) { + temp = r[1]; + r[1] = r[3]; + r[3] = temp; + } + } + + function between(x,x1,x2) { + return x1 <= x && x <= x2; + } + + function inside(rect,x,y) { + return between(x,rect[0],rect[2]) && between(y,rect[1],rect[3]); + } + + // only works for manhattan rectangles + function intersect(r1,r2) { + // look for non-intersection, negate result + var result = !(r2[0] > r1[2] || + r2[2] < r1[0] || + r2[1] > r1[3] || + r2[3] < r1[1]); + + // if I try to return the above expression, javascript returns undefined!!! + return result; + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Component base class + // + //////////////////////////////////////////////////////////////////////////////// + + function Component(type,x,y,rotation) { + this.sch = undefined; + this.type = type; + this.x = x; + this.y = y; + this.rotation = rotation; + this.selected = false; + this.properties = []; + this.bounding_box = [0,0,0,0]; // in device coords [left,top,right,bottom] + this.bbox = this.bounding_box; // in absolute coords + this.connections = []; + } + + Component.prototype.json = function(index) { + this.properties['_json_'] = index; // remember where we are in the JSON list + + var props = {}; + for (var p in this.properties) props[p] = this.properties[p]; + + var conns = []; + for (var i = 0; i < this.connections.length; i++) + conns.push(this.connections[i].json()); + + var json = [this.type,[this.x, this.y, this.rotation],props,conns]; + return json; + } + + Component.prototype.add_connection = function(offset_x,offset_y) { + this.connections.push(new ConnectionPoint(this,offset_x,offset_y)); + } + + Component.prototype.update_coords = function() { + var x = this.x; + var y = this.y; + + // update bbox + var b = this.bounding_box; + this.bbox[0] = this.transform_x(b[0],b[1]) + x; + this.bbox[1] = this.transform_y(b[0],b[1]) + y; + this.bbox[2] = this.transform_x(b[2],b[3]) + x; + this.bbox[3] = this.transform_y(b[2],b[3]) + y; + canonicalize(this.bbox); + + // update connections + for (var i = this.connections.length - 1; i >= 0; --i) + this.connections[i].update_location(); + } + + Component.prototype.rotate = function(amount) { + var old_rotation = this.rotation; + this.rotation = (this.rotation + amount) % 8; + this.update_coords(); + + // create an undoable edit record here + // using old_rotation + } + + Component.prototype.move_begin = function() { + // remember where we started this move + this.move_x = this.x; + this.move_y = this.y; + } + + Component.prototype.move = function(dx,dy) { + // update coordinates + this.x += dx; + this.y += dy; + this.update_coords(); + } + + Component.prototype.move_end = function() { + var dx = this.x - this.move_x; + var dy = this.y - this.move_y; + + if (dx != 0 || dy != 0) { + // create an undoable edit record here + + this.sch.check_wires(this); + } + } + + Component.prototype.add = function(sch) { + this.sch = sch; // we now belong to a schematic! + sch.add_component(this); + this.update_coords(); + } + + Component.prototype.remove = function() { + // remove connection points from schematic + for (var i = this.connections.length - 1; i >= 0; --i) { + var cp = this.connections[i]; + this.sch.remove_connection_point(cp,cp.location); + } + + // remove component from schematic + this.sch.remove_component(this); + this.sch = undefined; + + // create an undoable edit record here + } + + Component.prototype.transform_x = function(x,y) { + var rot = this.rotation; + if (rot == 0 || rot == 6) return x; + else if (rot == 1 || rot == 5) return -y; + else if (rot == 2 || rot == 4) return -x; + else return y; + } + + Component.prototype.transform_y = function(x,y) { + var rot = this.rotation; + if (rot == 1 || rot == 7) return x; + else if (rot == 2 || rot == 6) return -y; + else if (rot == 3 || rot == 5) return -x; + else return y; + } + + Component.prototype.moveTo = function(c,x,y) { + var nx = this.transform_x(x,y) + this.x; + var ny = this.transform_y(x,y) + this.y; + this.sch.moveTo(c,nx,ny); + } + + Component.prototype.lineTo = function(c,x,y) { + var nx = this.transform_x(x,y) + this.x; + var ny = this.transform_y(x,y) + this.y; + this.sch.lineTo(c,nx,ny); + } + + Component.prototype.draw_line = function(c,x1,y1,x2,y2) { + c.strokeStyle = this.selected ? selected_style : + this.type == 'w' ? normal_style : component_style; + var nx1 = this.transform_x(x1,y1) + this.x; + var ny1 = this.transform_y(x1,y1) + this.y; + var nx2 = this.transform_x(x2,y2) + this.x; + var ny2 = this.transform_y(x2,y2) + this.y; + this.sch.draw_line(c,nx1,ny1,nx2,ny2,1); + } + + Component.prototype.draw_circle = function(c,x,y,radius,filled) { + if (filled) c.fillStyle = this.selected ? selected_style : normal_style; + else c.strokeStyle = this.selected ? selected_style : + this.type == 'w' ? normal_style : component_style; + var nx = this.transform_x(x,y) + this.x; + var ny = this.transform_y(x,y) + this.y; + + this.sch.draw_arc(c,nx,ny,radius,0,2*Math.PI,false,1,filled); + } + + var rot_angle = [ + 0.0, // NORTH (identity) + Math.PI/2, // EAST (rot270) + Math.PI, // SOUTH (rot180) + 3*Math.PI/2, // WEST (rot90) + 0.0, // RNORTH (negy) + Math.PI/2, // REAST (int-neg) + Math.PI, // RSOUTH (negx) + 3*Math.PI/2, // RWEST (int-pos) + ]; + + Component.prototype.draw_arc = function(c,x,y,radius,start_radians,end_radians) { + c.strokeStyle = this.selected ? selected_style : + this.type == 'w' ? normal_style : component_style; + var nx = this.transform_x(x,y) + this.x; + var ny = this.transform_y(x,y) + this.y; + this.sch.draw_arc(c,nx,ny,radius, + start_radians+rot_angle[this.rotation],end_radians+rot_angle[this.rotation], + false,1,false); + } + + Component.prototype.draw = function(c) { + /* + for (var i = this.connections.length - 1; i >= 0; --i) { + var cp = this.connections[i]; + cp.draw_x(c); + } + */ + } + + // result of rotating an alignment [rot*9 + align] + var aOrient = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, // NORTH (identity) + 2, 5, 8, 1, 4, 7, 0, 3, 6, // EAST (rot270) + 8, 7, 6, 5, 4, 3, 2, 1, 0, // SOUTH (rot180) + 6, 3, 0, 7, 4, 1, 8, 5, 3, // WEST (rot90) + 2, 1, 0, 5, 4, 3, 8, 7, 6, // RNORTH (negy) + 8, 5, 2, 7, 4, 1, 6, 3, 0, // REAST (int-neg) + 6, 7, 8, 3, 4, 5, 0, 1, 2, // RSOUTH (negx) + 0, 3, 6, 1, 4, 7, 2, 5, 8 // RWEST (int-pos) + ]; + + var textAlign = [ + 'left', 'center', 'right', + 'left', 'center', 'right', + 'left', 'center', 'right' + ]; + + var textBaseline = [ + 'top', 'top', 'top', + 'middle', 'middle', 'middle', + 'bottom', 'bottom', 'bottom' + ]; + + Component.prototype.draw_text = function(c,text,x,y,alignment,size,fill) { + var a = aOrient[this.rotation*9 + alignment]; + c.textAlign = textAlign[a]; + c.textBaseline = textBaseline[a]; + if (fill == undefined) + c.fillStyle = this.selected ? selected_style : normal_style; + else + c.fillStyle = fill; + this.sch.draw_text(c,text, + this.transform_x(x,y) + this.x, + this.transform_y(x,y) + this.y, + size); + } + + Component.prototype.set_select = function(which) { + if (which != this.selected) { + this.selected = which; + // create an undoable edit record here + } + } + + Component.prototype.select = function(x,y,shiftKey) { + this.was_previously_selected = this.selected; + if (this.near(x,y)) { + this.set_select(shiftKey ? !this.selected : true); + return true; + } else return false; + } + + Component.prototype.select_rect = function(s) { + this.was_previously_selected = this.selected; + if (intersect(this.bbox,s)) + this.set_select(true); + } + + // if connection point of component c bisects the + // wire represented by this compononent, return that + // connection point. Otherwise return null. + Component.prototype.bisect = function(c) { + return null; + } + + // does mouse click fall on this component? + Component.prototype.near = function(x,y) { + return inside(this.bbox,x,y); + } + + Component.prototype.edit_properties = function(x,y) { + if (this.near(x,y)) { + // make an widget for each property + var fields = []; + for (var i in this.properties) + // underscore at beginning of property name => system property + if (i.charAt(0) != '_') + fields[i] = build_input('text',10,this.properties[i]); + + var content = build_table(fields); + content.fields = fields; + content.component = this; + + this.sch.dialog('Edit Properties',content,function(content) { + for (var i in content.fields) + content.component.properties[i] = content.fields[i].value; + content.component.sch.redraw_background(); + }); + return true; + } else return false; + } + + Component.prototype.clear_labels = function() { + for (var i = this.connections.length - 1; i >=0; --i) { + this.connections[i].clear_label(); + } + } + + // default action: don't propagate label + Component.prototype.propagate_label = function(label) { + } + + // give components a chance to generate default labels for their connection(s) + // default action: do nothing + Component.prototype.add_default_labels = function() { + } + + // component should generate labels for all unlabeled connections + Component.prototype.label_connections = function() { + for (var i = this.connections.length - 1; i >=0; --i) { + var cp = this.connections[i]; + if (!cp.label) + cp.propagate_label(this.sch.get_next_label()); + } + } + + // default behavior: no probe info + Component.prototype.probe_info = function() { return undefined; } + + // default behavior: nothing to display for DC analysis + Component.prototype.display_current = function(c,vmap) { + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Connection point + // + //////////////////////////////////////////////////////////////////////////////// + + var connection_point_radius = 2; + + function ConnectionPoint(parent,x,y) { + this.parent = parent; + this.offset_x = x; + this.offset_y = y; + this.location = ''; + this.update_location(); + this.label = undefined; + } + + ConnectionPoint.prototype.toString = function() { + return ''; + } + + ConnectionPoint.prototype.json = function() { + return this.label; + } + + ConnectionPoint.prototype.clear_label = function() { + this.label = undefined; + } + + ConnectionPoint.prototype.propagate_label = function(label) { + // should we check if existing label is the same? it should be... + + if (this.label === undefined) { + // label this connection point + this.label = label; + + // propagate label to coincident connection points + this.parent.sch.propagate_label(label,this.location); + + // possibly label other cp's for this device? + this.parent.propagate_label(label); + } else if (this.label != '0' && label != '0' && this.label != label) + alert("Node has two conflicting labels: "+this.label+", "+label); + } + + ConnectionPoint.prototype.update_location = function() { + // update location string which we use as a key to find coincident connection points + var old_location = this.location; + var parent = this.parent; + var nx = parent.transform_x(this.offset_x,this.offset_y) + parent.x; + var ny = parent.transform_y(this.offset_x,this.offset_y) + parent.y; + this.x = nx; + this.y = ny; + this.location = nx + ',' + ny; + + // add ourselves to the connection list for the new location + if (parent.sch) + parent.sch.update_connection_point(this,old_location); + } + + ConnectionPoint.prototype.coincident = function(x,y) { + return this.x==x && this.y==y; + } + + ConnectionPoint.prototype.draw = function(c,n) { + if (n != 2) + this.parent.draw_circle(c,this.offset_x,this.offset_y,connection_point_radius,n > 2); + } + + ConnectionPoint.prototype.draw_x = function(c) { + this.parent.draw_line(c,this.offset_x-2,this.offset_y-2,this.offset_x+2,this.offset_y+2,grid_style); + this.parent.draw_line(c,this.offset_x+2,this.offset_y-2,this.offset_x-2,this.offset_y+2,grid_style); + } + + ConnectionPoint.prototype.display_voltage = function(c,vmap) { + var v = vmap[this.label]; + if (v != undefined) { + var label = v.toFixed(2) + 'V'; + + // first draw some solid blocks in the background + c.globalAlpha = 0.85; + this.parent.draw_text(c,'\u2588\u2588\u2588',this.offset_x,this.offset_y, + 4,annotation_size,element_style); + c.globalAlpha = 1.0; + + // display the node voltage at this connection point + this.parent.draw_text(c,label,this.offset_x,this.offset_y, + 4,annotation_size,annotation_style); + + // only display each node voltage once + delete vmap[this.label]; + } + } + + // see if three connection points are collinear + function collinear(p1,p2,p3) { + // from http://mathworld.wolfram.com/Collinear.html + var area = p1.x*(p2.y - p3.y) + p2.x*(p3.y - p1.y) + p3.x*(p1.y - p2.y); + return area == 0; + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Wire + // + //////////////////////////////////////////////////////////////////////////////// + + var near_distance = 2; // how close to wire counts as "near by" + + function Wire(x1,y1,x2,y2) { + // arbitrarily call x1,y1 the origin + Component.call(this,'w',x1,y1,0); + this.dx = x2 - x1; + this.dy = y2 - y1; + this.add_connection(0,0); + this.add_connection(this.dx,this.dy); + + // compute bounding box (expanded slightly) + var r = [0,0,this.dx,this.dy]; + canonicalize(r); + r[0] -= near_distance; + r[1] -= near_distance; + r[2] += near_distance; + r[3] += near_distance; + this.bounding_box = r; + this.update_coords(); // update bbox + + // used in selection calculations + this.len = Math.sqrt(this.dx*this.dx + this.dy*this.dy); + } + Wire.prototype = new Component(); + Wire.prototype.constructor = Wire; + + Wire.prototype.toString = function() { + return ''; + } + + // return connection point at other end of wire from specified cp + Wire.prototype.other_end = function(cp) { + if (cp == this.connections[0]) return this.connections[1]; + else if (cp == this.connections[1]) return this.connections[0]; + else return undefined; + } + + Wire.prototype.json = function(index) { + var json = ['w',[this.x, this.y, this.x+this.dx, this.y+this.dy]]; + return json; + } + + Wire.prototype.draw = function(c) { + this.draw_line(c,0,0,this.dx,this.dy); + } + + Wire.prototype.clone = function(x,y) { + return new Wire(x,y,x+this.dx,y+this.dy); + } + + Wire.prototype.near = function(x,y) { + // crude check: (x,y) within expanded bounding box of wire + if (inside(this.bbox,x,y)) { + // compute distance between x,y and nearst point on line + // http://www.allegro.cc/forums/thread/589720 + var D = Math.abs((x - this.x)*this.dy - (y - this.y)*this.dx)/this.len; + if (D <= near_distance) return true; + } + return false; + } + + // selection rectangle selects wire only if it includes + // one of the end points + Wire.prototype.select_rect = function(s) { + this.was_previously_selected = this.selected; + if (inside(s,this.x,this.y) || inside(s,this.x+this.dx,this.y+this.dy)) + this.set_select(true); + } + + // if connection point cp bisects the + // wire represented by this compononent, return true + Wire.prototype.bisect_cp = function(cp) { + var x = cp.x; + var y = cp.y; + + // crude check: (x,y) within expanded bounding box of wire + if (inside(this.bbox,x,y)) { + // compute distance between x,y and nearst point on line + // http://www.allegro.cc/forums/thread/589720 + var D = Math.abs((x - this.x)*this.dy - (y - this.y)*this.dx)/this.len; + // final check: ensure point isn't an end point of the wire + if (D < 1 && !this.connections[0].coincident(x,y) && !this.connections[1].coincident(x,y)) + return true; + } + return false; + } + + // if some connection point of component c bisects the + // wire represented by this compononent, return that + // connection point. Otherwise return null. + Wire.prototype.bisect = function(c) { + if (c == undefined) return; + for (var i = c.connections.length - 1; i >= 0; --i) { + var cp = c.connections[i]; + if (this.bisect_cp(cp)) return cp; + } + return null; + } + + Wire.prototype.move_end = function() { + // look for wires bisected by this wire + this.sch.check_wires(this); + + // look for connection points that might bisect us + this.sch.check_connection_points(this); + } + + // wires "conduct" their label to the other end + Wire.prototype.propagate_label = function(label) { + // don't worry about relabeling a cp, it won't recurse! + this.connections[0].propagate_label(label); + this.connections[1].propagate_label(label); + } + + // Wires have no properties to edit + Wire.prototype.edit_properties = function(x,y) { + return false; + } + + // some actual component will start the labeling of electrical nodes, + // so do nothing here + Wire.prototype.label_connections = function() { + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Ground + // + //////////////////////////////////////////////////////////////////////////////// + + function Ground(x,y,rotation) { + Component.call(this,'g',x,y,rotation); + this.add_connection(0,0); + this.bounding_box = [-6,0,6,8]; + this.update_coords(); + } + Ground.prototype = new Component(); + Ground.prototype.constructor = Ground; + + Ground.prototype.toString = function() { + return ''; + } + + Ground.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,8); + this.draw_line(c,-6,8,6,8); + } + + Ground.prototype.clone = function(x,y) { + return new Ground(x,y,this.rotation); + } + + // Grounds no properties to edit + Ground.prototype.edit_properties = function(x,y) { + return false; + } + + // give components a chance to generate a label for their connection(s) + // default action: do nothing + Ground.prototype.add_default_labels = function() { + this.connections[0].propagate_label('0'); // canonical label for GND node + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Label + // + //////////////////////////////////////////////////////////////////////////////// + + function Label(x,y,rotation,label) { + Component.call(this,'L',x,y,rotation); + this.properties['label'] = label ? label : '???'; + this.add_connection(0,0); + this.bounding_box = [-2,0,2,8]; + this.update_coords(); + } + Label.prototype = new Component(); + Label.prototype.constructor = Label; + + Label.prototype.toString = function() { + return ''; + } + + Label.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,8); + this.draw_text(c,this.properties['label'],0,9,1,property_size); + } + + Label.prototype.clone = function(x,y) { + return new Label(x,y,this.rotation,this.properties['label']); + } + + // give components a chance to generate a label for their connection(s) + // default action: do nothing + Label.prototype.add_default_labels = function() { + this.connections[0].propagate_label(this.properties['label']); + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Voltage Probe + // + //////////////////////////////////////////////////////////////////////////////// + + var probe_colors = ['red','green','blue','cyan','magenta','yellow','black','x-axis']; + var probe_colors_rgb = { + 'red': 'rgb(255,64,64)', + 'green': 'rgb(64,255,64)', + 'blue': 'rgb(64,64,255)', + 'cyan': 'rgb(64,255,255)', + 'magenta' : 'rgb(255,64,255)', + 'yellow': 'rgb(255,255,64)', + 'black': 'rgb(0,0,0)', + 'x-axis': undefined + }; + + function Probe(x,y,rotation,color,offset) { + Component.call(this,'s',x,y,rotation); + this.add_connection(0,0); + this.properties['color'] = color ? color : 'cyan'; + this.properties['offset'] = (offset==undefined || offset=='') ? '0' : offset; + this.bounding_box = [0,0,27,-21]; + this.update_coords(); + } + Probe.prototype = new Component(); + Probe.prototype.constructor = Probe; + + Probe.prototype.toString = function() { + return ''; + } + + Probe.prototype.draw = function(c) { + // draw outline + this.draw_line(c,0,0,4,-4); + this.draw_line(c,2,-6,6,-2); + this.draw_line(c,2,-6,17,-21); + this.draw_line(c,6,-2,21,-17); + this.draw_line(c,17,-21,21,-17); + this.draw_arc(c,19,-11,8,3*Math.PI/2,0); + + // fill body with plot color + var color = probe_colors_rgb[this.properties['color']]; + if (color != undefined) { + c.fillStyle = color; + c.beginPath(); + this.moveTo(c,2,-6); + this.lineTo(c,6,-2); + this.lineTo(c,21,-17); + this.lineTo(c,17,-21); + this.lineTo(c,2,-6); + c.fill(); + } else { + this.draw_text(c,this.properties['color'],27,-11,1,property_size); + } + } + + Probe.prototype.clone = function(x,y) { + return new Probe(x,y,this.rotation,this.properties['color'],this.properties['offset']); + } + + Probe.prototype.edit_properties = function(x,y) { + if (inside(this.bbox,x,y)) { + var fields = []; + fields['Plot color'] = build_select(probe_colors,this.properties['color']); + fields['Plot offset'] = build_input('text',10,this.properties['offset']); + + var content = build_table(fields); + content.fields = fields; + content.component = this; + + this.sch.dialog('Edit Properties',content,function(content) { + var color_choice = content.fields['Plot color']; + content.component.properties['color'] = probe_colors[color_choice.selectedIndex]; + content.component.properties['offset'] = content.fields['Plot offset'].value; + content.component.sch.redraw_background(); + }); + return true; + } else return false; + } + + // return [color, node_label, offset, type] for this probe + Probe.prototype.probe_info = function() { + var color = this.properties['color']; + var offset = this.properties['offset']; + if (offset==undefined || offset=="") offset = '0'; + return [color,this.connections[0].label,offset,'voltage']; + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Ammeter Probe + // + //////////////////////////////////////////////////////////////////////////////// + + function Ammeter(x,y,rotation,color,offset) { + Component.call(this,'a',x,y,rotation); + this.add_connection(0,0); // pos + this.add_connection(16,0); // neg + this.properties['color'] = color ? color : 'magenta'; + this.properties['offset'] = (offset==undefined || offset=='') ? '0' : offset; + this.bounding_box = [-3,0,16,3]; + this.update_coords(); + } + Ammeter.prototype = new Component(); + Ammeter.prototype.constructor = Ammeter; + + Ammeter.prototype.toString = function() { + return ''; + } + + Ammeter.prototype.move_end = function() { + Component.prototype.move_end.call(this); // do the normal processing + + // special for current probes: see if probe has been placed + // in the middle of wire, creating three wire segments one + // of which is shorting the two terminals of the probe. If + // so, auto remove the shorting segment. + var e1 = this.connections[0].location; + var e2 = this.connections[1].location; + var cplist = this.sch.find_connections(this.connections[0]); + for (var i = cplist.length - 1; i >= 0; --i) { + var c = cplist[i].parent; // a component connected to ammeter terminal + // look for a wire whose end points match those of the ammeter + if (c.type == 'w') { + var c_e1 = c.connections[0].location; + var c_e2 = c.connections[1].location; + if ((e1 == c_e1 && c2 == c_e2) || (e1 == c_e2 && e2 == c_e1)) { + c.remove(); + break; + } + } + } + } + + Ammeter.prototype.draw = function(c) { + this.draw_line(c,0,0,16,0); + + // draw chevron in probe color + c.strokeStyle = probe_colors_rgb[this.properties['color']]; + if (c.strokeStyle != undefined) { + c.beginPath(); + this.moveTo(c,6,-3); + this.lineTo(c,10,0); + this.lineTo(c,6,3); + c.stroke(); + } + } + + Ammeter.prototype.clone = function(x,y) { + return new Ammeter(x,y,this.rotation,this.properties['color'],this.properties['offset']); + } + + // share code with voltage probe + Ammeter.prototype.edit_properties = Probe.prototype.edit_properties; + + Ammeter.prototype.label = function() { + var name = this.properties['name']; + var label = 'I(' + (name ? name : '_' + this.properties['_json_']) + ')'; + return label; + } + + // display current for DC analysis + Ammeter.prototype.display_current = function(c,vmap) { + var label = this.label(); + var v = vmap[label]; + if (v != undefined) { + var i = engineering_notation(v,2) + 'A'; + this.draw_text(c,i,8,-5,7,annotation_size,annotation_style); + + // only display each current once + delete vmap[label]; + } + } + + // return [color, current_label, offset, type] for this probe + Ammeter.prototype.probe_info = function() { + var color = this.properties['color']; + var offset = this.properties['offset']; + if (offset==undefined || offset=="") offset = '0'; + return [color,this.label(),offset,'current']; + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Resistor + // + //////////////////////////////////////////////////////////////////////////////// + + function Resistor(x,y,rotation,name,r) { + Component.call(this,'r',x,y,rotation); + this.properties['name'] = name; + this.properties['r'] = r ? r : '1'; + this.add_connection(0,0); + this.add_connection(0,48); + this.bounding_box = [-5,0,5,48]; + this.update_coords(); + } + Resistor.prototype = new Component(); + Resistor.prototype.constructor = Resistor; + + Resistor.prototype.toString = function() { + return ''; + } + + Resistor.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,12); + this.draw_line(c,0,12,4,14); + this.draw_line(c,4,14,-4,18); + this.draw_line(c,-4,18,4,22); + this.draw_line(c,4,22,-4,26); + this.draw_line(c,-4,26,4,30); + this.draw_line(c,4,30,-4,34); + this.draw_line(c,-4,34,0,36); + this.draw_line(c,0,36,0,48); + if (this.properties['r']) + this.draw_text(c,this.properties['r']+'\u03A9',5,24,3,property_size); + if (this.properties['name']) + this.draw_text(c,this.properties['name'],-5,24,5,property_size); + } + + Resistor.prototype.clone = function(x,y) { + return new Resistor(x,y,this.rotation,this.properties['name'],this.properties['r']); + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Capacitor + // + //////////////////////////////////////////////////////////////////////////////// + + function Capacitor(x,y,rotation,name,c) { + Component.call(this,'c',x,y,rotation); + this.properties['name'] = name; + this.properties['c'] = c ? c : '1p'; + this.add_connection(0,0); + this.add_connection(0,48); + this.bounding_box = [-8,0,8,48]; + this.update_coords(); + } + Capacitor.prototype = new Component(); + Capacitor.prototype.constructor = Capacitor; + + Capacitor.prototype.toString = function() { + return ''; + } + + Capacitor.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,22); + this.draw_line(c,-8,22,8,22); + this.draw_line(c,-8,26,8,26); + this.draw_line(c,0,26,0,48); + if (this.properties['c']) + this.draw_text(c,this.properties['c']+'F',9,24,3,property_size); + if (this.properties['name']) + this.draw_text(c,this.properties['name'],-9,24,5,property_size); + } + + Capacitor.prototype.clone = function(x,y) { + return new Capacitor(x,y,this.rotation,this.properties['name'],this.properties['c']); + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Inductor + // + //////////////////////////////////////////////////////////////////////////////// + + function Inductor(x,y,rotation,name,l) { + Component.call(this,'l',x,y,rotation); + this.properties['name'] = name; + this.properties['l'] = l ? l : '1n'; + this.add_connection(0,0); + this.add_connection(0,48); + this.bounding_box = [-4,0,5,48]; + this.update_coords(); + } + Inductor.prototype = new Component(); + Inductor.prototype.constructor = Inductor; + + Inductor.prototype.toString = function() { + return ''; + } + + Inductor.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,14); + this.draw_arc(c,0,18,4,6*Math.PI/4,3*Math.PI/4); + this.draw_arc(c,0,24,4,5*Math.PI/4,3*Math.PI/4); + this.draw_arc(c,0,30,4,5*Math.PI/4,2*Math.PI/4); + this.draw_line(c,0,34,0,48); + + if (this.properties['l']) + this.draw_text(c,this.properties['l']+'H',6,24,3,property_size); + if (this.properties['name']) + this.draw_text(c,this.properties['name'],-3,24,5,property_size); + } + + Inductor.prototype.clone = function(x,y) { + return new Inductor(x,y,this.rotation,this.properties['name'],this.properties['l']); + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Diode + // + //////////////////////////////////////////////////////////////////////////////// + + var diode_types = ['normal','ideal']; + + function Diode(x,y,rotation,name,area,type) { + Component.call(this,'d',x,y,rotation); + this.properties['name'] = name; + this.properties['area'] = area ? area : '1'; + this.properties['type'] = type ? type : 'normal'; + this.add_connection(0,0); // anode + this.add_connection(0,48); // cathode + this.bounding_box = (type == 'ideal') ? [-12,0,12,48] : [-8,0,8,48]; + this.update_coords(); + } + Diode.prototype = new Component(); + Diode.prototype.constructor = Diode; + + Diode.prototype.toString = function() { + return ''; + } + + Diode.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,16); + this.draw_line(c,-8,16,8,16); + this.draw_line(c,-8,16,0,32); + this.draw_line(c,8,16,0,32); + this.draw_line(c,-8,32,8,32); + this.draw_line(c,0,32,0,48); + + if (this.properties['type'] == 'ideal') { + // put a box around an ideal diode + this.draw_line(c,-10,12,10,12); + this.draw_line(c,-10,12,-10,36); + this.draw_line(c,10,12,10,36); + this.draw_line(c,-10,36,10,36); + } + + if (this.properties['area']) + this.draw_text(c,this.properties['area'],10,24,3,property_size); + if (this.properties['name']) + this.draw_text(c,this.properties['name'],-10,24,5,property_size); + } + + Diode.prototype.clone = function(x,y) { + return new Diode(x,y,this.rotation,this.properties['name'],this.properties['area'],this.properties['type']); + } + + Diode.prototype.edit_properties = function(x,y) { + if (inside(this.bbox,x,y)) { + var fields = []; + fields['name'] = build_input('text',10,this.properties['name']); + fields['area'] = build_input('text',10,this.properties['area']); + fields['type'] = build_select(diode_types,this.properties['type']); + + var content = build_table(fields); + content.fields = fields; + content.component = this; + + this.sch.dialog('Edit Properties',content,function(content) { + content.component.properties['name'] = content.fields['name'].value; + content.component.properties['area'] = content.fields['area'].value; + content.component.properties['type'] = diode_types[content.fields['type'].selectedIndex]; + content.component.sch.redraw_background(); + }); + return true; + } else return false; + } + + //////////////////////////////////////////////////////////////////////////////// + // + // N-channel Mosfet + // + //////////////////////////////////////////////////////////////////////////////// + + function NFet(x,y,rotation,name,w_over_l) { + Component.call(this,'n',x,y,rotation); + this.properties['name'] = name; + this.properties['W/L'] = w_over_l ? w_over_l : '2'; + this.add_connection(0,0); // drain + this.add_connection(-24,24); // gate + this.add_connection(0,48); // source + this.bounding_box = [-24,0,8,48]; + this.update_coords(); + } + NFet.prototype = new Component(); + NFet.prototype.constructor = NFet; + + NFet.prototype.toString = function() { + return ''; + } + + NFet.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,16); + this.draw_line(c,-8,16,0,16); + this.draw_line(c,-8,16,-8,32); + this.draw_line(c,-8,32,0,32); + this.draw_line(c,0,32,0,48); + this.draw_line(c,-24,24,-12,24); + this.draw_line(c,-12,16,-12,32); + + var dim = this.properties['W/L']; + if (this.properties['name']) { + this.draw_text(c,this.properties['name'],2,22,6,property_size); + this.draw_text(c,dim,2,26,0,property_size); + } else + this.draw_text(c,dim,2,24,3,property_size); + } + + NFet.prototype.clone = function(x,y) { + return new NFet(x,y,this.rotation,this.properties['name'],this.properties['W/L']); + } + + //////////////////////////////////////////////////////////////////////////////// + // + // P-channel Mosfet + // + //////////////////////////////////////////////////////////////////////////////// + + function PFet(x,y,rotation,name,w_over_l) { + Component.call(this,'p',x,y,rotation); + this.properties['name'] = name; + this.properties['W/L'] = w_over_l ? w_over_l : '2'; + this.add_connection(0,0); // drain + this.add_connection(-24,24); // gate + this.add_connection(0,48); // source + this.bounding_box = [-24,0,8,48]; + this.update_coords(); + } + PFet.prototype = new Component(); + PFet.prototype.constructor = PFet; + + PFet.prototype.toString = function() { + return ''; + } + + PFet.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,16); + this.draw_line(c,-8,16,0,16); + this.draw_line(c,-8,16,-8,32); + this.draw_line(c,-8,32,0,32); + this.draw_line(c,0,32,0,48); + this.draw_line(c,-24,24,-16,24); + this.draw_circle(c,-14,24,2,false); + this.draw_line(c,-12,16,-12,32); + + var dim = this.properties['W/L']; + if (this.properties['name']) { + this.draw_text(c,this.properties['name'],2,22,6,property_size); + this.draw_text(c,dim,2,26,0,property_size); + } else + this.draw_text(c,dim,2,24,3,property_size); + } + + PFet.prototype.clone = function(x,y) { + return new PFet(x,y,this.rotation,this.properties['name'],this.properties['W/L']); + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Op Amp + // + //////////////////////////////////////////////////////////////////////////////// + + function OpAmp(x,y,rotation,name,A) { + Component.call(this,'o',x,y,rotation); + this.properties['name'] = name; + this.properties['A'] = A ? A : '30000'; + this.add_connection(0,0); // + + this.add_connection(0,16); // - + this.add_connection(48,8); // output + this.add_connection(24,32); // ground + this.bounding_box = [0,-8,48,32]; + this.update_coords(); + } + OpAmp.prototype = new Component(); + OpAmp.prototype.constructor = OpAmp; + + OpAmp.prototype.toString = function() { + return ''; + } + + OpAmp.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + // triangle + this.draw_line(c,8,-8,8,24); + this.draw_line(c,8,-8,40,8); + this.draw_line(c,8,24,40,8); + // inputs and output + this.draw_line(c,0,0,8,0); + this.draw_line(c,0,16,8,16); + this.draw_text(c,'gnd',37,18,property_size); + this.draw_line(c,40,8,48,8); + this.draw_line(c,24,16,24,32); + // + and - + this.draw_line(c,10,0,16,0); + this.draw_line(c,13,-3,13,3); + this.draw_line(c,10,16,16,16); + + if (this.properties['name']) + this.draw_text(c,this.properties['name'],32,16,0,property_size); + } + + OpAmp.prototype.clone = function(x,y) { + return new OpAmp(x,y,this.rotation,this.properties['name'],this.properties['A']); + } + + //////////////////////////////////////////////////////////////////////////////// + // + // Source + // + //////////////////////////////////////////////////////////////////////////////// + + function Source(x,y,rotation,name,type,value) { + Component.call(this,type,x,y,rotation); + this.properties['name'] = name; + if (value == undefined) value = 'dc(1)'; + this.properties['value'] = value; + this.add_connection(0,0); + this.add_connection(0,48); + this.bounding_box = [-12,0,12,48]; + this.update_coords(); + this.content = document.createElement('div'); // used by edit_properties + } + Source.prototype = new Component(); + Source.prototype.constructor = Source; + + Source.prototype.toString = function() { + return '<'+this.type+'source '+this.properties['params']+' ('+this.x+','+this.y+')>'; + } + + Source.prototype.draw = function(c) { + Component.prototype.draw.call(this,c); // give superclass a shot + this.draw_line(c,0,0,0,12); + this.draw_circle(c,0,24,12,false); + this.draw_line(c,0,36,0,48); + + if (this.type == 'v') { // voltage source + // draw + and - + this.draw_line(c,0,15,0,21); + this.draw_line(c,-3,18,3,18); + this.draw_line(c,-3,30,3,30); + } else if (this.type == 'i') { // current source + // draw arrow: pos to neg + this.draw_line(c,0,15,0,32); + this.draw_line(c,-3,26,0,32); + this.draw_line(c,3,26,0,32); + } + + if (this.properties['name']) + this.draw_text(c,this.properties['name'],-13,24,5,property_size); + if (this.properties['value']) + this.draw_text(c,this.properties['value'],13,24,3,property_size); + } + + // map source function name to labels for each source parameter + var source_functions = { + 'dc': ['DC value'], + + 'impulse': ['Height', + 'Width (secs)'], + + 'step': ['Initial value', + 'Plateau value', + 'Delay until step (secs)', + 'Rise time (secs)'], + + 'square': ['Initial value', + 'Plateau value', + 'Frequency (Hz)', + 'Duty cycle (%)'], + + 'triangle': ['Initial value', + 'Plateau value', + 'Frequency (Hz)'], + + 'pwl': ['Comma-separated list of alternating times and values'], + + 'pwl_repeating': ['Comma-separated list of alternating times and values'], + + 'pulse': ['Initial value', + 'Plateau value', + 'Delay until pulse (secs)', + 'Time for first transition (secs)', + 'Time for second transition (secs)', + 'Pulse width (secs)', + 'Period (secs)'], + + 'sin': ['Offset value', + 'Amplitude', + 'Frequency (Hz)', + 'Delay until sin starts (secs)', + 'Phase offset (degrees)'] + } + + // build property editor div + Source.prototype.build_content = function(src) { + // make an widget for each property + var fields = [] + fields['name'] = build_input('text',10,this.properties['name']); + + if (src == undefined) { + fields['value'] = this.properties['value']; + } else { + // fancy version: add select tag for source type + var src_types = []; + for (var t in source_functions) src_types.push(t); + var type_select = build_select(src_types,src.fun); + type_select.component = this; + type_select.addEventListener('change',source_type_changed,false) + fields['type'] = type_select; + + if (src.fun == 'pwl' || src.run == 'pwl_repeating') { + var v = ''; + var first = true; + for (var i = 0; i < src.args.length; i++) { + if (first) first = false; + else v += ','; + v += engineering_notation(src.args[i],3); + if (i % 2 == 0) v += 's'; + } + fields[source_functions[src.fun][0]] = build_input('text',30,v); + } else { + // followed separate input tag for each parameter + var labels = source_functions[src.fun]; + for (var i = 0; i < labels.length; i++) { + var v = engineering_notation(src.args[i],3); + fields[labels[i]] = build_input('text',10,v); + } + } + } + + var div = this.content; + if (div.hasChildNodes()) + div.removeChild(div.firstChild); // remove table of input fields + div.appendChild(build_table(fields)); + div.fields = fields; + div.component = this; + return div; + } + + function source_type_changed(event) { + if (!event) event = window.event; + var select = (window.event) ? event.srcElement : event.target; + + // see where to get source parameters from + var type = select.options[select.selectedIndex].value; + var src = undefined; + if (this.src != undefined && type == this.src.fun) + src = this.src; + else if (typeof cktsim != 'undefined') + src = cktsim.parse_source(type+'()'); + + select.component.build_content(src); + } + + Source.prototype.edit_properties = function(x,y) { + if (this.near(x,y)) { + this.src = undefined; + if (typeof cktsim != 'undefined') + this.src = cktsim.parse_source(this.properties['value']); + var content = this.build_content(this.src); + + this.sch.dialog('Edit Properties',content,function(content) { + var c = content.component; + var fields = content.fields; + + var first = true; + var value = ''; + for (var label in fields) { + if (label == 'name') + c.properties['name'] = fields['name'].value; + else if (label == 'value') { + // if unknown source type + value = fields['value'].value; + c.sch.redraw_background(); + return; + } else if (label == 'type') { + var select = fields['type']; + value = select.options[select.selectedIndex].value + '('; + } else { + if (first) first = false; + else value += ','; + value += fields[label].value; + } + } + c.properties['value'] = value + ')'; + c.sch.redraw_background(); + }); + return true; + } else return false; + } + + function VSource(x,y,rotation,name,value) { + Source.call(this,x,y,rotation,name,'v',value); + this.type = 'v'; + } + VSource.prototype = new Component(); + VSource.prototype.constructor = VSource; + VSource.prototype.toString = Source.prototype.toString; + VSource.prototype.draw = Source.prototype.draw; + VSource.prototype.clone = Source.prototype.clone; + VSource.prototype.build_content = Source.prototype.build_content; + VSource.prototype.edit_properties = Source.prototype.edit_properties; + + // display current for DC analysis + VSource.prototype.display_current = function(c,vmap) { + var name = this.properties['name']; + var label = 'I(' + (name ? name : '_' + this.properties['_json_']) + ')'; + var v = vmap[label]; + if (v != undefined) { + // first draw some solid blocks in the background + c.globalAlpha = 0.5; + this.draw_text(c,'\u2588\u2588\u2588',-8,8,4,annotation_size,element_style); + c.globalAlpha = 1.0; + + // display the element current + var i = engineering_notation(v,2) + 'A'; + this.draw_text(c,i,-3,5,5,annotation_size,annotation_style); + // draw arrow for current + this.draw_line(c,-3,4,0,8); + this.draw_line(c,3,4,0,8); + // only display each current once + delete vmap[label]; + } + } + + VSource.prototype.clone = function(x,y) { + return new VSource(x,y,this.rotation,this.properties['name'],this.properties['value']); + } + + function ISource(x,y,rotation,name,value) { + Source.call(this,x,y,rotation,name,'i',value); + this.type = 'i'; + } + ISource.prototype = new Component(); + ISource.prototype.constructor = ISource; + ISource.prototype.toString = Source.prototype.toString; + ISource.prototype.draw = Source.prototype.draw; + ISource.prototype.clone = Source.prototype.clone; + ISource.prototype.build_content = Source.prototype.build_content; + ISource.prototype.edit_properties = Source.prototype.edit_properties; + + ISource.prototype.clone = function(x,y) { + return new ISource(x,y,this.rotation,this.properties['name'],this.properties['value']); + } + + /////////////////////////////////////////////////////////////////////////////// + // + // JQuery slider support for setting a component value + // + /////////////////////////////////////////////////////////////////////////////// + + function component_slider(event,ui) { + var sname = $(this).slider("option","schematic"); + + // set value of specified component + var cname = $(this).slider("option","component"); + var pname = $(this).slider("option","property"); + var suffix = $(this).slider("option","suffix"); + if (typeof suffix != "string") suffix = ""; + + var v = ui.value; + $(this).slider("value",v); // move slider's indicator + + var choices = $(this).slider("option","choices"); + if (choices instanceof Array) v = choices[v]; + + // selector may match several schematics + $("." + sname).each(function(index,element) { + element.schematic.set_property(cname,pname,v.toString() + suffix); + }) + + // perform requested analysis + var analysis = $(this).slider("option","analysis"); + if (analysis == "dc") + $("." + sname).each(function(index,element) { + element.schematic.dc_analysis(); + }) + + return false; + } + + /////////////////////////////////////////////////////////////////////////////// + // + // Module definition + // + /////////////////////////////////////////////////////////////////////////////// + + var module = { + 'Schematic': Schematic, + 'component_slider': component_slider + } + return module; +}()); diff --git a/src/activities/digital_electricity/Dataset.qml b/src/activities/digital_electricity/Dataset.qml --- a/src/activities/digital_electricity/Dataset.qml +++ b/src/activities/digital_electricity/Dataset.qml @@ -162,8 +162,8 @@ playAreaComponentList: [andGate, digitalLight], determiningComponentsIndex: [1], wires: [ [0, 0, 1, 0] ], // from_component_index, from_terminal_no, to_component_index, to_terminal_no - playAreaComponentPositionX: [0.4, 0.6], - playAreaComponentPositionY: [0.3, 0.3], + playAreaComponentPositionX: [0.4,0.6], + playAreaComponentPositionY: [0.3,0.3], type: [problemType.lightTheBulb], introMessage: [ qsTr("The AND gate produces an output of one when both of its input terminals are of value 1."), diff --git a/src/activities/digital_electricity/components/TerminalPoint.qml b/src/activities/digital_electricity/components/TerminalPoint.qml --- a/src/activities/digital_electricity/components/TerminalPoint.qml +++ b/src/activities/digital_electricity/components/TerminalPoint.qml @@ -26,24 +26,24 @@ Image { id: terminalPoint - property double posX property double posY property double size: parent.terminalSize property bool selected: false property string type property int value: 0 property var wires: [] - width: size * parent.paintedHeight + width: size * parent.paintedHeight height: width source: Activity.url + "tPoint.svg" sourceSize.width: width sourceSize.height: width antialiasing: true - x: (parent.width - parent.paintedWidth) / 2 + posX * parent.paintedWidth - width / 2 - y: (parent.height - parent.paintedHeight) / 2 + posY * parent.paintedHeight - height / 2 + + x: ((parent.width - parent.paintedWidth) / 2) + posX * parent.paintedWidth - (width / 2) + y: ((parent.height - parent.paintedHeight) / 2)+ posY * parent.paintedHeight- (height / 2) property double xCenter: terminalPoint.parent.x + terminalPoint.x + width/2 property double yCenter: terminalPoint.parent.y + terminalPoint.y + height/2