Skin:
[NORMAL]
[BLUE] [DOS] [LIGHT]  / コピーするための表示 / 実行
このファイル: /home/web6047/www/js/20210909-logicanalyzer/a - snapshot 20210914.js
1 class LogicAnalyzer {
2 constructor( cc, style, doNotStartFrame ) {
3 this.cc = cc;
4
5 this.style = Object.assign( {
6 //表示スタイル指定
7 titleFontSize : 10, //左端のチャートタイトルのフォントサイズ
8 commentFontSize : 10, //コメントのフォントサイズ
9 cellHeight : 32, //各チャート領域の高さ
10 palseHeight : 8, //パルスの表示高さ
11 horizontalDiv : 8, //TIME/DIV 横方向を1/nの大きさで表示する(圧縮度)
12 horizontalShift : 32, //チャートを左右に動かす
13 //top : 0, //指定すると、CANVASの上からの位置
14 //bottom : 0, //指定すると、CANVASの下からの位置
15 //trigChart : "test", //指定すると、そのチャートの最初の記録を基準に画面描画
16 }, style );
17
18 this.etc = new Object();
19 this.etc.title = "JavaScript LOGIC ANALYZER by web6047";
20 cc.font = this.style.titleFontSize + "px''";
21 this.etc.titleX = cc.canvas.width - cc.measureText( this.etc.title ).width - this.style.titleFontSize;
22
23 this.records = new Object();
24 this.cursorLeftTime = 0;
25
26 this.time = 0;
27 this.maxTime = 100; //画面更新頻度ms CPU使用率を下げたいときに増やす。波形の精度に影響しない。
28
29 this.backTm = 0;
30
31 if( ! doNotStartFrame ) this.frame( 0 );
32 }
33 log( name, hiLow, comment ) {
34 //check. 配列の作成
35 if( ! this.records[ name ] ) this.records[ name ] = new Array();
36 //check. 同じ動きは記録しない。
37 let lastRecord = this.records[ name ][ this.records[ name ].length - 1 ];
38 if( lastRecord && lastRecord[ 1 ] == hiLow ) return;
39
40 let now = Date.now();
41 this.records[ name ].push( [ now, hiLow, comment ] );
42 }
43 frame( tm ) {
44 let diff = tm - this.backTm;
45 this.backTm = tm;
46 this.time += diff;
47 if( this.time >= this.maxTime ) {
48 this.time = 0;
49 this.draw( this.cc );
50 }
51 if( this.autoFlg ) this.trig();
52 requestAnimationFrame( this.frame.bind( this ) );
53 }
54 auto() {
55 this.autoFlg = true;
56 this.style.horizontalShift = this.cc.canvas.width;
57 }
58 stop() {
59 setTimeout( function() {
60 this.trig();
61 this.records = new Object();
62 if( this.style.trigChart )
63 this.cursorLeftTime = this.lines[ this.style.trigChart ][ 0 ][ 0 ];
64 else
65 this.cursorLeftTime = this.lines[ Object.keys( this.lines )[ 0 ] ][ 0 ][ 0 ];
66 //参考:
67 // this.lines[ チャートタイトル ][ 何番目の記録 ][ 0:記録したときの経過時間 ]
68 }.bind( this ), 1000 );
69 }
70 trig() {
71 let now = Date.now();
72 this.lines = new Object();
73 //各チャートについて
74 for( let name in this.records ) {
75 let record = this.records[ name ];
76 let drawPoints = new Array();
77 //2次元配列 [ [ x, y ], ... ]
78 //x 下記yが起こった時間から現在時刻までの経過時間
79 //y 1:信号の立ち上がり、0:立ち下がり
80 //そのチャートの、各記録について
81 for( let j = 0; j < record.length; j++ ) {
82 let sample = record[ j ];
83 let recordTime = sample[ 0 ];
84 let method = sample[ 1 ];
85 let comment = sample[ 2 ];
86
87 let leftTime = now - recordTime;
88
89 //波形にパルスをセット
90 if( method == 1 ) {
91 //立ち上がり
92 drawPoints.push( [ leftTime, 0 ] );
93 drawPoints.push( [ leftTime, 1, comment ] );
94 } else {
95 //立ち下がり
96 //check. 画面左端に来たらパルスを削除予定(null)
97 if( leftTime < 0 ) {
98 record[ j ] = null;
99 record[ j - 1 ] = null;
100 }
101 drawPoints.push( [ leftTime, 1 ] );
102 drawPoints.push( [ leftTime, 0, comment ] );
103 }
104 }//for record[]
105 //check. 削除実行
106 for( let j = record.length - 1; j >= 0; j-- ) {
107 if( record[ j ] === null ) record.splice( j, 1 );
108 }
109 this.lines[ name ] = drawPoints;
110 }//for this.records[]
111 }
112 draw( cc ) {
113 cc.save();
114 cc.lineWidth = 0.5;
115 let height;
116 if( this.lines ) {
117 height = ( Object.keys( this.lines ).length + 1) * this.style.cellHeight;
118 } else {
119 height = this.style.cellHeight;
120 }
121 let top = 0;
122 //check.
123 if( this.style.top != undefined )
124 top = this.style.top;
125 else if( this.style.bottom != undefined )
126 top = cc.canvas.height - this.style.bottom -height;
127 cc.translate( 0, top );
128
129 cc.fillStyle = "black";
130 cc.fillRect( 0, 0, cc.canvas.width, height );
131 cc.strokeStyle = "lightgray";
132 cc.strokeRect( 0, 0, cc.canvas.width, height );
133
134 cc.font = this.style.titleFontSize + "px''";
135 cc.fillStyle = "magenta";
136 cc.fillText( this.etc.title, this.etc.titleX, this.style.titleFontSize );
137
138 //check.
139 if( ! this.lines ) {
140 let sz = 16;
141 cc.font = sz + "px''";
142 cc.fillText( "Trig?", sz, sz );
143 } else {
144
145 let i = 0;
146 for( let name in this.lines ) {
147 let drawPoints = this.lines[ name ];
148 cc.beginPath();
149 let gyBase = ( i + 1 ) * this.style.cellHeight;
150 cc.moveTo( 0, gyBase );
151 for( let drawPoint of drawPoints ) {
152 let leftTime = drawPoint[ 0 ];
153 let hiLow = drawPoint[ 1 ];
154 let comment = drawPoint[ 2 ];
155 let gx = ( leftTime - this.cursorLeftTime ) * -1 / this.style.horizontalDiv;
156 gx += this.style.horizontalShift;
157 let gy = gyBase - hiLow * this.style.palseHeight;
158 cc.lineTo( gx, gy );
159 if( comment != null ) {
160 cc.save();
161 cc.font = this.style.commentFontSize + "px''";
162 gx = gx - this.style.commentFontSize / 2;
163 cc.fillStyle = "cyan";
164 if( hiLow ) {
165 gy = gyBase - ( this.style.palseHeight + 3 );
166 cc.fillText( "↓" + comment, gx, gy );
167 } else {
168 gy = gyBase + ( this.style.palseHeight + 3 );
169 cc.fillText( "↑" + comment, gx, gy );
170 }
171 cc.restore();
172 }
173 }
174 //画面右端まで描画
175 if( drawPoints.length / 2 % 2 == 1 ) {
176 //記録数が奇数なら、記録の最後はハイ
177 cc.lineTo( cc.canvas.width, gyBase - this.style.palseHeight );
178 } else {
179 //記録数が偶数なら、記録の最後はロー
180 cc.lineTo( cc.canvas.width, gyBase );
181 }
182 cc.strokeStyle = "cyan";
183 cc.stroke();
184
185 cc.fillStyle = "yellow";
186 cc.fillText( name + "↓", 4, gyBase - this.style.titleFontSize * 2 );
187
188 i++;
189 }//for
190 }//if
191 cc.restore();
192 }
193 }