タイミングチャート清書サービス のバックアップ差分(No.6)
更新- バックアップ一覧
- 現在との差分 を表示
- ソース を表示
- バックアップ を表示
- ソフトウェア/タイミングチャート清書サービス へ行く。
- 追加された行はこの色です。
- 削除された行はこの色です。
[[公開メモ]] * 設置アドレス [#s578cb5d] SIZE(20){http://dora.bk.tsukuba.ac.jp/~takeuchi/tchart.html} *** スクリーンイメージ [#vb49705b] &ref(screenshot.png,nolink,border,66%); * 概要 [#td75a95f] [[こちらで紹介したタイミングチャート清書スクリプト>ソフトウェア/tchart.rb]] と同等の物を javascript で実装し、オンラインで使えるようにしました。 このようなテキストを入力すると、 aclk ~_~_~_~_~_~_~_~_~_~_ awaddr ==?X=A1==X=A2X=A3==X==?=X=A4X=? awvalid __~~~~~~~~~~____~~__ awready ____[~~~~]__[~~]____[~~]__ wdata ====?X=D1X=D2X=?X=D3X=?X=D4==X=? wvalid ____~~~~__~~__~~~~__ wready ____[~~~~]__[~~]____~~__ wready ____~~~~__~~____~~__ bresp ====00================ bvalid ~~~~~~~~~~~~~~~~~1~~~ bvalid ____~~~~__~~____~~__ bready ~~~~~~~~~~~~~~~~~~1~~ こんなタイミングチャートを生成できます。 こんなタイミングチャートを生成できるサービスです。 &tchart( aclk ~_~_~_~_~_~_~_~_~_~_ awaddr ==?X=A1==X=A2X=A3==X==?=X=A4X=? awvalid __~~~~~~~~~~____~~__ awready ____[~~~~]__[~~]____[~~]__ wdata ====?X=D1X=D2X=?X=D3X=?X=D4==X=? wvalid ____~~~~__~~__~~~~__ wready ____[~~~~]__[~~]____~~__ wready ____~~~~__~~____~~__ bresp ====00================ bvalid ~~~~~~~~~~~~~~~~~1~~~ bvalid ____~~~~__~~____~~__ bready ~~~~~~~~~~~~~~~~~~1~~ ); コードを書けばほぼリアルタイムで清書結果を確認できます ソースコード編集中に、ほぼリアルタイムで清書結果を確認できるので、試行錯誤しているうちに正しく書けると思います。 清書したタイミングチャートは SVG または PNG 形式で保存できます 清書したタイミングチャートは SVG または PNG 形式で保存できます。 * 設置アドレス [#s578cb5d] 入力内容がサーバーに送られることはなく、完全にブラウザ上だけで画像を生成していますので、守秘義務の問題も発生しません。心配であればリンク先の html を PC に保存して、そこから立ち上げても動作します。いくつかの javascript ライブラリへの参照さえ解決すれば、完全にオフラインでも作業が可能です。 こちらです: http://dora.bk.tsukuba.ac.jp/~takeuchi/tchart.html 設置アドレスはこちらです:~ SIZE(20){http://dora.bk.tsukuba.ac.jp/~takeuchi/tchart.html} ~ ~ [[>>>> 記述文法についてはこちらをご覧下さい。>#g7420e8f]] * チャート記述文法 [#ydbb2dea] コメントや質問などがあれば[[このページの一番下に投稿フォームがあります>#m9652e62]]のでご活用下さい。 - [[こちらをご覧下さい。>http://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%2Ftchart.rb#ya5f8236]] ** 不具合 [#a0ceca1d] IE ではリンク先で議論されている問題のため、[Save as PNG] および [Generate Images for Copy] のボタンが正常に働きません。~ https://connect.microsoft.com/IE/feedback/details/809823/draw-svg-image-on-canvas-context 代わりに、SVG 画像上で右クリックから [名前を付けて画像を保存] で形式を PNG にすれば保存できます。 同様に右クリックから [コピー] で画像をクリップボードへ入れられるので、 Word などへ貼り付ける用途ではむしろ IE の方が便利かもしれません。 ** クリップボードへのコピーの仕方 [#m4d46332] セキュリティ上の制限のため、javascript からクリップボードへ 自動的にコピーすることはできないようになっているため、 手動で対応していただく必要があります。 [Generate Images for Copy] ボタンを押すと SVG ソースと PNG 画像が生成されます - SVG ソースをご入り用であれば、SVG ソースにフォーカスが当たっている状況でそのまま Ctrl+V すればコピー可能です - PNG 画像がご入り用であれば、PNG 画像上で右クリックから [画像をコピー] します -- なぜか空の HTML も一緒にコピーされてしまうようで、なおかつこの空の HTML が優先的に貼り付けられるようなので、Word などへ貼り付ける際には [形式を選択して貼り付け]-[ビットマップ(DIB)] などとして下さい -- Office でのショートカットは Alt+E,S です -- 上記の制限のため IE では [Generate Images for Copy] で PNG 画像が生成されません -- 代わりに SVG 画像上の右クリックから [コピー] でコピーできますので、そちらをご利用下さい * 謝辞 [#j084c7a9] 熊谷正朗さんの "Timing chart formatter by kumagai" ~ http://www.mech.tohoku-gakuin.ac.jp/rde/contents/library/tchart/indexframe.html を大いに参考にさせていただきました。 記述文法はほぼ熊谷さんの tchart を踏襲しています。 大変有用なツールをご提供くださったことに感謝いたします。 * 目次 [#ad7e0323] #contents * タイミング記述テキストの文法 [#g7420e8f] ** # から始まる行はコメント行です [#ld750e11] # This line will not appear in the chart clk _~_~_~_~_~ signal ___~~~~___ &tchart( # This line will not appear in the chart clk _~_~_~_~_~ signal ___~~~~___ ); ** @ から始まる行で設定を変更できます [#q06c69eb] 形式は次の通りです。 @[設定値の名称][スペース][設定値] [[設定可能な値としてどんな物があるかについてはこちらです。>#rd2a2e82]] @signal_style stroke-linecap="round" stroke-width="2" stroke="green" fill="none" clk _~_~_~_~_~ signal ___~~~~___ &tchart( @signal_style stroke-linecap="round" stroke-width="2" stroke="green" fill="none" clk _~_~_~_~_~ signal ___~~~~___ ); ** % から始まる行で自由な位置に文字列を追加できます [#z209ee2f] 与えるパラメータは、次の通りです。 %[x座標][スペース][y座標][スペース][文字列] @margin 20 %100 -7 test! clk _~_~_~_~_~ signal ___~~~~___ &tchart( @margin 20 %100 -7 test! clk _~_~_~_~_~ signal ___~~~~___ ); ** 空行があれば1行分だけ空白が空きます [#le587f61] clk1 _~_~_~_~_~ clk2 __~~__~~__ signal ___~~_____ &tchart( clk1 _~_~_~_~_~ clk2 __~~__~~__ signal ___~~_____ ); ** その他の文字から始まる行が信号定義になります [#e6c10712] フォーマットは 信号名 [空白] タイミング定義 の形です。 * タイミング定義の文法と用例 [#qdaa4e35] ** _ と ~ で 0 と 1 を表します。 [#dd9965b7] ** - がハイインピーダンス状態です。 [#x82e48ed] clk _~_~_~_~_~_~_~_~_~ data ___~~~~__~~____~~_ enable ___~~~~~~~~~~_____ output ---~~~~__~~__----- &tchart( clk _~_~_~_~_~_~_~_~_~ data ___~~~~__~~____~~_ enable ___~~~~~~~~~~_____ output ---~~~~__~~__----- ); ** バス信号や不定値を表すのに = を使えます。 [#r60d0319] ** X で値の切り替えを表せます。 [#uad781ca] X は時間が進みます。イメージ的には X= のように働きます。 clk _~_~_~_~_~ data =X=X=X=X=X &tchart( clk _~_~_~_~_~ data =X=X=X=X=X ); ** 信号定義に文字列を書き入れることができます。 [#f601e0b1] 文字列を書いても時間は進みません。 clk _~_~_~_~_~_~_~_~_~ enable ___~~~~~~~~~~_____ output ---=D0=X=D1X=D2X=D3X=D4----- &tchart( clk _~_~_~_~_~_~_~_~_~ enable ___~~~~~~~~~~_____ output ---=D0=X=D1X=D2X=D3X=D4----- ); ** 文字列に特殊文字を含めたい場合には " " でくくります [#wa93120b] ** " を含めたければ "" のように重ねます [#e669d881] スペースも入れられます "=" -======"A = B"- " -======" ""A"" = ""B"" "- A -======A- space -======"A "- &tchart( "=" -======"A = B"- " -======" ""A"" = ""B"" "- A -======A- space -======"A "- ); ** 右寄せ、左寄せ [#d7e5f20d] 文字列は通常センタリングされますが、_<_ あるいは _>_ から始めることで 左寄せ、右寄せにできます left -======"_<_DATA"- middle -======DATA- right -======"_>_DATA"- &tchart( left -======"_<_DATA"- middle -======DATA- right -======"_>_DATA"- ); ** ? を一文字だけ書くと不定値を表すために色が付きます。 [#dc4c5057] clk _~_~_~_~_~_~ data =?==XDATA=====X=?= valid ___~~~~~~___ &tchart( clk _~_~_~_~_~_~ data =?==XDATA=====X=?= valid ___~~~~~~___ ); ** : を入れると空白を入れ、途切れさせることができます。 [#yb67ee5a] clk _~_~_~_:...:~_~_~_~_~ data ___~~~~:...:~~____~~_ &tchart( clk _~_~_~_:...:~_~_~_~_~ data ___~~~~:...:~~____~~_ ); ** 不定値部分を表すのに、/ \ * が使えます。 [#b5b09f01] clk _~_~_~_~_~_~_~ rising ___==/=/=~~~~~ falling ~~~==\=\=_____ transition ___=D0=*=D1*=D2*=D3___ &tchart( clk _~_~_~_~_~_~_~ rising ___==/=/=~~~~~ falling ~~~==\=\=_____ transition ___=D0=*=D1*=D2*=D3___ ); ** | を入れるとグリッド線を引けます。 [#d1263d2a] ** [ ] でくくるとハイライトできます。 [#d41e1c81] clk _~_~_~_~_~_~_~_~_~ data ___~~~~~~~~|____~~_ enable ___[~~~~~~~~~~]_____ output ---~~~~~~~~__----- &tchart( clk _~_~_~_~_~_~_~_~_~ data ___~~~~~~~~|____~~_ enable ___[~~~~~~~~~~]_____ output ---~~~~~~~~__----- ); ** 全ての組み合わせを試してみます [#f93875da] # :-~_=/\X* 0 _~_~_~_~_~_~_[~_~_]~_ 1 :::-:~:_:=:/:\:X:*: 2 -:---~-_-=-/-\-X-*- 3 ~:~-~~~_~=~/~\~X~*~ 4 _:_-_~___=_/_\_X_*_ 5 =:=-=|~=_===/=\=X=*= 6 /:/-/~/_/=///\/X/*/ 7 \:\-\~\_\=\/\\\X\*\ 8 X:X-X~X_X=X/X\XXX*X 9 *:*-*~*_*=*/*\*X*** &tchart( # :-~_=/\X* 0 _~_~_~_~_~_~_[~_~_]~_ 1 :::-:~:_:=:/:\:X:*: 2 -:---~-_-=-/-\-X-*- 3 ~:~-~~~_~=~/~\~X~*~ 4 _:_-_~___=_/_\_X_*_ 5 =:=-=|~=_===/=\=X=*= 6 /:/-/~/_/=///\/X/*/ 7 \:\-\~\_\=\/\\\X\*\ 8 X:X-X~X_X=X/X\XXX*X 9 *:*-*~*_*=*/*\*X*** ); ** 不定値の塗り分けをテスト。 [#h695f4bc] @h_line 30 @h_skip 20 @w_transient 5 @w_caption 60 test =/=?\=\=?/=X=?X=*?=*=X=?-=?= =?X &tchart( @h_line 30 @h_skip 20 @w_transient 5 @w_caption 60 test =/=?\=\=?/=X=?X=*?=*=X=?-=?= =?X ); ** 遷移の傾きをなくすには @w_transient 0 とします [#l5475a84] @w_transient 0 clk _~_~_~_~_~_~_~ data ___|~~~~|_______ &tchart( @w_transient 0 clk _~_~_~_~_~_~_~ data ___|~~~~|_______ ); ** svg の特殊文字も正しくエスケープされます [#b0b8f714] clk _~_~_~_~_~_~_~ data ---|===<D1>=X=<D2>==|--- &tchart( clk _~_~_~_~_~_~_~ data ---|===<D1>=X=<D2>==|--- ); ** 生成された svg には変換元のソースコードが埋め込まれます。 [#c058d952] 下記の CDATA の部分です。ソースコードに CDATA の終了を示す ]]> が現れる場合には、 ]]> にエンコードされます。 LANG:xml <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="240pt" height="60pt" viewBox="-10 -10 220 40" version="1.1"> <![CDATA[ clk _~_~_~_~_~_~_~ data ---|===<D1>=X=<D2>==|--- ]]> <g> <text x="35" y="8.5" text-anchor="end" font-size="10" fill="black" font-family="Helvetica">clk</text> <path stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none" d="M42,10H52L54,0H64L66,10H76L78,0H88L90,10H100L102,0H112L114,10H124L126,0H136L138,10H148L150,0H160L162,10H172L174,0H184L186,10H196L198,0H208" /> <text x="35" y="28.5" text-anchor="end" font-size="10" fill="black" font-family="Helvetica">data</text> <text x="101.0" y="28.5" text-anchor="middle" font-size="10" fill="black" font-family="Helvetica"><D1></text> <text x="149.0" y="28.5" text-anchor="middle" font-size="10" fill="black" font-family="Helvetica"><D2></text><path stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none" d="M42,25H52H54H64H66H76L78,20H88H90H100H102H112H114H124L126,30H136H138H148H150H160H162H172L174,25H184H186H196H198H208M76,25L78,30H88H90H100H102H112H114H124L126,20H136H138H148H150H160H162H172L174,25" /> <path d="M77,-10V40" stroke-linecap="round" stroke-width="0.6" stroke="red" fill="none" /> <path d="M173,-10V40" stroke-linecap="round" stroke-width="0.6" stroke="red" fill="none" /> </g> </svg> * 設定値 [#rd2a2e82] 括弧内が何も指定しないときの既定値です。 ** scale (= 1.0) [#k3b33db2] 図のサイズを拡大・縮小します。 複数指定した場合、最後の値だけが意味を持ちます。 @scale 1.4 clk _~_~_~_~_~_~_~_~ data ==?=X=D0X=D1X=D2X=D3X=?=== &tchart( @scale 1.4 clk _~_~_~_~_~_~_~_~ data ==?=X=D0X=D1X=D2X=D3X=?=== ); @scale 0.7 clk _~_~_~_~_~_~_~_~ data ==?=X=D0X=D1X=D2X=D3X=?=== &tchart( @scale 0.7 clk _~_~_~_~_~_~_~_~ data ==?=X=D0X=D1X=D2X=D3X=?=== ); ** margin (= 10) [#b7fe0b8a] チャートの周囲の余白の幅を指定します。 ** w_caption (= 40) [#ge8b8cec] 信号名称部分の幅を指定します。 long_signal_name _~~~~__~~~~______~~___ &tchart( long_signal_name _~~~~__~~~~______~~___ ); @w_caption 100 long_signal_name _~~~~__~~~~______~~___ &tchart( @w_caption 100 long_signal_name _~~~~__~~~~______~~___ ); ** w_hold (= 10) [#le7dd0fb] 信号の単位時間から遷移時間を引いた部分の幅を指定します。 途中で変更すれば異なるクロックドメインを表したりできます。 @w_hold 10 clock _~_~_~_~_~_~_~_~_~_~_~ @w_hold 22 clock ~_~_~_~_~_~ @w_hold 16 clock _~_~_~_~_~_~_~_ &tchart( @w_hold 10 clock _~_~_~_~_~_~_~_~_~_~_~ @w_hold 22 clock ~_~_~_~_~_~ @w_hold 16 clock _~_~_~_~_~_~_~_ ); ** w_transient (= 2) [#n3c4fb61] 信号の遷移時間の幅を指定します。 ゼロを指定すると、遷移のエッジは垂直になります。 @w_transient 0 clock _~_~_~_~_~_~_~_~_~_~_~ @w_transient 2 clock _~_~_~_~_~_~_~_~_~_~_~ @w_transient 4 clock _~_~_~_~_~_~_~_~_~_~_~ &tchart( @w_transient 0 clock _~_~_~_~_~_~_~_~_~_~_~ @w_transient 2 clock _~_~_~_~_~_~_~_~_~_~_~ @w_transient 4 clock _~_~_~_~_~_~_~_~_~_~_~ ); ** h_line (= 10) [#p7e6f34c] 1行の高さを指定します。信号名のフォントサイズもこの値に等しくなります。 @h_line 10 clock _~_~_~_~_~_~_~_~_~_~_~ @h_line 16 clock _~_~_~_~_~_~_~_~_~_~_~ &tchart( @h_line 10 clock _~_~_~_~_~_~_~_~_~_~_~ @h_line 16 clock _~_~_~_~_~_~_~_~_~_~_~ ); ** h_space (= 10) [#teb7c9f7] 行間のスペースを指定します。 clock _~_~_~_~_~_~_~_~_~_~_~ data1 _~~~~__~~~~______~~___ @h_space 20 data2 _~~~~__~~~~______~~___ data3 _~~~~__~~~~______~~___ &tchart( clock _~_~_~_~_~_~_~_~_~_~_~ data1 _~~~~__~~~~______~~___ @h_space 20 data2 _~~~~__~~~~______~~___ data3 _~~~~__~~~~______~~___ ); ** signal_style [#v5ac38b6] 信号線のスタイルを svg の path の属性値の形で与えます。 規定値は次の通りです。 stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none" data1 _~~~~__~~~~______~~___ @signal_style stroke-linecap="round" stroke-width="2" stroke="green" fill="none" data2 _~~~~__~~~~______~~___ &tchart( data1 _~~~~__~~~~______~~___ @signal_style stroke-linecap="round" stroke-width="2" stroke="green" fill="none" data2 _~~~~__~~~~______~~___ ); ** grid_style [#ra37b0f5] グリッド線のスタイルを svg の path の属性値の形で与えます。 規定値は次の通りです。 stroke-linecap="round" stroke-width="0.6" stroke="red" fill="none" @grid_style stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none" data1 _~~~~__|~~~~______~~___ @grid_style stroke-linecap="round" stroke-width="0.6" stroke="#0CC" fill="none" data2 _~~~~__~~~~______|~~___ &tchart( @grid_style stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none" data1 _~~~~__|~~~~______~~___ @grid_style stroke-linecap="round" stroke-width="0.6" stroke="#0CC" fill="none" data2 _~~~~__~~~~______|~~___ ); ** highlight_style [#d1714e07] ハイライト部分のスタイルを指定します。 規定値は次の通りです。 stroke="none" fill="#ff8" data1 _~~~~__[~~~~]______~~___ @highlight_style stroke="green" fill="#8f8" stroke-width="1" data2 _~~~~__~~~~______[~~]___ &tchart( data1 _~~~~__[~~~~]______~~___ @highlight_style stroke="green" fill="#8f8" stroke-width="1" data2 _~~~~__~~~~______[~~]___ ); ** notcare_style [#r0fb27ce] 不定値部分のスタイルを指定します。 fill="#ccc" clk _~_~_~_~_~_~_~_~_~_~_~ data1 ====?=*========*=?====== @notcare_style stroke="none" fill="#8f8" data1 ====?=*========*=?====== &tchart( clk _~_~_~_~_~_~_~_~_~_~_~ data1 ====?=*========*=?====== @notcare_style stroke="none" fill="#8f8" data1 ====?=*========*=?====== ); ** caption_font [#z0c3eaff] 信号名のフォントを指定します。 規定値は次の通りです。 fill="black" font-family="Helvetica" clk _~_~_~_~_~_~_~_~_~_~_~ @caption_font fill="red" font-family="Helvetica" @signal_style stroke="red" fill="none" data _~~~~______~~____~~~~~ &tchart( clk _~_~_~_~_~_~_~_~_~_~_~ @caption_font fill="red" font-family="Helvetica" @signal_style stroke="red" fill="none" data _~~~~______~~____~~~~~ ); ** signal_font [#sfe73988] 信号部分で用いるフォントを指定します。 規定値は次の通りです。 fill="black" font-family="Helvetica" clk _~_~_~_~_~_~_~_~ @signal_font fill="red" font-family="Helvetica" data ==?=X=D0X=D1X=D2X=D3X=?=== &tchart( clk _~_~_~_~_~_~_~_~ @signal_font fill="red" font-family="Helvetica" data ==?=X=D0X=D1X=D2X=D3X=?=== ); ** rotate (= 0) [#s041342a] 未実装 * ソースコード [#sc7a574d] こちらでも参照可能です:http://jsbin.com/qumezaxofi/edit?html,css,js,output こちらでも参照可能です:http://jsbin.com/lezujowaba/1/edit?html,css,js,output LANG:html(linenumber) <!DOCTYPE html> <html> <head> <script src="https://code.jquery.com/jquery-2.1.4.js"></script> <script src="https://rawgit.com/eligrey/FileSaver.js/master/FileSaver.js"></script> <script src="https://rawgit.com/eligrey/canvas-toBlob.js/master/canvas-toBlob.js"></script> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Timing Chart Formatter</title> </head> <body> <h1>Timing Chart Formatter</h1> <textarea id="source" cols="60" rows="10" spellcheck="false"> clock _~_~_~_~_~_~_~_~_~_~_ data =?====X=DATA========X=?==== valid _____~~~~~~~~~~______ ready _____________[~~]______ </textarea> <div id="result"></div> <input type="button" value="Download as SVG" id="as_svg" /> <input type="button" value="Download as PNG" id="as_png" /> Background: <input id="background" value="white" style="width:60px" /> </div> </body> </html> LANG:scss(linenumber) @import "compass"; textarea { font-size: 15px; $line-height: 18px; line-height: $line-height; padding: 0px 10px; @include background-image( linear-gradient(left, white 5px, transparent 5px), linear-gradient(right, white 5px, transparent 5px), linear-gradient(white $line-height - 1px, #ddd $line-height - 1px, #ddd $line-height, white $line-height) ); background-size: 100% 100%, 100% 100%, 100% $line-height; } LANG:coffeescript(linenumber) class SvgPath constructor: (style)-> @segments = [] @style = style draw: (x1, y1, x2, y2)-> @segments.push([x1,y1,x2,y2]) svg: -> for s in @segments s[4]= 0 s[5]= null for s1 in @segments for s2 in @segments if s1[2]==s2[0] and s1[3]==s2[1] s1[4] += 1 s2[4] += 1 for s1 in @segments for s2 in @segments continue if s2[4]<2 or s1[2]!=s2[0] or s1[3]!=s2[1] s1[5]= s2 s2[4]= -1 break continue if s1[5] for s2 in @segments continue if s2[4]!=1 or s1[2]!=s2[0] or s1[3]!=s2[1] s1[5]= s2 s2[4]= -1 break path = [] for s1 in @segments continue if s1[4]<0 s = s1 cx = s[0] cy = s[1] path.push "M#{cx},#{cy}" while s if cx == s[2] && cy == s[3] else if cx == s[2] if path[path.length-1][0]=='V' path[path.length-1]= "V#{s[3]}" else path.push "V#{s[3]}" else if cy == s[3] if path[path.length-1][0]=='H' path[path.length-1]= "H#{s[2]}" else path.push "H#{s[2]}" else path.push "L#{s[2]},#{s[3]}" cx = s[2] cy = s[3] s = s[5] """<path #{@style} d="#{path.join('')}" />\n""" class TimeLine # : - ~ _ = @transitions = [ ' ', # : ' - 1 4 14', # - ' 2 ~ / ~/', # ~ ' 3 ` _ _`', # _ ' 23`~/_= ', # = ' 23`~/_=/', # / ' 23`~/_=`', # \ ' 23`~/_X ', # X ' 23`~/_=X', # * ] @transitionLines = ' ' : [] '~' : [[1,1]] '_' : [[0,0]] '=' : [[1,1],[0,0]] 'X' : [[1,0],[0,1]] '`' : [[1,0]] '/' : [[0,1]] '1' : [[1,0.5]] '2' : [[0.5,1]] '3' : [[0.5,0]] '4' : [[0,0.5]] '-' : [[0.5,0.5]] # : - ~ _ = @stateLines = [[],[0.5],[1],[0],[0,1]] # @codes = ':-~_=/\\X*' constructor: (config, y)-> @config = config @x = config.w_caption @y = y @path = new SvgPath(config.signal_style) @current = 0 @crosses = [] @strings = [] @grids = [] @highlights = [] ys: (s)-> @y + (1-s) * @config.h_line y0: -> @y + @config.h_line y1: -> @y yz: -> @y + @config.h_line/2.0 xh: -> @x + @config.w_transient/2.0 xt: -> @x + @config.w_transient xr: -> @x + @config.w_transient + @config.w_hold parse: (line)-> while line != '' if maches = /^\s+/.exec(line) ; else if maches = /^\|/.exec(line) @grids.push [@xh(), @config.grid_style] else if maches = /^\[/.exec(line) if @highlights.length==0 or Array.isArray(@highlights[@highlights.length-1]) @highlights.push @xh() else if maches = /^\]/.exec(line) if @highlights.length>0 and not Array.isArray(@highlights[@highlights.length-1]) @highlights[@highlights.length-1] = [@highlights[@highlights.length-1], @xh(), @config.highlight_style] else if matches = /^([:\-~_=\/\\X*])/.exec(line) @addState(matches[1]) else if matches = /"(([^"]|"")+)"/.exec(line) @addString(matches[1]) else if matches = /^"(([^"]|"")*)"/.exec(line) @addString(matches[1].replace(/""/g, '"').replace(/[ ]/g, ' ')) else if matches = /([^:\-~_=\/\\X*\|\]\[]+)/.exec(line) @addString(matches[1]) line = line.substr(matches[0].length, line.length-matches[0].length) @processStrings() + @path.svg() addState: (c)-> s = TimeLine.codes.indexOf(c) crosses = @drawTransition(s) s = 4 if s > 4 @drawState(s) @crosses.push([@x, crosses]) if crosses!='' if (@current == 0 and s != 0) or (@current != 0 and s == 0) if (@current == 0 and s != 0) or (@current != 0 and s == 0) or (@crosses.length==0 and s == 0) @crosses.push([@x, '|']) @current = s @x = @xr() addString: (s)-> @strings.push [@crosses.length, s.replace(/^\s+|\s+$/g, '')] drawTransition: (s)-> crosses = '' transitions = TimeLine.transitions[s].substr(2*@current,2) for i in [0..transitions.length-1] crosses += @drawTransitionSub(transitions[i]) crosses drawTransitionSub: (c)-> crosses = '' for line in TimeLine.transitionLines[c] @path.draw(@x, @ys(line[0]), @xt(), @ys(line[1])) crosses += c if line[0] != line[1] crosses drawState: (s)-> for line in TimeLine.stateLines[s] @path.draw(@xt(), @ys(line), @xr(), @ys(line)) processStrings: -> svg = [] @crosses.push [@x,'|'] for string in @strings y0 = @ys(0) y1 = @ys(1) yz = @ys(0.5) x1 = @crosses[string[0]-1][0] x1t = x1 + @config.w_transient x1h = x1 + @config.w_transient/2.0 x1r = x1t + @config.w_hold x2 = @crosses[string[0] ][0] x2t = x2 + @config.w_transient x2h = x2 + @config.w_transient/2.0 x2r = x2t + @config.w_hold if string[1]=='?' path= ["M#{x1t},#{y1}H#{x2}"] path.push switch @crosses[string[0]][1] when '|' then "" when 'XX' then "L#{x2h},#{yz}" when '/' then "H#{x2t}" when '`' then "L#{x2t},#{y0}" when '23' then "H#{x2t}L#{x2},#{yz}L#{x2t},#{y0}" when '14' then "L#{x2t},#{yz}" when '1' then "L#{x2t},#{yz}V#{y0}" when '2' then "H#{x2t}L#{x2},#{yz}" when '3' then "V#{yz}L#{x2t},#{y0}" when '4' then "H#{x2t}V#{yz}" path.push "L#{x2},#{y0}H#{x1t}" path.push switch @crosses[string[0]-1][1] when '|' then "" when 'XX' then "L#{x1h},#{yz}" when '/' then "H#{x1}" when '`' then "L#{x1},#{y1}" when '23' then "L#{x1},#{yz}" when '14' then "H#{x1}L#{x1t},#{yz}L#{x1},#{y1}" when '1' then "V#{yz}L#{x1},#{y1}" when '2' then "H#{x1}V#{yz}" when '3' then "L#{x1},#{yz}V{y1}" when '4' then "H#{x1}L#{xt},#{yz}" path.push "Z" svg.push """\n<path stroke="none" d="#{path.join('')}" #{@config.notcare_style}/>""" sanitized = string[1].replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') svg.push """<text x="#{(x1h + x2h)/2.0}" y="#{@ys(0)-1.5}" text-anchor="middle" """ + if string[1].substr(0,3)=='_<_' x = x1t anchor = 'start' sanitized = sanitized.substring(6) else if string[1].substr(0,3)=='_>_' x = x2 anchor = 'end' sanitized = sanitized.substring(6) else x = (x1h+x2h)/2.0 anchor = 'middle' svg.push """<text x="#{x}" y="#{@ys(0)-1.5}" text-anchor="#{anchor}" """ + """font-size="#{@config.h_line}" #{@config.signal_font}>#{sanitized}</text>\n""" svg.join("") class TimingChart @config: scale: 1.0 margin: 10 w_caption: 40 w_hold: 10 w_transient: 2 h_line: 10 h_space: 10 signal_style: 'stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none"' grid_style: 'stroke-linecap="round" stroke-width="0.6" stroke="red" fill="none"' highlight_style:'stroke="none" fill="#ff8"' notcare_style: 'fill="#ccc"' rotate: 0 caption_font: 'fill="black" font-family="Helvetica"' signal_font: 'fill="black" font-family="Helvetica"' constructor: (config= {})-> @config= {} @setConfig(TimingChart.config) @setConfig(config) setConfig: (config)-> @config[k]= v for own k,v of config parse: (source)-> @svg= [] @grids= [] @highlights= [] @y= -1 @x_max= @config.w_caption source= source.replace(/^\n+/, '') source= source.replace(/\n+$/, '') for line in source.split("\n") @parseLine(line) @processGrids() @processHighlights() @formatSVG(source) formatSVG: (source)-> m= @config.margin w= (@x_max + 2 * m) * @config.scale * 1.3 h= (@y + 2 * m) * @config.scale * 1.3 @width = w @height = h """ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="#{w}px" height="#{h}px" viewBox="#{-m} #{-m} #{@x_max+2*m} #{@y+2*m}" version="1.1"> <![CDATA[ #{source.replace(/\]\]\>/g, ']]>')} ]]> <g> #{@svg.join("\n")} </g> </svg> """ parseLine: (line)-> return if line[0] == '#' #### comment if line[0]=='@' #### configuration if !(matches = /^@([^\s]+)[\s]+([^\s].*)$/.exec(line)) throw new SyntaxError("Illegal Line: #{line}") if $.isNumeric(@config[matches[1]]) @config[matches[1]] = Number(matches[2]) else @config[matches[1]] = matches[2] return if line[0] == '%' #### free string if !(matches = /^%(-?[\d\.]+)\s+(-?[\d\.]+)\s+?(.*)$/.exec(line)) throw new SyntaxError("Illegal Line: #{line}") @svg.push("""<text x="#{matches[1]}" y="#{matches[2]}" text-anchor="middle" """ + """font-size="#{@config.h_line}" #{@config.signal_font}>#{matches[3]}</text>""") return if @y<0 @y= 0 else @y+= @config.h_space line= line.replace(/\s*$/, '') return if line=='' #### empty line if !(matches = /^([^\s]+)[\s]+([^\s].*)$/.exec(line)) throw new SyntaxError("Illegal Line: #{line}") @formatCaption(matches[1]) @formatTimeline(matches[2]) @y+= @config.h_line formatCaption: (caption)-> sanitized = caption.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') @svg.push( """<text x="#{@config.w_caption-5}" y="#{@y+@config.h_line-1.5}" text-anchor="end" """+ """font-size="#{@config.h_line}" #{@config.caption_font}>#{sanitized}</text>""" ) formatTimeline: (line)-> tline= new TimeLine(@config, @y) @svg.push tline.parse(line) @x_max= tline.x if tline.x > @x_max for g in tline.grids @grids.push g for h in tline.highlights @highlights.push h processGrids: -> t = -@config.margin/2.0 b = @y+@config.margin/2.0 for g in @grids @svg.push """<path d="M#{g[0]},#{t}V#{b}" #{g[1]} />""" processHighlights: -> t = -@config.margin/2.0 b = @y+@config.margin/2.0 for h in @highlights if Array.isArray(h) @svg.unshift """<path d="M#{h[0]},#{t}V#{b}H#{h[1]}V#{t}Z" #{h[2]} />""" download= (dataUrl, filename)-> form = $('<form>') form.action = dataUrl form.target = '_blank' form.submit() lastSource = '' update = -> source = $('#source').val() return if lastSource==source lastSource = source tchart= new TimingChart() svg= tchart.parse(source) $('#result').html(svg) $ -> $('#as_svg').on 'click', -> update() blob = new Blob([$('#result').html()], {type: "image/svg+xml"}); saveAs(blob, 'timing-chart.svg') $('#as_png').on 'click', -> source = $('#source').val() tchart= new TimingChart() svg= tchart.parse(source) canvas = document.createElement('canvas') canvas.width = tchart.width canvas.height = tchart.height # http://nmi.jp/archives/223 img = new Image() img.onload = -> ctx = canvas.getContext("2d") ctx.fillStyle = $('#background').val() ctx.fillRect(0, 0, canvas.width, canvas.height) ctx.drawImage(img, 0, 0, canvas.width, canvas.height) url = canvas.toDataURL('image/png') link = document.createElement('a') link.href = url link.download = 'timing-chart.png' link.click() img.src = "data:image/svg+xml;base64," + btoa(svg) setInterval(update, 100) * コメント・質問 [#m9652e62] #article_kcaptcha
Counter: 60565 (from 2010/06/03),
today: 2,
yesterday: 0