diff --git a/app/index.html b/app/index.html
index 4872408a..0c57ed88 100755
--- a/app/index.html
+++ b/app/index.html
@@ -241,6 +241,7 @@
Tutorial
Delay
Clock
LED
+ LED Array
Display
Debug
Beep
diff --git a/app/js/components.js b/app/js/components.js
index 87fdd8c9..e57fea3e 100644
--- a/app/js/components.js
+++ b/app/js/components.js
@@ -2046,7 +2046,7 @@ class Button extends Component {
}
class Constant extends Component {
- constructor(name,pos,value = 0) {
+ constructor(name, pos, properties, value = 0) {
super(name,pos,2,1,{ type: "value" });
this.addOutputPort({ side: 1, pos: 0 });
this.value = 1;
@@ -2378,10 +2378,11 @@ class Counter extends Component {
}
class LED extends Component {
- constructor(name,pos,color = [100,0,0]) {
+ constructor(name, pos, properties, color = [100,0,0]) {
super(name,pos,1,1,{ type: "value" });
this.addInputPort({ side: 3, pos: 0 });
this.value = 0;
+ this.properties = properties;
this.color = color;
}
@@ -2493,6 +2494,217 @@ class LED extends Component {
}
}
+ // Draw output pins
+ for(let i = 0; i < this.output.length; ++i) {
+ const screen = {x, y};
+ const pos = this.output[i].pos;
+
+ const angle = Math.PI / 2 * pos.side;
+ screen.x += Math.sin(angle) * zoom;
+ screen.y -= Math.cos(angle) * zoom;
+ if(pos.side == 1) screen.x += (this.width - 1) * zoom;
+ else if(pos.side == 2) screen.y += (this.height - 1) * zoom;
+
+ if(pos.side % 2 == 0) screen.x += pos.pos * zoom;
+ else screen.y += pos.pos * zoom;
+
+ ctx.beginPath();
+ ctx.moveTo(
+ screen.x - Math.sin(angle) / 2 * zoom,
+ screen.y + Math.cos(angle) / 2 * zoom
+ );
+ ctx.lineTo(
+ screen.x,
+ screen.y
+ );
+ ctx.lineWidth = zoom / 8;
+ ctx.stroke();
+
+ if(zoom > 10) {
+ ctx.beginPath();
+ ctx.arc(
+ screen.x,
+ screen.y,
+ zoom / 8,
+ 0,
+ Math.PI * 2
+ );
+ ctx.fillStyle = "#111";
+ ctx.fill();
+ }
+
+ if(zoom > 30) {
+ const name = this.output[i].name;
+ if(name) {
+ ctx.fillStyle = "#888";
+ ctx.font = zoom / 7 + "px Ubuntu";
+ ctx.fillText(
+ name,
+ screen.x - ctx.measureText(name).width / 2,
+ (pos.side == 2 ? screen.y + zoom / 4 : screen.y - zoom / 4)
+ );
+ }
+ }
+ }
+ }
+}
+
+class LEDArray extends Component {
+ constructor(name, pos, properties, color = [100,0,0]) {
+ super(name,pos,8,8,{ type: "value" });
+ this.properties = properties || {};
+
+ this.CE = 0;
+ this.WE = 1;
+ this.PUSH = 2;
+ this.ADDR0 = 3;
+ this.ADDR1 = 4;
+ this.ADDR2 = 5;
+ this.DATA = 6;
+
+ this.addInputPort({ side: 3, pos: this.CE }, 'CE');
+ this.addInputPort({ side: 3, pos: this.WE }, 'WE');
+ this.addInputPort({ side: 3, pos: this.PUSH }, 'PUSH');
+ this.addInputPort({ side: 3, pos: this.ADDR0 }, 'ADDR 0');
+ this.addInputPort({ side: 3, pos: this.ADDR1 }, 'ADDR 1');
+ this.addInputPort({ side: 3, pos: this.ADDR2 }, 'ADDR 2');
+ for (let x = 0; x < this.width; x++) {
+ this.addInputPort({ side: 2, pos: x }, x.toString());
+ }
+ this.value = 0;
+ if (!this.properties.values) {
+ this.properties.values = [];
+ this.properties.values_buffer = [];
+ }
+
+ this.color = color;
+ }
+
+ function() {
+ if (!this.input[this.CE].value) {
+ return;
+ }
+
+ if (this.input[this.WE].value) {
+ let address_line = parseInt(this.input[this.ADDR2].value.toString() + this.input[this.ADDR1].value.toString()+ this.input[this.ADDR0].value.toString(), 2);
+ for (let x = 0; x < this.width; x++) {
+ this.properties.values_buffer[address_line * this.width + x] = this.input[this.DATA + x].value;
+ }
+ }
+ if (this.input[this.PUSH].value) {
+ this.properties.values = this.properties.values_buffer.slice();
+ }
+ }
+
+ draw() {
+ const x = (this.pos.x - offset.x) * zoom;
+ const y = -(this.pos.y - offset.y) * zoom;
+
+ if(!(
+ x + this.width * zoom + zoom / 2 >= 0 &&
+ x - zoom * 1.5 <= c.width &&
+ y + this.height * zoom + zoom / 2 >= 0 &&
+ y - zoom * 1.5 <= c.height
+ )) return;
+
+ // Draw the frame of the component
+ ctx.fillStyle = "#111";
+ ctx.strokeStyle = "#111";
+ ctx.lineWidth = zoom / 12 | 0;
+ ctx.beginPath();
+ ctx.rect(
+ x - zoom / 2,
+ y - zoom / 2,
+ this.width * zoom,
+ this.height * zoom
+ );
+ ctx.fill();
+ ctx.stroke();
+
+ for (let x_ = 0; x_ < this.width; x_++) {
+ for (let y_ = 0; y_ < this.height; y_++) {
+ ctx.shadowBlur = 0;
+ let color;
+ if(this.properties.values[y_ * this.width + x_] == 1 && this.input[this.CE].value == 1) {
+ color = this.color.map(n => Math.min((n * 2), 255) | 0);
+
+ if(zoom > 20) ctx.shadowBlur = zoom / 3;
+ ctx.shadowColor = "rgb(" + color[0] + "," + color[1] + "," + color[2] + ")";
+ } else {
+ color = this.color.map(n => Math.min((n / 2), 255) | 0);
+ }
+ ctx.fillStyle = "rgb(" + color[0] + "," + color[1] + "," + color[2] + ")";
+
+ ctx.beginPath();
+ const margin = 0.025;
+ ctx.rect(
+ x - zoom / 2 + (x_ + margin) * zoom,
+ y - zoom / 2 + (y_ + margin) * zoom,
+ zoom * (1 - margin * 2),
+ zoom * (1 - margin * 2)
+ );
+ ctx.fill();
+ }
+ }
+
+ ctx.shadowBlur = 0;
+
+
+ // Draw input pins
+ for(let i = 0; i < this.input.length; ++i) {
+ const screen = {x, y};
+ const pos = this.input[i].pos;
+
+ const angle = Math.PI / 2 * pos.side;
+ screen.x += Math.sin(angle) * zoom;
+ screen.y -= Math.cos(angle) * zoom;
+ if(pos.side == 1) screen.x += (this.width - 1) * zoom;
+ else if(pos.side == 2) screen.y += (this.height - 1) * zoom;
+
+ if(pos.side % 2 == 0) screen.x += pos.pos * zoom;
+ else screen.y += pos.pos * zoom;
+
+ ctx.beginPath();
+ ctx.moveTo(
+ screen.x - Math.sin(angle) / 2 * zoom,
+ screen.y + Math.cos(angle) / 2 * zoom
+ );
+ ctx.lineTo(
+ screen.x,
+ screen.y
+ );
+ ctx.lineWidth = zoom / 8;
+ ctx.stroke();
+
+ if(zoom > 10) {
+ ctx.beginPath();
+ ctx.arc(
+ screen.x,
+ screen.y,
+ zoom / 8 - zoom / 20,
+ 0,
+ Math.PI * 2
+ );
+ ctx.lineWidth = zoom / 10;
+ ctx.fillStyle = "#fff";
+ ctx.stroke();
+ ctx.fill();
+ }
+
+ if(zoom > 30) {
+ const name = this.input[i].name;
+ if(name) {
+ ctx.fillStyle = "#888";
+ ctx.font = zoom / 7 + "px Ubuntu";
+ ctx.fillText(
+ name,
+ screen.x - ctx.measureText(name).width / 2,
+ (pos.side == 2 ? screen.y + zoom / 4 : screen.y - zoom / 4)
+ );
+ }
+ }
+ }
+
// Draw output pins
for(let i = 0; i < this.output.length; ++i) {
const screen = {x, y};
diff --git a/app/js/localStorage2.js b/app/js/localStorage2.js
index d3f4550c..a89a07a4 100644
--- a/app/js/localStorage2.js
+++ b/app/js/localStorage2.js
@@ -98,7 +98,7 @@ const constructors = {
Button,Constant,Delay,Clock,Debug,
Beep,Counter,LED,Display,
Custom, TimerStart, TimerEnd,
- ROM
+ ROM, LEDArray
};
/*
@@ -248,7 +248,7 @@ function parse(data) {
}
}
- const component = new constructors[constructor]();
+ const component = new constructors[constructor](data.name, data.pos, data.properties);
if(constructor == "Custom") {
const parsed = parse(JSON.stringify(data.componentData));
@@ -260,17 +260,21 @@ function parse(data) {
const input = data.input;
for(let i = 0; i < component.input.length; ++i) {
- component.input[i].name = input[i].name;
- component.input[i].value = input[i].value;
- component.input[i].pos = input[i].pos;
+ if (input[i]) {
+ component.input[i].name = input[i].name;
+ component.input[i].value = input[i].value;
+ component.input[i].pos = input[i].pos;
+ }
}
delete data.input;
const output = data.output;
for(let i = 0; i < component.output.length; ++i) {
- component.output[i].name = output[i].name;
- component.output[i].value = output[i].value;
- component.output[i].pos = output[i].pos;
+ if (output[i]) {
+ component.output[i].name = output[i].name;
+ component.output[i].value = output[i].value;
+ component.output[i].pos = output[i].pos;
+ }
}
delete data.output;