2 <title>Digital Logic Simulator
</title>
5 var grid_status
= 1; /* boolean status of stage grid lines */
6 var grid_size
= 50; /* this is stored here for reference */
7 var canvas
; /* object id of canvas tag */
8 var ctx
; /* context of canvas */
9 var item_selected
= "gate_and" /* only one type of object can be drawn at a time */
11 var color_on
= "#fe0"; /* color of objects in high state */
12 var color_on_hlt
= "#f90";
14 var color_off
= "#bbb"; /* color of objects in low state */
15 var color_off_hlt
= "#ddd";
17 var out
= new Array(); /* output bits */
18 var input
= new Array(); /* intput bits */
19 var grid
= new Array(); /* status of grid - all details stored here */
21 /* create new output - only called during init phase */
22 function output(value
, xpos
, ypos
)
29 /* each square on grid has an associated block of data tied to it */
30 function grid(type
, xpos
, ypos
)
32 this.type
= type
; /* type of entity @ location */
33 this.value
= value
; /* many entities have a value associated */
34 this.xpos
= xpos
; /* horiz position on grid */
35 this.ypos
= ypos
; /* vertical position on grid */
38 /* flip bit of specified input and redraw on screen */
39 function input_flip(v
)
41 if(v
== 'undefined') { alert("Cannot flip unknown value"); }
42 if(input
[v
].val
== 0) { input
[v
].val
= 1; } else { input
[v
].val
= 0; }
43 // redraw output on screen
48 /* flip bit of specified output and redraw on screen */
49 function output_flip(v
)
51 if(v
== 'undefined') { alert("Cannot flip unknown value"); }
52 if(out
[v
].val
== 0) { out
[v
].val
= 1; } else { out
[v
].val
= 0; }
53 // redraw output on screen
54 draw_output_simple(v
);
57 /* reset all outputs to zero and redraw on screen */
58 function output_reset()
60 for(var i
= 0; i
< 9; i
++) {
62 // redraw outputs on screen
63 draw_output_simple(i
);
67 /* converts decimal degrees to radians */
68 function deg_to_rad(deg
)
70 return (Math
.PI
/180)*deg
;
73 /* create all output data structures and draw inital values on screen */
74 function init_outputs()
78 for(x
= 0; x
< 9; x
++) {
79 out
[x
] = new output(0,15,x
+2);
80 draw_output(15,x
+2, x
, 0);
83 for(y
= "A", x
= 0; x
< 9; x
++, y
= String
.fromCharCode(y
.charCodeAt() + 1)) {
84 input
[x
] = new output(0,0,x
+2);
89 /* intial setup of page - must be called on page load */
93 /* initalize canvas element for use */
94 canvas
= document
.getElementById("stage");
95 ctx
= canvas
.getContext("2d");
96 /* get width and height of window and set stage (canvas) with it. */
97 canvas
.height
= window
.innerHeight
-125;
98 canvas
.width
= window
.innerWidth
- 45;
100 if(grid_status
) {draw_grid(); }
112 function draw_clock(x
,y
,phase
)
114 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
115 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
116 if(phase
> 1 || phase
< 0) { alert("Clock phase not sent"); return ; }
117 x
= (x
*grid_size
) + (grid_size
/2); /* offset
from conrner
of grid */
118 y
= (y
*grid_size
) + (grid_size
/2);
119 ctx
.strokeStyle
= "#f33";
123 ctx
.arc(x
,y
,15, deg_to_rad(360), deg_to_rad(0), false);
125 ctx
.font
= "10pt Arial";
126 ctx
.textAlign
= "center";
127 ctx
.textBaseline
= "middle";
128 ctx
.fillText("CLK", x
, y
);
129 /* draw line over text */
131 ctx
.strokeStyle
= "#000";
140 /* inputs have are represented by a character with a parameter v */
141 function draw_input(x
,y
,v
,s
)
143 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
144 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
145 x
= (x
*grid_size
) + (grid_size
/2); /* offset
from corner
of grid */
146 y
= (y
*grid_size
) + (grid_size
/2);
147 if(s
) { ctx
.strokeStyle
= color_on_hlt
} else { ctx
.strokeStyle
= color_off
; }
148 if(s
) { ctx
.fillStyle
= color_on
} else { ctx
.fillStyle
= color_off_hlt
; }
151 /* draw background circle */
153 ctx
.arc(x
,y
,15, deg_to_rad(360), deg_to_rad(0), false);
157 ctx
.arc(x
,y
,15, deg_to_rad(360), deg_to_rad(0), false);
160 if(s
) { ctx
.fillStyle
= color_on_hlt
} else { ctx
.fillStyle
= color_off
; }
161 /* draw character on top */
162 ctx
.font
= "15pt Arial";
163 ctx
.textAlign
= "center";
164 ctx
.textBaseline
= "middle";
165 ctx
.fillText(v
, x
, y
);
168 /* simple version with auto lookup to data structure */
169 function draw_input_simple(v
)
172 if(v
== 'undefined') { alert("Cannot modify unknown output"); }
173 // TODO: Make this work with lib function instead...
200 draw_input(input
[v
].xpos
, input
[v
].ypos
, x
, input
[v
].val
);
203 /* draw output button.
205 x = grid position on x axis.
206 y = grid position on y axis.
207 v = char to print inside button.
208 s = state of output (on or off)
210 function draw_output(x
,y
,v
,s
)
212 var w
= 30; /* width of box */
213 var tx
= x
; var ty
= y
;
214 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
215 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
217 tx
= x
* grid_size
+ (grid_size
/ 2);
218 ty
= y
* grid_size
+ (grid_size
/ 2);
221 x
= (x
* grid_size
) + (grid_size
/ 5); /* offset from corner of grid */
222 y
= (y
* grid_size
) + (grid_size
/ 5);
224 /* draw filled box around char */
225 if(s
) { ctx
.fillStyle
= color_on
} else { ctx
.fillStyle
= color_off_hlt
; }
236 /* draw outline box around char */
237 if(s
) { ctx
.strokeStyle
= color_on_hlt
} else { ctx
.strokeStyle
= color_off
; }
248 /* draw char inside box */
249 if(s
) { ctx
.fillStyle
= color_on_hlt
; } else { ctx
.fillStyle
= color_off
; }
250 ctx
.font
= "15pt Arial";
251 ctx
.textAlign
= "center";
252 ctx
.textBaseline
= "middle";
253 ctx
.fillText(v
, tx
, ty
);
256 /* simple version with auto lookup to data structure */
257 function draw_output_simple(v
)
259 if(v
== 'undefined') { alert("Cannot modify unknown output"); }
260 draw_output(out
[v
].xpos
, out
[v
].ypos
, v
, out
[v
].val
);
263 /* draw faint gridlines on stage - used as a guide for the user */
266 var x
, y
; /* current x and y position */
267 var offset
= 10; /* x and y maximum offset (far bottom or side of the window) */
268 ctx
.strokeStyle
= "#ccc";
270 /* draw vertical lines */
271 for(x
= grid_size
, y
= 0, offset
= window
.innerWidth
; x
< window
.innerWidth
; x
= x
+ grid_size
)
275 ctx
.lineTo(x
,y
+offset
);
278 /* draw horizontal lines */
279 for(x
= 0, y
= grid_size
, offset
= window
.innerWidth
; y
< window
.innerWidth
; y
= y
+ grid_size
)
283 ctx
.lineTo(x
+offset
,y
);
288 function draw_and_gate(x
,y
)
290 var h
= 50; /* height of square of gate */
291 var w
= 30; /* width of square area of gate */
292 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
293 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
294 ctx
.strokeStyle
= "#11f";
296 x
= 10 + (grid_size
*x
); /* offset from conrner of grid */
297 y
= 10 + (grid_size
*y
);
301 ctx
.arc( x
+w
, y
+(h
/2), (h/2), deg_to_rad(-90), deg_to_rad(90), false);
302 ctx
.lineTo(x
+w
, y
+h
);
308 function draw_nand_gate(x
,y
)
310 var h
= 50; /* height of square of gate */
311 var w
= 30; /* width of square area of gate */
312 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
313 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
314 ctx
.strokeStyle
= "#11f";
316 x
= 10 + (grid_size
*x
); /* offset from conrner of grid */
317 y
= 10 + (grid_size
*y
);
321 ctx
.arc( x
+w
, y
+(h
/2), (h/2), deg_to_rad(-90), deg_to_rad(90), false);
322 ctx
.lineTo(x
+w
, y
+h
);
328 ctx
.arc( x
+(w
*2), y
+(h
/2),5, deg_to_rad(0), deg_to_rad(360), false);
332 function draw_not_gate(x
,y
)
334 var h
= 50; /* height of square of gate */
335 var w
= 40; /* width of square area of gate */
336 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
337 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
338 ctx
.strokeStyle
= "#11f";
340 ctx
.lineJoin
= 'bevel';
341 x
= 10 + (grid_size
*x
); /* offset from conrner of grid */
342 y
= 10 + (grid_size
*y
);
347 ctx
.lineTo(x
+w
,y
+(h
/2));
354 ctx
.arc( x
+w
+6, y
+(h
/2),5, deg_to_rad(0), deg_to_rad(360), false);
358 function draw_or_gate(x
,y
)
360 var h
= 50; /* height of square of gate */
361 var w
= 21; /* width of square area of gate */
362 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
363 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
364 ctx
.strokeStyle
= "#11f";
366 ctx
.lineJoin
= 'bevel';
367 x
= 10 + (grid_size
*x
); /* offset from conrner of grid */
368 y
= 10 + (grid_size
*y
);
369 /* back curve - inputs */
371 ctx
.arc(x
-(2*w
), y
+(h
/2), h
, deg_to_rad(-30), deg_to_rad(30), false);
380 ctx
.arc(x
+w
, y
+h
, h
, deg_to_rad(-90), deg_to_rad(-30), false);
389 ctx
.arc(x
+w
, y
, h
, deg_to_rad(30), deg_to_rad(90), false);
393 function draw_nor_gate(x
,y
)
395 var h
= 50; /* height of square of gate */
396 var w
= 21; /* width of square area of gate */
397 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
398 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
399 ctx
.strokeStyle
= "#11f";
401 ctx
.lineJoin
= 'bevel';
402 x
= 10 + (grid_size
*x
); /* offset from conrner of grid */
403 y
= 10 + (grid_size
*y
);
404 /* back curve - inputs */
406 ctx
.arc(x
-(2*w
), y
+(h
/2), h
, deg_to_rad(-30), deg_to_rad(30), false);
415 ctx
.arc(x
+w
, y
+h
, h
, deg_to_rad(-90), deg_to_rad(-30), false);
424 ctx
.arc(x
+w
, y
, h
, deg_to_rad(30), deg_to_rad(90), false);
428 ctx
.arc(x
+(w
*3)+6, y
+(h
/2),5, deg_to_rad(0), deg_to_rad(360), false);
432 function draw_xor_gate(x
,y
)
434 var h
= 50; /* height of square of gate */
435 var w
= 21; /* width of square area of gate */
436 if(x
== 'undefined' || y
== 'undefined') { alert("Coordinates Not Sent to Function"); return; }
437 if(x
< 0 || y
< 0) { alert("Coordinates Cannot Be Negative"); return ; }
438 ctx
.strokeStyle
= "#11f";
440 ctx
.lineJoin
= 'bevel';
441 x
= 10 + (grid_size
*x
); /* offset from conrner of grid */
442 y
= 10 + (grid_size
*y
);
443 /* back curve - inputs */
445 ctx
.arc(x
-(2*w
), y
+(h
/2), h
, deg_to_rad(-30), deg_to_rad(30), false);
447 /* extra back curve - inputs */
449 ctx
.arc(x
-(2*w
)-10, y
+(h
/2), h
, deg_to_rad(-30), deg_to_rad(30), false);
458 ctx
.arc(x
+w
, y
+h
, h
, deg_to_rad(-90), deg_to_rad(-30), false);
467 ctx
.arc(x
+w
, y
, h
, deg_to_rad(30), deg_to_rad(90), false);
471 /* user changes what type of gate will be drawn next */
472 function change_selection(sel
)
474 var button
= document
.getElementById(sel
);
475 if(!button
) { alert("Cannot Find Selected Button"); return; }
476 /* enable old button */
477 document
.getElementById(item_selected
).disabled
= false;
478 /* disable new button */
479 button
.disabled
= true;
484 /* returns coordinates of canvas in pixels */
485 function cnvs_get_coordinates(e
)
487 var x_offset
= canvas
.offsetLeft
;
488 var y_offset
= canvas
.offsetTop
;
489 if(canvas
== 'undefined') { alert("Canvas parameter is undefined"); }
490 x_offset
= e
.clientX
- x_offset
;
491 y_offset
= e
.clientY
- y_offset
;
492 document
.getElementById("xycoordinates").innerHTML
="Coordinates: (" + x_offset
+ "," + y_offset
+ ")";
493 return [x_offset
,y_offset
];
496 /* canvas has been clicked find out which grid and make correct change to square if needed. */
497 function cnvs_clicked(e
)
499 var coords
= cnvs_get_coordinates(e
);
500 var x_pos
= Math
.floor(coords
[0] / grid_size
);
501 var y_pos
= Math
.floor(coords
[1] / grid_size
);
503 alert(x_pos
+ " " + y_pos
);
505 // if an input or output, flip value
508 // ...otherwise perform whatever the current selected function is
513 <style type=
"text/css">
516 border: solid
1px #000;
520 <body onLoad=
"init_form();">
522 <center><h2>Digital Logic Simulator
</h2></center>
524 <button id=
"gate_and" onClick='change_selection(
"gate_and");' disabled
>AND
</button>
526 <button id=
"gate_nand" onClick='change_selection(
"gate_nand");'
>NAND
</button>
528 <button id=
"gate_nor" onClick='change_selection(
"gate_nor");'
>NOR
</button>
530 <button id=
"gate_not" onClick='change_selection(
"gate_not");'
>NOT
</button>
532 <button id=
"gate_or" onClick='change_selection(
"gate_or");'
>OR
</button>
534 <button id=
"gate_xor" onClick='change_selection(
"gate_xor");'
>XOR
</button>
536 <button id=
"gate_connect" onClick='change_selection(
"gate_connect");'
>Connect
</button>
538 <button id=
"gate_connect" onClick='input_flip(
2);'
>In Flip
</button>
540 <button id=
"gate_connect" onClick='output_flip(
2);'
>Out Flip
</button>
543 <div id=xycoordinates
> </div>
545 <canvas id=
"stage" width=
"200" height=
"200" onMouseMove=
"cnvs_get_coordinates(event)" onClick=
"cnvs_clicked(event);">
546 Your browser does not support HTML5 Canvas.