Added ability to modify memory location at any time.
[CS-101.git] / digital_logic_simulator.html
blob6d8a57eef0cf690476ec73cc1794854575d9bf3a
1 <html>
2 <title>Digital Logic Simulator</title>
3 <noscript>
4 <b>Your browser does not support JavaScript or JavaScript is disabled.</b>
5 </noscript>
6 <script>
7 /* DEFAULT COLOR SETTINGS */
8 var color_on = "#fe0"; /* color of objects in high state */
9 var color_on_hlt = "#f90";
11 var color_off = "#bbb"; /* color of objects in low state */
12 var color_off_hlt = "#ddd";
14 var gate_stroke_style = "#11f";
15 var gate_stroke_width = 1;
17 var con_stroke_style_low = "#000";
18 var con_stroke_style_high = "#f00";
20 var con_stroke_width = 1;
22 /* GENERAL DATA STRUCTRURES */
23 var stage = new Array(); /* status of stage - all details stored here */
24 var stage_rows = 0; /* number of rows on stage */
25 var stage_cols = 0; /* number of columns on stage */
26 var grid_status = 1; /* boolean status of stage grid lines */
27 var grid_size = 60; /* this is stored here for reference */
28 var canvas; /* object id of canvas tag */
29 var ctx; /* context of canvas */
30 var item_selected = "gate_and"; /* only one type of object can be drawn at a time */
31 var connection_started = false; /* connections require two clicks - source and dest */
32 var connection_coord = new Array(); /* new connection x1,y1,x2,y2 */
33 var clock_speed = 0; /* speed of clock in seconds (can be fractional) */
34 var clock_status = 0; /* status of normal clock signal */
35 var clock_timer = null; /* stores clock timer so it can be stopped */
37 var out = new Array(); /* output bit value */
38 var input = new Array(); /* intput bit value */
40 /* change speed of clock */
41 function clk_change()
43 clock_speed = document.getElementById("clock_speed_select").value;
46 /* start and stop clock */
47 function clk_toggle()
49 if(clock_timer != null ){
50 clearInterval(clock_timer);
51 clock_timer = null;
52 document.getElementById("clock").innerHTML = "Clock Start";
53 } else {
54 clock_timer = setInterval("clk_adv()", clock_speed * 1000);
55 document.getElementById("clock").innerHTML = "Clock Stop";
59 /* advance clock one step */
60 function clk_adv()
62 clock_status++;
63 if(clock_status > 1) { clock_status = 0; }
64 draw_stage();
67 function clock_neg()
69 if(clock_status) { return 0; } else { return 1; }
72 /* each square on grid has an associated block of data tied to it */
73 function grid(type, value)
75 this.type = type; /* type of entity @ location */
76 this.value = value; /* many entities have a value associated */
77 this.name = ''; /* used for inputs and outputs */
80 /* flip bit of specified input and call redraw on screen */
81 function input_flip(v)
83 if(v == 'undefined') { alert("Cannot flip unknown value"); }
84 var x; var y;
85 if(input[v].val == 0) { input[v].val = 1 } /* set data value */
86 /* loop through all grids on stage, flipping inputs */
87 for(x=0; x < stage_cols; x++) {
88 for(y = 0; y < stage_rows; y++) {
89 if(stage[x][y].type == "input") {
90 stage[x][y].val = input[v].val;
91 draw_input_simple(v);
97 /* flip bit of specified output and call redraw on screen */
98 function output_flip(v)
100 if(v == 'undefined') { alert("Cannot flip unknown value"); }
101 if(out[v].val == 0) { out[v].val = 1; } else { out[v].val = 0; }
102 // redraw output on screen
103 draw_output_simple(v);
106 /* reset all outputs to zero and redraw on screen */
107 function output_reset()
109 for(var i = 0; i < 9; i++) {
110 out[i].val = 0;
111 // redraw outputs on screen
112 draw_output_simple(i);
116 /* converts decimal degrees to radians */
117 function deg_to_rad(deg)
119 return (Math.PI/180)*deg;
122 /* create all output data structures and draw inital values on screen */
123 function init_stage()
125 var x; var y;
127 /* create blank grid data structure */
128 for(x = 0; x < stage_cols; x++) {
129 stage[x] = new Array();
130 for(y = 0; y < stage_rows; y++) {
131 stage[x][y] = new grid('', '');
135 /* setup clocks */
136 stage[0][0].type = "clock";
137 stage[0][1].type = "clock_";
139 /* setup inputs */
140 for(x = 0; x < 5; x++) {
141 stage[15][x+3].type = "output";
142 stage[15][x+3].value = 0;
143 stage[15][x+3].name = x;
146 /* setup outputs */
147 for(y = "A", x = 0; x < 5; x++, y = String.fromCharCode(y.charCodeAt() + 1)) {
148 stage[0][x+3].type = "input";
149 stage[0][x+3].value = 0;
150 stage[0][x+3].name = y;
153 /* reset all command buttons */
154 item_selected = "gate_and";
155 document.getElementById("gate_and").disabled = true;
156 document.getElementById("gate_nand").disabled = false;
157 document.getElementById("gate_nor").disabled = false;
158 document.getElementById("gate_not").disabled = false;
159 document.getElementById("gate_or").disabled = false;
160 document.getElementById("gate_xor").disabled = false;
161 document.getElementById("delete").disabled = false;
162 document.getElementById("gate_connect").disabled = false;
163 clock_speed = 5;
164 clock_timer = null;
168 move through each grid in stage and draw contents.
169 this function can be used to refresh the screen at any time.
171 function draw_stage()
173 var x; var y;
174 /* loop through all grids on stage, drawing contents */
175 for(x=0; x < stage_cols; x++) {
176 for(y = 0; y < stage_rows; y++) {
177 switch(stage[x][y].type) {
178 case "clock":
179 draw_clock(x,y,clock_status);
180 break;
181 case "clock_":
182 draw_clock(x,y,clock_neg(clock_status));
183 break;
184 case "input":
185 draw_input(x,y,x);
186 break;
187 case "output":
188 draw_output(x,y,x);
189 break;
194 /* draw lines (wires) connecting gates */
196 /* update inputs */
198 /* update outputs */
201 /* intial setup of page - must be called on page load */
202 function init_form()
204 var x; var y;
205 /* initalize canvas element for use */
206 canvas = document.getElementById("stage");
207 ctx = canvas.getContext("2d");
208 /* get width and height of window and set stage (canvas) with it. */
209 canvas.height = window.innerHeight-125;
210 canvas.width = window.innerWidth - 45;
211 if(grid_status) {draw_grid(); }
212 init_stage();
213 draw_stage();
216 function draw_clock(x,y,phase)
218 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
219 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
220 if(phase > 1 || phase < 0) { alert("Clock phase not sent"); return ; }
221 x = (x*grid_size) + (grid_size/2); /* offset from conrner of grid */
222 y = (y*grid_size) + (grid_size/2);
223 if(phase) {
224 ctx.strokeStyle = con_stroke_style_high;
225 ctx.fillStyle = con_stroke_style_high;
226 } else {
227 ctx.strokeStyle = con_stroke_style_low;
228 ctx.fillStyle = con_stroke_style_low;
230 ctx.lineWidth = 2;
231 ctx.moveTo(x,y);
232 ctx.beginPath();
233 ctx.arc(x,y,15, deg_to_rad(360), deg_to_rad(0), false);
234 ctx.stroke();
235 ctx.font = "10pt Arial";
236 ctx.textAlign = "center";
237 ctx.textBaseline = "middle";
238 ctx.fillText("CLK", x, y);
239 /* draw line over text */
240 if(phase == 0) {
241 ctx.moveTo(x,y);
242 ctx.beginPath();
243 ctx.lineTo(x-8,y-8);
244 ctx.lineTo(x+8,y-8);
245 ctx.stroke();
250 draw connection (wire) from one component to another.
251 connections are automatically drawn from one place to another.
252 grids have a certain number of evenly-spaced nodes where a line can be drawn.
253 connections can only be drawn through grids that are empty.
254 inputs can only connect to outputs.
256 function draw_connect(x1, y1, x2, y2)
258 if(x1 == x2 && y1 == y2) { return; } /* cannot connect same grid */
259 x1 = x1 * grid_size; y1 = y1 * grid_size;
260 x2 = x2 * grid_size; y2 = y2 * grid_size;
261 /* TODO: draw line color on basis of output (high or low) */
263 /* draw line */
264 ctx.strokeStyle = con_stroke_style_low;
265 ctx.lineWidth = con_stroke_width;
266 ctx.moveTo(x1,y1);
267 ctx.beginPath();
268 ctx.lineTo(x1,y1);
269 ctx.lineTo(x2,y2);
270 ctx.stroke();
274 start new connection from one entity to another.
276 function start_connect(e)
278 connection_started = true;
279 var coords = cnvs_get_grid(e);
280 connection_coord[0] = coords[0];
281 connection_coord[1] = coords[1];
284 function stop_connect(e)
286 connection_started = false;
287 var coords = cnvs_get_grid(e);
288 connection_coord[2] = coords[0];
289 connection_coord[3] = coords[1];
291 // check inputs
293 // draw line on canvas
294 draw_connect(connection_coord[0], connection_coord[1], connection_coord[2], connection_coord[3]);
297 /* inputs have are represented by a character with a parameter v */
298 function draw_input(x,y)
300 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
301 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
302 var s = stage[x][y].value;
303 var name = stage[x][y].name;
304 x = (x*grid_size) + (grid_size/2); /* offset from corner of grid */
305 y = (y*grid_size) + (grid_size/2);
306 if(s) { ctx.strokeStyle = color_on_hlt } else { ctx.strokeStyle = color_off; }
307 if(s) { ctx.fillStyle = color_on } else { ctx.fillStyle = color_off_hlt; }
308 ctx.lineWidth = 2;
309 ctx.moveTo(x,y);
310 /* draw background circle */
311 ctx.beginPath();
312 ctx.arc(x,y,15, deg_to_rad(360), deg_to_rad(0), false);
313 ctx.fill();
315 ctx.beginPath();
316 ctx.arc(x,y,15, deg_to_rad(360), deg_to_rad(0), false);
317 ctx.stroke();
319 if(s) { ctx.fillStyle = color_on_hlt } else { ctx.fillStyle = color_off; }
320 /* draw character on top */
321 ctx.font = "15pt Arial";
322 ctx.textAlign = "center";
323 ctx.textBaseline = "middle";
324 ctx.fillText(name, x, y);
327 /* simple version with auto lookup to data structure */
328 function draw_input_simple(v)
330 var x;
331 if(v == 'undefined') { alert("Cannot modify unknown output"); }
332 // TODO: Make this work with lib function instead...
333 switch(v) {
334 case 1:
335 x = "A";
336 break;
337 case 2:
338 x = "B";
339 break;
340 case 3:
341 x = "C";
342 break;
343 case 4:
344 x = "D";
345 break;
346 case 5:
347 x = "E";
348 break;
349 case 6:
350 x = "F";
351 break;
352 case 7:
353 x = "G";
354 break;
355 case 8:
356 x = "H";
357 break;
359 // TODO: cannot get position of input from this location - must search grid.
360 draw_input(input[v].xpos, input[v].ypos, x, input[v].val);
363 /* draw output button.
365 x = grid position on x axis.
366 y = grid position on y axis.
368 function draw_output(x,y)
370 var w = 30; /* width of box */
371 var tx = x; var ty = y;
372 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
373 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
374 var s = stage[x][y].value;
375 var name = stage[x][y].name;
376 tx = x * grid_size + (grid_size / 2);
377 ty = y * grid_size + (grid_size / 2);
379 x = (x * grid_size) + (grid_size / 5); /* offset from corner of grid */
380 y = (y * grid_size) + (grid_size / 5);
382 /* draw filled box around char */
383 if(s) { ctx.fillStyle = color_on } else { ctx.fillStyle = color_off_hlt; }
384 ctx.lineWidth = 2;
385 ctx.moveTo(x,y);
386 ctx.beginPath();
387 ctx.lineTo(x+w,y);
388 ctx.lineTo(x+w,y+w);
389 ctx.lineTo(x,y+w);
390 ctx.lineTo(x,y);
391 ctx.lineTo(x+w,y);
392 ctx.fill();
394 /* draw outline box around char */
395 if(s) { ctx.strokeStyle = color_on_hlt } else { ctx.strokeStyle = color_off; }
396 ctx.lineWidth = 2;
397 ctx.moveTo(x,y);
398 ctx.beginPath();
399 ctx.lineTo(x+w,y);
400 ctx.lineTo(x+w,y+w);
401 ctx.lineTo(x,y+w);
402 ctx.lineTo(x,y);
403 ctx.lineTo(x+w,y);
404 ctx.stroke();
406 /* draw char inside box */
407 if(s) { ctx.fillStyle = color_on_hlt; } else { ctx.fillStyle = color_off; }
408 ctx.font = "15pt Arial";
409 ctx.textAlign = "center";
410 ctx.textBaseline = "middle";
411 ctx.fillText(name, tx, ty);
414 /* simple version with auto lookup to data structure */
415 function draw_output_simple(v)
417 if(v == 'undefined') { alert("Cannot modify unknown output"); }
418 // TODO: cannot get position of input from this location - must search grid.
419 draw_output(out[v].xpos, out[v].ypos, v, out[v].val);
422 /* draw faint gridlines on stage - used as a guide for the user */
423 function draw_grid()
425 var x, y; /* current x and y position */
426 var offset = 10; /* x and y maximum offset (far bottom or side of the window) */
427 ctx.strokeStyle = "#ccc";
428 ctx.lineWidth = 1;
429 /* draw vertical lines */
430 for(x = grid_size, y = 0, offset = window.innerWidth; x < window.innerWidth; x = x + grid_size)
432 ctx.beginPath();
433 ctx.moveTo(x,y);
434 ctx.lineTo(x,y+offset);
435 ctx.stroke();
436 stage_cols++;
438 /* draw horizontal lines */
439 for(x = 0, y = grid_size, offset = window.innerWidth; y < window.innerWidth; y = y + grid_size)
441 ctx.beginPath();
442 ctx.moveTo(x,y);
443 ctx.lineTo(x+offset,y);
444 ctx.stroke();
445 stage_rows++;
449 function draw_and_gate(x,y)
451 var h = grid_size * .5; /* height of square of gate */
452 var w = grid_size * .250; /* width of square area of gate */
453 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
454 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
455 ctx.strokeStyle = gate_stroke_style;
456 ctx.lineWidth = gate_stroke_width;
457 x = (grid_size*.25) + (grid_size*x); /* offset from conrner of grid */
458 y = (grid_size*.25) + (grid_size*y);
459 ctx.beginPath();
460 ctx.moveTo(x,y);
461 ctx.lineTo(x+w, y);
462 ctx.arc( x+w, y+(h/2), (h/2), deg_to_rad(-90), deg_to_rad(90), false);
463 ctx.lineTo(x+w, y+h);
464 ctx.lineTo(x,y+h);
465 ctx.lineTo(x,y);
466 ctx.stroke();
469 function draw_nand_gate(x,y)
471 var h = grid_size * .5; /* height of square of gate */
472 var w = grid_size * .250; /* width of square area of gate */
473 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
474 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
475 ctx.strokeStyle = gate_stroke_style;
476 ctx.lineWidth = gate_stroke_width;
477 x = (grid_size*.25) + (grid_size*x); /* offset from conrner of grid */
478 y = (grid_size*.25) + (grid_size*y);
479 ctx.beginPath();
480 ctx.moveTo(x,y);
481 ctx.lineTo(x+w, y);
482 ctx.arc( x+w, y+(h/2), (h/2), deg_to_rad(-90), deg_to_rad(90), false);
483 ctx.lineTo(x+w, y+h);
484 ctx.lineTo(x,y+h);
485 ctx.lineTo(x,y);
486 ctx.stroke();
487 /* nose */
488 ctx.beginPath();
489 ctx.arc( x+(w*2)+(grid_size*.07), y+(h/2), grid_size*.08, deg_to_rad(0), deg_to_rad(360), false);
490 ctx.stroke();
493 function draw_not_gate(x,y)
495 var h = grid_size * .5; /* height of square of gate */
496 var w = grid_size * .375; /* width of square area of gate */
497 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
498 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
499 ctx.strokeStyle = gate_stroke_style;
500 ctx.lineWidth = gate_stroke_width;
501 ctx.lineJoin = 'bevel';
502 x = (grid_size*.25) + (grid_size*x); /* offset from conrner of grid */
503 y = (grid_size*.25) + (grid_size*y);
505 /* triangle */
506 ctx.beginPath();
507 ctx.moveTo(x,y);
508 ctx.lineTo(x+w,y+(h/2));
509 ctx.lineTo(x,y+h);
510 ctx.lineTo(x,y);
511 ctx.stroke();
513 /* nose */
514 ctx.beginPath();
515 ctx.arc( x+w+6, y+(h/2),grid_size*.08, deg_to_rad(0), deg_to_rad(360), false);
516 ctx.stroke();
519 function draw_or_gate(x,y)
521 var h = grid_size * .5; /* height of square of gate */
522 var w = grid_size * .20; /* width of square area of gate */
523 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
524 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
525 ctx.strokeStyle = gate_stroke_style;
526 ctx.lineWidth = gate_stroke_width;
527 ctx.lineJoin = 'bevel';
528 x = (grid_size*.25) + (grid_size*x); /* offset from conrner of grid */
529 y = (grid_size*.25) + (grid_size*y);
530 /* back curve - inputs */
531 ctx.beginPath();
532 ctx.arc(x-(2*w), y +(h/2), h, deg_to_rad(-30), deg_to_rad(30), false);
533 ctx.stroke();
534 /* top line */
535 ctx.beginPath();
536 ctx.moveTo(x,y);
537 ctx.lineTo(x+w,y);
538 ctx.stroke();
539 /* top curve */
540 ctx.beginPath();
541 ctx.arc(x+w, y+h, h, deg_to_rad(-90), deg_to_rad(-30), false);
542 ctx.stroke();
543 /* bottom line */
544 ctx.beginPath();
545 ctx.moveTo(x,y+h);
546 ctx.lineTo(x+w,y+h);
547 ctx.stroke();
548 /* bottom curve */
549 ctx.beginPath();
550 ctx.arc(x+w, y, h, deg_to_rad(30), deg_to_rad(90), false);
551 ctx.stroke();
554 function draw_nor_gate(x,y)
556 var h = grid_size * .5; /* height of square of gate */
557 var w = grid_size * .10; /* width of square area of gate */
558 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
559 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
560 ctx.strokeStyle = gate_stroke_style;
561 ctx.lineWidth = gate_stroke_width;
562 ctx.lineJoin = 'bevel';
563 x = (grid_size*.25) + (grid_size*x); /* offset from conrner of grid */
564 y = (grid_size*.25) + (grid_size*y);
565 /* back curve - inputs */
566 ctx.beginPath();
567 ctx.arc(x-(4*w), y +(h/2), h, deg_to_rad(-30), deg_to_rad(30), false);
568 ctx.stroke();
569 /* top line */
570 ctx.beginPath();
571 ctx.moveTo(x,y);
572 ctx.lineTo(x+w,y);
573 ctx.stroke();
574 /* top curve */
575 ctx.beginPath();
576 ctx.arc(x+w, y+h, h, deg_to_rad(-90), deg_to_rad(-30), false);
577 ctx.stroke();
578 /* bottom line */
579 ctx.beginPath();
580 ctx.moveTo(x,y+h);
581 ctx.lineTo(x+w,y+h);
582 ctx.stroke();
583 /* bottom curve */
584 ctx.beginPath();
585 ctx.arc(x+w, y, h, deg_to_rad(30), deg_to_rad(90), false);
586 ctx.stroke();
587 /* nose */
588 ctx.beginPath();
589 ctx.arc(x+(w*3)+(grid_size*.30), y+(h/2),grid_size*.08, deg_to_rad(0), deg_to_rad(360), false);
590 ctx.stroke();
593 function draw_xor_gate(x,y)
595 var h = grid_size * .5; /* height of square of gate */
596 var w = grid_size * .10; /* width of square area of gate */
597 if(x == 'undefined' || y == 'undefined') { alert("Coordinates Not Sent to Function"); return; }
598 if(x < 0 || y < 0) { alert("Coordinates Cannot Be Negative"); return ; }
599 ctx.strokeStyle = gate_stroke_style;
600 ctx.lineWidth = gate_stroke_width;
601 ctx.lineJoin = 'bevel';
602 x = (grid_size*.25) + (grid_size*x); /* offset from conrner of grid */
603 y = (grid_size*.25) + (grid_size*y);
604 /* back curve - inputs */
605 ctx.beginPath();
606 ctx.arc(x-(2*w)-(grid_size*.20), y +(h/2), h, deg_to_rad(-30), deg_to_rad(30), false);
607 ctx.stroke();
608 /* extra back curve - inputs */
609 ctx.beginPath();
610 ctx.arc(x-(2*w)-(grid_size*.315), y +(h/2), h, deg_to_rad(-30), deg_to_rad(30), false);
611 ctx.stroke();
612 /* top line */
613 ctx.beginPath();
614 ctx.moveTo(x,y);
615 ctx.lineTo(x+w,y);
616 ctx.stroke();
617 /* top curve */
618 ctx.beginPath();
619 ctx.arc(x+w, y+h, h, deg_to_rad(-90), deg_to_rad(-30), false);
620 ctx.stroke();
621 /* bottom line */
622 ctx.beginPath();
623 ctx.moveTo(x,y+h);
624 ctx.lineTo(x+w,y+h);
625 ctx.stroke();
626 /* bottom curve */
627 ctx.beginPath();
628 ctx.arc(x+w, y, h, deg_to_rad(30), deg_to_rad(90), false);
629 ctx.stroke();
632 /* user changes what type of gate will be drawn next */
633 function change_selection(sel)
635 var button = document.getElementById(sel);
636 if(!button) { alert("Cannot Find Selected Button"); return; }
637 /* enable old button */
638 document.getElementById(item_selected).disabled = false;
639 //alert("enabling " + item_selected);
640 /* disable new button */
641 button.disabled = true;
642 /* set variable */
643 item_selected = sel;
646 /* returns coordinates of canvas in pixels */
647 function cnvs_get_coordinates(e)
649 var x_offset = canvas.offsetLeft;
650 var y_offset = canvas.offsetTop;
651 if(canvas == 'undefined') { alert("Canvas parameter is undefined"); }
652 x_offset = e.clientX - x_offset;
653 y_offset = e.clientY - y_offset;
654 document.getElementById("xycoordinates").innerHTML="Coordinates: (" + x_offset + "," + y_offset + ")";
655 return [x_offset,y_offset];
658 /* returns coordinates of canvas in grids 0,0 is top left corner */
659 function cnvs_get_grid(e)
661 var coords = cnvs_get_coordinates(e);
662 return [Math.floor(coords[0] / grid_size), Math.floor(coords[1] / grid_size)];
665 /* canvas has been clicked find out which grid and make correct change to square if needed. */
666 function cnvs_clicked(e)
668 var coords = cnvs_get_coordinates(e);
669 var x_pos = Math.floor(coords[0] / grid_size);
670 var y_pos = Math.floor(coords[1] / grid_size);
671 // TODO: create case starement for each type of entity
672 // if delete command, remove contents of grid
673 if(item_selected == "delete") {
674 // cannot allow inputs and outputs to be deleted
675 if(stage[x_pos][y_pos].type == "input" || stage[x_pos][y_pos].type == "output") { return; }
676 stage[x_pos][y_pos].type = "";
677 draw_stage();
680 // if an input or output, flip value
681 if(stage[x_pos][y_pos].type == "input") {
682 input_flip(stage[x_pos][y_pos].value);
683 // TODO: Finish this
686 if(stage[x_pos][y_pos].type == "output") {
687 // TODO: Finish this
690 // if connection started, begin connection process
691 if(item_selected == "gate_connect"){
692 if(connection_started == false){
693 start_connect(e);
694 } else {
695 stop_connect(e);
699 // ...otherwise perform whatever the current selected function is
700 if(stage[x_pos][y_pos].type != "") { return; } // check for presence of an item
701 switch(item_selected) {
702 case "gate_and":
703 stage[x_pos][y_pos].type = "and";
704 draw_and_gate(x_pos,y_pos);
705 break;
706 case "gate_nand":
707 stage[x_pos][y_pos].type = "nand";
708 draw_nand_gate(x_pos,y_pos);
709 break;
710 case "gate_nor":
711 stage[x_pos][y_pos].type = "nor";
712 draw_nor_gate(x_pos,y_pos);
713 break;
714 case "gate_not":
715 stage[x_pos][y_pos].type = "not";
716 draw_not_gate(x_pos,y_pos);
717 break;
718 case "gate_or":
719 stage[x_pos][y_pos].type = "or";
720 draw_or_gate(x_pos,y_pos);
721 break;
722 case "gate_xor":
723 stage[x_pos][y_pos].type = "xor";
724 draw_xor_gate(x_pos,y_pos);
725 break;
729 </script>
731 <style type="text/css">
733 #stage {
734 border: solid 1px #000;
737 </style>
738 <body onLoad="init_form();">
740 <center><h2>Digital Logic Simulator</h2></center>
741 <center>
742 <button type="button" id="gate_and" onClick='change_selection("gate_and");' disabled="disabled">AND</button>
743 &nbsp;&nbsp;
744 <button type="button" id="gate_nand" onClick='change_selection("gate_nand");'>NAND</button>
745 &nbsp;&nbsp;
746 <button type="button" id="gate_nor" onClick='change_selection("gate_nor");'>NOR</button>
747 &nbsp;&nbsp;
748 <button type="button" id="gate_not" onClick='change_selection("gate_not");'>NOT</button>
749 &nbsp;&nbsp;
750 <button type="button" id="gate_or" onClick='change_selection("gate_or");'>OR</button>
751 &nbsp;&nbsp;
752 <button type="button" id="gate_xor" onClick='change_selection("gate_xor");'>XOR</button>
753 &nbsp;&nbsp;
754 <button type="button" id="delete" onClick='change_selection("delete");'>Delete</button>
756 <button type="button" id="gate_connect" onClick='change_selection("gate_connect");'>Connect</button>
757 &nbsp;&nbsp;
758 <button type="button" id="move" onClick='change_selection("move");'>Move</button>
759 &nbsp;&nbsp;
760 <button type="button" id="pan" onClick='change_selection("pan");'>Pan</button>
761 &nbsp;&nbsp;
762 <button type="button" id="zoom" onClick='change_selection("zoom");'>Zoom</button>
763 &nbsp;&nbsp;
764 <button type="button" id="clock" onClick='clk_toggle();'>Clock Start</button>
765 &nbsp;&nbsp;
766 <select id="clock_speed_select" onChange='clk_change();'>
767 <option value="5">Slow</option>
768 <option value="1">Medium</option>
769 <option value=".5">Fast</option>
770 <option value="-1">Unlimited</option>
771 </select>
772 </center>
774 <div id=xycoordinates>&nbsp;</div>
776 <canvas id="stage" width="200" height="200" onMouseMove="cnvs_get_coordinates(event)" onClick="cnvs_clicked(event);">
777 Your browser does not support HTML5 Canvas.
778 </canvas>
780 </body>
781 </html>