]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
driver40-ja.html:
authorTakao Abe <abe@ntp.org>
Tue, 28 Apr 2015 11:47:00 +0000 (11:47 +0000)
committerTakao Abe <abe@ntp.org>
Tue, 28 Apr 2015 11:47:00 +0000 (11:47 +0000)
  new file
driver40.html, refclock_jjy.c:
  [BUG 2806] refclock_jjy.c supports the Tel-JJY

bk: 553f7334VpHWbjP-f5k8Fax3LHnvaw

html/drivers/driver40-ja.html [new file with mode: 0644]
html/drivers/driver40.html
ntpd/refclock_jjy.c

diff --git a/html/drivers/driver40-ja.html b/html/drivers/driver40-ja.html
new file mode 100644 (file)
index 0000000..3b5c58c
--- /dev/null
@@ -0,0 +1,481 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html lang="ja">
+
+       <head>
+               <meta http-equiv="content-type" content="text/html;charset=utf-8">
+               <meta name="generator" content="HTML Tidy, see www.w3.org">
+               <meta http-equiv="Content-Script-Type" content="text/javascript">
+               <title>JJY Receivers</title>
+               <link rev="made" href="http://www.bea.hi-ho.ne.jp/abetakao/">
+               <link rel="start" href="http://www.eecis.udel.edu/~mills/ntp/html/refclock.html">
+               <link href="scripts/style.css" type="text/css" rel="stylesheet">
+       </head>
+
+       <body>
+               <h3>JJY Receivers</h3>
+<p>Last update:
+  <!-- #BeginDate format:En2m -->11-Apr-2015  00:00<!-- #EndDate -->
+  UTC &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="driver40.html">ENGLISH(英語)</a> &nbsp; <a href="driver40-ja.html">JAPANESE(日本語)</a></p>
+               <hr>
+               <h4>Synopsis</h4>
+               Address: 127.127.40.<em>u</em><br>
+               Reference ID: <code>JJY</code><br>
+               Driver ID: <code>JJY</code><br>
+               Serial Port: <code>/dev/jjy<em>u</em></code>; それぞれのJJY受信機、GPS時計、テレフォンJJYを参照して下さい。
+               <h4>Description</h4>
+               <p>このドライバーは、以下の、日本で販売されている JJY受信機、GPS時計と、電話回線による時刻配信サービスをサポートしています。<br>
+               <a href="#mode-1">トライステート &nbsp; TS-JJY01, TS-JJY02</a><br>
+               <a href="#mode-2">シーデックス &nbsp; JST2000</a><br>
+               <a href="#mode-3">エコー計測器 &nbsp; LT-2000</a><br>
+               <a href="#mode-4">シチズンTIC &nbsp; JJY-200</a><br>
+               <a href="#mode-5">トライステート &nbsp; TS-GPSclock-01</a><br>
+               <a href="#mode-100">テレフォンJJY</a></p>
+               <ul>
+
+                       <li>
+                               <p><a name="mode-1">トライステート &nbsp; TS-JJY01, TS-JJY02</a> &nbsp; <a href="http://www.tristate.ne.jp/">http://www.tristate.ne.jp/</a> (日本語)</p><br>
+                               <dl>
+                                       <dt>NTPの設定 ( ntp.conf )</dt>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 1</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1 &nbsp; time1 0.NNN &nbsp; flag1 0|1</dt>
+                                                       <dd>
+                                                               <p>Time1 は、受信機からの時刻に加算する調整時間を、固定小数点形式の秒で設定します。<br>
+                                                               この受信機には、数10ミリ秒 ( 0.0NN秒 ) から百数10ミリ秒 ( 0.1NN秒 ) の調整時間を設定すると良いでしょう。</p>
+                                                               <p>Flag1 は、時刻同期には無関係です。Flag1 を 1 に設定すると、状態を問い合わせるコマンドを DATE コマンドと STIM コマンドの前に発行して、応答を clockstats ファイルに記録します。</p>
+                                                               <table border="1" summary="fudge flag1">
+                                                                       <tr><td>0 (Default)</td><td>DCST と STUS コマンドは、発行しません。</td></tr>
+                                                                       <tr><td>1</td><td>DCST と STUS コマンドを、発行します。</td></tr>
+                                                               </table>
+                                                       </dd>
+                                               </dl>
+                                               <br>
+                                       </dd>
+                                       <dt>インターフェース</dt>
+                                       <dd>
+                                               <p>RS-232C, 9600 BPS, 8ビット, パリティなし, 1ストップ・ビット</p>
+                                               <br>
+                                       </dd>
+                                       <dt>日時データの形式</dt>
+                                       <dd><br>
+                                               <table summary="CommandAndReply">
+                                                       <tr>
+                                                               <td>コマンド</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>応答</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>dcst{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>valid{CR}{LF} | invalid{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>stus{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>adjusted{CR}{LF} | unadjusted{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>time{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HH:MM:SS{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>date{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>YYYY/MM/DD WWW{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>stim{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HH:MM:SS{CR}{LF}</code></td>
+                                                       </tr>
+                                               </table>
+                                               <p>日付と時刻は、別々に問い合わせます。日付が深夜0時の前か後かの不確定をチェックするため、日付の問い合わせの前後に時刻を問い合わせています。</p><br>
+                                       </dd>
+                               </dl>
+                       </li>
+
+                       <li>
+                               <p><a name="mode-2">シーデックス &nbsp; JST2000</a> &nbsp; <a href="http://www.c-dex.co.jp/">http://www.c-dex.co.jp/</a> (日本語)</p><br>
+                               <dl>
+                                       <dt>NTPの設定 ( ntp.conf )</dt>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 2</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1</dt>
+                                               </dl>
+                                               <br>
+                                       </dd>
+                                       <dt>インターフェース</dt>
+                                       <dd>
+                                               <p>RS-232C, 9600 BPS, 8ビット, パリティなし, 1ストップ・ビット</p>
+                                               <br>
+                                       </dd>
+                                       <dt>日時データの形式</dt>
+                                       <dd><br>
+                                               <table summary="CommandAndReply">
+                                                       <tr>
+                                                               <td>コマンド</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>応答</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>{ENQ}1J{ETX}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>{STX}JYYMMDD HHMMSSS{ETX}</code></td>
+                                                       </tr>
+                                               </table>
+                                               <br>
+                                       </dd>
+                               </dl>
+                       </li>
+
+                       <li>
+                               <p><a name="mode-3">エコー計測器 &nbsp; LT-2000</a> &nbsp; <a href="http://www.clock.co.jp/">http://www.clock.co.jp/</a> (日本語)</p><br>
+                               <dl>
+                                       <dt>NTPの設定 ( ntp.conf )</dt>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 3</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1</dt>
+                                               </dl>
+                                               <br>
+                                       </dd>
+                                       <dt>Interface</dt>
+                                       <dd>
+                                               <p>RS-232C, 9600 BPS, 8ビット, パリティなし, 1ストップ・ビット</p>
+                                               <br>
+                                       </dd>
+                                       <dt>Time code format</dt>
+                                       <dd><br>
+                                               <table summary="CommandAndReply">
+                                                       <tr>
+                                                               <td>コマンド</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>応答</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>C</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>( Mode 2 : Continuous )</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>( Every second before 0.5 second )</td>
+                                                               <td></td>
+                                                               <td><code>YYMMDDWHHMMSS{ST1}{ST2}{ST3}{ST4}{CR}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>#</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>( Mode 1 : Request&amp;Send )</td>
+                                                       </tr>
+                                               </table>
+                                               <br>
+                                       </dd>
+                               </dl>
+                       </li>
+
+                       <li>
+                               <p><a name="mode-4">シチズンTIC &nbsp; JJY-200</a> &nbsp; <a href="http://www.tic-citizen.co.jp/">http://www.tic-citizen.co.jp/</a> (日本語)</p><br>
+                               <dl>
+                                       <dt>NTPの設定 ( ntp.conf )</dt>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 4</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1</dt>
+                                               </dl>
+                                               <br>
+                                       </dd>
+                                       <dt>インターフェース</dt>
+                                       <dd>
+                                               <p>RS-232C, 4800 BPS, 8ビット, パリティなし, 1ストップ・ビット</p>
+                                               <br>
+                                       </dd>
+                                       <dt>日時データの形式</dt>
+                                       <dd><br>
+                                               <table summary="CommandAndReply">
+                                                       <tr>
+                                                               <td>コマンド</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>応答</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>( Every second )</td>
+                                                               <td></td>
+                                                               <td><code>'XX YY/MM/DD W HH:MM:SS{CR}</code></td>
+                                                       </tr>
+                                               </table>
+                                               <br>
+                                       </dd>
+                               </dl>
+                       </li>
+
+                       <li>
+                               <p><a name="mode-5">トライステート &nbsp; TS-GPSclock-01</a> &nbsp; <a href="http://www.tristate.ne.jp/">http://www.tristate.ne.jp/</a> (日本語)</p>
+                               <p>このドライバーは、JJY受信機ではないGPS時計のトライステート TS-GPSclock-01 のコマンド・レスポンス・モードをサポートします。<br>
+                               TS-GPSclock-01 は、オンボードのスイッチとメニューでコマンド・レスポンス・モードとタイム・ゾーンをJST(日本標準時)に設定しなければなりまん。<br>
+                               この Type 40 のドライバーの他, TS-GPSclock-01 のNMEAモードは、<a href="driver20.html">一般 NMEA GPS ドライバー ( Type 20 )</a> でも利用することができます。</p>
+                               <dl>
+                                       <dt>NTPの設定 ( ntp.conf )</dt>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 5</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1 &nbsp; time1 0.NNN &nbsp; flag1 0|1</dt>
+                                                       <dd>
+                                                               <p>Time1 は、受信機からの時刻に加算する調整時間を、固定小数点形式の秒で設定します</p>
+                                                               <p>Flag1 は、時刻同期には無関係です。Flag1 を 1 に設定すると、状態を問い合わせるコマンドを DATE コマンドと STIM コマンドの前に発行して、応答を clockstats ファイルに記録します。</p>
+                                                               <table border="1" summary="fudge flag1">
+                                                                       <tr><td>0 (Default)</td><td>STUS コマンドは、発行しません。</td></tr>
+                                                                       <tr><td>1</td><td>STUS コマンドを、発行します。</td></tr>
+                                                               </table>
+                                                       </dd>
+                                               </dl>
+                                               <br>
+                                       </dd>
+                                       <dt>インターフェース</dt>
+                                       <dd>
+                                               <p>USB ( /dev/ttyACM<em>0</em> )</p>
+                                               <br>
+                                       </dd>
+                                       <dt>日時データの形式</dt>
+                                       <dd><br>
+                                               <table summary="CommandAndReply">
+                                                       <tr>
+                                                               <td>コマンド</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>応答</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>stus{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>*R{CR}{LF} | *G{CR}{LF} | *U{CR}{LF} | +U{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>time{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HH:MM:SS{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>date{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>YYYY/MM/DD{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>time{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HH:MM:SS{CR}{LF}</code></td>
+                                                       </tr>
+                                               </table>
+                                               <p>日付と時刻は、別々に問い合わせます。日付が深夜0時の前か後かの不確定をチェックするため、日付の問い合わせの前後に時刻を問い合わせています。</p><br>
+                                       </dd>
+                               </dl>
+                       </li>
+
+                       <li>
+                               <p><a name="mode-100">テレフォンJJY</a> &nbsp; <a href="http://jjy.nict.go.jp/">http://jjy.nict.go.jp/</a> (英語と日本語)</p>
+                               <p>テレフォンJJYは、電話回線による時刻配信サービスです。<br>
+                               このサービスは、国立研究開発法人 情報通信研究機構が提供しています。</p>
+                               <p>注意: このモード(テレフォンJJY)は、refclock_acts ( Type 18 ) のドライバーと同時に利用することはできません。
+                               設定ファイルの phone は、server と関係付けられていないため、ドライバーの refclock_acts ( type 18 ) も、この refclock_jjy ( type 40, mode 100 to 180 ) のいずれも、
+                               複数の phone のうち、どれが自分に関係するものか識別できないからです。</p>
+                               <dl>
+                                       <dt>NTPの設定 ( ntp.conf )</dt>
+                                       <dd>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode (100, 101 to 180) &nbsp; minpoll N</dt>
+                                                       <dd>
+                                                       <p>モード 100 を設定した場合、このドライバーは、遅延を計測するためのループバック・コマンドは発行せず、電話回線とシステムの処理による遅延は調整しません。<br>
+                                                       モード 101 から 180 を設定した場合、このドライバーは、ループバック・コマンドを発行して、テレフォンJJYのループバック回路を通して電話回線とシステムの処理による遅延を計測します。<br>
+                                                       テレフォンJJYのループバック回路を経由した往復の時間は、5回、計測されます。
+                                                       それぞれの遅延時間のうち、700ミリ秒を超えたものは、平均遅延時間の計算より除外されます。
+                                                       また、700ミリ秒以下の有効な遅延時間が、3回以上の場合は、そのうち、最大の遅延時間は、平均遅延時間の計算より除外され、
+                                                       4回以上の場合は、そのうち、最小の遅延時間は、平均遅延時間の計算より除外されます。
+                                                       調整時間は、往復時間 × ( モード番号 - 100 ) % で計算し、同期する時刻に加算されます。<br>
+                                                       モード 101 から 180 を設定して自動遅延補正を選択するなら、モード 145 から 165 が良いでしょう。</p>
+                                                       <p>デフォルトの日時問い合わせ処理間隔 6 ( 64 秒 ) は、このモードには、短すぎます。 "minpoll" は、8 ( 256 秒, 約 4 分 ) 以上を設定して下さい。<br>
+                                                       日時問い合わせ処理間隔は、秒数を 2 のべき乗で指定します。 minpoll の値が、12 なら 4096 秒(約1時間)、14 なら 16384 秒(約4.5時間)、16 なら 65536 秒(約18時間)となります。</p><br>
+                                                       </dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1 &nbsp; flag1 0|1 &nbsp; flag2 0|1 &nbsp; flag3 0|1 &nbsp; flag4 0|1</dt>
+                                                       <dd>
+                                                               <p>Time1 は、受信機からの時刻に加算する調整時間を、固定小数点形式の秒で設定します。<br>
+                                                               mode 100 の場合は、time1 で調整する時間を設定したほうが良いでしょう。<br>
+                                                               mode 101 から 108 の場合は、このドライバーが計測したループバックの遅延時間の一定の割合を同期時刻に加算しますので、time1 は設定しないほうが良いでしょう。</p>
+                                                               <div style="text-align:left;">Flag1 は、タッチ・トーンかダイヤル・パルスかを指定します。</div>
+                                                               <table border="1" summary="fudge flag1">
+                                                                       <tr><td>0 (Default)</td><td>タッチ・トーン</td><td>ATDWTnn...nn</td></tr>
+                                                                       <tr><td>1</td><td>ダイヤル・パルス</td><td>ATDWPnn...nn</td></tr>
+                                                               </table>
+                                                               <br>
+                                                               <div style="text-align:left;">Flag2 は、エラー訂正プロトコルを指定します。</div>
+                                                               <table border="1" summary="fudge flag2">
+                                                                       <tr><td>0 (Default)</td><td>ノーマル(エラー訂正なし)</td><td>AT\N0</td></tr>
+                                                                       <tr><td>1</td><td>V42, MNP, ノーマルの自動選択</td><td>AT\N3</td></tr>
+                                                               </table>
+                                                               <br>
+                                                               <div style="text-align:left;">Flag3 は、スピーカーのオン/オフを指定します。</div>
+                                                               <table border="1" summary="fudge flag3">
+                                                                       <tr><td>0 (Default)</td><td>オフ</td><td>ATM0Ln</td></tr>
+                                                                       <tr><td>1</td><td>オン</td><td>ATM2Ln</td></tr>
+                                                               </table>
+                                                               <br>
+                                                               <div style="text-align:left;">Flag4 は、スピーカーの音量を指定します。</div>
+                                                               <table border="1" summary="fudge flag4">
+                                                                       <tr><td>0 (Default)</td><td>低</td><td>ATMnL1</td></tr>
+                                                                       <tr><td>1</td><td>中</td><td>ATMnL2</td></tr>
+                                                               </table>
+                                                               <br>
+                                                       </dd>
+                                                       <dt>phone 042NNNNNNN</dt>
+                                                       <dd>
+                                                               <p>電話番号は、<a href="http://jjy.nict.go.jp/">http://jjy.nict.go.jp/</a> で公開されています。<br>
+                                                               電話番号の桁数をチェックしています。もし、日本国外から発信するために国際電話アクセス番号と国番号を付加すると、桁数制限を超えます。<br>
+                                                               また、電話番号の最初の2桁や3桁をチェックしています。日本の緊急番号や特別のサービスの番号を指定することはできません。<br>
+                                                               内線から外線に発信する時は、"0," ( ゼロとカンマ ) を先頭に付加して下さい。外線発信番号は、チェックしていて、それ以外の外線発信番号を指定することはできません。</p>
+                                                       </dd>
+                                               </dl>
+                                               <br>
+                                       </dd>
+                                       <dt>インターフェース</dt>
+                                       <dd>
+                                               <p>RS-232C 又は USB, 2400 BPS, 8ビット, パリティなし, 1ストップ・ビット</p>
+                                               <p>モデム制御コマンド:<br>
+                                               <code>ATE0Q0V1, ATMnLn, AT&amp;K4, AT+MS=V22B, AT%C0, AT\Nn, ATH1, ATDWxnn...nn</code><br>
+                                               <code>+++, ATH0</code></p>
+                                               <br>
+                                       </dd>
+                                       <dt>日時データの形式</dt>
+                                       <dd><br>
+                                               <table summary="CommandAndReply">
+                                                       <tr>
+                                                               <td>プロンプト</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>コマンド</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>応答</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>Name{SP}?{SP}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>TJJY{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>Welcome messages</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>LOOP{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>( Switch to the loopback circuit )</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&nbsp;</code></td>
+                                                               <td>&nbsp;&nbsp;</td>
+                                                               <td><code>( One char. )</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>( One char. )</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&nbsp;</code></td>
+                                                               <td>&nbsp;&nbsp;</td>
+                                                               <td><code>COM{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>( Exit from the loopback circuit )</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>TIME{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HHMMSS{CR}HHMMSS{CR}HHMMSS{CR}</code> 3 times on second</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>4DATE{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>YYYYMMDD{CR}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>LEAPSEC{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>{SP}0{CR} | +1{CR} | -1{CR}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>TIME{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HHMMSS{CR}HHMMSS{CR}HHMMSS{CR}</code> 3 times on second</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>BYE{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>Sayounara messages</td>
+                                                       </tr>
+                                               </table>
+                                               <p>日付と時刻は、別々に問い合わせます。日付が深夜0時の前か後かの不確定をチェックするため、日付の問い合わせの前後に時刻を問い合わせています。<br>
+                                               うるう秒は、処理していません。情報として clockstats ファイルに記録しているだけです。</p>
+                                               <br>
+                                       </dd>
+                               </dl>
+                       </li>
+
+               </ul>
+
+               <p>JJY は、長波で日本標準時(JST)を送信している無線局で、国立研究開発法人 情報通信研究機構が運用しています。JJY の運用情報などは、 <a href="http://www.nict.go.jp/">http://www.nict.go.jp/</a>(英語と日本語)や <a href="http://jjy.nict.go.jp/">http://jjy.nict.go.jp/</a>(英語と日本語)で提供されています。</p>
+               <p>実際のシリアル・ポートのデバイスにシンボリック・リンクを作成して下さい。シンボリック・リンクを作成するコマンドは、以下のとおりです。</p>
+               <p><code>ln -s /dev/ttyS0 /dev/jjy0</code></p>
+               <p>RS-232C から USB への変換ケーブルを利用して、JJY受信機、GPS時計、モデムをRS-232Cポートではなく、USBに接続することができます。この場合のシンボリック・リンクを作成するコマンドは、以下のとおりです。</p>
+               <p><code>ln -s /dev/ttyUSB0 /dev/jjy0</code></p>
+               <p>Windows NT の場合は、 COM<em>X</em>: の数字部分がドライバーのユニット番号に使用されます。 ドライバーのユニット 1 は、COM1: にユニット 3 は、COM3: に対応します。</p>
+               <h4>Monitor Data</h4>
+               <p>このドライバーは、JJY受信機、GPS時計、モデムとの送受信データを <code>clockstats</code> ファイルに記録します。</p>
+               <p><code>
+               statsdir /var/log/ntpd/<br>
+               filegen clockstats file  clockstats type day enable
+               </code></p>
+               <div style="text-align:left;">レコード中のマークについて</div>
+               <table border="1" summary="Clockstats">
+                       <tr><td><code>JJY</code>&nbsp;</td><td>情報(このドライバーの開始または終了)</td></tr>
+                       <tr><td><code>--&gt;</code>&nbsp;</td><td>送信データ</td></tr>
+                       <tr><td><code>&lt;--</code>&nbsp;</td><td>受信データ</td></tr>
+                       <tr><td><code>---</code>&nbsp;</td><td>情報</td></tr>
+                       <tr><td><code>===</code>&nbsp;</td><td>情報(ポーリングの開始、および、同期時刻)</td></tr>
+                       <tr><td><code>-W-</code>&nbsp;</td><td>警告メッセージ</td></tr>
+                       <tr><td><code>-X-</code>&nbsp;</td><td>エラー・メッセージ</td></tr>
+               </table>
+               <h4>Fudge Factors</h4>
+               <dl>
+                       <dt><code>time1 <em>time</em></code></dt>
+                       <dd>受信機からの時刻に対する調整時間を、固定小数点形式の秒で設定します。デフォルトは、0.0秒です。</dd>
+                       <dt><code>time2 <em>time</em></code></dt>
+                       <dd>未使用。</dd>
+                       <dt><code>stratum <em>number</em></code></dt>
+                       <dd>NTPの階層番号を 0 から 15 で指定します。デフォルトは、0です。</dd>
+                       <dt><code>refid <em>string</em></code></dt>
+                       <dd>ドライバーIDで、ASCII の1文字から4文字で指定します。デフォルトは、<code>JJY</code> です。</dd>
+                       <dt><code>flag1 0 | 1</code></dt>
+                       <dd>それぞれのモードを参照して下さい。</dd>
+                       <dt><code>flag2 0 | 1</code></dt>
+                       <dd>それぞれのモードを参照して下さい。</dd>
+                       <dt><code>flag3 0 | 1</code></dt>
+                       <dd>それぞれのモードを参照して下さい。</dd>
+                       <dt><code>flag4 0 | 1</code></dt>
+                       <dd>それぞれのモードを参照して下さい。</dd>
+               </dl>
+               <hr>
+               <script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
+       </body>
+
+</html>
index 6799f7699611b183df9745276d94f76a115352e5..29123bdd6b48ed46d7b15e7800f2bb4211d0e6a0 100644 (file)
@@ -15,8 +15,8 @@
        <body>
                <h3>JJY Receivers</h3>
 <p>Last update:
-  <!-- #BeginDate format:En2m -->3-May-2011  00:20<!-- #EndDate -->
-  UTC</p>
+  <!-- #BeginDate format:En2m -->11-Apr-2015  00:00<!-- #EndDate -->
+  UTC &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="driver40.html">ENGLISH</a> &nbsp; <a href="driver40-ja.html">JAPANESE</a></p>
                <hr>
                <h4>Synopsis</h4>
                Address: 127.127.40.<em>u</em><br>
                Driver ID: <code>JJY</code><br>
                Serial Port: <code>/dev/jjy<em>u</em></code>; See corresponding receiver
                <h4>Description</h4>
-               <p>This driver supports the following JJY receivers sold in Japan.</p>
+               <p>This driver supports the following the JJY receivers and the GPS clock sold in Japan, and the time service through a telephone line.<br>
+               <a href="#mode-1">Tristate Ltd. &nbsp; TS-JJY01, TS-JJY02</a><br>
+               <a href="#mode-2">C-DEX Co.,Ltd. &nbsp; JST2000</a><br>
+               <a href="#mode-3">Echo Keisokuki Co.,Ltd. &nbsp; LT-2000</a><br>
+               <a href="#mode-4">CITIZEN T.I.C. CO.,LTD. &nbsp; JJY-200</a><br>
+               <a href="#mode-5">Tristate Ltd. &nbsp; TS-GPSclock-01</a><br>
+               <a href="#mode-100">Telephone JJY</a></p>
                <ul>
 
                        <li>
-                               <p>Tristate Ltd. JJY01, JJY02 <a href="http://www.tristate.ne.jp/">http://www.tristate.ne.jp/</a> (Japanese only)</p><br>
+                               <p><a name="mode-1">Tristate Ltd. &nbsp; TS-JJY01, TS-JJY02</a> &nbsp; <a href="http://www.tristate.ne.jp/">http://www.tristate.ne.jp/</a> (Japanese only)</p><br>
                                <dl>
                                        <dt>NTP configuration ( ntp.conf )</dt>
-                                       <dd>
-                                               <p>server &nbsp; 127.127.40.X &nbsp; mode 1</p>
+                                       <dd><br>
                                                <dl>
-                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; flag1 0|1</dt>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 1</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1 &nbsp; time1 0.NNN &nbsp; flag1 0|1</dt>
                                                        <dd>
-                                                               <p>Flag1 has no effect for time synchronization. When a flag1 is set to 1, status commands are issued before DATE and STIM commands, and write a response text into a clockstats file.</p>
+                                                               <p>Time1 may specify a constant to be added to the time offset for the time from the receiver, a fixed-point decimal number in seconds. You may specify the time offset from several tens of milli-seconds ( 0.0NN seconds ) to a hundred and several tens of milli-seconds  ( 0.1NN seconds ) for this clock.</p>
+                                                               <p>Flag1 has no effect for time synchronization. When flag1 is set to 1, status commands are issued before DATE and STIM commands, and write a response text into the clockstats file.</p>
                                                                <table border="1" summary="fudge flag1">
                                                                        <tr><td>0 (Default)</td><td>DCST and STUS commands are not issued</td></tr>
                                                                        <tr><td>1</td><td>DCST and STUS commands are issued</td></tr>
@@ -47,7 +55,7 @@
                                        </dd>
                                        <dt>Interface</dt>
                                        <dd>
-                                               <p>RS-232C, 9600 baud, 8-bits, no parity, 1 stop bit</p>
+                                               <p>RS-232C, 9600 BPS, 8-bits, no parity, 1 stop bit</p>
                                                <br>
                                        </dd>
                                        <dt>Time code format</dt>
                                                                <td>&nbsp;--&gt;&nbsp;</td>
                                                                <td>Reply</td>
                                                        </tr>
+                                                       <tr>
+                                                               <td><code>dcst{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>valid{CR}{LF} | invalid{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>stus{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>adjusted{CR}{LF} | unadjusted{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>time{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HH:MM:SS{CR}{LF}</code></td>
+                                                       </tr>
                                                        <tr>
                                                                <td><code>date{CR}{LF}</code></td>
                                                                <td>&nbsp;--&gt;&nbsp;</td>
                                                                <td><code>HH:MM:SS{CR}{LF}</code></td>
                                                        </tr>
                                                </table>
-                                               <br>
+                                               <p>The date and time are requested separately. The time is requested before and after the date request to check uncertainty of the date whether it's before or after midnight.</p><br>
                                        </dd>
                                </dl>
                        </li>
 
                        <li>
-                               <p>C-DEX Co.,Ltd. JST2000 <a href="http://www.c-dex.co.jp/">http://www.c-dex.co.jp/</a> (Japanese only)</p><br>
+                               <p><a name="mode-2">C-DEX Co.,Ltd. &nbsp; JST2000</a> &nbsp; <a href="http://www.c-dex.co.jp/">http://www.c-dex.co.jp/</a> (Japanese only)</p><br>
                                <dl>
                                        <dt>NTP configuration ( ntp.conf )</dt>
-                                       <dd>
-                                               <p>server &nbsp; 127.127.40.X &nbsp; mode 2</p>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 2</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1</dt>
+                                               </dl>
                                                <br>
                                        </dd>
                                        <dt>Interface</dt>
                                        <dd>
-                                               <p>RS-232C, 9600 baud, 8-bits, no parity, 1 stop bit</p>
+                                               <p>RS-232C, 9600 BPS, 8-bits, no parity, 1 stop bit</p>
                                                <br>
                                        </dd>
                                        <dt>Time code format</dt>
                        </li>
 
                        <li>
-                               <p>Echo Keisokuki Co.,Ltd. LT-2000 <a href="http://www.clock.co.jp/">http://www.clock.co.jp/</a> (Japanese only)</p><br>
+                               <p><a name="mode-3">Echo Keisokuki Co.,Ltd. &nbsp; LT-2000</a> &nbsp; <a href="http://www.clock.co.jp/">http://www.clock.co.jp/</a> (Japanese only)</p><br>
                                <dl>
                                        <dt>NTP configuration ( ntp.conf )</dt>
-                                       <dd>
-                                               <p>server &nbsp; 127.127.40.X &nbsp; mode 3</p>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 3</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1</dt>
+                                               </dl>
                                                <br>
                                        </dd>
                                        <dt>Interface</dt>
                                        <dd>
-                                               <p>RS-232C, 9600 baud, 8-bits, no parity, 1 stop bit</p>
+                                               <p>RS-232C, 9600 BPS, 8-bits, no parity, 1 stop bit</p>
                                                <br>
                                        </dd>
                                        <dt>Time code format</dt>
                        </li>
 
                        <li>
-                               <p>CITIZEN T.I.C. CO.,LTD. JJY-200 <a href="http://www.tic-citizen.co.jp/">http://www.tic-citizen.co.jp/</a> (Japanese only)</p><br>
+                               <p><a name="mode-4">CITIZEN T.I.C. CO.,LTD. &nbsp; JJY-200</a> &nbsp; <a href="http://www.tic-citizen.co.jp/">http://www.tic-citizen.co.jp/</a> (Japanese only)</p><br>
                                <dl>
                                        <dt>NTP configuration ( ntp.conf )</dt>
-                                       <dd>
-                                               <p>server &nbsp; 127.127.40.X &nbsp; mode 4</p>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 4</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1</dt>
+                                               </dl>
                                                <br>
                                        </dd>
                                        <dt>Interface</dt>
                                        <dd>
-                                               <p>RS-232C, 4800 baud, 8-bits, no parity, 1 stop bit</p>
+                                               <p>RS-232C, 4800 BPS, 8-bits, no parity, 1 stop bit</p>
                                                <br>
                                        </dd>
                                        <dt>Time code format</dt>
                        </li>
 
                        <li>
-                               <p>Tristate Ltd. TS-GPSclock-01 <a href="http://www.tristate.ne.jp/">http://www.tristate.ne.jp/</a> (Japanese only)</p>
+                               <p><a name="mode-5">Tristate Ltd. &nbsp; TS-GPSclock-01</a> &nbsp; <a href="http://www.tristate.ne.jp/">http://www.tristate.ne.jp/</a> (Japanese only)</p>
                                <p>This driver supports the Tristate TS-GPSclock-01 in command/response mode, though it is a GPS clock, not JJY radio clock. Using the menus and the onboard switches, the TS-GPSclock-01 should be set to command/response mode and JST time zone.<br>
                                Besides this driver ( Type 40 ), <a href="driver20.html">the generic NMEA GPS driver ( Type 20 )</a> supports the TS-GPSclock-01 in NMEA mode.</p>
                                <dl>
                                        <dt>NTP configuration ( ntp.conf )</dt>
-                                       <dd>
-                                               <p>server &nbsp; 127.127.40.X &nbsp; mode 5</p>
+                                       <dd><br>
                                                <dl>
-                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; flag1 0|1</dt>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode 5</dt>
+                                                       <dd><br></dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1 &nbsp; time1 0.NNN &nbsp; flag1 0|1</dt>
                                                        <dd>
+                                                               <p>Time1 may specify a constant to be added to the time offset for the time from the receiver, a fixed-point decimal number in seconds.</p>
                                                                <p>Flag1 has no effect for time synchronization. When a flag1 is set to 1, status command is issued before DATE and TIME commands, and write a response text into a clockstats file.</p>
                                                                <table border="1" summary="fudge flag1">
                                                                        <tr><td>0 (Default)</td><td>STUS command is not issued</td></tr>
                                                                <td>&nbsp;--&gt;&nbsp;</td>
                                                                <td>Reply</td>
                                                        </tr>
+                                                       <tr>
+                                                               <td><code>stus{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>*R{CR}{LF} | *G{CR}{LF} | *U{CR}{LF} | +U{CR}{LF}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>time{CR}{LF}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HH:MM:SS{CR}{LF}</code></td>
+                                                       </tr>
                                                        <tr>
                                                                <td><code>date{CR}{LF}</code></td>
                                                                <td>&nbsp;--&gt;&nbsp;</td>
                                                                <td><code>HH:MM:SS{CR}{LF}</code></td>
                                                        </tr>
                                                </table>
+                                               <p>The date and time are requested separately. The time is requested before and after the date request to check uncertainty of the date whether it's before or after midnight.</p><br>
+                                       </dd>
+                               </dl>
+                       </li>
+
+                       <li>
+                               <p><a name="mode-100">Telephone JJY</a> &nbsp; <a href="http://jjy.nict.go.jp/">http://jjy.nict.go.jp/</a> (English and Japanese)</p>
+                               <p>The telephone JJY is the time service through a public telephone line.<br>
+                               The service is provided by the National Institute of Information and Communications Technology in Japan.</p>
+                               <p>ATTENTION; This mode, the telephone JJY, can not be used with the refclock_acts ( type 18 ) at the same time.
+                               Because the "phone" statement in the ntp configuration file is not involved with the "server" statement,
+                               so the both the refclock_acts ( type 18 ) and this refclock_jjy ( type 40, mode 100 to 180 ) can not recognize the appropriate "phone" statement among the "phone" statements.</p>
+                               <dl>
+                                       <dt>NTP configuration ( ntp.conf )</dt>
+                                       <dd><br>
+                                               <dl>
+                                                       <dt>server &nbsp; 127.127.40.X &nbsp; mode (100, 101 to 180) &nbsp; minpoll N</dt>
+                                                       <dd>
+                                                       <p>The mode 100 is specified, this driver does not issue the loopback command in order to measure the delay, and the delay of the telephone line and the system processing is not adjusted.<br>
+                                                       The mode 101 to 180 is specified, this driver issues the loopback command and measures the delay of the telephone line and the system processing through the Telphone JJY loopback circuit.<br>
+                                                       The round trip time through the Telphone JJY loopback circuit is measured 5 times, and each delay time is greater than 700 milli-seconds,
+                                                       that delay time is ignored during average delay time calculation. Also, if the valid delay time ( &lt;= 700 mS. ) is measured more than 3 times, the maximum delay time among the valid delay times is ignored,
+                                                       and if the valid delay time is measured more than 4 times, the minimum delay time among them is ignored, like marking/grading sports judgment.<br>
+                                                       The adjustment time is calculated by the formula,<br>
+                                                       multiply ( the measured round trip time ) by ( ( the mode number ) - 100 ) %,<br>
+                                                       and the adjustment delay time is added to the syncronizing time.<br>
+                                                       If you choose the automatic delay ajustment, in other words, the mode 101 to 180 is specifed, the recommended mode number is 145 to 165.</p>
+                                                       <p>The default polling interval 6 ( 64 seconds ) is too short for this mode. The "minpoll" should be set to greater than or equal to 8 ( 256 seconds, about 4 minutes ).<br>
+                                                       The interval time is given the value in second power of 2. The minpoll value 12 is 4096 seconds interval ( about 1 hour ), 14 is 16384 seconds interval ( about 4.5 hours ), 16 is 65536 seconds ( about 18 hours ), respectively.</p><br>
+                                                       </dd>
+                                                       <dt>fudge &nbsp; 127.127.40.X &nbsp; stratum 1 &nbsp; flag1 0|1 &nbsp; flag2 0|1 &nbsp; flag3 0|1 &nbsp; flag4 0|1</dt>
+                                                       <dd>
+                                                               <p>Time1 may specify a constant to be added to the time offset for the time from the receiver, a fixed-point decimal number in seconds.<br>
+                                                               When the mode 100 is specified, the time1 may be specified in order to adjust the time offset.<br>
+                                                               When the mode 101 to 180 is specified, the time1 should not be specified because this driver adds some percentage of the measured loopback delay, depending on the value of the mode number.</p>
+                                                               <div style="text-align:left;">Flag1 is the modem dialing type.</div>
+                                                               <table border="1" summary="fudge flag1">
+                                                                       <tr><td>0 (Default)</td><td>Tone</td><td>ATDWTnn...nn</td></tr>
+                                                                       <tr><td>1</td><td>Pulse</td><td>ATDWPnn...nn</td></tr>
+                                                               </table>
+                                                               <br>
+                                                               <div style="text-align:left;">Flag2 is the modem error correction type.</div>
+                                                               <table border="1" summary="fudge flag2">
+                                                                       <tr><td>0 (Default)</td><td>Normal</td><td>AT\N0</td></tr>
+                                                                       <tr><td>1</td><td>Auto V42, MNP, Normal</td><td>AT\N3</td></tr>
+                                                               </table>
+                                                               <br>
+                                                               <div style="text-align:left;">Flag3 is the modem speaker switch.</div>
+                                                               <table border="1" summary="fudge flag3">
+                                                                       <tr><td>0 (Default)</td><td>Off</td><td>ATM0Ln</td></tr>
+                                                                       <tr><td>1</td><td>On</td><td>ATM2Ln</td></tr>
+                                                               </table>
+                                                               <br>
+                                                               <div style="text-align:left;">Flag4 is the modem speaker volume.</div>
+                                                               <table border="1" summary="fudge flag4">
+                                                                       <tr><td>0 (Default)</td><td>Low</td><td>ATMnL1</td></tr>
+                                                                       <tr><td>1</td><td>Middle</td><td>ATMnL2</td></tr>
+                                                               </table>
+                                                               <br>
+                                                       </dd>
+                                                       <dt>phone 042NNNNNNN</dt>
+                                                       <dd>
+                                                               <p>The phone number is available at <a href="http://jjy.nict.go.jp/">http://jjy.nict.go.jp/</a><br>
+                                                               The number of digits of the phone number is checked. If the international access number and the country number are added in order to call from outside of Japan, the number of digits is over the limit.<br>
+                                                               The first 2 or 3 digits are checked. The emergency service number and the special service number in Japan are not allowed.<br>
+                                                               Calling from extension line, the number for an outside line should be prefix "0," ( Zero, Comma ). The prefix is also checked, and no other outside access number is allowed.</p>
+                                                       </dd>
+                                               </dl>
+                                               <br>
+                                       </dd>
+                                       <dt>Interface</dt>
+                                       <dd>
+                                               <p>RS-232C or USB, 2400 BPS, 8-bits, no parity, 1 stop bit</p>
+                                               <p>Modem control commands:<br>
+                                               <code>ATE0Q0V1, ATMnLn, AT&amp;K4, AT+MS=V22B, AT%C0, AT\Nn, ATH1, ATDWxnn...nn</code><br>
+                                               <code>+++, ATH0</code></p>
+                                               <br>
+                                       </dd>
+                                       <dt>Time code format</dt>
+                                       <dd><br>
+                                               <table summary="CommandAndReply">
+                                                       <tr>
+                                                               <td>Prompt</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>Command</td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>Reply</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>Name{SP}?{SP}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>TJJY{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>Welcome messages</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>LOOP{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>( Switch to the loopback circuit )</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&nbsp;</code></td>
+                                                               <td>&nbsp;&nbsp;</td>
+                                                               <td><code>( One char. )</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>( One char. )</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&nbsp;</code></td>
+                                                               <td>&nbsp;&nbsp;</td>
+                                                               <td><code>COM{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>( Exit from the loopback circuit )</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>TIME{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HHMMSS{CR}HHMMSS{CR}HHMMSS{CR}</code> 3 times on second</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>4DATE{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>YYYYMMDD{CR}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>LEAPSEC{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>{SP}0{CR} | +1{CR} | -1{CR}</code></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>TIME{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>HHMMSS{CR}HHMMSS{CR}HHMMSS{CR}</code> 3 times on second</td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><code>&gt;</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td><code>BYE{CR}</code></td>
+                                                               <td>&nbsp;--&gt;&nbsp;</td>
+                                                               <td>Sayounara messages</td>
+                                                       </tr>
+                                               </table>
+                                               <p>The date and time are requested separately. The time is requested before and after the date request to check uncertainty of the date whether it's before or after midnight.<br>
+                                               The leap second is not handled, and only written in the clockstats file as an information.</p>
                                                <br>
                                        </dd>
                                </dl>
                        </li>
 
                </ul>
-               <p>JJY is the radio station which transmites the JST (Japan Standard Time) in long wave radio. The station JJY is operated by the National Institute of Information and Communications Technology. An operating announcement and some information are avaiable from <a href="http://www.nict.go.jp/">http://www.nict.go.jp/</a> (English and Japanese) and <a href="http://jjy.nict.go.jp/">http://jjy.nict.go.jp/</a> (English and Japanese)</p>
+
+               <p>The JJY is the radio station which transmits the JST (Japan Standard Time) in long wave radio. The station JJY is operated by the National Institute of Information and Communications Technology.
+               An operating announcement and some information are available from <a href="http://www.nict.go.jp/">http://www.nict.go.jp/</a> (English and Japanese) and <a href="http://jjy.nict.go.jp/">http://jjy.nict.go.jp/</a> (English and Japanese)</p>
                <p>The user is expected to provide a symbolic link to an available serial port device. This is typically performed by a command such as;</p>
                <p><code>ln -s /dev/ttyS0 /dev/jjy0</code></p>
-               <p>Using RS232C to USB converter cable, the clock can be connected to an USB port instead of a serial port. In this case, typical symbolic link command is as follows;
+               <p>Using an RS-232C to USB converter cable, the clock or a modem can be connected to a USB port instead of a serial port. In this case, the typical symbolic link command is as follows;</p>
                <p><code>ln -s /dev/ttyUSB0 /dev/jjy0</code></p>
                <p>Windows NT does not support symbolic links to device files. COM<em>X</em>: is the unit used by the driver, based on the refclock unit number, where unit 1 corresponds to COM1: and unit 3 corresponds to COM3:</p>
                <h4>Monitor Data</h4>
-               <p>The driver writes each timecode as received to the <code>clockstats</code> file.</p>
+               <p>The driver writes sent and received data to/from the JJY receivers, GPS clock, and the modem into the <code>clockstats</code> file.</p>
+               <p><code>
+               statsdir /var/log/ntpd/<br>
+               filegen clockstats file clockstats type day enable
+               </code></p>
+               <div style="text-align:left;">Mark of the clockstats record</div>
+               <table border="1" summary="Clockstats">
+                       <tr><td><code>JJY</code>&nbsp;</td><td>Infomation message ( This refclock starts or stops. )</td></tr>
+                       <tr><td><code>--&gt;</code>&nbsp;</td><td>Sent data</td></tr>
+                       <tr><td><code>&lt;--</code>&nbsp;</td><td>Received data</td></tr>
+                       <tr><td><code>---</code>&nbsp;</td><td>Infomation message</td></tr>
+                       <tr><td><code>===</code>&nbsp;</td><td>Infomation message ( Start of each polling, and sync. time. )</td></tr>
+                       <tr><td><code>-W-</code>&nbsp;</td><td>Warning message</td></tr>
+                       <tr><td><code>-X-</code>&nbsp;</td><td>Error message</td></tr>
+               </table>
                <h4>Fudge Factors</h4>
                <dl>
-                       <dt><code>time1 <em>time</em></code>
-                       <dd>Specifies the time offset calibration factor, in seconds and fraction, with default 0.0.
-                       <dt><code>time2 <em>time</em></code>
-                       <dd>Not used by this driver.
-                       <dt><code>stratum <em>number</em></code>
-                       <dd>Specifies the driver stratum, in decimal from 0 to 15, with default 0.
-                       <dt><code>refid <em>string</em></code>
-                       <dd>Specifies the driver reference identifier, an ASCII string from one to four characters, with default <code>JJY</code>.
-                       <dt><code>flag1 0 | 1</code>
-                       <dd>See corresponding receiver.
-                       <dt><code>flag2 0 | 1</code>
-                       <dd>Not used by this driver.
-                       <dt><code>flag3 0 | 1</code>
-                       <dd>Not used by this driver.
-                       <dt><code>flag4 0 | 1</code>
+                       <dt><code>time1 <em>time</em></code></dt>
+                       <dd>Specifies the time offset calibration factor, in seconds and fraction, with default 0.0.</dd>
+                       <dt><code>time2 <em>time</em></code></dt>
                        <dd>Not used by this driver.
+                       <dt><code>stratum <em>number</em></code></dt>
+                       <dd>Specifies the driver stratum, in decimal from 0 to 15, with default 0.</dd>
+                       <dt><code>refid <em>string</em></code></dt>
+                       <dd>Specifies the driver reference identifier, an ASCII string from one to four characters, with default <code>JJY</code>.</dd>
+                       <dt><code>flag1 0 | 1</code></dt>
+                       <dd>See corresponding receiver.</dd>
+                       <dt><code>flag2 0 | 1</code></dt>
+                       <dd>See corresponding receiver.</dd>
+                       <dt><code>flag3 0 | 1</code></dt>
+                       <dd>See corresponding receiver.</dd>
+                       <dt><code>flag4 0 | 1</code></dt>
+                       <dd>See corresponding receiver.</dd>
                </dl>
                <hr>
                <script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
index e279ee307d7370300c2953c9606ad07d54acf007..420f8bb8c7174450d50748610cca7e67f595da17 100644 (file)
@@ -4,7 +4,7 @@
 
 /**********************************************************************/
 /*                                                                   */
-/*  Copyright (C) 2001-2011, Takao Abe.  All rights reserved.        */
+/*  Copyright (C) 2001-2015, Takao Abe.  All rights reserved.        */
 /*                                                                   */
 /*  Permission to use, copy, modify, and distribute this software     */
 /*  and its documentation for any purpose is hereby granted          */
 /*  2011/04/30                                                       */
 /*    [Add]    Support the Tristate Ltd. TS-GPSclock-01                      */
 /*                                                                   */
+/*  2015/03/29                                                       */
+/*    [Add]    Support the Telephone JJY                             */
+/*    [Change] Split the start up routine into each JJY receivers.    */
+/*             Change raw data internal bufferring process            */
+/*             Change over midnight handling of TS-JJY01 and TS-GPS01 */
+/*             to put DATE command between before and after TIME's.   */
+/*             Unify the writing clockstats of all JJY receivers.     */
+/*                                                                   */
 /**********************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include "ntp_calendar.h"
 #include "ntp_stdlib.h"
 
-/**********************************************************************/
-/*                                                                   */
-/*  The Tristate Ltd. JJY receiver JJY01                             */
-/*                                                                   */
-/*  Command       Response                 Remarks                   */
-/*  ------------   ----------------------   ---------------------     */
-/*  dcst<CR><LF>   VALID|INVALID<CR><LF>                             */
-/*  stus<CR><LF>   ADJUSTED|UNADJUSTED<CR><LF>                       */
-/*  date<CR><LF>   YYYY/MM/DD XXX<CR><LF>                            */
-/*  time<CR><LF>   HH:MM:SS<CR><LF>        Not used by this driver   */
-/*  stim<CR><LF>   HH:MM:SS<CR><LF>        Reply at just second      */
-/*                                                                   */
-/*  During synchronization after a receiver is turned on,            */
-/*  It replies the past time from 2000/01/01 00:00:00.               */
-/*  The function "refclock_process" checks the time and tells        */
-/*  as an insanity time.                                             */
-/*                                                                   */
-/**********************************************************************/
-/*                                                                   */
-/*  The C-DEX Co. Ltd. JJY receiver JST2000                          */
-/*                                                                   */
-/*  Command       Response                 Remarks                   */
-/*  ------------   ----------------------   ---------------------     */
-/*  <ENQ>1J<ETX>   <STX>JYYMMDD HHMMSSS<ETX>                         */
-/*                                                                   */
-/**********************************************************************/
-/*                                                                   */
-/*  The Echo Keisokuki Co. Ltd. JJY receiver LT2000                  */
-/*                                                                   */
-/*  Command        Response                Remarks                   */
-/*  ------------   ----------------------   ---------------------     */
-/*  #                                      Mode 1 (Request&Send)     */
-/*  T             YYMMDDWHHMMSS<BCC1><BCC2><CR>                      */
-/*  C                                      Mode 2 (Continuous)       */
-/*                YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR>              */
-/*                <SUB>                    Second signal             */
-/*                                                                   */
-/**********************************************************************/
-/*                                                                   */
-/*  The CITIZEN T.I.C CO., LTD. JJY receiver JJY200                  */
-/*                                                                   */
-/*  Command       Response                 Remarks                   */
-/*  ------------   ----------------------   ---------------------     */
-/*                'XX YY/MM/DD W HH:MM:SS<CR>                        */
-/*                                         XX: OK|NG|ER              */
-/*                                         W:  0(Monday)-6(Sunday)   */
-/*                                                                   */
-/**********************************************************************/
-/*                                                                   */
-/*  The Tristate Ltd. GPS clock TS-GPSCLOCK-01                       */
-/*                                                                   */
-/*  This clock has NMEA mode and command/respose mode.               */
-/*  When this jjy driver are used, set to command/respose mode        */
-/*  of this clock by the onboard switch SW4, and make sure the        */
-/*  LED-Y is tured on.                                               */
-/*  Other than this JJY driver, the refclock driver type 20,         */
-/*  generic NMEA driver, works with the NMEA mode of this clock.      */
-/*                                                                   */
-/*  Command       Response                 Remarks                   */
-/*  ------------   ----------------------   ---------------------     */
-/*  stus<CR><LF>   *R|*G|*U|+U<CR><LF>                               */
-/*  date<CR><LF>   YY/MM/DD<CR><LF>                                  */
-/*  time<CR><LF>   HH:MM:SS<CR><LF>                                  */
-/*                                                                   */
 /**********************************************************************/
 
 /*
  * Interface definitions
  */
 #define        DEVICE          "/dev/jjy%d"    /* device name and unit */
-#define        SPEED232        B9600           /* uart speed (9600 baud) */
 #define        SPEED232_TRISTATE_JJY01         B9600   /* UART speed (9600 baud) */
 #define        SPEED232_CDEX_JST2000           B9600   /* UART speed (9600 baud) */
 #define        SPEED232_ECHOKEISOKUKI_LT2000   B9600   /* UART speed (9600 baud) */
 #define        SPEED232_CITIZENTIC_JJY200      B4800   /* UART speed (4800 baud) */
 #define        SPEED232_TRISTATE_GPSCLOCK01    B38400  /* USB  speed (38400 baud) */
+#define        SPEED232_TELEPHONE              B2400   /* UART speed (4800 baud) */
 #define        REFID           "JJY"           /* reference ID */
 #define        DESCRIPTION     "JJY Receiver"
 #define        PRECISION       (-3)            /* precision assumed (about 100 ms) */
 /*
  * JJY unit control structure
  */
+
+struct jjyRawDataBreak {
+       char    *pString ;
+       int     iLength ;
+} ;
+
+#define        MAX_TIMESTAMP   6
+#define        MAX_RAWBUF      100
+#define        MAX_LOOPBACK    5
+
 struct jjyunit {
+/* Set up by the function "jjy_start_xxxxxxxx" */
        char    unittype ;          /* UNITTYPE_XXXXXXXXXX */
-       short   operationmode ;     /* Echo Keisokuki LT-2000 : 1 or 2 */
-       short   version ;
+       short   operationmode ;     /* Echo Keisokuki LT-2000 */
+       int     linespeed ;         /* SPEED232_XXXXXXXXXX */
        short   linediscipline ;    /* LDISC_CLK or LDISC_RAW */
-       char    bPollFlag ;         /* Set by jjy_pool and Reset by jjy_receive */
-       int     linecount ;
-       int     lineerror ;
+/* Receiving data */
+       char    bInitError ;        /* Set by jjy_start if any error during initialization */
+       short   iProcessState ;     /* JJY_PROCESS_STATE_XXXXXX */
+       char    bReceiveFlag ;      /* Set and reset by jjy_receive */
+       char    bLineError ;        /* Reset by jjy_poll / Set by jjy_receive_xxxxxxxx*/
+       int     iCommandSeq ;       /* 0:Idle  Non-Zero:Issued */
+       int     iLineCount ;
        int     year, month, day, hour, minute, second, msecond ;
+       int     leapsecond ;
+       int     iTimestampCount ;   /* TS-JJY01, TS-GPS01, Telephone-JJY */
+       int     iTimestamp [ MAX_TIMESTAMP ] ;  /* Serial second ( 0 - 86399 ) */
 /* LDISC_RAW only */
-#define        MAX_LINECOUNT   8
-#define        MAX_RAWBUF      64
-       int     lineexpect ;
-       int     charexpect [ MAX_LINECOUNT ] ;
-       int     charcount ;
-       char    rawbuf [ MAX_RAWBUF ] ;
+       char    sRawBuf [ MAX_RAWBUF ] ;
+       int     iRawBufLen ;
+       struct  jjyRawDataBreak *pRawBreak ;
+       char    bWaitBreakString ;
+       char    sLineBuf [ MAX_RAWBUF ] ;
+       int     iLineBufLen ;
+       char    sTextBuf [ MAX_RAWBUF ] ;
+       int     iTextBufLen ;
+       char    bSkipCntrlCharOnly ;
+/* Telephone JJY auto measurement of the loopback delay */
+       char    bLoopbackMode ;
+       short   iLoopbackCount ;
+       struct  timeval sendTime[MAX_LOOPBACK], delayTime[MAX_LOOPBACK] ;
+       char    bLoopbackTimeout[MAX_LOOPBACK] ;
+       short   iLoopbackValidCount ;
+/* Telephone JJY timer */
+       short   iTeljjySilentTimer ;
+       short   iTeljjyStateTimer ;
+/* Telephone JJY control finite state machine */
+       short   iClockState ;
+       short   iClockEvent ;
+       short   iClockCommandSeq ;
+/* Modem timer */
+       short   iModemSilentCount ;
+       short   iModemSilentTimer ;
+       short   iModemStateTimer ;
+/* Modem control finite state machine */
+       short   iModemState ;
+       short   iModemEvent ;
+       short   iModemCommandSeq ;
 };
 
 #define        UNITTYPE_TRISTATE_JJY01         1
@@ -222,12 +208,87 @@ struct jjyunit {
 #define        UNITTYPE_ECHOKEISOKUKI_LT2000   3
 #define        UNITTYPE_CITIZENTIC_JJY200      4
 #define        UNITTYPE_TRISTATE_GPSCLOCK01    5
+#define        UNITTYPE_TELEPHONE              100
+
+#define        JJY_PROCESS_STATE_IDLE          0
+#define        JJY_PROCESS_STATE_POLL          1
+#define        JJY_PROCESS_STATE_RECEIVE       2
+#define        JJY_PROCESS_STATE_DONE          3
+#define        JJY_PROCESS_STATE_ERROR         4
+
+/**********************************************************************/
 
 /*
+ *  Function calling structure
+ *
+ *  jjy_start
+ *   |--  jjy_start_tristate_jjy01
+ *   |--  jjy_start_cdex_jst2000
+ *   |--  jjy_start_echokeisokuki_lt2000
+ *   |--  jjy_start_citizentic_jjy200
+ *   |--  jjy_start_tristate_gpsclock01
+ *   |--  jjy_start_telephone
+ *
+ *  jjy_shutdown
+ *
+ *  jjy_poll
+ *   |--  jjy_poll_tristate_jjy01
+ *   |--  jjy_poll_cdex_jst2000
+ *   |--  jjy_poll_echokeisokuki_lt2000
+ *   |--  jjy_poll_citizentic_jjy200
+ *   |--  jjy_poll_tristate_gpsclock01
+ *   |--  jjy_poll_telephone
+ *         |--  teljjy_control
+ *               |--  teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
+ *                     |--  modem_connect
+ *                           |--  modem_control
+ *                                 |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
+ *
+ *  jjy_receive
+ *   |
+ *   |--  jjy_receive_tristate_jjy01
+ *   |     |--  jjy_synctime
+ *   |--  jjy_receive_cdex_jst2000
+ *   |     |--  jjy_synctime
+ *   |--  jjy_receive_echokeisokuki_lt2000
+ *   |     |--  jjy_synctime
+ *   |--  jjy_receive_citizentic_jjy200
+ *   |     |--  jjy_synctime
+ *   |--  jjy_receive_tristate_gpsclock01
+ *   |     |--  jjy_synctime
+ *   |--  jjy_receive_telephone
+ *         |--  modem_receive
+ *         |     |--  modem_control
+ *         |           |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
+ *         |--  teljjy_control
+ *               |--  teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
+ *                     |--  jjy_synctime
+ *                     |--  modem_disconnect
+ *                           |--  modem_control
+ *                                 |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
+ *
+ *  jjy_timer
+ *   |--  jjy_timer_telephone
+ *         |--  modem_timer
+ *         |     |--  modem_control
+ *         |           |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
+ *         |--  teljjy_control
+ *               |--  teljjy_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
+ *                     |--  modem_disconnect
+ *                           |--  modem_control
+ *                                 |--  modem_XXXX_YYYY ( XXXX_YYYY is an event handler name. )
+ *
  * Function prototypes
  */
+
 static int     jjy_start                       (int, struct peer *);
+static int     jjy_start_tristate_jjy01        (int, struct peer *, struct jjyunit *);
+static int     jjy_start_cdex_jst2000          (int, struct peer *, struct jjyunit *);
+static int     jjy_start_echokeisokuki_lt2000  (int, struct peer *, struct jjyunit *);
+static int     jjy_start_citizentic_jjy200     (int, struct peer *, struct jjyunit *);
+static int     jjy_start_tristate_gpsclock01   (int, struct peer *, struct jjyunit *);
+static int     jjy_start_telephone             (int, struct peer *, struct jjyunit *);
+
 static void    jjy_shutdown                    (int, struct peer *);
 
 static void    jjy_poll                        (int, struct peer *);
@@ -236,15 +297,34 @@ static    void    jjy_poll_cdex_jst2000           (int, struct peer *);
 static void    jjy_poll_echokeisokuki_lt2000   (int, struct peer *);
 static void    jjy_poll_citizentic_jjy200      (int, struct peer *);
 static void    jjy_poll_tristate_gpsclock01    (int, struct peer *);
+static void    jjy_poll_telephone              (int, struct peer *);
 
 static void    jjy_receive                     (struct recvbuf *);
-static int     jjy_receive_tristate_jjy01      (struct recvbuf *);
-static int     jjy_receive_cdex_jst2000        (struct recvbuf *);
-static int     jjy_receive_echokeisokuki_lt2000 (struct recvbuf *);
-static  int    jjy_receive_citizentic_jjy200   (struct recvbuf *);
-static int     jjy_receive_tristate_gpsclock01 (struct recvbuf *);
+static int     jjy_receive_tristate_jjy01      (struct recvbuf *);
+static int     jjy_receive_cdex_jst2000        (struct recvbuf *);
+static int     jjy_receive_echokeisokuki_lt2000 (struct recvbuf *);
+static  int    jjy_receive_citizentic_jjy200   (struct recvbuf *);
+static int     jjy_receive_tristate_gpsclock01 (struct recvbuf *);
+static int     jjy_receive_telephone           (struct recvbuf *);
 
-static void    printableString ( char*, int, char*, int ) ;
+static void    jjy_timer                       (int, struct peer *);
+static void    jjy_timer_telephone             (int, struct peer *);
+
+static void    jjy_synctime                    ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static void    jjy_write_clockstats            ( struct peer *, int, const char* ) ;
+
+static int     getRawDataBreakPosition         ( struct jjyunit *, int ) ;
+
+static short   getModemState                   ( struct jjyunit * ) ;
+static int     isModemStateConnect             ( short ) ;
+static int     isModemStateDisconnect          ( short ) ;
+static int     isModemStateTimerOn             ( struct jjyunit * ) ;
+static void    modem_connect                   ( int, struct peer * ) ;
+static void    modem_disconnect                ( int, struct peer * ) ;
+static int     modem_receive                   ( struct recvbuf * ) ;
+static void    modem_timer                     ( int, struct peer * );
+
+static void    printableString ( char*, int, const char*, int ) ;
 
 /*
  * Transfer vector
@@ -256,7 +336,7 @@ struct      refclock refclock_jjy = {
        noentry,        /* not used */
        noentry,        /* not used */
        noentry,        /* not used */
-       NOFLAGS         /* not used */
+       jjy_timer       /* 1 second interval timer */
 };
 
 /*
@@ -269,88 +349,64 @@ struct    refclock refclock_jjy = {
  * Local constants definition
  */
 
-#define        MAX_LOGTEXT     64
-
-/*
- * Tristate JJY01/JJY02 constants definition
- */
-
-#define        TS_JJY01_COMMAND_NUMBER_DATE    1
-#define        TS_JJY01_COMMAND_NUMBER_TIME    2
-#define        TS_JJY01_COMMAND_NUMBER_STIM    3
-#define        TS_JJY01_COMMAND_NUMBER_STUS    4
-#define        TS_JJY01_COMMAND_NUMBER_DCST    5
-
-#define        TS_JJY01_REPLY_DATE             "yyyy/mm/dd www\r\n"
-#define        TS_JJY01_REPLY_STIM             "hh:mm:ss\r\n"
-#define        TS_JJY01_REPLY_STUS_YES         "adjusted\r\n"
-#define        TS_JJY01_REPLY_STUS_NO          "unadjusted\r\n"
-#define        TS_JJY01_REPLY_DCST_VALID       "valid\r\n"
-#define        TS_JJY01_REPLY_DCST_INVALID     "invalid\r\n"
-
-#define        TS_JJY01_REPLY_LENGTH_DATE          14  /* Length without <CR><LF> */
-#define        TS_JJY01_REPLY_LENGTH_STIM          8   /* Length without <CR><LF> */
-#define        TS_JJY01_REPLY_LENGTH_STUS_YES      8   /* Length without <CR><LF> */
-#define        TS_JJY01_REPLY_LENGTH_STUS_NO       10  /* Length without <CR><LF> */
-#define        TS_JJY01_REPLY_LENGTH_DCST_VALID    5   /* Length without <CR><LF> */
-#define        TS_JJY01_REPLY_LENGTH_DCST_INVALID  7   /* Length without <CR><LF> */
-
-static  struct
-{
-       const char      commandNumber ;
-       const char      *commandLog ;
-       const char      *command ;
-       int     commandLength ;
-} tristate_jjy01_command_sequence[] =
-{
-       /* dcst<CR><LF> -> VALID<CR><LF> or INVALID<CR><LF> */
-       { TS_JJY01_COMMAND_NUMBER_DCST, "dcst", "dcst\r\n", 6 },
-       /* stus<CR><LF> -> ADJUSTED<CR><LF> or UNADJUSTED<CR><LF> */
-       { TS_JJY01_COMMAND_NUMBER_STUS, "stus", "stus\r\n", 6 },
-       /* date<CR><LF> -> YYYY/MM/DD WWW<CR><LF> */
-       { TS_JJY01_COMMAND_NUMBER_DATE, "date", "date\r\n", 6 },
-       /* stim<CR><LF> -> HH:MM:SS<CR><LF> */
-       { TS_JJY01_COMMAND_NUMBER_STIM, "stim", "stim\r\n", 6 },
-       /* End of command */
-       { 0, NULL, NULL, 0 }
-} ;
-
-/*
- * Tristate TS-GPSCLOCK01 constants definition
- */
-
-#define        TS_GPSCLOCK01_COMMAND_NUMBER_DATE       1
-#define        TS_GPSCLOCK01_COMMAND_NUMBER_TIME       2
-#define        TS_GPSCLOCK01_COMMAND_NUMBER_STUS       4
-
-#define        TS_GPSCLOCK01_REPLY_DATE                "yyyy/mm/dd\r\n"
-#define        TS_GPSCLOCK01_REPLY_TIME                "hh:mm:ss\r\n"
-#define        TS_GPSCLOCK01_REPLY_STUS_RTC            "*R\r\n"
-#define        TS_GPSCLOCK01_REPLY_STUS_GPS            "*G\r\n"
-#define        TS_GPSCLOCK01_REPLY_STUS_UTC            "*U\r\n"
-#define        TS_GPSCLOCK01_REPLY_STUS_PPS            "+U\r\n"
+#define        MAX_LOGTEXT     100
 
-#define        TS_GPSCLOCK01_REPLY_LENGTH_DATE     10  /* Length without <CR><LF> */
-#define        TS_GPSCLOCK01_REPLY_LENGTH_TIME     8   /* Length without <CR><LF> */
-#define        TS_GPSCLOCK01_REPLY_LENGTH_STUS     2   /* Length without <CR><LF> */
+#ifndef        TRUE
+#define        TRUE    (0==0)
+#endif
+#ifndef        FALSE
+#define        FALSE   (!TRUE)
+#endif
 
-static  struct
-{
-       char    commandNumber ;
-       const char      *commandLog ;
-       const char      *command ;
-       int     commandLength ;
-} tristate_gpsclock01_command_sequence[] =
-{
-       /* stus<CR><LF> -> *R<CR><LF> or *G<CR><LF> or *U<CR><LF> or +U<CR><LF> */
-       { TS_GPSCLOCK01_COMMAND_NUMBER_STUS, "stus", "stus\r\n", 6 },
-       /* date<CR><LF> -> YYYY/MM/DD WWW<CR><LF> */
-       { TS_GPSCLOCK01_COMMAND_NUMBER_DATE, "date", "date\r\n", 6 },
-       /* time<CR><LF> -> HH:MM:SS<CR><LF> */
-       { TS_GPSCLOCK01_COMMAND_NUMBER_TIME, "time", "time\r\n", 6 },
-       /* End of command */
-       { 0, NULL, NULL, 0 }
-} ;
+/* Local constants definition for the return code of the jjy_receive_xxxxxxxx */
+
+#define        JJY_RECEIVE_DONE        0
+#define        JJY_RECEIVE_SKIP        1
+#define        JJY_RECEIVE_UNPROCESS   2
+#define        JJY_RECEIVE_WAIT        3
+#define        JJY_RECEIVE_ERROR       4
+
+/* Local constants definition for the 2nd parameter of the jjy_write_clockstats */
+
+#define        JJY_CLOCKSTATS_MARK_NONE        0
+#define        JJY_CLOCKSTATS_MARK_JJY         1
+#define        JJY_CLOCKSTATS_MARK_SEND        2
+#define        JJY_CLOCKSTATS_MARK_RECEIVE     3
+#define        JJY_CLOCKSTATS_MARK_INFORMATION 4
+#define        JJY_CLOCKSTATS_MARK_ATTENTION   5
+#define        JJY_CLOCKSTATS_MARK_WARNING     6
+#define        JJY_CLOCKSTATS_MARK_ERROR       7
+
+/* Local constants definition for the clockstats messages */
+
+#define        JJY_CLOCKSTATS_MESSAGE_ECHOBACK                 "* Echoback"
+#define        JJY_CLOCKSTATS_MESSAGE_IGNORE_REPLY             "* Ignore replay : [%s]"
+#define        JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2          "* Over midnight : timestamp=%d, %d"
+#define        JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_3          "* Over midnight : timestamp=%d, %d, %d"
+#define        JJY_CLOCKSTATS_MESSAGE_TIMESTAMP_UNSURE         "* Unsure timestamp : %s"
+#define        JJY_CLOCKSTATS_MESSAGE_LOOPBACK_DELAY           "* Loopback delay : %d.%03d mSec."
+#define        JJY_CLOCKSTATS_MESSAGE_DELAY_ADJUST             "* Delay adjustment : %d mSec. ( valid=%hd/%d )"
+#define        JJY_CLOCKSTATS_MESSAGE_DELAY_UNADJUST           "* Delay adjustment : None ( valid=%hd/%d )"
+
+#define        JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY         "# Unexpected reply : [%s]"
+#define        JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH           "# Invalid length : length=%d"
+#define        JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY           "# Too many reply : count=%d"
+#define        JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY            "# Invalid reply : [%s]"
+#define        JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2             "# Slow reply : timestamp=%d, %d"
+#define        JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_3             "# Slow reply : timestamp=%d, %d, %d"
+#define        JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE      "# Invalid date : rc=%d year=%d month=%d day=%d"
+#define        JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME      "# Invalid time : rc=%d hour=%d minute=%d second=%d"
+#define        JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME  "# Invalid time : rc=%d year=%d month=%d day=%d hour=%d minute=%d second=%d"
+#define        JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_LEAP      "# Invalid leap : leapsecond=[%s]"
+#define        JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_STATUS    "# Invalid status : status=[%s]"
+
+/* Debug print macro */
+
+#ifdef DEBUG
+#define        DEBUG_PRINTF_JJY_RECEIVE(sFunc,iLen)    { if ( debug ) { printf ( "refclock_jjy.c : %s : iProcessState=%d bLineError=%d iCommandSeq=%d iLineCount=%d iTimestampCount=%d iLen=%d\n", sFunc, up->iProcessState, up->bLineError, up->iCommandSeq, up->iLineCount, up->iTimestampCount, iLen ) ; } }
+#else
+#define        DEBUG_PRINTF_JJY_RECEIVE(sFunc,iLen)
+#endif
 
 /**************************************************************************************************/
 /*  jjy_start - open the devices and initialize data for processing                               */
@@ -359,31 +415,42 @@ static int
 jjy_start ( int unit, struct peer *peer )
 {
 
-       struct jjyunit      *up ;
-       struct refclockproc *pp ;
+       struct  refclockproc *pp ;
+       struct  jjyunit      *up ;
+       int     rc ;
        int     fd ;
-       char    *pDeviceName ;
-       short   iDiscipline ;
-       int     iSpeed232 ;
-
-       char    sLogText [ MAX_LOGTEXT ] , sDevText [ MAX_LOGTEXT ] ;
+       char    sDeviceName [ sizeof(DEVICE) + 10 ], sLog [ 60 ] ;
 
 #ifdef DEBUG
        if ( debug ) {
-               printf ( "jjy_start (refclock_jjy.c) : %s  mode=%d  ", ntoa(&peer->srcadr), peer->ttl ) ;
-               printf ( DEVICE, unit ) ;
-               printf ( "\n" ) ;
+               printf( "refclock_jjy.c : jjy_start : %s  mode=%d  dev=%s  unit=%d\n",
+                        ntoa(&peer->srcadr), peer->ttl, DEVICE, unit ) ;
        }
 #endif
-       snprintf ( sDevText, sizeof(sDevText), DEVICE, unit ) ;
-       snprintf ( sLogText, sizeof(sLogText), "*Initialze*  %s  mode=%d", sDevText, peer->ttl ) ;
-       record_clock_stats ( &peer->srcadr, sLogText ) ;
 
-       /*
-        * Open serial port
-        */
-       pDeviceName = emalloc ( strlen(DEVICE) + 10 );
-       snprintf ( pDeviceName, strlen(DEVICE) + 10, DEVICE, unit ) ;
+       /* Allocate memory for the unit structure */
+       up = emalloc( sizeof(*up) ) ;
+       if ( up == NULL ) {
+               msyslog ( LOG_ERR, "refclock_jjy.c : jjy_start : emalloc" ) ;
+               return RC_START_ERROR ;
+       }
+       memset ( up, 0, sizeof(*up) ) ;
+
+       up->bInitError = FALSE ;
+       up->iProcessState = JJY_PROCESS_STATE_IDLE ;
+       up->bReceiveFlag = FALSE ;
+       up->iCommandSeq = 0 ;
+       up->iLineCount = 0 ;
+       up->iTimestampCount = 0 ;
+       up->bWaitBreakString = FALSE ;
+       up->iRawBufLen = up->iLineBufLen = up->iTextBufLen = 0 ;
+       up->bSkipCntrlCharOnly = TRUE ;
+
+       /* Set up the device name */
+       snprintf( sDeviceName, sizeof(sDeviceName), DEVICE, unit ) ;
+
+       snprintf( sLog, sizeof(sLog), "mode=%d dev=%s", peer->ttl, sDeviceName ) ;
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ;
 
        /*
         * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
@@ -391,101 +458,54 @@ jjy_start ( int unit, struct peer *peer )
        switch ( peer->ttl ) {
        case 0 :
        case 1 :
-               iDiscipline = LDISC_CLK ;
-               iSpeed232   = SPEED232_TRISTATE_JJY01 ;
+               rc = jjy_start_tristate_jjy01 ( unit, peer, up ) ;
                break ;
        case 2 :
-               iDiscipline = LDISC_RAW ;
-               iSpeed232   = SPEED232_CDEX_JST2000   ;
+               rc = jjy_start_cdex_jst2000 ( unit, peer, up ) ;
                break ;
        case 3 :
-               iDiscipline = LDISC_CLK ;
-               iSpeed232   = SPEED232_ECHOKEISOKUKI_LT2000 ;
+               rc = jjy_start_echokeisokuki_lt2000 ( unit, peer, up ) ;
                break ;
        case 4 :
-               iDiscipline = LDISC_CLK ;
-               iSpeed232   = SPEED232_CITIZENTIC_JJY200 ;
+               rc = jjy_start_citizentic_jjy200 ( unit, peer, up ) ;
                break ;
        case 5 :
-               iDiscipline = LDISC_CLK ;
-               iSpeed232   = SPEED232_TRISTATE_GPSCLOCK01 ;
+               rc = jjy_start_tristate_gpsclock01 ( unit, peer, up ) ;
+               break ;
+       case 100 :
+               rc = jjy_start_telephone ( unit, peer, up ) ;
                break ;
        default :
-               msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
+               if ( 101 <= peer->ttl && peer->ttl <= 180 ) {
+                       rc = jjy_start_telephone ( unit, peer, up ) ;
+               } else {
+                       msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
+                                 ntoa(&peer->srcadr), peer->ttl ) ;
+                       free ( (void*) up ) ;
+               return RC_START_ERROR ;
+               }
+       }
+
+       if ( rc != 0 ) {
+               msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Initialize error",
                          ntoa(&peer->srcadr), peer->ttl ) ;
-               free ( (void*) pDeviceName ) ;
+               free ( (void*) up ) ;
                return RC_START_ERROR ;
        }
 
-       fd = refclock_open ( pDeviceName, iSpeed232, iDiscipline ) ;
+       /* Open the device */
+       fd = refclock_open ( sDeviceName, up->linespeed, up->linediscipline ) ;
        if ( fd <= 0 ) {
-               free ( (void*) pDeviceName ) ;
+               free ( (void*) up ) ;
                return RC_START_ERROR ;
        }
-       free ( (void*) pDeviceName ) ;
-
-       /*
-        * Allocate and initialize unit structure
-        */
-       up = emalloc (sizeof(*up));
-       memset ( up, 0, sizeof(*up) ) ;
-       up->linediscipline = iDiscipline ;
 
        /*
-        * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
+        * Initialize variables
         */
-       switch ( peer->ttl ) {
-       case 0 :
-               /*
-                * The mode 0 is a default clock type at this time.
-                * But this will be change to auto-detect mode in the future.
-                */
-       case 1 :
-               up->unittype = UNITTYPE_TRISTATE_JJY01 ;
-               up->version  = 100 ;
-               /* 2010/11/20 */
-               /* Command sequence is defined by the struct tristate_jjy01_command_sequence, */
-               /* and the following 3 lines are not used in the mode LDISC_CLK. */
-               /* up->lineexpect = 2 ; */
-               /* up->charexpect[0] = 14 ; */ /* YYYY/MM/DD WWW<CR><LF> */
-               /* up->charexpect[1] =  8 ; */ /* HH:MM:SS<CR><LF> */
-               break ;
-       case 2 :
-               up->unittype = UNITTYPE_CDEX_JST2000 ;
-               up->lineexpect = 1 ;
-               up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
-               break ;
-       case 3 :
-               up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
-               up->operationmode = 2 ;  /* Mode 2 : Continuous mode */
-               up->lineexpect = 1 ;
-               switch ( up->operationmode ) {
-               case 1 :
-                       up->charexpect[0] = 15 ; /* YYMMDDWHHMMSS<BCC1><BCC2><CR> */
-                       break ;
-               case 2 :
-                       up->charexpect[0] = 17 ; /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
-                       break ;
-               }
-               break ;
-       case 4 :
-               up->unittype = UNITTYPE_CITIZENTIC_JJY200 ;
-               up->lineexpect = 1 ;
-               up->charexpect[0] = 23 ; /* 'XX YY/MM/DD W HH:MM:SS<CR> */
-               break ;
-       case 5 :
-               up->unittype = UNITTYPE_TRISTATE_GPSCLOCK01 ;
-               break ;
-
-       /* 2010/11/20 */
-       /* The "default:" section of this switch block is never executed,     */
-       /* because the former switch block traps the same "default:" case.    */
-       /* This "default:" section codes are removed to avoid spending time   */
-       /* in the future looking, though the codes are functionally harmless. */
-
-       }
-
        pp = peer->procptr ;
+
+       pp->clockdesc   = DESCRIPTION ;
        pp->unitptr       = up ;
        pp->io.clock_recv = jjy_receive ;
        pp->io.srcclock   = peer ;
@@ -498,19 +518,17 @@ jjy_start ( int unit, struct peer *peer )
                pp->unitptr = NULL ;
                return RC_START_ERROR ;
        }
+       memcpy( (char*)&pp->refid, REFID, strlen(REFID) ) ;
 
-       /*
-        * Initialize miscellaneous variables
-        */
        peer->precision = PRECISION ;
-       pp->clockdesc   = DESCRIPTION ;
-       memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
+
+       snprintf( sLog, sizeof(sLog), "minpoll=%d maxpoll=%d", peer->minpoll, peer->maxpoll ) ;
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ;
 
        return RC_START_SUCCESS ;
 
 }
 
-
 /**************************************************************************************************/
 /*  jjy_shutdown - shutdown the clock                                                             */
 /**************************************************************************************************/
@@ -521,15 +539,21 @@ jjy_shutdown ( int unit, struct peer *peer )
        struct jjyunit      *up;
        struct refclockproc *pp;
 
+       char    sLog [ 60 ] ;
+
        pp = peer->procptr ;
        up = pp->unitptr ;
-       if ( -1 != pp->io.fd )
+       if ( -1 != pp->io.fd ) {
                io_closeclock ( &pp->io ) ;
-       if ( NULL != up )
+       }
+       if ( NULL != up ) {
                free ( up ) ;
+       }
 
-}
+       snprintf( sLog, sizeof(sLog), "JJY stopped. unit=%d mode=%d", unit, peer->ttl ) ;
+       record_clock_stats( &peer->srcadr, sLog ) ;
 
+}
 
 /**************************************************************************************************/
 /*  jjy_receive - receive data from the serial interface                                          */
@@ -537,6 +561,9 @@ jjy_shutdown ( int unit, struct peer *peer )
 static void
 jjy_receive ( struct recvbuf *rbufp )
 {
+#ifdef DEBUG
+       static const char *sFunctionName = "jjy_receive" ;
+#endif
 
        struct jjyunit      *up ;
        struct refclockproc *pp ;
@@ -544,8 +571,9 @@ jjy_receive ( struct recvbuf *rbufp )
 
        l_fp    tRecvTimestamp;         /* arrival timestamp */
        int     rc ;
-       char    sLogText [ MAX_LOGTEXT ] ;
-       int     i, bCntrlChar ;
+       char    *pBuf, sLogText [ MAX_LOGTEXT ] ;
+       int     iLen, iCopyLen ;
+       int     i, j, iReadRawBuf, iBreakPosition ;
 
        /*
         * Initialize pointers and read the timecode and timestamp
@@ -557,1138 +585,3563 @@ jjy_receive ( struct recvbuf *rbufp )
        /*
         * Get next input line
         */
-       pp->lencode  = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
-
        if ( up->linediscipline == LDISC_RAW ) {
+
+               pp->lencode  = refclock_gtraw ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
+
                /*
-                * The reply with <STX> and <ETX> may give a blank line
-                */
-               if ( pp->lencode == 0  &&  up->charcount == 0 ) return ;
-               /*
-                * Copy received charaters to temporary buffer 
+                * Append received charaters to temporary buffer
                 */
                for ( i = 0 ;
-                     i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ;
-                     i ++ , up->charcount ++ ) {
-                       up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
-               }
-               while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
-                       for ( i = 0 ; i < up->charcount - 1 ; i ++ )
-                               up->rawbuf[i] = up->rawbuf[i+1] ;
-                       up->charcount -- ;
-               }
-               bCntrlChar = 0 ;
-               for ( i = 0 ; i < up->charcount ; i ++ ) {
-                       if ( up->rawbuf[i] < ' ' ) {
-                               bCntrlChar = 1 ;
-                               break ;
-                       }
+                     i < pp->lencode && up->iRawBufLen < MAX_RAWBUF - 2 ;
+                     i ++ , up->iRawBufLen ++ ) {
+                       up->sRawBuf[up->iRawBufLen] = pp->a_lastcode[i] ;
                }
-               if ( pp->lencode > 0  &&  up->linecount < up->lineexpect ) {
-                       if ( bCntrlChar == 0  &&
-                            up->charcount < up->charexpect[up->linecount] )
-                               return ;
-               }
-               up->rawbuf[up->charcount] = 0 ;
+               up->sRawBuf[up->iRawBufLen] = 0 ;
+
+
        } else {
-               /*
-                * The reply with <CR><LF> gives a blank line
-                */
-               if ( pp->lencode == 0 ) return ;
-       }
-       /*
-        * We get down to business
-        */
 
+               pp->lencode  = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
+
+       }
 #ifdef DEBUG
-       if ( debug ) {
-               if ( up->linediscipline == LDISC_RAW ) {
-                       printableString( sLogText, MAX_LOGTEXT, up->rawbuf, up->charcount ) ;
+       printf( "\nrefclock_jjy.c : %s : Len=%d  ", sFunctionName, pp->lencode ) ;
+       for ( i = 0 ; i < pp->lencode ; i ++ ) {
+               if ( iscntrl( pp->a_lastcode[i] & 0x7F ) ) {
+                       printf( "<x%02X>", pp->a_lastcode[i] & 0xFF ) ;
                } else {
-                       printableString( sLogText, MAX_LOGTEXT, pp->a_lastcode, pp->lencode ) ;
+                       printf( "%c", pp->a_lastcode[i] ) ;
                }
-               printf ( "jjy_receive (refclock_jjy.c) : [%s]\n", sLogText ) ;
        }
+       printf( "\n" ) ;
 #endif
 
-       pp->lastrec = tRecvTimestamp ;
+       /*
+        * The reply with <CR><LF> gives a blank line
+        */
 
-       up->linecount ++ ;
+       if ( pp->lencode == 0 ) return ;
 
-       if ( up->lineerror != 0 ) return ;
+       /*
+        * Receiving data is not expected
+        */
 
-       switch ( up->unittype ) {
-       
-       case UNITTYPE_TRISTATE_JJY01 :
-               rc = jjy_receive_tristate_jjy01  ( rbufp ) ;
-               break ;
+       if ( up->iProcessState == JJY_PROCESS_STATE_IDLE
+         || up->iProcessState == JJY_PROCESS_STATE_DONE
+         || up->iProcessState == JJY_PROCESS_STATE_ERROR ) {
+               /* Discard received data */
+               up->iRawBufLen = 0 ;
+#ifdef DEBUG
+               if ( debug ) {
+                       printf( "refclock_jjy.c : %s : Discard received data\n", sFunctionName ) ;
+               }
+#endif
+               return ;
+       }
 
-       case UNITTYPE_CDEX_JST2000 :
-               rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
-               break ;
+       /*
+        * We get down to business
+        */
 
-       case UNITTYPE_ECHOKEISOKUKI_LT2000 :
-               rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
-               break ;
+       pp->lastrec = tRecvTimestamp ;
 
-       case UNITTYPE_CITIZENTIC_JJY200 :
-               rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
-               break ;
+       up->iLineCount ++ ;
 
-       case UNITTYPE_TRISTATE_GPSCLOCK01 :
-               rc = jjy_receive_tristate_gpsclock01  ( rbufp ) ;
-               break ;
+       up->iProcessState = JJY_PROCESS_STATE_RECEIVE ;
+       up->bReceiveFlag = TRUE ;
 
-       default :
-               rc = 0 ;
-               break ;
+       iReadRawBuf = 0 ;
+       iBreakPosition = up->iRawBufLen - 1 ;
+       for ( ; up->iProcessState == JJY_PROCESS_STATE_RECEIVE ; ) {
 
-       }
+               if ( up->linediscipline == LDISC_RAW ) {
 
-       if ( up->linediscipline == LDISC_RAW ) {
-               if ( up->linecount <= up->lineexpect  &&
-                    up->charcount > up->charexpect[up->linecount-1] ) {
-                       for ( i = 0 ;
-                             i < up->charcount - up->charexpect[up->linecount-1] ;
-                             i ++ ) {
-                               up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
+                       if ( up->bWaitBreakString ) {
+                               iBreakPosition = getRawDataBreakPosition( up, iReadRawBuf ) ;
+                               if ( iBreakPosition == -1 ) {
+                                       /* Break string have not come yet */
+                                       if ( up->iRawBufLen < MAX_RAWBUF - 2
+                                         || iReadRawBuf > 0 ) {
+                                               /* Temporary buffer is not full */
+                                               break ;
+                                       } else {
+                                               /* Temporary buffer is full */
+                                               iBreakPosition = up->iRawBufLen - 1 ;
+                                       }
+                               }
+                       } else {
+                               iBreakPosition = up->iRawBufLen - 1 ;
                        }
-                       up->charcount -= up->charexpect[up->linecount-1] ;
-               } else {
-                       up->charcount = 0 ;
-               }
-       }
 
-       if ( rc == 0 ) {
-               return ;
-       }
+                       /* Copy charaters from temporary buffer to process buffer */
+                       up->iLineBufLen = up->iTextBufLen = 0 ;
+                       for ( i = iReadRawBuf ; i <= iBreakPosition ; i ++ ) {
 
-       up->bPollFlag = 0 ;
+                               /* Copy all characters */
+                               up->sLineBuf[up->iLineBufLen] = up->sRawBuf[i] ;
+                               up->iLineBufLen ++ ;
 
-       if ( up->lineerror != 0 ) {
-               refclock_report ( peer, CEVNT_BADREPLY ) ;
-               strlcpy  ( sLogText, "BAD REPLY [",
-                          sizeof( sLogText ) ) ;
-               if ( up->linediscipline == LDISC_RAW ) {
-                       strlcat ( sLogText, up->rawbuf,
-                                 sizeof( sLogText ) ) ;
-               } else {
-                       strlcat ( sLogText, pp->a_lastcode,
-                                 sizeof( sLogText ) ) ;
-               }
-               sLogText[MAX_LOGTEXT-1] = 0 ;
-               if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 )
-                       strlcat ( sLogText, "]",
-                                 sizeof( sLogText ) ) ;
-               record_clock_stats ( &peer->srcadr, sLogText ) ;
-               return ;
-       }
+                               /* Copy printable characters */
+                               if ( ! iscntrl( up->sRawBuf[i] ) ) {
+                                       up->sTextBuf[up->iTextBufLen] = up->sRawBuf[i] ;
+                                       up->iTextBufLen ++ ;
+                               }
 
-       pp->year   = up->year ;
-       pp->day    = ymd2yd ( up->year, up->month, up->day ) ;
-       pp->hour   = up->hour ;
-       pp->minute = up->minute ;
-       pp->second = up->second ;
-       pp->nsec   = up->msecond * 1000000;
+                       }
+                       up->sLineBuf[up->iLineBufLen] = 0 ;
+                       up->sTextBuf[up->iTextBufLen] = 0 ;
+#ifdef DEBUG
+                       printf( "refclock_jjy.c : %s : up->iLineBufLen=%d up->iTextBufLen=%d\n",
+                                sFunctionName, up->iLineBufLen, up->iTextBufLen ) ;
+#endif
 
-       /* 
-        * JST to UTC 
-        */
-       pp->hour -= 9 ;
-       if ( pp->hour < 0 ) {
-               pp->hour += 24 ;
-               pp->day -- ;
-               if ( pp->day < 1 ) {
-                       pp->year -- ;
-                       pp->day  = ymd2yd ( pp->year, 12, 31 ) ;
-               }
-       }
+                       if ( up->bSkipCntrlCharOnly && up->iTextBufLen == 0 ) {
 #ifdef DEBUG
-       if ( debug ) {
-               printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d.%1d JST   ", 
-                         up->year, up->month, up->day, up->hour,
-                         up->minute, up->second, up->msecond/100 ) ;
-               printf ( "( %04d/%03d %02d:%02d:%02d.%1d UTC )\n",
-                         pp->year, pp->day, pp->hour, pp->minute,
-                         pp->second, (int)(pp->nsec/100000000) ) ;
-       }
+                               printf( "refclock_jjy.c : %s : Skip cntrl char only : up->iRawBufLen=%d iReadRawBuf=%d iBreakPosition=%d\n",
+                                        sFunctionName, up->iRawBufLen, iReadRawBuf, iBreakPosition ) ;
 #endif
+                               if ( iBreakPosition + 1 < up->iRawBufLen ) {
+                                       iReadRawBuf = iBreakPosition + 1 ;
+                                       continue ;
+                               } else {
+                                       break ;
+                               }
 
-       /*
-        * Process the new sample in the median filter and determine the
-        * timecode timestamp.
-        */
+                       }
 
-       snprintf ( sLogText, sizeof(sLogText),
-                  "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
-                  up->year, up->month, up->day,
-                  up->hour, up->minute, up->second, up->msecond/100 ) ;
-       record_clock_stats ( &peer->srcadr, sLogText ) ;
+               }
 
-       if ( ! refclock_process ( pp ) ) {
-               refclock_report(peer, CEVNT_BADTIME);
-               return ;
-       }
+               if ( up->linediscipline == LDISC_RAW ) {
+                       pBuf = up->sLineBuf ;
+                       iLen = up->iLineBufLen ;
+               } else {
+                       pBuf = pp->a_lastcode ;
+                       iLen = pp->lencode ;
+               }
 
-       pp->lastref = pp->lastrec;
-       refclock_receive(peer);
+               iCopyLen = ( iLen <= sizeof(sLogText)-1 ? iLen : sizeof(sLogText)-1 ) ;
+               strncpy( sLogText, pBuf, iCopyLen ) ;
+               sLogText[iCopyLen] = 0 ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_RECEIVE, sLogText ) ;
 
-}
+               switch ( up->unittype ) {
 
-/**************************************************************************************************/
+               case UNITTYPE_TRISTATE_JJY01 :
+                       rc = jjy_receive_tristate_jjy01  ( rbufp ) ;
+                       break ;
 
-static int
-jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
-{
-#ifdef DEBUG
-       static  const char      *sFunctionName = "jjy_receive_tristate_jjy01" ;
-#endif
+               case UNITTYPE_CDEX_JST2000 :
+                       rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
+                       break ;
 
-       struct jjyunit      *up ;
-       struct refclockproc *pp ;
-       struct peer         *peer;
+               case UNITTYPE_ECHOKEISOKUKI_LT2000 :
+                       rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
+                       break ;
 
-       char    *pBuf ;
-       int     iLen ;
-       int     rc ;
+               case UNITTYPE_CITIZENTIC_JJY200 :
+                       rc = jjy_receive_citizentic_jjy200 ( rbufp ) ;
+                       break ;
 
-       int     bOverMidnight = 0 ;
+               case UNITTYPE_TRISTATE_GPSCLOCK01 :
+                       rc = jjy_receive_tristate_gpsclock01 ( rbufp ) ;
+                       break ;
 
-       char    sLogText [ MAX_LOGTEXT ], sReplyText  [ MAX_LOGTEXT ] ;
+               case UNITTYPE_TELEPHONE :
+                       rc = jjy_receive_telephone ( rbufp ) ;
+                       break ;
 
-       const char *pCmd ;
-       int     iCmdLen ;
+               default :
+                       rc = JJY_RECEIVE_ERROR ;
+                       break ;
 
-       /*
-        * Initialize pointers and read the timecode and timestamp
-        */
-       peer = rbufp->recv_peer ;
-       pp = peer->procptr ;
-       up = pp->unitptr ;
+               }
+
+               switch ( rc ) {
+               case JJY_RECEIVE_DONE :
+               case JJY_RECEIVE_SKIP :
+                       up->iProcessState = JJY_PROCESS_STATE_DONE ;
+                       break ;
+               case JJY_RECEIVE_ERROR :
+                       up->iProcessState = JJY_PROCESS_STATE_ERROR ;
+                       break ;
+               default :
+                       break ;
+               }
+
+               if ( up->linediscipline == LDISC_RAW ) {
+                       if ( rc == JJY_RECEIVE_UNPROCESS ) {
+                               break ;
+                       }
+                       iReadRawBuf = iBreakPosition + 1 ;
+                       if ( iReadRawBuf >= up->iRawBufLen ) {
+                               /* Processed all received data */
+                               break ;
+                       }
+               }
+
+               if ( up->linediscipline == LDISC_CLK ) {
+                       break ;
+               }
+
+       }
+
+       if ( up->linediscipline == LDISC_RAW && iReadRawBuf > 0 ) {
+               for ( i = 0, j = iReadRawBuf ; j < up->iRawBufLen ; i ++, j++ ) {
+                       up->sRawBuf[i] = up->sRawBuf[j] ;
+               }
+               up->iRawBufLen -= iReadRawBuf ;
+               if ( up->iRawBufLen < 0 ) {
+                       up->iRawBufLen = 0 ;
+               }
+       }
+
+       up->bReceiveFlag = FALSE ;
+
+}
+
+/**************************************************************************************************/
+
+static int
+getRawDataBreakPosition ( struct jjyunit *up, int iStart )
+{
+
+       int     i, j ;
+
+       if ( iStart >= up->iRawBufLen ) {
+#ifdef DEBUG
+               printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=-1\n", iStart ) ;
+#endif
+               return -1 ;
+       }
+
+       for ( i = iStart ; i < up->iRawBufLen ; i ++ ) {
+
+               for ( j = 0 ; up->pRawBreak[j].pString != NULL ; j ++ ) {
+
+                       if ( i + up->pRawBreak[j].iLength <= up->iRawBufLen ) {
+
+                               if ( strncmp( up->sRawBuf + i,
+                                       up->pRawBreak[j].pString,
+                                       up->pRawBreak[j].iLength ) == 0 ) {
+
+#ifdef DEBUG
+                                       printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=%d\n",
+                                               iStart, i + up->pRawBreak[j].iLength - 1 ) ;
+#endif
+                                       return i + up->pRawBreak[j].iLength - 1 ;
+
+                               }
+                       }
+               }
+       }
+
+#ifdef DEBUG
+       printf( "refclock_jjy.c : getRawDataBreakPosition : iStart=%d return=-1\n", iStart ) ;
+#endif
+       return -1 ;
+
+}
+
+/**************************************************************************************************/
+/*  jjy_poll - called by the transmit procedure                                                   */
+/**************************************************************************************************/
+static void
+jjy_poll ( int unit, struct peer *peer )
+{
+
+       char    sLog [ 40 ], sReach [ 9 ] ;
+
+       struct jjyunit      *up;
+       struct refclockproc *pp;
+
+       pp = peer->procptr;
+       up = pp->unitptr ;
+
+       if ( up->bInitError ) {
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, "Ignore polling because of error during initializing" ) ;
+               return ;
+       }
+
+       if ( pp->polls > 0  &&  up->iLineCount == 0 ) {
+               /*
+                * No reply for last command
+                */
+               refclock_report ( peer, CEVNT_TIMEOUT ) ;
+       }
+
+       pp->polls ++ ;
+
+       sReach[0] = peer->reach & 0x80 ? '1' : '0' ;
+       sReach[1] = peer->reach & 0x40 ? '1' : '0' ;
+       sReach[2] = peer->reach & 0x20 ? '1' : '0' ;
+       sReach[3] = peer->reach & 0x10 ? '1' : '0' ;
+       sReach[4] = peer->reach & 0x08 ? '1' : '0' ;
+       sReach[5] = peer->reach & 0x04 ? '1' : '0' ;
+       sReach[6] = peer->reach & 0x02 ? '1' : '0' ;
+       sReach[7] = 0 ; /* This poll */
+       sReach[8] = 0 ;
+
+       snprintf( sLog, sizeof(sLog), "polls=%ld reach=%s", pp->polls, sReach ) ;
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ATTENTION, sLog ) ;
+
+       up->iProcessState = JJY_PROCESS_STATE_POLL ;
+       up->iCommandSeq = 0 ;
+       up->iLineCount = 0 ;
+       up->bLineError = FALSE ;
+       up->iRawBufLen = 0 ;
+
+       switch ( up->unittype ) {
+       
+       case UNITTYPE_TRISTATE_JJY01 :
+               jjy_poll_tristate_jjy01  ( unit, peer ) ;
+               break ;
+
+       case UNITTYPE_CDEX_JST2000 :
+               jjy_poll_cdex_jst2000 ( unit, peer ) ;
+               break ;
+
+       case UNITTYPE_ECHOKEISOKUKI_LT2000 :
+               jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
+               break ;
+
+       case UNITTYPE_CITIZENTIC_JJY200 :
+               jjy_poll_citizentic_jjy200 ( unit, peer ) ;
+               break ;
+
+       case UNITTYPE_TRISTATE_GPSCLOCK01 :
+               jjy_poll_tristate_gpsclock01 ( unit, peer ) ;
+               break ;
+
+       case UNITTYPE_TELEPHONE :
+               jjy_poll_telephone ( unit, peer ) ;
+               break ;
+
+       default :
+               break ;
+
+       }
+
+}
+
+/**************************************************************************************************/
+/*  jjy_timer - called at one-second intervals                                                    */
+/**************************************************************************************************/
+static void
+jjy_timer ( int unit, struct peer *peer )
+{
+
+       struct  refclockproc *pp ;
+       struct  jjyunit      *up ;
+
+#ifdef DEBUG
+       if ( debug ) {
+               printf ( "refclock_jjy.c : jjy_timer\n" ) ;
+       }
+#endif
+
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       if ( up->bReceiveFlag ) {
+#ifdef DEBUG
+               if ( debug ) {
+                       printf ( "refclock_jjy.c : jjy_timer : up->bReceiveFlag= TRUE : Timer skipped.\n" ) ;
+               }
+#endif
+               return ;
+       }
+
+       switch ( up->unittype ) {
+       
+       case UNITTYPE_TELEPHONE :
+               jjy_timer_telephone ( unit, peer ) ;
+               break ;
+
+       default :
+               break ;
+
+       }
+
+}
+
+/**************************************************************************************************/
+/*  jjy_synctime                                                                                  */
+/**************************************************************************************************/
+static void
+jjy_synctime ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       char    sLog [ 80 ], cStatus ;
+       const char      *pStatus ;
+
+       pp->year   = up->year ;
+       pp->day    = ymd2yd( up->year, up->month, up->day ) ;
+       pp->hour   = up->hour ;
+       pp->minute = up->minute ;
+       pp->second = up->second ;
+       pp->nsec   = up->msecond * 1000000 ;
+
+       /* 
+        * JST to UTC 
+        */
+       pp->hour -= 9 ;
+       if ( pp->hour < 0 ) {
+               pp->hour += 24 ;
+               pp->day -- ;
+               if ( pp->day < 1 ) {
+                       pp->year -- ;
+                       pp->day  = ymd2yd( pp->year, 12, 31 ) ;
+               }
+       }
+
+       /*
+        * Process the new sample in the median filter and determine the
+        * timecode timestamp.
+        */
+
+       if ( ! refclock_process( pp ) ) {
+               refclock_report( peer, CEVNT_BADTIME ) ;
+               return ;
+       }
+
+       pp->lastref = pp->lastrec ;
+
+       refclock_receive( peer ) ;
+
+       /*
+        * Write into the clockstats file
+        */
+       snprintf ( sLog, sizeof(sLog),
+                  "%04d/%02d/%02d %02d:%02d:%02d.%03d JST   ( %04d/%03d %02d:%02d:%02d.%03d UTC )",
+                  up->year, up->month, up->day,
+                  up->hour, up->minute, up->second, up->msecond,
+                  pp->year, pp->day, pp->hour, pp->minute, pp->second,
+                  (int)(pp->nsec/1000000) ) ;
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ATTENTION, sLog ) ;
+
+       cStatus = ' ' ;
+       pStatus = "" ;
+
+       switch ( peer->status ) {
+       case 0 : cStatus = ' ' ; pStatus = "Reject"    ; break ;
+       case 1 : cStatus = 'x' ; pStatus = "FalseTick" ; break ;
+       case 2 : cStatus = '.' ; pStatus = "Excess"    ; break ;
+       case 3 : cStatus = '-' ; pStatus = "Outlier"   ; break ;
+       case 4 : cStatus = '+' ; pStatus = "Candidate" ; break ;
+       case 5 : cStatus = '#' ; pStatus = "Selected"  ; break ;
+       case 6 : cStatus = '*' ; pStatus = "Sys.Peer"  ; break ;
+       case 7 : cStatus = 'o' ; pStatus = "PPS.Peer"  ; break ;
+       default : break ; 
+       }
+
+       snprintf ( sLog, sizeof(sLog),
+                  "status %d [%c] %s : offset %3.3f mSec. : jitter %3.3f mSec.",
+                   peer->status, cStatus, pStatus, peer->offset * 1000, peer->jitter * 1000 ) ;
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
+
+}
+
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    The Tristate Ltd. JJY receiver TS-JJY01, TS-JJY02                                      ##*/
+/*##                                                                                           ##*/
+/*##    server  127.127.40.X  mode 1                                                           ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
+/*                                                                                                */
+/*  Command               Response                                  Remarks                       */
+/*  --------------------  ----------------------------------------  ----------------------------  */
+/*  dcst<CR><LF>          VALID<CR><LF> or INVALID<CR><LF>                                        */
+/*  stus<CR><LF>          ADJUSTED<CR><LF> or UNADJUSTED<CR><LF>                                  */
+/*  date<CR><LF>          YYYY/MM/DD XXX<CR><LF>                    XXX is the day of the week    */
+/*  time<CR><LF>          HH:MM:SS<CR><LF>                          Not used by this driver       */
+/*  stim<CR><LF>          HH:MM:SS<CR><LF>                          Reply at just second          */
+/*                                                                                                */
+/*################################################################################################*/
+
+#define        TS_JJY01_COMMAND_NUMBER_DATE    1
+#define        TS_JJY01_COMMAND_NUMBER_TIME    2
+#define        TS_JJY01_COMMAND_NUMBER_STIM    3
+#define        TS_JJY01_COMMAND_NUMBER_STUS    4
+#define        TS_JJY01_COMMAND_NUMBER_DCST    5
+
+#define        TS_JJY01_REPLY_DATE             "yyyy/mm/dd www"
+#define        TS_JJY01_REPLY_STIM             "hh:mm:ss"
+#define        TS_JJY01_REPLY_STUS_ADJUSTED    "adjusted"
+#define        TS_JJY01_REPLY_STUS_UNADJUSTED  "unadjusted"
+#define        TS_JJY01_REPLY_DCST_VALID       "valid"
+#define        TS_JJY01_REPLY_DCST_INVALID     "invalid"
+
+#define        TS_JJY01_REPLY_LENGTH_DATE              14      /* Length without <CR><LF> */
+#define        TS_JJY01_REPLY_LENGTH_TIME              8       /* Length without <CR><LF> */
+#define        TS_JJY01_REPLY_LENGTH_STIM              8       /* Length without <CR><LF> */
+#define        TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED     8       /* Length without <CR><LF> */
+#define        TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED   10      /* Length without <CR><LF> */
+#define        TS_JJY01_REPLY_LENGTH_DCST_VALID        5       /* Length without <CR><LF> */
+#define        TS_JJY01_REPLY_LENGTH_DCST_INVALID      7       /* Length without <CR><LF> */
+
+static  struct
+{
+       const char      commandNumber ;
+       const char      *command ;
+       int     commandLength ;
+       int     iExpectedReplyLength [ 2 ] ;
+} tristate_jjy01_command_sequence[] =
+{
+       { 0, NULL, 0, { 0, 0 } }, /* Idle */
+       { TS_JJY01_COMMAND_NUMBER_DCST, "dcst\r\n", 6, { TS_JJY01_REPLY_LENGTH_DCST_VALID   , TS_JJY01_REPLY_LENGTH_DCST_INVALID } },
+       { TS_JJY01_COMMAND_NUMBER_STUS, "stus\r\n", 6, { TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED, TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED } },
+       { TS_JJY01_COMMAND_NUMBER_TIME, "time\r\n", 6, { TS_JJY01_REPLY_LENGTH_TIME         , TS_JJY01_REPLY_LENGTH_TIME } },
+       { TS_JJY01_COMMAND_NUMBER_DATE, "date\r\n", 6, { TS_JJY01_REPLY_LENGTH_DATE         , TS_JJY01_REPLY_LENGTH_DATE } },
+       { TS_JJY01_COMMAND_NUMBER_STIM, "stim\r\n", 6, { TS_JJY01_REPLY_LENGTH_STIM         , TS_JJY01_REPLY_LENGTH_STIM } },
+       /* End of command */
+       { 0, NULL, 0, { 0, 0 } }
+} ;
+
+/**************************************************************************************************/
+
+static int
+jjy_start_tristate_jjy01 ( int unit, struct peer *peer, struct jjyunit *up )
+{
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Tristate Ltd. TS-JJY01, TS-JJY02" ) ;
+
+       up->unittype  = UNITTYPE_TRISTATE_JJY01 ;
+       up->linespeed = SPEED232_TRISTATE_JJY01 ;
+       up->linediscipline = LDISC_CLK ;
+
+       return 0 ;
+
+}
+
+/**************************************************************************************************/
+
+static int
+jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
+{
+       struct jjyunit      *up ;
+       struct refclockproc *pp ;
+       struct peer         *peer;
+
+       char    *pBuf, sLog [ 100 ] ;
+       int     iLen ;
+       int     rc ;
+
+       const char *pCmd ;
+       int     iCmdLen ;
+
+       /* Initialize pointers  */
+
+       peer = rbufp->recv_peer ;
+       pp = peer->procptr ;
+       up = pp->unitptr ;
 
        if ( up->linediscipline == LDISC_RAW ) {
-               pBuf = up->rawbuf ;
-               iLen = up->charcount ;
+               pBuf = up->sTextBuf ;
+               iLen = up->iTextBufLen ;
        } else {
                pBuf = pp->a_lastcode ;
                iLen = pp->lencode ;
        }
 
-       switch ( tristate_jjy01_command_sequence[up->linecount-1].commandNumber ) {
+       DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_tristate_jjy01", iLen ) ;
 
-       case TS_JJY01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD WWW */
+       /* Check expected reply */
 
-               if ( iLen != TS_JJY01_REPLY_LENGTH_DATE ) {
-                       up->lineerror = 1 ;
-                       break ;
-               }
+       if ( tristate_jjy01_command_sequence[up->iCommandSeq].command == NULL ) {
+               /* Command sequence has not been started, or has been completed */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
+                         pBuf ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
 
-               rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year,
-                             &up->month, &up->day ) ;
-               if ( rc != 3 || up->year < 2000 || up->month < 1 ||
-                    up->month > 12 || up->day < 1 || up->day > 31 ) {
-                       up->lineerror = 1 ;
-                       break ;
-               }
+       /* Check reply length */
 
-               /*** Start of modification on 2004/10/31 ***/
-               /*
-                * Following codes are moved from the function jjy_poll_tristate_jjy01 in this source.
-                * The Tristate JJY-01 ( Firmware version 1.01 ) accepts "time" and "stim" commands without any delay.
-                * But the JJY-01 ( Firmware version 2.01 ) does not accept these commands continuously,
-                * so this driver issues the second command "stim" after the reply of the first command "date".
-                */
+       if ( iLen != tristate_jjy01_command_sequence[up->iCommandSeq].iExpectedReplyLength[0]
+         && iLen != tristate_jjy01_command_sequence[up->iCommandSeq].iExpectedReplyLength[1] ) {
+               /* Unexpected reply length */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
+                         iLen ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
 
-               /*** 2010/11/20 ***/
-               /*
-                * Codes of a next command issue are moved to the end of this function.
-                */
+       /* Parse reply */
+
+       switch ( tristate_jjy01_command_sequence[up->iCommandSeq].commandNumber ) {
+
+       case TS_JJY01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD WWW */
 
-               /*** End of modification ***/
+               rc = sscanf ( pBuf, "%4d/%2d/%2d",
+                             &up->year, &up->month, &up->day ) ;
+
+               if ( rc != 3 || up->year < 2000 || 2099 <= up->year
+                 || up->month < 1 || 12 < up->month
+                 || up->day < 1 || 31 < up->day ) {
+                       /* Invalid date */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE,
+                                 rc, up->year, up->month, up->day ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
 
                break ;
 
        case TS_JJY01_COMMAND_NUMBER_TIME : /* HH:MM:SS */
        case TS_JJY01_COMMAND_NUMBER_STIM : /* HH:MM:SS */
 
-               if ( iLen != TS_JJY01_REPLY_LENGTH_STIM ) {
-                       up->lineerror = 1 ;
-                       break ;
+               if ( up->iTimestampCount >= 2 ) {
+                       /* Too many time reply */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY,
+                                 up->iTimestampCount ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
                }
 
-               rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour,
-                             &up->minute, &up->second ) ;
+               rc = sscanf ( pBuf, "%2d:%2d:%2d",
+                             &up->hour, &up->minute, &up->second ) ;
+
                if ( rc != 3 || up->hour > 23 || up->minute > 59 ||
                     up->second > 60 ) {
-                       up->lineerror = 1 ;
-                       break ;
+                       /* Invalid time */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME,
+                                 rc, up->hour, up->minute, up->second ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
                }
 
+               up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ;
+
+               up->iTimestampCount++ ;
+
                up->msecond = 0 ;
-               if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) {
-                       /*
-                        * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver separately,
-                        * and the JJY receiver replies a date and time separately.
-                        * Just after midnight transitions, we ignore this time.
-                        */
-                       bOverMidnight = 1 ;
-               }
+
                break ;
 
        case TS_JJY01_COMMAND_NUMBER_STUS :
 
-               if ( ( iLen == TS_JJY01_REPLY_LENGTH_STUS_YES
-                   && strncmp( pBuf, TS_JJY01_REPLY_STUS_YES,
-                               TS_JJY01_REPLY_LENGTH_STUS_YES ) == 0 )
-                 || ( iLen == TS_JJY01_REPLY_LENGTH_STUS_NO
-                   && strncmp( pBuf, TS_JJY01_REPLY_STUS_NO,
-                               TS_JJY01_REPLY_LENGTH_STUS_NO ) == 0 ) ) {
+               if ( strncmp( pBuf, TS_JJY01_REPLY_STUS_ADJUSTED,
+                            TS_JJY01_REPLY_LENGTH_STUS_ADJUSTED ) == 0
+                 || strncmp( pBuf, TS_JJY01_REPLY_STUS_UNADJUSTED,
+                            TS_JJY01_REPLY_LENGTH_STUS_UNADJUSTED ) == 0 ) {
                        /* Good */
                } else {
-                       up->lineerror = 1 ;
-                       break ;
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
+                                 pBuf ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
                }
 
                break ;
 
        case TS_JJY01_COMMAND_NUMBER_DCST :
 
-               if ( ( iLen == TS_JJY01_REPLY_LENGTH_DCST_VALID
-                   && strncmp( pBuf, TS_JJY01_REPLY_DCST_VALID,
-                               TS_JJY01_REPLY_LENGTH_DCST_VALID ) == 0 )
-                 || ( iLen == TS_JJY01_REPLY_LENGTH_DCST_INVALID
-                   && strncmp( pBuf, TS_JJY01_REPLY_DCST_INVALID,
-                               TS_JJY01_REPLY_LENGTH_DCST_INVALID ) == 0 ) ) {
+               if ( strncmp( pBuf, TS_JJY01_REPLY_DCST_VALID,
+                            TS_JJY01_REPLY_LENGTH_DCST_VALID ) == 0
+                 || strncmp( pBuf, TS_JJY01_REPLY_DCST_INVALID,
+                            TS_JJY01_REPLY_LENGTH_DCST_INVALID ) == 0 ) {
                        /* Good */
                } else {
-                       up->lineerror = 1 ;
-                       break ;
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
+                                 pBuf ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
                }
 
-               break ;
+               break ;
+
+       default : /*  Unexpected reply */
+
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
+                         pBuf ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+
+       }
+
+       if ( up->iTimestampCount == 2 ) {
+               /* Process date and time */
+
+               if ( up->iTimestamp[1] - 2 <= up->iTimestamp[0]
+                 && up->iTimestamp[0]     <= up->iTimestamp[1] ) {
+                       /* 3 commands (time,date,stim) was excuted in two seconds */
+                       jjy_synctime( peer, pp, up ) ;
+                       return JJY_RECEIVE_DONE ;
+               } else if ( up->iTimestamp[0] > up->iTimestamp[1] ) {
+                       /* Over midnight, and date is unsure */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2,
+                                 up->iTimestamp[0], up->iTimestamp[1] ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
+                       return JJY_RECEIVE_SKIP ;
+               } else {
+                       /* Slow reply */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2,
+                                 up->iTimestamp[0], up->iTimestamp[1] ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
+
+       }
+
+       /* Issue next command */
+
+       if ( tristate_jjy01_command_sequence[up->iCommandSeq].command != NULL ) {
+               up->iCommandSeq ++ ;
+       }
+
+       if ( tristate_jjy01_command_sequence[up->iCommandSeq].command == NULL ) {
+               /* Command sequence completed */
+               return JJY_RECEIVE_DONE ;
+       }
+
+       pCmd =  tristate_jjy01_command_sequence[up->iCommandSeq].command ;
+       iCmdLen = tristate_jjy01_command_sequence[up->iCommandSeq].commandLength ;
+       if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+               refclock_report ( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
+
+       return JJY_RECEIVE_WAIT ;
+
+}
+
+/**************************************************************************************************/
+
+static void
+jjy_poll_tristate_jjy01  ( int unit, struct peer *peer )
+{
+#ifdef DEBUG
+       static const char *sFunctionName = "jjy_poll_tristate_jjy01" ;
+#endif
+
+       struct refclockproc *pp ;
+       struct jjyunit      *up ;
+
+       const char *pCmd ;
+       int     iCmdLen ;
+
+       pp = peer->procptr;
+       up = pp->unitptr ;
+
+       up->bLineError = FALSE ;
+       up->iTimestampCount = 0 ;
+
+       if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
+               /* Skip "dcst" and "stus" commands */
+               up->iCommandSeq = 2 ;
+               up->iLineCount = 2 ;
+       }
+
+#ifdef DEBUG
+       if ( debug ) {
+               printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->iLineCount=%d\n",
+                       sFunctionName, pp->sloppyclockflag, CLK_FLAG1,
+                       up->iLineCount ) ;
+       }
+#endif
+
+       /*
+        * Send a first command
+        */
+
+       up->iCommandSeq ++ ;
+
+       pCmd =  tristate_jjy01_command_sequence[up->iCommandSeq].command ;
+       iCmdLen = tristate_jjy01_command_sequence[up->iCommandSeq].commandLength ;
+       if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+               refclock_report ( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
+
+}
+
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    The C-DEX Co. Ltd. JJY receiver JST2000                                                        ##*/
+/*##                                                                                           ##*/
+/*##    server  127.127.40.X  mode 2                                                           ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
+/*                                                                                                */
+/*  Command               Response                                  Remarks                       */
+/*  --------------------  ----------------------------------------  ----------------------------  */
+/*  <ENQ>1J<ETX>          <STX>JYYMMDD HHMMSSS<ETX>                 J is a fixed character        */
+/*                                                                                                */
+/*################################################################################################*/
+
+static struct jjyRawDataBreak cdex_jst2000_raw_break [ ] =
+{
+       { "\x03", 1 }, { NULL, 0 }
+} ;
+
+/**************************************************************************************************/
+
+static int
+jjy_start_cdex_jst2000 ( int unit, struct peer *peer, struct jjyunit *up )
+{
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: C-DEX Co. Ltd. JST2000" ) ;
+
+       up->unittype  = UNITTYPE_CDEX_JST2000 ;
+       up->linespeed = SPEED232_CDEX_JST2000 ;
+       up->linediscipline = LDISC_RAW ;
+
+       up->pRawBreak = cdex_jst2000_raw_break ;
+       up->bWaitBreakString = TRUE ;
+
+       up->bSkipCntrlCharOnly = FALSE ;
+
+       return 0 ;
+
+}
+
+/**************************************************************************************************/
+
+static int
+jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
+{
+
+       struct jjyunit      *up ;
+       struct refclockproc *pp ;
+       struct peer         *peer ;
+
+       char    *pBuf, sLog [ 100 ] ;
+       int     iLen ;
+       int     rc ;
+
+       /* Initialize pointers */
+
+       peer = rbufp->recv_peer ;
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       if ( up->linediscipline == LDISC_RAW ) {
+               pBuf = up->sTextBuf ;
+               iLen = up->iTextBufLen ;
+       } else {
+               pBuf = pp->a_lastcode ;
+               iLen = pp->lencode ;
+       }
+
+       DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_cdex_jst2000", iLen ) ;
+
+       /* Check expected reply */
+
+       if ( up->iCommandSeq != 1 ) {
+               /* Command sequence has not been started, or has been completed */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
+                         pBuf ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
+
+       /* Wait until ETX comes */
+
+       if ( up->iLineBufLen < 17 || up->sLineBuf[up->iLineBufLen-1] != 0x03 ) {
+               return JJY_RECEIVE_UNPROCESS ;
+       }
+
+       /* Check reply length */
+
+       if ( iLen != 15 ) {
+               /* Unexpected reply length */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
+                         iLen ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
+
+       /* JYYMMDD HHMMSSS */
+
+       rc = sscanf ( pBuf, "J%2d%2d%2d %2d%2d%2d%1d",
+                     &up->year, &up->month, &up->day,
+                     &up->hour, &up->minute, &up->second,
+                     &up->msecond ) ;
+
+       if ( rc != 7 || up->month < 1 || up->month > 12 ||
+            up->day < 1 || up->day > 31 || up->hour > 23 ||
+            up->minute > 59 || up->second > 60 ) {
+               /* Invalid date and time */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME,
+                         rc, up->year, up->month, up->day,
+                         up->hour, up->minute, up->second ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
+
+       up->year    += 2000 ;
+       up->msecond *= 100 ;
+
+       jjy_synctime( peer, pp, up ) ;
+
+       return JJY_RECEIVE_DONE ;
+
+}
+
+/**************************************************************************************************/
+
+static void
+jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
+{
+
+       struct refclockproc *pp ;
+       struct jjyunit      *up ;
+
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       up->bLineError = FALSE ;
+       up->iRawBufLen = 0 ;
+       up->iLineBufLen = 0 ;
+       up->iTextBufLen = 0 ;
+
+       /*
+        * Send "<ENQ>1J<ETX>" command
+        */
+
+       up->iCommandSeq ++ ;
+
+       if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4  ) {
+               refclock_report ( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, "\0051J\003" ) ;
+
+}
+
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    The Echo Keisokuki Co. Ltd. JJY receiver LT2000                                                ##*/
+/*##                                                                                           ##*/
+/*##    server  127.127.40.X  mode 3                                                           ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
+/*                                                                                                */
+/*  Command               Response                                  Remarks                       */
+/*  --------------------  ----------------------------------------  ----------------------------  */
+/*  #                                                               Mode 1 ( Request & Send )     */
+/*  T                     YYMMDDWHHMMSS<BCC1><BCC2><CR>                                           */
+/*  C                                                               Mode 2 ( Continuous )         */
+/*                        YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR>     0.5 sec before time stamp     */
+/*                        <SUB>                                     Second signal                 */
+/*                                                                                                */
+/*################################################################################################*/
+
+#define        ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND          1
+#define        ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS            2
+#define        ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS  3
+
+#define        ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND       "#"
+#define        ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_TIME       "T"
+#define        ECHOKEISOKUKI_LT2000_COMMAND_CONTINUOUS         "C"
+
+/**************************************************************************************************/
+
+static int
+jjy_start_echokeisokuki_lt2000 ( int unit, struct peer *peer, struct jjyunit *up )
+{
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Echo Keisokuki Co. Ltd. LT2000" ) ;
+
+       up->unittype  = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
+       up->linespeed = SPEED232_ECHOKEISOKUKI_LT2000 ;
+       up->linediscipline = LDISC_CLK ;
+
+       up->operationmode = ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ;
+
+       return 0 ;
+
+}
+
+/**************************************************************************************************/
+
+static int
+jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
+{
+
+       struct jjyunit      *up ;
+       struct refclockproc *pp ;
+       struct peer         *peer;
+
+       char    *pBuf, sLog [ 100 ], sErr [ 60 ] ;
+       int     iLen ;
+       int     rc ;
+       int     i, ibcc, ibcc1, ibcc2 ;
+
+       /* Initialize pointers */
+
+       peer = rbufp->recv_peer ;
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       if ( up->linediscipline == LDISC_RAW ) {
+               pBuf = up->sTextBuf ;
+               iLen = up->iTextBufLen ;
+       } else {
+               pBuf = pp->a_lastcode ;
+               iLen = pp->lencode ;
+       }
+
+       DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_echokeisokuki_lt2000", iLen ) ;
+
+       /* Check reply length */
+
+       if ( ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND
+              && iLen != 15 )
+         || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS
+              && iLen != 17 )
+         || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS
+              && iLen != 17 ) ) {
+               /* Unexpected reply length */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
+                         iLen ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
+
+       if ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND && iLen == 15 ) {
+               /* YYMMDDWHHMMSS<BCC1><BCC2> */
+
+               for ( i = ibcc = 0 ; i < 13 ; i ++ ) {
+                       ibcc ^= pBuf[i] ;
+               }
+
+               ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
+               ibcc2 = 0x30 | ( ( ibcc      ) & 0xF ) ;
+               if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
+                       snprintf( sErr, sizeof(sErr)-1, " BCC error : Recv=%02X,%02X / Calc=%02X,%02X ",
+                                 pBuf[13] & 0xFF, pBuf[14] & 0xFF,
+                                 ibcc1, ibcc2 ) ;
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
+                                 sErr ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
+
+       }
+
+       if ( ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND
+              && iLen == 15 )
+         || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS
+              && iLen == 17 )
+         || ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS
+              && iLen == 17 ) ) {
+               /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
+
+               rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
+                             &up->year, &up->month, &up->day,
+                             &up->hour, &up->minute, &up->second ) ;
+
+               if ( rc != 6 || up->month < 1 || up->month > 12
+                 || up->day < 1 || up->day > 31
+                 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+                       /* Invalid date and time */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME,
+                                 rc, up->year, up->month, up->day,
+                                 up->hour, up->minute, up->second ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
+
+               up->year += 2000 ;
+
+               if ( up->operationmode == ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS
+                 || up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ) {
+                       /* A time stamp comes on every 0.5 second in the mode 2 of the LT-2000. */
+
+                       up->msecond = 500 ;
+                       up->second -- ;
+                       if ( up->second < 0 ) {
+                               up->second = 59 ;
+                               up->minute -- ;
+                               if ( up->minute < 0 ) {
+                                       up->minute = 59 ;
+                                       up->hour -- ;
+                                       if ( up->hour < 0 ) {
+                                               up->hour = 23 ;
+                                               up->day -- ;
+                                               if ( up->day < 1 ) {
+                                                       up->month -- ;
+                                                       if ( up->month < 1 ) {
+                                                               up->month = 12 ;
+                                                               up->year -- ;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+               }
+
+               jjy_synctime( peer, pp, up ) ;
+
+
+       }
+
+       if (up->operationmode == ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS ) {
+               /* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
+
+               iLen = strlen( ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND ) ;
+               if ( write ( pp->io.fd, ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND, iLen ) != iLen  ) {
+                       refclock_report ( peer, CEVNT_FAULT ) ;
+               }
+
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, ECHOKEISOKUKI_LT2000_COMMAND_REQUEST_SEND ) ;
+
+       }
+
+       return JJY_RECEIVE_DONE ;
+
+}
+
+/**************************************************************************************************/
+
+static void
+jjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer )
+{
+
+       struct refclockproc *pp ;
+       struct jjyunit      *up ;
+
+       char    sCmd[2] ;
+
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       up->bLineError = FALSE ;
+
+       /*
+        * Send "T" or "C" command
+        */
+
+       switch ( up->operationmode ) {
+       case ECHOKEISOKUKI_LT2000_MODE_REQUEST_SEND :
+               sCmd[0] = 'T' ;
+               break ;
+       case ECHOKEISOKUKI_LT2000_MODE_CONTINUOUS :
+       case ECHOKEISOKUKI_LT2000_MODE_SWITCHING_CONTINUOUS :
+               sCmd[0] = 'C' ;
+               break ;
+       }
+       sCmd[1] = 0 ;
+
+       if ( write ( pp->io.fd, sCmd, 1 ) != 1  ) {
+               refclock_report ( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, sCmd ) ;
+
+}
+
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    The CITIZEN T.I.C CO., LTD. JJY receiver JJY200                                                ##*/
+/*##                                                                                           ##*/
+/*##    server  127.127.40.X  mode 4                                                           ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
+/*                                                                                                */
+/*  Command               Response                                  Remarks                       */
+/*  --------------------  ----------------------------------------  ----------------------------  */
+/*                        'XX YY/MM/DD W HH:MM:SS<CR>               XX:OK|NG|ER  W:0(Mon)-6(Sun)  */
+/*                                                                                                */
+/*################################################################################################*/
+
+static int
+jjy_start_citizentic_jjy200 ( int unit, struct peer *peer, struct jjyunit *up )
+{
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: CITIZEN T.I.C CO. LTD. JJY200" ) ;
+
+       up->unittype  = UNITTYPE_CITIZENTIC_JJY200 ;
+       up->linespeed = SPEED232_CITIZENTIC_JJY200 ;
+       up->linediscipline = LDISC_CLK ;
+
+       return 0 ;
+
+}
+
+/**************************************************************************************************/
+
+static int
+jjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp )
+{
+
+       struct jjyunit          *up ;
+       struct refclockproc     *pp ;
+       struct peer             *peer;
+
+       char    *pBuf, sLog [ 100 ], sMsg [ 16 ] ;
+       int     iLen ;
+       int     rc ;
+       char    cApostrophe, sStatus[3] ;
+       int     iWeekday ;
+
+       /* Initialize pointers */
+
+       peer = rbufp->recv_peer ;
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       if ( up->linediscipline == LDISC_RAW ) {
+               pBuf = up->sTextBuf ;
+               iLen = up->iTextBufLen ;
+       } else {
+               pBuf = pp->a_lastcode ;
+               iLen = pp->lencode ;
+       }
+
+       DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_citizentic_jjy200", iLen ) ;
+
+       /*
+        * JJY-200 sends a timestamp every second.
+        * So, a timestamp is ignored unless it is right after polled.
+        */
+
+       if ( up->iProcessState != JJY_PROCESS_STATE_RECEIVE ) {
+               return JJY_RECEIVE_SKIP ;
+       }
+
+       /* Check reply length */
+
+       if ( iLen != 23 ) {
+               /* Unexpected reply length */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
+                         iLen ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
+
+       /* 'XX YY/MM/DD W HH:MM:SS<CR> */
+
+       rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
+                     &cApostrophe, sStatus,
+                     &up->year, &up->month, &up->day, &iWeekday,
+                     &up->hour, &up->minute, &up->second ) ;
+       sStatus[2] = 0 ;
+
+       if ( rc != 9 || cApostrophe != '\''
+         || ( strcmp( sStatus, "OK" ) != 0
+           && strcmp( sStatus, "NG" ) != 0
+           && strcmp( sStatus, "ER" ) != 0 )
+         || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
+         || iWeekday > 6
+         || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+               /* Invalid date and time */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATETIME,
+                         rc, up->year, up->month, up->day,
+                         up->hour, up->minute, up->second ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       } else if ( strcmp( sStatus, "NG" ) == 0
+                || strcmp( sStatus, "ER" ) == 0 ) {
+               /* Timestamp is unsure */
+               snprintf( sMsg, sizeof(sMsg)-1, "status=%s", sStatus ) ;
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TIMESTAMP_UNSURE,
+                         sMsg ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ;
+               return JJY_RECEIVE_SKIP ;
+       }
+
+       up->year += 2000 ;
+       up->msecond = 0 ;
+
+       jjy_synctime( peer, pp, up ) ;
+
+       return JJY_RECEIVE_DONE ;
+
+}
+
+/**************************************************************************************************/
+
+static void
+jjy_poll_citizentic_jjy200 ( int unit, struct peer *peer )
+{
+
+       struct refclockproc *pp ;
+       struct jjyunit      *up ;
+
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       up->bLineError = FALSE ;
+
+}
+
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    The Tristate Ltd. GPS clock TS-GPS01                                                   ##*/
+/*##                                                                                           ##*/
+/*##    server  127.127.40.X  mode 5                                                           ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
+/*                                                                                                */
+/*  This clock has NMEA mode and command/respose mode.                                            */
+/*  When this jjy driver are used, set to command/respose mode of this clock                      */
+/*  by the onboard switch SW4, and make sure the LED-Y is tured on.                               */
+/*  Other than this JJY driver, the refclock driver type 20, generic NMEA driver,                 */
+/*  works with the NMEA mode of this clock.                                                       */
+/*                                                                                                */
+/*  Command               Response                                  Remarks                       */
+/*  --------------------  ----------------------------------------  ----------------------------  */
+/*  stus<CR><LF>          *R|*G|*U|+U<CR><LF>                                                     */
+/*  date<CR><LF>          YY/MM/DD<CR><LF>                                                        */
+/*  time<CR><LF>          HH:MM:SS<CR><LF>                                                        */
+/*                                                                                                */
+/*################################################################################################*/
+
+#define        TS_GPS01_COMMAND_NUMBER_DATE    1
+#define        TS_GPS01_COMMAND_NUMBER_TIME    2
+#define        TS_GPS01_COMMAND_NUMBER_STUS    4
+
+#define        TS_GPS01_REPLY_DATE             "yyyy/mm/dd"
+#define        TS_GPS01_REPLY_TIME             "hh:mm:ss"
+#define        TS_GPS01_REPLY_STUS_RTC         "*R"
+#define        TS_GPS01_REPLY_STUS_GPS         "*G"
+#define        TS_GPS01_REPLY_STUS_UTC         "*U"
+#define        TS_GPS01_REPLY_STUS_PPS         "+U"
+
+#define        TS_GPS01_REPLY_LENGTH_DATE          10  /* Length without <CR><LF> */
+#define        TS_GPS01_REPLY_LENGTH_TIME          8   /* Length without <CR><LF> */
+#define        TS_GPS01_REPLY_LENGTH_STUS          2   /* Length without <CR><LF> */
+
+static  struct
+{
+       char    commandNumber ;
+       const char      *command ;
+       int     commandLength ;
+       int     iExpectedReplyLength ;
+} tristate_gps01_command_sequence[] =
+{
+       { 0, NULL, 0, 0 }, /* Idle */
+       { TS_GPS01_COMMAND_NUMBER_STUS, "stus\r\n", 6, TS_GPS01_REPLY_LENGTH_STUS },
+       { TS_GPS01_COMMAND_NUMBER_TIME, "time\r\n", 6, TS_GPS01_REPLY_LENGTH_TIME },
+       { TS_GPS01_COMMAND_NUMBER_DATE, "date\r\n", 6, TS_GPS01_REPLY_LENGTH_DATE },
+       { TS_GPS01_COMMAND_NUMBER_TIME, "time\r\n", 6, TS_GPS01_REPLY_LENGTH_TIME },
+       /* End of command */
+       { 0, NULL, 0, 0 }
+} ;
+
+/**************************************************************************************************/
+
+static int
+jjy_start_tristate_gpsclock01 ( int unit, struct peer *peer, struct jjyunit *up )
+{
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Tristate Ltd. TS-GPS01" ) ;
+
+       up->unittype  = UNITTYPE_TRISTATE_GPSCLOCK01 ;
+       up->linespeed = SPEED232_TRISTATE_GPSCLOCK01 ;
+       up->linediscipline = LDISC_CLK ;
+
+       return 0 ;
+
+}
+
+/**************************************************************************************************/
+
+static int
+jjy_receive_tristate_gpsclock01 ( struct recvbuf *rbufp )
+{
+#ifdef DEBUG
+       static  const char      *sFunctionName = "jjy_receive_tristate_gpsclock01" ;
+#endif
+
+       struct jjyunit      *up ;
+       struct refclockproc *pp ;
+       struct peer         *peer;
+
+       char    *pBuf, sLog [ 100 ] ;
+       int     iLen ;
+       int     rc ;
+
+       const char      *pCmd ;
+       int     iCmdLen ;
+
+       /* Initialize pointers */
+
+       peer = rbufp->recv_peer ;
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       if ( up->linediscipline == LDISC_RAW ) {
+               pBuf = up->sTextBuf ;
+               iLen = up->iTextBufLen ;
+       } else {
+               pBuf = pp->a_lastcode ;
+               iLen = pp->lencode ;
+       }
+
+       DEBUG_PRINTF_JJY_RECEIVE( "jjy_receive_tristate_gpsclock01", iLen ) ;
+
+       /* Ignore NMEA data stream */
+
+       if ( iLen > 5
+         && ( strncmp( pBuf, "$GP", 3 ) == 0 || strncmp( pBuf, "$PFEC", 5 ) == 0 ) ) {
+#ifdef DEBUG
+               if ( debug ) {
+                       printf ( "%s (refclock_jjy.c) : Skip NMEA stream [%s]\n",
+                               sFunctionName, pBuf ) ;
+               }
+#endif
+               return JJY_RECEIVE_WAIT ;
+       }
+
+       /*
+        * Skip command prompt '$Cmd>' from the TS-GPSclock-01
+        */
+       if ( iLen == 5 && strncmp( pBuf, "$Cmd>", 5 ) == 0 ) {
+               return JJY_RECEIVE_WAIT ;
+       } else if ( iLen > 5 && strncmp( pBuf, "$Cmd>", 5 ) == 0 ) {
+               pBuf += 5 ;
+               iLen -= 5 ;
+       }
+
+       /*
+        * Ignore NMEA data stream after command prompt
+        */
+       if ( iLen > 5
+         && ( strncmp( pBuf, "$GP", 3 ) == 0 || strncmp( pBuf, "$PFEC", 5 ) == 0 ) ) {
+#ifdef DEBUG
+               if ( debug ) {
+                       printf ( "%s (refclock_jjy.c) : Skip NMEA stream [%s]\n",
+                               sFunctionName, pBuf ) ;
+               }
+#endif
+               return JJY_RECEIVE_WAIT ;
+       }
+
+       /* Check expected reply */
+
+       if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) {
+               /* Command sequence has not been started, or has been completed */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
+                         pBuf ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
+
+       /* Check reply length */
+
+       if ( iLen != tristate_gps01_command_sequence[up->iCommandSeq].iExpectedReplyLength ) {
+               /* Unexpected reply length */
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_LENGTH,
+                         iLen ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+       }
+
+       /* Parse reply */
+
+       switch ( tristate_gps01_command_sequence[up->iCommandSeq].commandNumber ) {
+
+       case TS_GPS01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD */
+
+               rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
+
+               if ( rc != 3 || up->year < 2000 || 2099 <= up->year
+                 || up->month < 1 || 12 < up->month
+                 || up->day < 1 || 31 < up->day ) {
+                       /* Invalid date */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE,
+                                 rc, up->year, up->month, up->day ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
+
+               break ;
+
+       case TS_GPS01_COMMAND_NUMBER_TIME : /* HH:MM:SS */
+
+               if ( up->iTimestampCount >= 2 ) {
+                       /* Too many time reply */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_TOO_MANY_REPLY,
+                                 up->iTimestampCount ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
+
+               rc = sscanf ( pBuf, "%2d:%2d:%2d",
+                             &up->hour, &up->minute, &up->second ) ;
+
+               if ( rc != 3
+                 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+                       /* Invalid time */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME,
+                                 rc, up->hour, up->minute, up->second ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
+
+               up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ;
+
+               up->iTimestampCount++ ;
+
+               up->msecond = 0 ;
+
+               break ;
+
+       case TS_GPS01_COMMAND_NUMBER_STUS :
+
+               if ( strncmp( pBuf, TS_GPS01_REPLY_STUS_RTC, TS_GPS01_REPLY_LENGTH_STUS ) == 0
+                 || strncmp( pBuf, TS_GPS01_REPLY_STUS_GPS, TS_GPS01_REPLY_LENGTH_STUS ) == 0
+                 || strncmp( pBuf, TS_GPS01_REPLY_STUS_UTC, TS_GPS01_REPLY_LENGTH_STUS ) == 0
+                 || strncmp( pBuf, TS_GPS01_REPLY_STUS_PPS, TS_GPS01_REPLY_LENGTH_STUS ) == 0 ) {
+                       /* Good */
+               } else {
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
+                                 pBuf ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
+
+               break ;
+
+       default : /*  Unexpected reply */
+
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_INVALID_REPLY,
+                         pBuf ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+               up->bLineError = TRUE ;
+               return JJY_RECEIVE_ERROR ;
+
+       }
+
+       if ( up->iTimestampCount == 2 ) {
+               /* Process date and time */
+
+               if ( up->iTimestamp[1] - 2 <= up->iTimestamp[0]
+                 && up->iTimestamp[0]     <= up->iTimestamp[1] ) {
+                       /* 3 commands (time,date,stim) was excuted in two seconds */
+                       jjy_synctime( peer, pp, up ) ;
+                       return JJY_RECEIVE_DONE ;
+               } else if ( up->iTimestamp[0] > up->iTimestamp[1] ) {
+                       /* Over midnight, and date is unsure */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_OVER_MIDNIGHT_2,
+                                 up->iTimestamp[0], up->iTimestamp[1] ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
+                       return JJY_RECEIVE_SKIP ;
+               } else {
+                       /* Slow reply */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SLOW_REPLY_2,
+                                 up->iTimestamp[0], up->iTimestamp[1] ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+                       return JJY_RECEIVE_ERROR ;
+               }
+
+       }
+
+       if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) {
+               /* Command sequence completed */
+               jjy_synctime( peer, pp, up ) ;
+               return JJY_RECEIVE_DONE ;
+       }
+
+       /* Issue next command */
+
+       if ( tristate_gps01_command_sequence[up->iCommandSeq].command != NULL ) {
+               up->iCommandSeq ++ ;
+       }
+
+       if ( tristate_gps01_command_sequence[up->iCommandSeq].command == NULL ) {
+               /* Command sequence completed */
+               up->iProcessState = JJY_PROCESS_STATE_DONE ;
+               return JJY_RECEIVE_DONE ;
+       }
+
+       pCmd =  tristate_gps01_command_sequence[up->iCommandSeq].command ;
+       iCmdLen = tristate_gps01_command_sequence[up->iCommandSeq].commandLength ;
+       if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+               refclock_report ( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
+
+       return JJY_RECEIVE_WAIT ;
+
+}
+
+/**************************************************************************************************/
+
+static void
+jjy_poll_tristate_gpsclock01 ( int unit, struct peer *peer )
+{
+#ifdef DEBUG
+       static const char *sFunctionName = "jjy_poll_tristate_gpsclock01" ;
+#endif
+
+       struct refclockproc *pp ;
+       struct jjyunit      *up ;
+
+       const char      *pCmd ;
+       int     iCmdLen ;
+
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       up->iTimestampCount = 0 ;
+
+       if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
+               /* Skip "stus" command */
+               up->iCommandSeq = 1 ;
+               up->iLineCount = 1 ;
+       }
+
+#ifdef DEBUG
+       if ( debug ) {
+               printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->iLineCount=%d\n",
+                       sFunctionName, pp->sloppyclockflag, CLK_FLAG1,
+                       up->iLineCount ) ;
+       }
+#endif
+
+       /*
+        * Send a first command
+        */
+
+       up->iCommandSeq ++ ;
+
+       pCmd =  tristate_gps01_command_sequence[up->iCommandSeq].command ;
+       iCmdLen = tristate_gps01_command_sequence[up->iCommandSeq].commandLength ;
+       if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+               refclock_report ( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
+
+}
+
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    Telephone JJY                                                                          ##*/
+/*##                                                                                           ##*/
+/*##    server  127.127.40.X  mode 100 to 180                                                  ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
+/*                                                                                                */
+/*  Prompt                Command               Response              Remarks                     */
+/*  --------------------  --------------------  --------------------  --------------------------  */
+/*  Name<SP>?<SP>         TJJY<CR>              Welcome messages      TJJY is a guest user ID     */
+/*  >                     4DATE<CR>             YYYYMMDD<CR>                                      */
+/*  >                     LEAPSEC<CR>           XX<CR>                One of <SP>0, +1, -1        */
+/*  >                     TIME<CR>              HHMMSS<CR>            3 times on second           */
+/*  >                     BYE<CR>               Sayounara messages                                */
+/*                                                                                                */
+/*################################################################################################*/
+
+static struct jjyRawDataBreak teljjy_raw_break [ ] =
+{
+       { "\r\n", 2 },
+       { "\r"  , 1 },
+       { "\n"  , 1 },
+       { "Name ? ", 7 },
+       { ">"   , 1 },
+       { "+++" , 3 },
+       { NULL  , 0 }
+} ;
+
+#define        TELJJY_STATE_IDLE       0
+#define        TELJJY_STATE_DAILOUT    1
+#define        TELJJY_STATE_LOGIN      2
+#define        TELJJY_STATE_CONNECT    3
+#define        TELJJY_STATE_BYE        4
+
+#define        TELJJY_EVENT_NULL       0
+#define        TELJJY_EVENT_START      1
+#define        TELJJY_EVENT_CONNECT    2
+#define        TELJJY_EVENT_DISCONNECT 3
+#define        TELJJY_EVENT_COMMAND    4
+#define        TELJJY_EVENT_LOGIN      5       /* Posted by the jjy_receive_telephone */
+#define        TELJJY_EVENT_PROMPT     6       /* Posted by the jjy_receive_telephone */
+#define        TELJJY_EVENT_DATA       7       /* Posted by the jjy_receive_telephone */
+#define        TELJJY_EVENT_ERROR      8       /* Posted by the jjy_receive_telephone */
+#define        TELJJY_EVENT_SILENT     9       /* Posted by the jjy_timer_telephone */
+#define        TELJJY_EVENT_TIMEOUT    10      /* Posted by the jjy_timer_telephone */
+
+static void    teljjy_control          ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+
+static int     teljjy_idle_ignore      ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_idle_dialout     ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_dial_ignore      ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_dial_login       ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_dial_disc        ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_login_ignore     ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_login_disc       ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_login_conn       ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_login_login      ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_login_silent     ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_login_error      ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_conn_ignore      ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_conn_disc        ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_conn_send        ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_conn_data        ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_conn_silent      ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_conn_error       ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_bye_ignore       ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_bye_disc         ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+static int     teljjy_bye_modem        ( struct peer *peer, struct refclockproc *, struct jjyunit * ) ;
+
+static int ( *pTeljjyHandler [ ] [ 5 ] ) ( ) =
+{                      /*STATE_IDLE           STATE_DAILOUT       STATE_LOGIN           STATE_CONNECT       STATE_BYE        */
+/* NULL       */       { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore },
+/* START      */       { teljjy_idle_dialout, teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore },
+/* CONNECT    */       { teljjy_idle_ignore , teljjy_dial_login , teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_ignore },
+/* DISCONNECT */       { teljjy_idle_ignore , teljjy_dial_disc  , teljjy_login_disc  , teljjy_conn_disc  , teljjy_bye_disc   },
+/* COMMAND    */       { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_ignore, teljjy_bye_modem  },
+/* LOGIN      */       { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_login , teljjy_conn_error , teljjy_bye_ignore },
+/* PROMPT     */       { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_conn  , teljjy_conn_send  , teljjy_bye_ignore },
+/* DATA       */       { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_ignore, teljjy_conn_data  , teljjy_bye_ignore },
+/* ERROR      */       { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_error , teljjy_conn_error , teljjy_bye_ignore },
+/* SILENT     */       { teljjy_idle_ignore , teljjy_dial_ignore, teljjy_login_silent, teljjy_conn_silent, teljjy_bye_ignore },
+/* TIMEOUT    */       { teljjy_idle_ignore , teljjy_dial_disc  , teljjy_login_error , teljjy_conn_error , teljjy_bye_modem  }
+} ;
+
+static short iTeljjyNextState [ ] [ 5 ] =
+{                      /*STATE_IDLE            STATE_DAILOUT         STATE_LOGIN           STATE_CONNECT         STATE_BYE         */
+/* NULL       */       { TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
+/* START      */       { TELJJY_STATE_DAILOUT, TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
+/* CONNECT    */       { TELJJY_STATE_IDLE   , TELJJY_STATE_LOGIN  , TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
+/* DISCONNECT */       { TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE },
+/* COMMAND    */       { TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
+/* LOGIN      */       { TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_BYE    , TELJJY_STATE_BYE  },
+/* PROMPT     */       { TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_CONNECT, TELJJY_STATE_BYE    , TELJJY_STATE_BYE  },
+/* DATA       */       { TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
+/* ERROR      */       { TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_BYE    , TELJJY_STATE_BYE    , TELJJY_STATE_BYE  },
+/* SILENT     */       { TELJJY_STATE_IDLE   , TELJJY_STATE_DAILOUT, TELJJY_STATE_LOGIN  , TELJJY_STATE_CONNECT, TELJJY_STATE_BYE  },
+/* TIMEOUT    */       { TELJJY_STATE_IDLE   , TELJJY_STATE_IDLE   , TELJJY_STATE_BYE    , TELJJY_STATE_BYE    , TELJJY_STATE_BYE  }
+} ;
+
+static short iTeljjyPostEvent [ ] [ 5 ] =
+{                      /*STATE_IDLE         STATE_DAILOUT      STATE_LOGIN           STATE_CONNECT         STATE_BYE         */
+/* NULL       */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
+/* START      */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
+/* CONNECT    */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
+/* DISCONNECT */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
+/* COMMAND    */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
+/* LOGIN      */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL },
+/* PROMPT     */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_PROMPT , TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL },
+/* DATA       */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
+/* ERROR      */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_COMMAND, TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL },
+/* SILENT     */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL   , TELJJY_EVENT_NULL },
+/* TIMEOUT    */       { TELJJY_EVENT_NULL, TELJJY_EVENT_NULL, TELJJY_EVENT_COMMAND, TELJJY_EVENT_COMMAND, TELJJY_EVENT_NULL }
+} ;
+
+static short iTeljjySilentTimeout [ 5 ] = { 0,   0, 10,  5,  0 } ;
+static short iTeljjyStateTimeout  [ 5 ] = { 0, 120, 60, 60, 40 } ;
+
+#define        TELJJY_STAY_CLOCK_STATE         0
+#define        TELJJY_CHANGE_CLOCK_STATE       1
+
+/* Command and replay */
+
+#define        TELJJY_REPLY_NONE       0
+#define        TELJJY_REPLY_4DATE      1
+#define        TELJJY_REPLY_TIME       2
+#define        TELJJY_REPLY_LEAPSEC    3
+#define        TELJJY_REPLY_LOOP       4
+#define        TELJJY_REPLY_PROMPT     5
+#define        TELJJY_REPLY_LOOPBACK   6
+#define        TELJJY_REPLY_COM        7
+
+#define        TELJJY_COMMAND_START_SKIP_LOOPBACK      7
+
+static  struct
+{
+       const char      *command ;
+       int     commandLength ;
+       int     iEchobackReplyLength ;
+       int     iExpectedReplyType   ;
+       int     iExpectedReplyLength ;
+} teljjy_command_sequence[] =
+{
+       { NULL, 0, 0, 0, 0 }, /* Idle */
+       { "LOOP\r"   , 5, 4, TELJJY_REPLY_LOOP    , 0 }, /* Getting into loopback mode */
+       { ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
+       { ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
+       { ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
+       { ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
+       { ">"        , 1, 1, TELJJY_REPLY_LOOPBACK, 0 }, /* Loopback measuring of delay time */
+       { "COM\r"    , 4, 3, TELJJY_REPLY_COM     , 0 }, /* Exit from loopback mode */
+       /* TELJJY_COMMAND_START_SKIP_LOOPBACK */
+       { "TIME\r"   , 5, 4, TELJJY_REPLY_TIME    , 6 },
+       { "4DATE\r"  , 6, 5, TELJJY_REPLY_4DATE   , 8 },
+       { "LEAPSEC\r", 8, 7, TELJJY_REPLY_LEAPSEC , 2 },
+       { "TIME\r"   , 5, 4, TELJJY_REPLY_TIME    , 6 },
+       { "BYE\r"    , 4, 3, TELJJY_REPLY_NONE    , 0 },
+       /* End of command */
+       { NULL, 0, 0, 0, 0 }
+} ;
+
+#define        TELJJY_LOOPBACK_DELAY_THRESHOLD         700 /* Milli second */
+
+#ifdef DEBUG
+#define        DEBUG_TELJJY_PRINTF(sFunc)      { if ( debug ) { printf ( "refclock_jjy.c : %s : iClockState=%d iClockEvent=%d iTeljjySilentTimer=%d iTeljjyStateTimer=%d iClockCommandSeq=%d\n", sFunc, up->iClockState, up->iClockEvent, up->iTeljjySilentTimer, up->iTeljjyStateTimer, up->iClockCommandSeq ) ; } }
+#else
+#define        DEBUG_TELJJY_PRINTF(sFunc)
+#endif
+
+/**************************************************************************************************/
+
+static int
+jjy_start_telephone ( int unit, struct peer *peer, struct jjyunit *up )
+{
+
+       char    sLog [ 80 ], sFirstThreeDigits [ 4 ] ;
+       int     i, iNumberOfDigitsOfPhoneNumber, iCommaCount, iCommaPosition ;
+       int     iFirstThreeDigitsCount ;
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, "Refclock: Telephone JJY" ) ;
+
+       up->unittype  = UNITTYPE_TELEPHONE ;
+       up->linespeed = SPEED232_TELEPHONE ;
+       up->linediscipline = LDISC_RAW ;
+
+       up->pRawBreak = teljjy_raw_break ;
+       up->bWaitBreakString = TRUE ;
+
+       up->bSkipCntrlCharOnly = TRUE ;
+
+       up->iClockState = TELJJY_STATE_IDLE ;
+       up->iClockEvent = TELJJY_EVENT_NULL ;
+
+       /* Check the telephone number */
+
+       if ( sys_phone[0] == NULL ) {
+               msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf must be specified." ) ;
+               up->bInitError = TRUE ;
+               return 1 ;
+       }
+
+       if ( sys_phone[1] != NULL ) {
+               msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be only one." ) ;
+               up->bInitError = TRUE ;
+               return 1 ;
+       }
+
+       iNumberOfDigitsOfPhoneNumber = iCommaCount = iCommaPosition = iFirstThreeDigitsCount = 0 ;
+       for ( i = 0 ; i < strlen( sys_phone[0] ) ; i ++ ) {
+               if ( isdigit( *(sys_phone[0]+i) ) ) {
+                       if ( iFirstThreeDigitsCount < MAX_LOOPBACK ) {
+                               sFirstThreeDigits[iFirstThreeDigitsCount++] = *(sys_phone[0]+i) ;
+                       }
+                       iNumberOfDigitsOfPhoneNumber ++ ;
+               } else if ( *(sys_phone[0]+i) == ',' ) {
+                       iCommaCount ++ ;
+                       if ( iCommaCount > 1 ) {
+                               msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be zero or one comma." ) ;
+                               up->bInitError = TRUE ;
+                               return 1 ;
+                       }
+                       iFirstThreeDigitsCount = 0 ;
+                       iCommaPosition = i ;
+               } else if ( *(sys_phone[0]+i) != '-' ) {
+                       msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone in the ntpd.conf should be a number or a hyphen." ) ;
+                       up->bInitError = TRUE ;
+                       return 1 ;
+               }
+       }
+       sFirstThreeDigits[iFirstThreeDigitsCount] = 0 ;
+
+       if ( iCommaCount == 1 ) {
+               if ( iCommaPosition != 1 || *sys_phone[0] != '0' ) {
+                       msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : Getting an outside line should be '0,'." ) ;
+                       up->bInitError = TRUE ;
+                       return 1 ;
+               }
+       }
+
+       if ( iNumberOfDigitsOfPhoneNumber - iCommaPosition < 6 || 10 < iNumberOfDigitsOfPhoneNumber - iCommaPosition ) {
+               /* Too short or too long */
+               msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone=%s : Number of digits should be 6 to 10.", sys_phone[0] ) ;
+               up->bInitError = TRUE ;
+               return 1 ;
+       }
+
+       if ( strncmp( sFirstThreeDigits + iCommaPosition, "00" , 2 ) == 0
+         || strncmp( sFirstThreeDigits + iCommaPosition, "10" , 2 ) == 0
+         || strncmp( sFirstThreeDigits + iCommaPosition, "11" , 2 ) == 0
+         || strncmp( sFirstThreeDigits + iCommaPosition, "12" , 2 ) == 0
+         || strncmp( sFirstThreeDigits + iCommaPosition, "171", 3 ) == 0
+         || strncmp( sFirstThreeDigits + iCommaPosition, "177", 3 ) == 0
+         || ( sFirstThreeDigits[0] == '0' &&  sFirstThreeDigits[2] == '0' ) ) {
+               /* Not allowed because of emergency numbers or special service numbers */
+               msyslog( LOG_ERR, "refclock_jjy.c : jjy_start_telephone : phone=%s : First 2 or 3 digits are not allowed.", sys_phone[0] ) ;
+               up->bInitError = TRUE ;
+               return 1 ;
+       }
+
+       snprintf( sLog, sizeof(sLog), "phone=%s", sys_phone[0] ) ;
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ;
+
+       if ( peer->minpoll < 8 ) {
+               /* minpoll must be greater or equal to 8 ( 256 seconds = about 4 minutes ) */
+               int oldminpoll = peer->minpoll ;
+               peer->minpoll = 8 ;
+               if ( peer->ppoll < peer->minpoll ) {
+                       peer->ppoll = peer->minpoll ;
+               }
+               if ( peer->maxpoll < peer->minpoll ) {
+                       peer->maxpoll = peer->minpoll ;
+               }
+               snprintf( sLog, sizeof(sLog), "minpoll=%d -> %d", oldminpoll, peer->minpoll ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_JJY, sLog ) ;
+       }
+
+       return 0 ;
+
+}
+
+/**************************************************************************************************/
+
+static int
+jjy_receive_telephone ( struct recvbuf *rbufp )
+{
+#ifdef DEBUG
+       static  const char      *sFunctionName = "jjy_receive_telephone" ;
+#endif
+
+       struct  peer         *peer;
+       struct  refclockproc *pp ;
+       struct  jjyunit      *up ;
+       char    *pBuf ;
+       int     iLen ;
+       short   iPreviousModemState ;
+
+       peer = rbufp->recv_peer ;
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       DEBUG_TELJJY_PRINTF( sFunctionName ) ;
+
+       if ( up->iClockState == TELJJY_STATE_IDLE
+         || up->iClockState == TELJJY_STATE_DAILOUT
+         || up->iClockState == TELJJY_STATE_BYE ) {
+
+               iPreviousModemState = getModemState( up ) ;
+
+               modem_receive ( rbufp ) ;
+
+               if ( iPreviousModemState != up->iModemState ) {
+                       /* Modem state is changed just now. */
+                       if ( isModemStateDisconnect( up->iModemState ) ) {
+                               up->iClockEvent = TELJJY_EVENT_DISCONNECT ;
+                               teljjy_control ( peer, pp, up ) ;
+                       } else if ( isModemStateConnect( up->iModemState ) ) {
+                               up->iClockEvent = TELJJY_EVENT_CONNECT ;
+                               teljjy_control ( peer, pp, up ) ;
+                       }
+               }
+
+               return JJY_RECEIVE_WAIT ;
+
+       }
+
+       if ( up->linediscipline == LDISC_RAW ) {
+               pBuf = up->sTextBuf ;
+               iLen = up->iTextBufLen ;
+       } else {
+               pBuf = pp->a_lastcode ;
+               iLen = pp->lencode ;
+       }
+
+       up->iTeljjySilentTimer = 0 ;
+       if      ( iLen == 7 && strncmp( pBuf, "Name ? ", 7 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_LOGIN  ; }
+       else if ( iLen == 1 && strncmp( pBuf, ">"      , 1 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_PROMPT ; }
+       else if ( iLen >= 1 && strncmp( pBuf, "?"      , 1 ) == 0 ) { up->iClockEvent = TELJJY_EVENT_ERROR  ; }
+       else                                                        { up->iClockEvent = TELJJY_EVENT_DATA   ; }
+
+       teljjy_control ( peer, pp, up ) ;
+
+       return JJY_RECEIVE_WAIT ;
+
+}
+
+/**************************************************************************************************/
+
+static void
+jjy_poll_telephone ( int unit, struct peer *peer )
+{
+#ifdef DEBUG
+       static const char *sFunctionName = "jjy_poll_telephone" ;
+#endif
+
+       struct  refclockproc *pp ;
+       struct  jjyunit      *up ;
+
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       DEBUG_TELJJY_PRINTF( sFunctionName ) ;
+
+       if ( up->iClockState == TELJJY_STATE_IDLE ) {
+               up->iRawBufLen = 0 ;
+               up->iLineBufLen = 0 ;
+               up->iTextBufLen = 0 ;
+       }
+
+       up->iClockEvent = TELJJY_EVENT_START ;
+       teljjy_control ( peer, pp, up ) ;
+
+}
+
+/**************************************************************************************************/
+
+static void
+jjy_timer_telephone ( int unit, struct peer *peer )
+{
+#ifdef DEBUG
+       static const char *sFunctionName = "jjy_timer_telephone" ;
+#endif
+
+       struct  refclockproc *pp ;
+       struct  jjyunit      *up ;
+       short   iPreviousModemState ;
+
+       pp = peer->procptr ;
+       up = pp->unitptr ;
+
+       DEBUG_TELJJY_PRINTF( sFunctionName ) ;
+
+       if ( iTeljjySilentTimeout[up->iClockState] != 0 ) {
+               up->iTeljjySilentTimer++ ;
+               if ( iTeljjySilentTimeout[up->iClockState] <= up->iTeljjySilentTimer ) {
+                       up->iClockEvent = TELJJY_EVENT_SILENT ;
+                       teljjy_control ( peer, pp, up ) ;
+               }
+       }
+
+       if ( iTeljjyStateTimeout[up->iClockState] != 0 ) {
+               up->iTeljjyStateTimer++ ;
+               if ( iTeljjyStateTimeout[up->iClockState] <= up->iTeljjyStateTimer ) {
+                       up->iClockEvent = TELJJY_EVENT_TIMEOUT ;
+                       teljjy_control ( peer, pp, up ) ;
+               }
+       }
+
+       if ( isModemStateTimerOn( up ) ) {
+
+               iPreviousModemState = getModemState( up ) ;
+
+               modem_timer ( unit, peer ) ;
+
+               if ( iPreviousModemState != up->iModemState ) {
+                       /* Modem state is changed just now. */
+                       if ( isModemStateDisconnect( up->iModemState ) ) {
+                               up->iClockEvent = TELJJY_EVENT_DISCONNECT ;
+                               teljjy_control ( peer, pp, up ) ;
+                       } else if ( isModemStateConnect( up->iModemState ) ) {
+                               up->iClockEvent = TELJJY_EVENT_CONNECT ;
+                               teljjy_control ( peer, pp, up ) ;
+                       }
+               }
+
+       }
+
+}
+
+/**************************************************************************************************/
+
+static void
+teljjy_control ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       int     i, rc ;
+       short   iPostEvent = TELJJY_EVENT_NULL ;
+
+       DEBUG_TELJJY_PRINTF( "teljjy_control" ) ;
+
+       rc = (*pTeljjyHandler[up->iClockEvent][up->iClockState])( peer, pp, up ) ;
+
+       if ( rc == TELJJY_CHANGE_CLOCK_STATE ) {
+               iPostEvent = iTeljjyPostEvent[up->iClockEvent][up->iClockState] ;
+#ifdef DEBUG
+               if ( debug ) {
+                       printf( "refclock_jjy.c : teljjy_control : iClockState=%hd -> %hd  iPostEvent=%hd\n",
+                               up->iClockState, iTeljjyNextState[up->iClockEvent][up->iClockState], iPostEvent ) ;
+               }
+#endif
+               up->iTeljjySilentTimer = 0 ;
+               if ( up->iClockState != iTeljjyNextState[up->iClockEvent][up->iClockState] ) {
+                       /* Telephone JJY state is changing now */
+                       up->iTeljjyStateTimer = 0 ;
+                       up->bLineError = FALSE ;
+                       up->iClockCommandSeq = 0 ;
+                       up->iTimestampCount = 0 ;
+                       up->iLoopbackCount = 0 ;
+                       for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) {
+                               up->bLoopbackTimeout[i] = FALSE ;
+                       }
+                       if (iTeljjyNextState[up->iClockEvent][up->iClockState] == TELJJY_STATE_IDLE ) {
+                               /* Telephone JJY state is changing to IDLE just now */
+                               up->iProcessState = JJY_PROCESS_STATE_DONE ;
+                       }
+               }
+               up->iClockState = iTeljjyNextState[up->iClockEvent][up->iClockState] ;
+
+       }
+
+       if ( iPostEvent != TELJJY_EVENT_NULL ) {
+               up->iClockEvent = iPostEvent ;
+               teljjy_control ( peer, pp, up ) ;
+       }
+
+       up->iClockEvent = TELJJY_EVENT_NULL ;
+
+}
+
+/**************************************************************************************************/
+
+static void
+teljjy_setDelay ( struct peer *peer, struct jjyunit *up )
+{
+
+       char    sLog [ 60 ] ;
+       int     milliSecond, microSecond ;
+
+       gettimeofday( &(up->delayTime[up->iLoopbackCount]), NULL ) ;
+
+       up->delayTime[up->iLoopbackCount].tv_sec  -= up->sendTime[up->iLoopbackCount].tv_sec ;
+       up->delayTime[up->iLoopbackCount].tv_usec -= up->sendTime[up->iLoopbackCount].tv_usec ;
+       if ( up->delayTime[up->iLoopbackCount].tv_usec < 0 ) {
+               up->delayTime[up->iLoopbackCount].tv_sec -- ;
+               up->delayTime[up->iLoopbackCount].tv_usec += 1000000 ;
+       }
+
+       milliSecond  = up->delayTime[up->iLoopbackCount].tv_usec / 1000 ;
+       microSecond  = up->delayTime[up->iLoopbackCount].tv_usec - milliSecond * 1000 ;
+       milliSecond += up->delayTime[up->iLoopbackCount].tv_sec * 1000 ;
+
+       snprintf( sLog, sizeof(sLog), JJY_CLOCKSTATS_MESSAGE_LOOPBACK_DELAY,
+                 milliSecond, microSecond ) ;
+
+       if ( milliSecond > TELJJY_LOOPBACK_DELAY_THRESHOLD ) {
+               /* Delay > 700 mS */
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ;
+       } else {
+               /* Delay <= 700 mS */
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
+       }
+
+}
+
+/**************************************************************************************************/
+
+static int
+teljjy_getDelay ( struct peer *peer, struct jjyunit *up )
+{
+
+       struct  timeval maxTime, minTime, averTime ;
+       int     i ;
+       int     minIndex = 0, maxIndex = 0, iAverCount = 0 ;
+       int     iThresholdSecond, iThresholdMicroSecond ;
+       int     iPercent ;
+
+       minTime.tv_sec = minTime.tv_usec = 0 ;
+       maxTime.tv_sec = maxTime.tv_usec = 0 ;
+
+       iThresholdSecond = TELJJY_LOOPBACK_DELAY_THRESHOLD / 1000 ;
+       iThresholdMicroSecond = ( TELJJY_LOOPBACK_DELAY_THRESHOLD - ( TELJJY_LOOPBACK_DELAY_THRESHOLD / 1000 ) * 1000 ) * 1000 ;
+
+       up->iLoopbackValidCount = 0 ;
+
+       for ( i = 0 ; i < MAX_LOOPBACK && i < up->iLoopbackCount ; i ++ ) {
+               if ( up->bLoopbackTimeout[i]
+                 || up->delayTime[i].tv_sec  > iThresholdSecond
+               || ( up->delayTime[i].tv_sec == iThresholdSecond
+                 && up->delayTime[i].tv_usec > iThresholdMicroSecond ) ) {
+                       continue ;
+               }
+               if ( up->iLoopbackValidCount == 0 ) {
+                       minTime.tv_sec  = up->delayTime[i].tv_sec  ;
+                       minTime.tv_usec = up->delayTime[i].tv_usec ;
+                       maxTime.tv_sec  = up->delayTime[i].tv_sec  ;
+                       maxTime.tv_usec = up->delayTime[i].tv_usec ;
+                       minIndex = maxIndex = i ;
+               } else if ( minTime.tv_sec  > up->delayTime[i].tv_sec
+                      || ( minTime.tv_sec == up->delayTime[i].tv_sec
+                        && minTime.tv_usec > up->delayTime[i].tv_usec ) ) {
+                       minTime.tv_sec  = up->delayTime[i].tv_sec  ;
+                       minTime.tv_usec = up->delayTime[i].tv_usec ;
+                       minIndex = i ;
+               } else if ( maxTime.tv_sec  < up->delayTime[i].tv_sec
+                      || ( maxTime.tv_sec == up->delayTime[i].tv_sec
+                        && maxTime.tv_usec < up->delayTime[i].tv_usec ) ) {
+                       maxTime.tv_sec  = up->delayTime[i].tv_sec  ;
+                       maxTime.tv_usec = up->delayTime[i].tv_usec ;
+                       maxIndex = i ;
+               }
+               up->iLoopbackValidCount ++ ;
+       }
+
+       if ( up->iLoopbackValidCount < 2 ) {
+               return -1 ;
+       }
+
+       averTime.tv_usec = 0;
+
+       for ( i = 0 ; i < MAX_LOOPBACK && i < up->iLoopbackCount ; i ++ ) {
+               if ( up->bLoopbackTimeout[i]
+                 || up->delayTime[i].tv_sec  > iThresholdSecond
+               || ( up->delayTime[i].tv_sec == iThresholdSecond
+                 && up->delayTime[i].tv_usec > iThresholdMicroSecond ) ) {
+                       continue ;
+               }
+               if ( up->iLoopbackValidCount >= 3 && i == maxIndex ) {
+                       continue ;
+               }
+               if ( up->iLoopbackValidCount >= 4 && i == minIndex ) {
+                       continue ;
+               }
+               averTime.tv_usec += up->delayTime[i].tv_usec ;
+               iAverCount ++ ;
+       }
+
+       /* mode 101 = 1%, mode 150 = 50%, mode 180 = 80% */
+
+       iPercent = ( peer->ttl - 100 ) ;
+
+       /* Average delay time in milli second */
+
+       return ( ( averTime.tv_usec / iAverCount ) * iPercent ) / 100000 ;
+
+}
+
+/******************************/
+static int
+teljjy_idle_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_idle_ignore" ) ;
+
+       return TELJJY_STAY_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_idle_dialout ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_idle_dialout" ) ;
+
+       modem_connect ( peer->refclkunit, peer ) ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_dial_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_dial_ignore" ) ;
+
+       return TELJJY_STAY_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_dial_login ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_dial_login" ) ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_dial_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_dial_disc" ) ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_login_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_login_ignore" ) ;
+
+       return TELJJY_STAY_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_login_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_login_disc" ) ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_login_conn ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       int     i ;
+
+       DEBUG_TELJJY_PRINTF( "teljjy_login_conn" ) ;
+
+       up->bLineError = FALSE ;
+       up->iClockCommandSeq = 0 ;
+       up->iTimestampCount = 0 ;
+       up->iLoopbackCount = 0 ;
+       for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) {
+               up->bLoopbackTimeout[i] = FALSE ;
+       }
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_login_login ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       char    *pCmd ;
+       int     iCmdLen ;
+
+       DEBUG_TELJJY_PRINTF( "teljjy_login_login" ) ;
+
+       /* Send a guest user ID */
+       pCmd = "TJJY\r" ;
+
+       /* Send login ID */
+       iCmdLen = strlen( pCmd ) ;
+       if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+               refclock_report( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
+
+       return TELJJY_STAY_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_login_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_login_silent" ) ;
+
+       if ( write( pp->io.fd, "\r", 1 ) != 1 ) {
+               refclock_report( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, "\r" ) ;
+
+       up->iTeljjySilentTimer = 0 ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_login_error ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_login_error" ) ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_conn_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_conn_ignore" ) ;
+
+       return TELJJY_STAY_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_conn_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_conn_disc" ) ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_conn_send ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       const char      *pCmd ;
+       int     i, iLen, iNextClockState ;
+
+       DEBUG_TELJJY_PRINTF( "teljjy_conn_send" ) ;
+
+       if ( up->iClockCommandSeq > 0
+         && teljjy_command_sequence[up->iClockCommandSeq].command == NULL ) {
+               /* Command sequence has been completed */
+               return TELJJY_CHANGE_CLOCK_STATE ;
+       }
+
+       if ( up->iClockCommandSeq == 0 && peer->ttl == 100 ) {
+               /* Skip loopback */
+
+               up->iClockCommandSeq = TELJJY_COMMAND_START_SKIP_LOOPBACK ;
+
+       } else if ( up->iClockCommandSeq == 0 && peer->ttl != 100 ) {
+               /* Loopback start */
+
+               up->iLoopbackCount = 0 ;
+               for ( i = 0 ; i < MAX_LOOPBACK ; i ++ ) {
+                       up->bLoopbackTimeout[i] = FALSE ;
+               }
+
+       } else if ( up->iClockCommandSeq > 0 && peer->ttl != 100
+                && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK
+                && up->iLoopbackCount < MAX_LOOPBACK ) {
+               /* Loopback character comes */
+#ifdef DEBUG
+               if ( debug ) {
+                       printf( "refclock_jjy.c : teljjy_conn_send : iLoopbackCount=%d\n",
+                                up->iLoopbackCount ) ;
+               }
+#endif
+
+               teljjy_setDelay( peer, up ) ;
+
+               up->iLoopbackCount ++ ;
+
+       }
+
+       up->iClockCommandSeq++ ;
+
+       pCmd = teljjy_command_sequence[up->iClockCommandSeq].command ;
+       iLen = teljjy_command_sequence[up->iClockCommandSeq].commandLength ;
+       
+       if ( pCmd != NULL ) {
+
+               if ( write( pp->io.fd, pCmd, iLen ) != iLen ) {
+                       refclock_report( peer, CEVNT_FAULT ) ;
+               }
+
+               if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) {
+                       /* Loopback character and timestamp */
+                       gettimeofday( &(up->sendTime[up->iLoopbackCount]), NULL ) ;
+                       up->bLoopbackMode = TRUE ;
+               } else {
+                       /* Regular command */
+                       up->bLoopbackMode = FALSE ;
+               }
+
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
+
+               if ( teljjy_command_sequence[up->iClockCommandSeq+1].command == NULL ) {
+                       /* Last command of the command sequence */
+                       iNextClockState = TELJJY_CHANGE_CLOCK_STATE ;
+               } else {
+                       /* More commands to be issued */
+                       iNextClockState = TELJJY_STAY_CLOCK_STATE ;
+               }
+
+       } else {
+
+               iNextClockState = TELJJY_CHANGE_CLOCK_STATE ;
+
+       }
+
+       return iNextClockState ;
+
+}
+
+/******************************/
+static int
+teljjy_conn_data ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       char    *pBuf ;
+       int     iLen, rc ;
+       char    sLog [ 80 ] ;
+       char    bAdjustment ;
+
+
+       DEBUG_TELJJY_PRINTF( "teljjy_conn_data" ) ;
+
+       if ( up->linediscipline == LDISC_RAW ) {
+               pBuf = up->sTextBuf ;
+               iLen = up->iTextBufLen ;
+       } else {
+               pBuf = pp->a_lastcode ;
+               iLen = pp->lencode ;
+       }
+
+       if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength == iLen
+         && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK
+         && up->sTextBuf[0] == *(teljjy_command_sequence[up->iClockCommandSeq].command)
+         && up->iLoopbackCount < MAX_LOOPBACK ) {
+               /* Loopback */
+
+               teljjy_setDelay( peer, up ) ;
+
+               up->iLoopbackCount ++ ;
+
+       } else if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength == iLen
+           && strncmp( pBuf, teljjy_command_sequence[up->iClockCommandSeq].command, iLen ) == 0 ) {
+               /* Maybe echoback */
+
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, JJY_CLOCKSTATS_MESSAGE_ECHOBACK ) ;
+
+       } else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen
+                && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_4DATE ) {
+               /* 4DATE<CR> -> YYYYMMDD<CR> */
+
+               rc = sscanf ( pBuf, "%4d%2d%2d", &up->year, &up->month, &up->day ) ;
+
+               if ( rc != 3 || up->year < 2000 || 2099 <= up->year
+                 || up->month < 1 || 12 < up->month || up->day < 1 || 31 < up->day ) {
+                       /* Invalid date */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_DATE,
+                                 rc, up->year, up->month, up->day ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+               }
+
+       } else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen
+                && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LEAPSEC
+                && ( strncmp( pBuf, " 0", 2 ) == 0 || strncmp( pBuf, "+1", 2 ) == 0 || strncmp( pBuf, "-1", 2 ) == 0 ) ) {
+               /* LEAPSEC<CR> -> XX<CR> ( One of <SP>0, +1, -1 ) */
+
+               rc = sscanf ( pBuf, "%2d", &up->leapsecond ) ;
+
+               if ( rc != 1 || up->leapsecond < -1 || 1 < up->leapsecond ) {
+                       /* Invalid leap second */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_LEAP,
+                                 pBuf ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+               }
+
+       } else if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyLength == iLen
+                && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_TIME ) {
+               /* TIME<CR> -> HHMMSS<CR> ( 3 times on second ) */
+
+               rc = sscanf ( pBuf, "%2d%2d%2d", &up->hour, &up->minute, &up->second ) ;
+
+               if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+                       /* Invalid time */
+                       snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_SSCANF_INVALID_TIME,
+                                 rc, up->hour, up->minute, up->second ) ;
+                       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                       up->bLineError = TRUE ;
+               }
+               up->iTimestamp[up->iTimestampCount] = ( up->hour * 60 + up->minute ) * 60 + up->second ;
+
+               up->iTimestampCount++ ;
+
+               if ( up->iTimestampCount == 6 && ! up->bLineError ) {
+#if DEBUG
+                       printf( "refclock_jjy.c : teljjy_conn_data : bLineError=%d iTimestamp=%d, %d, %d\n",
+                               up->bLineError,
+                               up->iTimestamp[3], up->iTimestamp[4], up->iTimestamp[5] ) ;
+#endif
+                       bAdjustment = TRUE ;
+
+                       if ( peer->ttl == 100 ) {
+                               /* mode=100 */
+                               up->msecond = 0 ;
+                       } else {
+                               /* mode=101 to 110 */
+                               up->msecond = teljjy_getDelay( peer, up ) ;
+                               if (up->msecond < 0 ) {
+                                       up->msecond = 0 ;
+                                       bAdjustment = FALSE ;
+                               }
+                       }
+
+                       if ( ( up->iTimestamp[3] - 15 ) <= up->iTimestamp[2]
+                         &&   up->iTimestamp[2]        <= up->iTimestamp[3]
+                         && ( up->iTimestamp[3] +  1 ) == up->iTimestamp[4]
+                         && ( up->iTimestamp[4] +  1 ) == up->iTimestamp[5] ) {
+                               /* Non over midnight */
+
+                               jjy_synctime( peer, pp, up ) ;
+
+                               if ( peer->ttl != 100 ) {
+                                       if ( bAdjustment ) {
+                                               snprintf( sLog, sizeof(sLog),
+                                                         JJY_CLOCKSTATS_MESSAGE_DELAY_ADJUST,
+                                                         up->msecond, up->iLoopbackValidCount, MAX_LOOPBACK ) ;
+                                               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_INFORMATION, sLog ) ;
+                                       } else {
+                                               snprintf( sLog, sizeof(sLog),
+                                                         JJY_CLOCKSTATS_MESSAGE_DELAY_UNADJUST,
+                                                          up->iLoopbackValidCount, MAX_LOOPBACK ) ;
+                                               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+                                       }
+                               }
+
+                       }
+               }
+
+       } else if ( teljjy_command_sequence[up->iClockCommandSeq].iEchobackReplyLength != iLen
+                && teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) {
+               /* Loopback noise ( Unexpected replay ) */
+
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_IGNORE_REPLY,
+                         pBuf ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_WARNING, sLog ) ;
+
+       } else {
+
+               up->bLineError = TRUE ;
+
+               snprintf( sLog, sizeof(sLog)-1, JJY_CLOCKSTATS_MESSAGE_UNEXPECTED_REPLY,
+                         pBuf ) ;
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_ERROR, sLog ) ;
+
+       }
+
+       return TELJJY_STAY_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_conn_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       const char      *pCmd ;
+
+       DEBUG_TELJJY_PRINTF( "teljjy_conn_silent" ) ;
+
+       if ( up->iClockCommandSeq >= 1
+         && up->iClockCommandSeq < TELJJY_COMMAND_START_SKIP_LOOPBACK ) {
+               /* Loopback */
+#ifdef DEBUG
+               if ( debug ) {
+                       printf( "refclock_jjy.c : teljjy_conn_silent : call teljjy_conn_send\n" ) ;
+               }
+#endif
+               if ( teljjy_command_sequence[up->iClockCommandSeq].iExpectedReplyType == TELJJY_REPLY_LOOPBACK ) {
+                       up->bLoopbackTimeout[up->iLoopbackCount] = TRUE ;
+               }
+               up->iTeljjySilentTimer = 0 ;
+               return teljjy_conn_send( peer, pp, up ) ;
+       } else {
+               pCmd = "\r" ;
+       }
+
+       if ( write( pp->io.fd, pCmd, 1 ) != 1 ) {
+               refclock_report( peer, CEVNT_FAULT ) ;
+       }
+
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
+
+       up->iTeljjySilentTimer = 0 ;
+
+       return TELJJY_STAY_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_conn_error ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_conn_error" ) ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_bye_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_bye_ignore" ) ;
+
+       return TELJJY_STAY_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_bye_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_bye_disc" ) ;
+
+       return TELJJY_CHANGE_CLOCK_STATE ;
+
+}
+
+/******************************/
+static int
+teljjy_bye_modem ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_TELJJY_PRINTF( "teljjy_bye_modem" ) ;
+
+       modem_disconnect ( peer->refclkunit, peer ) ;
 
-       default : /*  Unexpected reply */
+       return TELJJY_STAY_CLOCK_STATE ;
 
-               up->lineerror = 1 ;
-               break ;
+}
 
-       }
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    Modem control finite state machine                                                     ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
+
+/* struct jjyunit.iModemState */
+
+#define        MODEM_STATE_DISCONNECT          0
+#define        MODEM_STATE_INITIALIZE          1
+#define        MODEM_STATE_DAILING             2
+#define        MODEM_STATE_CONNECT             3
+#define        MODEM_STATE_ESCAPE              4
+
+/* struct jjyunit.iModemEvent */
+
+#define MODEM_EVENT_NULL               0
+#define        MODEM_EVENT_INITIALIZE          1
+#define        MODEM_EVENT_DIALOUT             2
+#define        MODEM_EVENT_DISCONNECT          3
+#define        MODEM_EVENT_RESP_OK             4
+#define        MODEM_EVENT_RESP_CONNECT        5
+#define        MODEM_EVENT_RESP_RING           6
+#define        MODEM_EVENT_RESP_NO_CARRIER     7
+#define        MODEM_EVENT_RESP_ERROR          8
+#define        MODEM_EVENT_RESP_CONNECT_X      9
+#define        MODEM_EVENT_RESP_NO_DAILTONE    10
+#define        MODEM_EVENT_RESP_BUSY           11
+#define        MODEM_EVENT_RESP_NO_ANSWER      12
+#define        MODEM_EVENT_RESP_UNKNOWN        13
+#define        MODEM_EVENT_SILENT              14
+#define        MODEM_EVENT_TIMEOUT             15
+
+/* Function prototypes */
+
+static void    modem_control           ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+
+static int     modem_disc_ignore       ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_disc_init         ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_init_ignore       ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_init_start        ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_init_disc         ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_init_resp00       ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_init_resp04       ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_dial_ignore       ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_dial_dialout      ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_dial_escape       ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_dial_connect      ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_dial_disc         ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_conn_ignore       ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_conn_escape       ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_esc_ignore        ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_esc_escape        ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_esc_data          ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_esc_silent        ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+static int     modem_esc_disc          ( struct peer *, struct refclockproc *, struct jjyunit * ) ;
+
+static int ( *pModemHandler [ ] [ 5 ] ) ( ) =
+{                              /*STATE_DISCONNECT   STATE_INITIALIZE   STATE_DAILING       STATE_CONNECT      STATE_ESCAPE     */
+/* NULL                 */     { modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_ignore },
+/* INITIALIZE           */     { modem_disc_init  , modem_init_start , modem_dial_ignore , modem_conn_ignore, modem_esc_ignore },
+/* DIALOUT              */     { modem_disc_ignore, modem_init_ignore, modem_dial_dialout, modem_conn_ignore, modem_esc_ignore },
+/* DISCONNECT           */     { modem_disc_ignore, modem_init_disc  , modem_dial_escape , modem_conn_escape, modem_esc_escape },
+/* RESP: 0: OK          */     { modem_disc_ignore, modem_init_resp00, modem_dial_ignore , modem_conn_ignore, modem_esc_data   },
+/* RESP: 1: CONNECT     */     { modem_disc_ignore, modem_init_ignore, modem_dial_connect, modem_conn_ignore, modem_esc_data   },
+/* RESP: 2: RING        */     { modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_data   },
+/* RESP: 3: NO CARRIER  */     { modem_disc_ignore, modem_init_ignore, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
+/* RESP: 4: ERROR       */     { modem_disc_ignore, modem_init_resp04, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
+/* RESP: 5: CONNECT     */     { modem_disc_ignore, modem_init_ignore, modem_dial_connect, modem_conn_ignore, modem_esc_data   },
+/* RESP: 6: NO DAILTONE */     { modem_disc_ignore, modem_init_ignore, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
+/* RESP: 7: BUSY        */     { modem_disc_ignore, modem_init_ignore, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
+/* RESP: 8: NO ANSWER   */     { modem_disc_ignore, modem_init_ignore, modem_dial_disc   , modem_conn_ignore, modem_esc_data   },
+/* RESP: 9: UNKNOWN     */     { modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_data   },
+/* SILENT               */     { modem_disc_ignore, modem_init_ignore, modem_dial_ignore , modem_conn_ignore, modem_esc_silent },
+/* TIMEOUT              */     { modem_disc_ignore, modem_init_disc  , modem_dial_escape , modem_conn_escape, modem_esc_disc   }
+} ;
 
-       /* Clockstats Log */
+static short iModemNextState [ ] [ 5 ] =
+{                              /*STATE_DISCONNECT        STATE_INITIALIZE        STATE_DAILING        STATE_CONNECT        STATE_ESCAPE           */
+/* NULL                 */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* INITIALIZE           */     { MODEM_STATE_INITIALIZE, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* DIALOUT              */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* DISCONNECT           */     { MODEM_STATE_DISCONNECT, MODEM_STATE_DISCONNECT, MODEM_STATE_ESCAPE    , MODEM_STATE_ESCAPE , MODEM_STATE_ESCAPE     },
+/* RESP: 0: OK          */     { MODEM_STATE_DISCONNECT, MODEM_STATE_DAILING   , MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 1: CONNECT     */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_CONNECT   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 2: RING        */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 3: NO CARRIER  */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 4: ERROR       */     { MODEM_STATE_DISCONNECT, MODEM_STATE_DAILING   , MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 5: CONNECT X   */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_CONNECT   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 6: NO DAILTONE */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 7: BUSY        */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 8: NO ANSWER   */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DISCONNECT, MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* RESP: 9: UNKNOWN     */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_ESCAPE     },
+/* SILENT               */     { MODEM_STATE_DISCONNECT, MODEM_STATE_INITIALIZE, MODEM_STATE_DAILING   , MODEM_STATE_CONNECT, MODEM_STATE_DISCONNECT },
+/* TIMEOUT              */     { MODEM_STATE_DISCONNECT, MODEM_STATE_DISCONNECT, MODEM_STATE_ESCAPE    , MODEM_STATE_ESCAPE , MODEM_STATE_DISCONNECT }
+} ;
 
-       printableString( sReplyText, sizeof(sReplyText), pBuf, iLen ) ;
-       snprintf ( sLogText, sizeof(sLogText), "%d: %s -> %c: %s",
-                  up->linecount,
-                  tristate_jjy01_command_sequence[up->linecount-1].commandLog,
-                  ( up->lineerror == 0 ) 
-                       ? ( ( bOverMidnight == 0 )
-                               ? 'O' 
-                               : 'S' ) 
-                       : 'X',
-                  sReplyText ) ;
-       record_clock_stats ( &peer->srcadr, sLogText ) ;
+static short iModemPostEvent [ ] [ 5 ] =
+{                              /*STATE_DISCONNECT        STATE_INITIALIZE     STATE_DAILING           STATE_CONNECT           STATE_ESCAPE     */
+/* NULL                 */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* INITIALIZE           */     { MODEM_EVENT_INITIALIZE, MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* DIALOUT              */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* DISCONNECT           */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_DISCONNECT, MODEM_EVENT_DISCONNECT, MODEM_EVENT_NULL },
+/* RESP: 0: OK          */     { MODEM_EVENT_NULL      , MODEM_EVENT_DIALOUT, MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 1: CONNECT     */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 2: RING        */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 3: NO CARRIER  */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 4: ERROR       */     { MODEM_EVENT_NULL      , MODEM_EVENT_DIALOUT, MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 5: CONNECT X   */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 6: NO DAILTONE */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 7: BUSY        */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 8: NO ANSWER   */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* RESP: 9: UNKNOWN     */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* SILENT               */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_NULL      , MODEM_EVENT_NULL      , MODEM_EVENT_NULL },
+/* TIMEOUT              */     { MODEM_EVENT_NULL      , MODEM_EVENT_NULL   , MODEM_EVENT_DISCONNECT, MODEM_EVENT_DISCONNECT, MODEM_EVENT_NULL }
+} ;
 
-       /* Check before issue next command */
+static short iModemSilentTimeout [ 5 ] = { 0,  0,  0, 0,  5 } ;
+static short iModemStateTimeout  [ 5 ] = { 0, 20, 90, 0, 20 } ;
 
-       if ( up->lineerror != 0 ) {
-               /* Do not issue next command */
-               return 0 ;
-       }
+#define        STAY_MODEM_STATE        0
+#define        CHANGE_MODEM_STATE      1
 
-       if ( bOverMidnight != 0 ) {
-               /* Do not issue next command */
-               return 0 ;
-       }
+#ifdef DEBUG
+#define        DEBUG_MODEM_PRINTF(sFunc)       { if ( debug ) { printf ( "refclock_jjy.c : %s : iModemState=%d iModemEvent=%d iModemSilentTimer=%d iModemStateTimer=%d\n", sFunc, up->iModemState, up->iModemEvent, up->iModemSilentTimer, up->iModemStateTimer ) ; } }
+#else
+#define        DEBUG_MODEM_PRINTF(sFunc)
+#endif
 
-       if ( tristate_jjy01_command_sequence[up->linecount].command == NULL ) {
-               /* Command sequence completed */
-               return 1 ;
-       }
+/**************************************************************************************************/
 
-       /* Issue next command */
+static short
+getModemState ( struct jjyunit *up )
+{
+       return up->iModemState ;
+}
 
-#ifdef DEBUG
-       if ( debug ) {
-               printf ( "%s (refclock_jjy.c) : send '%s'\n",
-                       sFunctionName, tristate_jjy01_command_sequence[up->linecount].commandLog ) ;
-       }
-#endif
+/**************************************************************************************************/
 
-       pCmd =  tristate_jjy01_command_sequence[up->linecount].command ;
-       iCmdLen = tristate_jjy01_command_sequence[up->linecount].commandLength ;
-       if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
-               refclock_report ( peer, CEVNT_FAULT ) ;
-       }
+static int
+isModemStateConnect ( short iCheckState )
+{
+       return ( iCheckState == MODEM_STATE_CONNECT ) ;
+}
 
-       return 0 ;
+/**************************************************************************************************/
 
+static int
+isModemStateDisconnect ( short iCheckState )
+{
+       return ( iCheckState == MODEM_STATE_DISCONNECT ) ;
 }
 
 /**************************************************************************************************/
 
 static int
-jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
+isModemStateTimerOn ( struct jjyunit *up )
 {
-#ifdef DEBUG
-       static  const char      *sFunctionName = "jjy_receive_cdex_jst2000" ;
-#endif
+       return ( iModemSilentTimeout[up->iModemState] != 0 || iModemStateTimeout[up->iModemState] != 0 ) ;
+}
 
-       struct jjyunit      *up ;
-       struct refclockproc *pp ;
-       struct peer         *peer;
+/**************************************************************************************************/
 
-       char    *pBuf ;
-       int     iLen ;
-       int     rc ;
+static void
+modem_connect ( int unit, struct peer *peer )
+{
+       struct  refclockproc    *pp;
+       struct  jjyunit         *up;
 
-       /*
-        * Initialize pointers and read the timecode and timestamp
-        */
-       peer = rbufp->recv_peer ;
        pp = peer->procptr ;
        up = pp->unitptr ;
 
-       if ( up->linediscipline == LDISC_RAW ) {
-               pBuf = up->rawbuf ;
-               iLen = up->charcount ;
-       } else {
-               pBuf = pp->a_lastcode ;
-               iLen = pp->lencode ;
-       }
+       DEBUG_MODEM_PRINTF( "modem_connect" ) ;
 
-       switch ( up->linecount ) {
+       up->iModemEvent = MODEM_EVENT_INITIALIZE ;
 
-       case 1 : /* JYYMMDD HHMMSSS */
+       modem_control ( peer, pp, up ) ;
 
-               if ( iLen != 15 ) {
-#ifdef DEBUG
-                       if ( debug >= 2 ) {
-                               printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
-                                        sFunctionName, iLen ) ;
-                       }
-#endif
-                       up->lineerror = 1 ;
-                       break ;
-               }
-               rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
-                             &up->year, &up->month, &up->day,
-                             &up->hour, &up->minute, &up->second,
-                             &up->msecond ) ;
-               if ( rc != 7 || up->month < 1 || up->month > 12 ||
-                    up->day < 1 || up->day > 31 || up->hour > 23 ||
-                    up->minute > 59 || up->second > 60 ) {
-#ifdef DEBUG
-                       if ( debug >= 2 ) {
-                               printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n",
-                                        sFunctionName, rc, up->year,
-                                        up->month, up->day, up->hour,
-                                        up->minute, up->second,
-                                        up->msecond ) ;
-                       }
-#endif
-                       up->lineerror = 1 ;
-                       break ;
-               }
-               up->year    += 2000 ;
-               up->msecond *= 100 ;
-               break ;
+}
 
-       default : /*  Unexpected reply */
+/**************************************************************************************************/
 
-               up->lineerror = 1 ;
-               break ;
+static void
+modem_disconnect ( int unit, struct peer *peer )
+{
+       struct  refclockproc    *pp;
+       struct  jjyunit         *up;
 
-       }
+       pp = peer->procptr ;
+       up = pp->unitptr ;
 
-       return 1 ;
+       DEBUG_MODEM_PRINTF( "modem_disconnect" ) ;
+
+       up->iModemEvent = MODEM_EVENT_DISCONNECT ;
+
+       modem_control ( peer, pp, up ) ;
 
 }
 
 /**************************************************************************************************/
 
 static int
-jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
+modem_receive ( struct recvbuf *rbufp )
 {
-#ifdef DEBUG
-       static  const char      *sFunctionName = "jjy_receive_echokeisokuki_lt2000" ;
-#endif
-
-       struct jjyunit      *up ;
-       struct refclockproc *pp ;
-       struct peer         *peer;
 
+       struct  peer            *peer;
+       struct  jjyunit         *up;
+       struct  refclockproc    *pp;
        char    *pBuf ;
-       int     iLen ;
-       int     rc ;
-       int     i, ibcc, ibcc1, ibcc2 ;
+       int     iLen ;
+
+#ifdef DEBUG
+       static const char *sFunctionName = "modem_receive" ;
+#endif
 
-       /*
-        * Initialize pointers and read the timecode and timestamp
-        */
        peer = rbufp->recv_peer ;
        pp = peer->procptr ;
        up = pp->unitptr ;
 
+       DEBUG_MODEM_PRINTF( sFunctionName ) ;
+
        if ( up->linediscipline == LDISC_RAW ) {
-               pBuf = up->rawbuf ;
-               iLen = up->charcount ;
+               pBuf = up->sTextBuf ;
+               iLen = up->iTextBufLen ;
        } else {
                pBuf = pp->a_lastcode ;
                iLen = pp->lencode ;
        }
 
-       switch ( up->linecount ) {
+       if      ( iLen ==  2 && strncmp( pBuf, "OK"         ,  2 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_OK          ; }
+       else if ( iLen ==  7 && strncmp( pBuf, "CONNECT"    ,  7 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_CONNECT     ; }
+       else if ( iLen ==  4 && strncmp( pBuf, "RING"       ,  4 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_RING        ; }
+       else if ( iLen == 10 && strncmp( pBuf, "NO CARRIER" , 10 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_CARRIER  ; }
+       else if ( iLen ==  5 && strncmp( pBuf, "ERROR"      ,  5 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_ERROR       ; }
+       else if ( iLen >=  8 && strncmp( pBuf, "CONNECT "   ,  8 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_CONNECT_X   ; }
+       else if ( iLen == 11 && strncmp( pBuf, "NO DAILTONE", 11 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_DAILTONE ; }
+       else if ( iLen ==  4 && strncmp( pBuf, "BUSY"       ,  4 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_BUSY        ; }
+       else if ( iLen ==  9 && strncmp( pBuf, "NO ANSWER"  ,  9 ) == 0 ) { up->iModemEvent = MODEM_EVENT_RESP_NO_ANSWER   ; }
+       else                                                              { up->iModemEvent = MODEM_EVENT_RESP_UNKNOWN     ; }
 
-       case 1 : /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
-
-               if ( ( up->operationmode == 1 && iLen != 15 ) ||
-                    ( up->operationmode == 2 && iLen != 17 ) ) {
-#ifdef DEBUG
-                       if ( debug >= 2 ) {
-                               printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
-                                        sFunctionName, iLen ) ;
-                       }
-#endif
-                       if ( up->operationmode == 1 ) {
 #ifdef DEBUG
-                               if ( debug ) {
-                                       printf ( "%s (refclock_jjy.c) : send '#'\n", __func__ ) ;
-                               }
+       if ( debug ) {
+               char    sResp [ 40 ] ;
+               int     iCopyLen ;
+               iCopyLen = ( iLen <= sizeof(sResp)-1 ? iLen : sizeof(sResp)-1 ) ;
+               strncpy( sResp, pBuf, iLen <= sizeof(sResp)-1 ? iLen : sizeof(sResp)-1 ) ;
+               sResp[iCopyLen] = 0 ;
+               printf ( "refclock_jjy.c : modem_receive : iLen=%d pBuf=[%s] iModemEvent=%d\n", iCopyLen, sResp, up->iModemEvent ) ;
+       }
 #endif
-                               if ( write ( pp->io.fd, "#",1 ) != 1  ) {
-                                       refclock_report ( peer, CEVNT_FAULT ) ;
-                               }
-                       }
-                       up->lineerror = 1 ;
-                       break ;
-               }
-
-               if ( up->operationmode == 1 ) {
+       modem_control ( peer, pp, up ) ;
 
-                       for ( i = ibcc = 0 ; i < 13 ; i ++ )
-                               ibcc ^= pBuf[i] ;
-                       ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
-                       ibcc2 = 0x30 | ( ( ibcc      ) & 0xF ) ;
-                       if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
-#ifdef DEBUG
-                               if ( debug >= 2 ) {
-                                       printf ( "%s (refclock_jjy.c) : BCC error ( Recv=%02X,%02X / Calc=%02X,%02X)\n",
-                                                sFunctionName,
-                                                pBuf[13] & 0xFF,
-                                                pBuf[14] & 0xFF,
-                                                ibcc1, ibcc2 ) ;
-                               }
-#endif
-                               up->lineerror = 1 ;
-                               break ;
-                       }
+       return 0 ;
 
-               }
+}
 
-               rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
-                             &up->year, &up->month, &up->day,
-                             &up->hour, &up->minute, &up->second ) ;
-               if ( rc != 6 || up->month < 1 || up->month > 12 ||
-                    up->day < 1 || up->day > 31 || up->hour > 23 ||
-                    up->minute > 59 || up->second > 60 ) {
-#ifdef DEBUG
-                       if ( debug >= 2 ) {
-                               printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d ]\n",
-                                        sFunctionName, rc, up->year,
-                                        up->month, up->day, up->hour,
-                                        up->minute, up->second ) ;
-                       }
-#endif
-                       up->lineerror = 1 ;
-                       break ;
-               }
+/**************************************************************************************************/
 
-               up->year += 2000 ;
+static void
+modem_timer ( int unit, struct peer *peer )
+{
 
-               if ( up->operationmode == 2 ) {
+       struct  refclockproc *pp ;
+       struct  jjyunit      *up ;
 
-                       /* A time stamp comes on every 0.5 seccond in the mode 2 of the LT-2000. */
-                       up->msecond = 500 ;
-                       pp->second -- ;
-                       if ( pp->second < 0 ) {
-                               pp->second = 59 ;
-                               pp->minute -- ;
-                               if ( pp->minute < 0 ) {
-                                       pp->minute = 59 ;
-                                       pp->hour -- ;
-                                       if ( pp->hour < 0 ) {
-                                               pp->hour = 23 ;
-                                               pp->day -- ;
-                                               if ( pp->day < 1 ) {
-                                                       pp->year -- ;
-                                                       pp->day  = ymd2yd ( pp->year, 12, 31 ) ;
-                                               }
-                                       }
-                               }
-                       }
+       pp = peer->procptr ;
+       up = pp->unitptr ;
 
-                       /* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
-#ifdef DEBUG
-                       if ( debug ) {
-                               printf ( "%s (refclock_jjy.c) : send '#'\n",
-                                        sFunctionName ) ;
-                       }
-#endif
-                       if ( write ( pp->io.fd, "#",1 ) != 1  ) {
-                               refclock_report ( peer, CEVNT_FAULT ) ;
-                       }
+       DEBUG_MODEM_PRINTF( "modem_timer" ) ;
 
+       if ( iModemSilentTimeout[up->iModemState] != 0 ) {
+               up->iModemSilentTimer++ ;
+               if ( iModemSilentTimeout[up->iModemState] <= up->iModemSilentTimer ) {
+                       up->iModemEvent = MODEM_EVENT_SILENT ;
+                       modem_control ( peer, pp, up ) ;
                }
+       }
 
-               break ;
-
-       default : /*  Unexpected reply */
-
-#ifdef DEBUG
-               if ( debug ) {
-                       printf ( "%s (refclock_jjy.c) : send '#'\n",
-                                sFunctionName ) ;
-               }
-#endif
-               if ( write ( pp->io.fd, "#",1 ) != 1  ) {
-                       refclock_report ( peer, CEVNT_FAULT ) ;
+       if ( iModemStateTimeout[up->iModemState] != 0 ) {
+               up->iModemStateTimer++ ;
+               if ( iModemStateTimeout[up->iModemState] <= up->iModemStateTimer ) {
+                       up->iModemEvent = MODEM_EVENT_TIMEOUT ;
+                       modem_control ( peer, pp, up ) ;
                }
-
-               up->lineerror = 1 ;
-               break ;
-
        }
 
-       return 1 ;
-
 }
 
 /**************************************************************************************************/
 
-static int
-jjy_receive_citizentic_jjy200 ( struct recvbuf *rbufp )
+static void
+modem_control ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
 {
-#ifdef DEBUG
-       static const char *sFunctionName = "jjy_receive_citizentic_jjy200" ;
-#endif
-
-       struct jjyunit          *up ;
-       struct refclockproc     *pp ;
-       struct peer             *peer;
 
-       char    *pBuf ;
-       int     iLen ;
        int     rc ;
-       char    cApostrophe, sStatus[3] ;
-       int     iWeekday ;
-
-       /*
-       * Initialize pointers and read the timecode and timestamp
-       */
-       peer = rbufp->recv_peer ;
-       pp = peer->procptr ;
-       up = pp->unitptr ;
-
-       if ( up->linediscipline == LDISC_RAW ) {
-               pBuf = up->rawbuf ;
-               iLen = up->charcount ;
-       } else {
-               pBuf = pp->a_lastcode ;
-               iLen = pp->lencode ;
-       }
-
-       /*
-       * JJY-200 sends a timestamp every second.
-       * So, a timestamp is ignored unless it is right after polled.
-       */
-       if ( ! up->bPollFlag )
-               return 0 ;
+       short   iPostEvent = MODEM_EVENT_NULL ;
 
-       switch ( up->linecount ) {
+       DEBUG_MODEM_PRINTF( "modem_control" ) ;
 
-       case 1 : /* 'XX YY/MM/DD W HH:MM:SS<CR> */
+       rc = (*pModemHandler[up->iModemEvent][up->iModemState])( peer, pp, up ) ;
 
-               if ( iLen != 23 ) {
+       if ( rc == CHANGE_MODEM_STATE ) {
+               iPostEvent = iModemPostEvent[up->iModemEvent][up->iModemState] ;
 #ifdef DEBUG
-                       if ( debug >= 2 ) {
-                               printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n",
-                                        sFunctionName, iLen ) ;
-                       }
-#endif
-                       up->lineerror = 1 ;
-                       break ;
+               if ( debug ) {
+                       printf( "refclock_jjy.c : modem_control : iModemState=%d -> %d  iPostEvent=%d\n",
+                                up->iModemState, iModemNextState[up->iModemEvent][up->iModemState], iPostEvent ) ;
                }
-
-               rc = sscanf ( pBuf, "%c%2s %2d/%2d/%2d %1d %2d:%2d:%2d",
-                             &cApostrophe, sStatus, &up->year,
-                             &up->month, &up->day, &iWeekday,
-                             &up->hour, &up->minute, &up->second ) ;
-               sStatus[2] = 0 ;
-               if ( rc != 9 || cApostrophe != '\'' ||
-                    strcmp( sStatus, "OK" ) != 0 || up->month < 1 ||
-                    up->month > 12 || up->day < 1 || up->day > 31 ||
-                    iWeekday > 6 || up->hour > 23 || up->minute > 59 ||
-                    up->second > 60 ) {
-#ifdef DEBUG
-                       if ( debug >= 2 ) {
-                               printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %c %2s %02d %02d %02d %d %02d %02d %02d ]\n",
-                                        sFunctionName, rc, cApostrophe,
-                                        sStatus, up->year, up->month,
-                                        up->day, iWeekday, up->hour,
-                                        up->minute, up->second ) ;
-                       }
 #endif
-                       up->lineerror = 1 ;
-                       break ;
+
+               if ( up->iModemState != iModemNextState[up->iModemEvent][up->iModemState] ) {
+                       up->iModemSilentCount = 0 ;
+                       up->iModemStateTimer = 0 ;
+                       up->iModemCommandSeq = 0 ;
                }
 
-               up->year += 2000 ;
-               up->msecond = 0 ;
+               up->iModemState = iModemNextState[up->iModemEvent][up->iModemState] ;
+       }
 
-               break ;
+       if ( iPostEvent != MODEM_EVENT_NULL ) {
+               up->iModemEvent = iPostEvent ;
+               modem_control ( peer, pp, up ) ;
+       }
 
-       default : /* Unexpected reply */
+       up->iModemEvent = MODEM_EVENT_NULL ;
 
-               up->lineerror = 1 ;
-               break ;
+}
 
-       }
+/******************************/
+static int
+modem_disc_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
-       return 1 ;
+       DEBUG_MODEM_PRINTF( "modem_disc_ignore" ) ;
 
-}
+       return STAY_MODEM_STATE ;
 
-/**************************************************************************************************/
+}
 
+/******************************/
 static int
-jjy_receive_tristate_gpsclock01 ( struct recvbuf *rbufp )
+modem_disc_init ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
 {
-#ifdef DEBUG
-       static  const char      *sFunctionName = "jjy_receive_tristate_gpsclock01" ;
-#endif
 
-       struct jjyunit      *up ;
-       struct refclockproc *pp ;
-       struct peer         *peer;
+       DEBUG_MODEM_PRINTF( "modem_disc_init" ) ;
 
-       char    *pBuf ;
-       int     iLen ;
-       int     rc ;
+       return CHANGE_MODEM_STATE ;
 
-       int     bOverMidnight = 0 ;
+}
 
-       char    sLogText [ MAX_LOGTEXT ], sReplyText [ MAX_LOGTEXT ] ;
+/******************************/
+static int
+modem_init_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
-       const char      *pCmd ;
-       int     iCmdLen ;
+       DEBUG_MODEM_PRINTF( "modem_init_ignore" ) ;
 
-       /*
-        * Initialize pointers and read the timecode and timestamp
-        */
-       peer = rbufp->recv_peer ;
-       pp = peer->procptr ;
-       up = pp->unitptr ;
+       return STAY_MODEM_STATE ;
 
-       if ( up->linediscipline == LDISC_RAW ) {
-               pBuf = up->rawbuf ;
-               iLen = up->charcount ;
-       } else {
-               pBuf = pp->a_lastcode ;
-               iLen = pp->lencode ;
-       }
+}
 
-       /*
-        * Ignore NMEA data stream
-        */
-       if ( iLen > 5
-         && ( strncmp( pBuf, "$GP", 3 ) == 0 || strncmp( pBuf, "$PFEC", 5 ) == 0 ) ) {
-#ifdef DEBUG
-               if ( debug ) {
-                       printf ( "%s (refclock_jjy.c) : Skip NMEA stream [%s]\n",
-                               sFunctionName, pBuf ) ;
-               }
-#endif
-               return 0 ;
-       }
+/******************************/
+static int
+modem_init_start ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
-       /*
-        * Skip command prompt '$Cmd>' from the TS-GPSclock-01
-        */
-       if ( iLen == 5 && strncmp( pBuf, "$Cmd>", 5 ) == 0 ) {
-               return 0 ;
-       } else if ( iLen > 5 && strncmp( pBuf, "$Cmd>", 5 ) == 0 ) {
-               pBuf += 5 ;
-               iLen -= 5 ;
-       }
+       DEBUG_MODEM_PRINTF( "modem_init_start" ) ;
+
+       up->iModemCommandSeq = 0 ;
 
-       /*
-        * Ignore NMEA data stream after command prompt
-        */
-       if ( iLen > 5
-         && ( strncmp( pBuf, "$GP", 3 ) == 0 || strncmp( pBuf, "$PFEC", 5 ) == 0 ) ) {
 #ifdef DEBUG
-               if ( debug ) {
-                       printf ( "%s (refclock_jjy.c) : Skip NMEA stream [%s]\n",
-                               sFunctionName, pBuf ) ;
-               }
-#endif
-               return 0 ;
+       if ( debug ) {
+               printf( "refclock_jjy.c : modem_init_start : call modem_init_resp00\n" ) ;
        }
+#endif
 
-       switch ( tristate_gpsclock01_command_sequence[up->linecount-1].commandNumber ) {
+       return modem_init_resp00( peer, pp, up ) ;
 
-       case TS_GPSCLOCK01_COMMAND_NUMBER_DATE : /* YYYY/MM/DD */
+}
 
-               if ( iLen != TS_GPSCLOCK01_REPLY_LENGTH_DATE ) {
-                       up->lineerror = 1 ;
-                       break ;
-               }
+/******************************/
+static int
+modem_init_resp00 ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
-               rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
-               if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 ||
-                    up->day < 1 || up->day > 31 ) {
-                       up->lineerror = 1 ;
-                       break ;
-               }
+       char    *pCmd, cBuf [ 46 ] ;
+       int     iCmdLen ;
+       int     iErrorCorrection, iSpeakerSwitch, iSpeakerVolume ;
+       int     iNextModemState = STAY_MODEM_STATE ;
 
-               break ;
+       DEBUG_MODEM_PRINTF( "modem_init_resp00" ) ;
 
-       case TS_GPSCLOCK01_COMMAND_NUMBER_TIME : /* HH:MM:SS */
+       up->iModemCommandSeq++ ;
 
-               if ( iLen != TS_GPSCLOCK01_REPLY_LENGTH_TIME ) {
-                       up->lineerror = 1 ;
-                       break ;
+       switch ( up->iModemCommandSeq ) {
+
+       case 1 :
+               /* En = Echoback      0:Off      1:On   */
+               /* Qn = Result codes  0:On       1:Off  */
+               /* Vn = Result codes  0:Numeric  1:Text */
+               pCmd = "ATE0Q0V1\r\n" ;
+               break ;
+
+       case 2 :
+               /* Mn = Speaker switch  0:Off  1:On until remote carrier detected  2:On */
+               if ( ( pp->sloppyclockflag & CLK_FLAG3 ) == 0 ) {
+                       /* fudge 127.127.40.n flag3 0 */
+                       iSpeakerSwitch = 0 ;
+               } else {
+                       /* fudge 127.127.40.n flag3 1 */
+                       iSpeakerSwitch = 2 ;
                }
 
-               rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ;
-               if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
-                       up->lineerror = 1 ;
-                       break ;
+               /* Ln = Speaker volume  0:Very low  1:Low  2:Middle  3:High */
+               if ( ( pp->sloppyclockflag & CLK_FLAG4 ) == 0 ) {
+                       /* fudge 127.127.40.n flag4 0 */
+                       iSpeakerVolume = 1 ;
+               } else {
+                       /* fudge 127.127.40.n flag4 1 */
+                       iSpeakerVolume = 2 ;
                }
 
-               up->msecond = 0 ;
+               pCmd = cBuf ;
+               snprintf( pCmd, sizeof(cBuf), "ATM%dL%d\r\n", iSpeakerSwitch, iSpeakerVolume ) ;
+               break ;
 
-               if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) {
-                       /*
-                        * The command "date" and "time" were sent to the JJY receiver separately,
-                        * and the JJY receiver replies a date and time separately.
-                        * Just after midnight transitions, we ignore this time.
-                        */
-                       bOverMidnight = 1 ;
-               }
+       case 3 :
+               /* &Kn = Flow control  4:XON/XOFF */
+               pCmd = "AT&K4\r\n" ;
+               break ;
 
+       case 4 :
+               /* +MS = Protocol  V22B:1200,2400bps\81iV.22bis) */
+               pCmd = "AT+MS=V22B\r\n" ;
                break ;
 
-       case TS_GPSCLOCK01_COMMAND_NUMBER_STUS :
+       case 5 :
+               /* %Cn = Data compression  0:No data compression */
+               pCmd = "AT%C0\r\n" ;
+               break ;
 
-               if ( iLen == TS_GPSCLOCK01_REPLY_LENGTH_STUS
-                 && ( strncmp( pBuf, TS_GPSCLOCK01_REPLY_STUS_RTC, TS_GPSCLOCK01_REPLY_LENGTH_STUS ) == 0
-                   || strncmp( pBuf, TS_GPSCLOCK01_REPLY_STUS_GPS, TS_GPSCLOCK01_REPLY_LENGTH_STUS ) == 0
-                   || strncmp( pBuf, TS_GPSCLOCK01_REPLY_STUS_UTC, TS_GPSCLOCK01_REPLY_LENGTH_STUS ) == 0
-                   || strncmp( pBuf, TS_GPSCLOCK01_REPLY_STUS_PPS, TS_GPSCLOCK01_REPLY_LENGTH_STUS ) == 0 ) ) {
-                       /* Good */
+       case 6 :
+               /* \Nn = Error correction  0:Normal mode  1:Direct mode  2:V42,MNP  3:V42,MNP,Normal */
+               if ( ( pp->sloppyclockflag & CLK_FLAG2 ) == 0 ) {
+                       /* fudge 127.127.40.n flag2 0 */
+                       iErrorCorrection = 0 ;
                } else {
-                       up->lineerror = 1 ;
-                       break ;
+                       /* fudge 127.127.40.n flag2 1 */
+                       iErrorCorrection = 3 ;
                }
 
+               pCmd = cBuf ;
+               snprintf( pCmd, sizeof(cBuf), "AT\\N%d\r\n", iErrorCorrection ) ;
                break ;
 
-       default : /*  Unexpected reply */
+       case 7 :
+               /* Hn = Hook  0:Hook-On ( Disconnect )  1:Hook-Off ( Connect ) */
+               pCmd = "ATH1\r\n" ;
+               break ;
+
+       case 8 :
+               /* Initialize completion */
+               pCmd = NULL ;
+               iNextModemState = CHANGE_MODEM_STATE ;
+               break ;
 
-               up->lineerror = 1 ;
+       default :
+               pCmd = NULL ;
                break ;
 
        }
 
-       /* Clockstats Log */
+       if ( pCmd != NULL ) {
 
-       printableString( sReplyText, sizeof(sReplyText), pBuf, iLen ) ;
-       snprintf ( sLogText, sizeof(sLogText), "%d: %s -> %c: %s",
-                  up->linecount,
-                  tristate_gpsclock01_command_sequence[up->linecount-1].commandLog,
-                  ( up->lineerror == 0 ) 
-                       ? ( ( bOverMidnight == 0 )
-                               ? 'O' 
-                               : 'S' ) 
-                       : 'X',
-                  sReplyText ) ;
-       record_clock_stats ( &peer->srcadr, sLogText ) ;
+               iCmdLen = strlen( pCmd ) ;
+               if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+                       refclock_report( peer, CEVNT_FAULT ) ;
+               }
 
-       /* Check before issue next command */
+               jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
 
-       if ( up->lineerror != 0 ) {
-               /* Do not issue next command */
-               return 0 ;
        }
 
-       if ( bOverMidnight != 0 ) {
-               /* Do not issue next command */
-               return 0 ;
-       }
+       return iNextModemState ;
 
-       if ( tristate_gpsclock01_command_sequence[up->linecount].command == NULL ) {
-               /* Command sequence completed */
-               return 1 ;
-       }
+}
 
-       /* Issue next command */
+/******************************/
+static int
+modem_init_resp04 ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_MODEM_PRINTF( "modem_init_resp04" ) ;
+
+       return modem_init_resp00( peer, pp, up ) ;
+
+}
+
+/******************************/
+static int
+modem_init_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
+       DEBUG_MODEM_PRINTF( "modem_init_disc" ) ;
 #ifdef DEBUG
        if ( debug ) {
-               printf ( "%s (refclock_jjy.c) : send '%s'\n",
-                       sFunctionName, tristate_gpsclock01_command_sequence[up->linecount].commandLog ) ;
+               printf( "refclock_jjy.c : modem_init_disc : call modem_esc_disc\n" ) ;
        }
 #endif
 
-       pCmd =  tristate_gpsclock01_command_sequence[up->linecount].command ;
-       iCmdLen = tristate_gpsclock01_command_sequence[up->linecount].commandLength ;
-       if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
-               refclock_report ( peer, CEVNT_FAULT ) ;
-       }
-
-       return 0 ;
+       return CHANGE_MODEM_STATE ;
 
 }
 
-/**************************************************************************************************/
-/*  jjy_poll - called by the transmit procedure                                                   */
-/**************************************************************************************************/
-static void
-jjy_poll ( int unit, struct peer *peer )
+/******************************/
+static int
+modem_dial_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
 {
 
-       struct jjyunit      *up;
-       struct refclockproc *pp;
+       DEBUG_MODEM_PRINTF( "modem_dial_ignore" ) ;
 
-       pp = peer->procptr;
-       up = pp->unitptr ;
+       return STAY_MODEM_STATE ;
 
-       if ( pp->polls > 0  &&  up->linecount == 0 ) {
-               /*
-                * No reply for last command
-                */
-               refclock_report ( peer, CEVNT_TIMEOUT ) ;
-       }
+}
 
-#ifdef DEBUG
-       if ( debug ) {
-               printf ( "jjy_poll (refclock_jjy.c) : %ld\n", pp->polls ) ;
-       }
-#endif
+/******************************/
+static int
+modem_dial_dialout ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
-       pp->polls ++ ;
+       char    sCmd [ 46 ] ;
+       int     iCmdLen ;
+       char    cToneOrPulse ;
 
-       up->bPollFlag = 1 ;
-       up->linecount = 0 ;
-       up->lineerror = 0 ;
-       up->charcount = 0 ;
+       DEBUG_MODEM_PRINTF( "modem_dial_dialout" ) ;
 
-       switch ( up->unittype ) {
-       
-       case UNITTYPE_TRISTATE_JJY01 :
-               jjy_poll_tristate_jjy01  ( unit, peer ) ;
-               break ;
+       /* Tone or Pulse */
+       if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
+               /* fudge 127.127.40.n flag1 0 */
+               cToneOrPulse = 'T' ;
+       } else {
+               /* fudge 127.127.40.n flag1 1 */
+               cToneOrPulse = 'P' ;
+       }
 
-       case UNITTYPE_CDEX_JST2000 :
-               jjy_poll_cdex_jst2000 ( unit, peer ) ;
-               break ;
+       /* Connect ( Dial number ) */
+       snprintf( sCmd, sizeof(sCmd), "ATDW%c%s\r\n", cToneOrPulse, *sys_phone ) ;
 
-       case UNITTYPE_ECHOKEISOKUKI_LT2000 :
-               jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
-               break ;
+       /* Send command */
+       iCmdLen = strlen( sCmd ) ;
+       if ( write( pp->io.fd, sCmd, iCmdLen ) != iCmdLen ) {
+               refclock_report( peer, CEVNT_FAULT ) ;
+       }
 
-       case UNITTYPE_CITIZENTIC_JJY200 :
-               jjy_poll_citizentic_jjy200 ( unit, peer ) ;
-               break ;
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, sCmd ) ;
 
-       case UNITTYPE_TRISTATE_GPSCLOCK01 :
-               jjy_poll_tristate_gpsclock01  ( unit, peer ) ;
-               break ;
+       return STAY_MODEM_STATE ;
 
-       default :
-               break ;
+}
+
+/******************************/
+static int
+modem_dial_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
+       DEBUG_MODEM_PRINTF( "modem_dial_escape" ) ;
+#ifdef DEBUG
+       if ( debug ) {
+               printf( "refclock_jjy.c : modem_dial_escape : call modem_conn_escape\n" ) ;
        }
+#endif
 
-}
+       return modem_conn_escape( peer, pp, up ) ;
 
-/**************************************************************************************************/
+}
 
-static void
-jjy_poll_tristate_jjy01  ( int unit, struct peer *peer )
+/******************************/
+static int
+modem_dial_connect ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
 {
-#ifdef DEBUG
-       static const char *sFunctionName = "jjy_poll_tristate_jjy01" ;
-#endif
 
-       struct jjyunit      *up;
-       struct refclockproc *pp;
+       DEBUG_MODEM_PRINTF( "modem_dial_connect" ) ;
 
-       const char *pCmd ;
-       int     iCmdLen ;
+       return CHANGE_MODEM_STATE ;
 
-       pp = peer->procptr;
-       up = pp->unitptr ;
+}
 
-       if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
-               up->linecount = 2 ;
-       }
+/******************************/
+static int
+modem_dial_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
+       DEBUG_MODEM_PRINTF( "modem_dial_disc" ) ;
 #ifdef DEBUG
        if ( debug ) {
-               printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->linecount=%d\n",
-                       sFunctionName, pp->sloppyclockflag, CLK_FLAG1,
-                       up->linecount ) ;
+               printf( "refclock_jjy.c : modem_dial_disc : call modem_esc_disc\n" ) ;
        }
 #endif
 
-       /*
-        * Send a first command
-        */
+       modem_esc_disc( peer, pp, up ) ;
 
-#ifdef DEBUG
-       if ( debug ) {
-               printf ( "%s (refclock_jjy.c) : send '%s'\n",
-                        sFunctionName,
-                        tristate_jjy01_command_sequence[up->linecount].commandLog ) ;
-       }
-#endif
+       return CHANGE_MODEM_STATE ;
 
-       pCmd =  tristate_jjy01_command_sequence[up->linecount].command ;
-       iCmdLen = tristate_jjy01_command_sequence[up->linecount].commandLength ;
-       if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
-               refclock_report ( peer, CEVNT_FAULT ) ;
-       }
+}
+
+/******************************/
+static int
+modem_conn_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_MODEM_PRINTF( "modem_conn_ignore" ) ;
+
+       return STAY_MODEM_STATE ;
 
 }
 
-/**************************************************************************************************/
+/******************************/
+static int
+modem_conn_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
-static void
-jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
+       DEBUG_MODEM_PRINTF( "modem_conn_escape" ) ;
+
+       return CHANGE_MODEM_STATE ;
+
+}
+
+/******************************/
+static int
+modem_esc_ignore ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
 {
 
-       struct refclockproc *pp;
+       DEBUG_MODEM_PRINTF( "modem_esc_ignore" ) ;
 
-       pp = peer->procptr;
+       return STAY_MODEM_STATE ;
 
-       /*
-        * Send "<ENQ>1J<ETX>" command
-        */
+}
 
-#ifdef DEBUG
-       if ( debug ) {
-               printf ( "jjy_poll_cdex_jst2000 (refclock_jjy.c) : send '<ENQ>1J<ETX>'\n" ) ;
-       }
-#endif
+/******************************/
+static int
+modem_esc_escape ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
-       if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4  ) {
-               refclock_report ( peer, CEVNT_FAULT ) ;
+       char    *pCmd ;
+       int     iCmdLen ;
+
+       DEBUG_MODEM_PRINTF( "modem_esc_escape" ) ;
+
+       /* Escape command ( Go to command mode ) */
+       pCmd = "+++" ;
+
+       /* Send command */
+       iCmdLen = strlen( pCmd ) ;
+       if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+               refclock_report( peer, CEVNT_FAULT ) ;
        }
 
-}
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
 
-/**************************************************************************************************/
+       return STAY_MODEM_STATE ;
 
-static void
-jjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer )
+}
+
+/******************************/
+static int
+modem_esc_data ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
 {
 
-       struct jjyunit      *up;
-       struct refclockproc *pp;
+       DEBUG_MODEM_PRINTF( "modem_esc_data" ) ;
 
-       char    sCmd[2] ;
+       up->iModemSilentTimer = 0 ;
 
-       pp = peer->procptr;
-       up = pp->unitptr ;
+       return STAY_MODEM_STATE ;
 
-       /*
-        * Send "T" or "C" command
-        */
+}
 
-       switch ( up->operationmode ) {
-       case 1 : sCmd[0] = 'T' ; break ;
-       case 2 : sCmd[0] = 'C' ; break ;
+/******************************/
+static int
+modem_esc_silent ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
+
+       DEBUG_MODEM_PRINTF( "modem_esc_silent" ) ;
+
+       up->iModemSilentCount ++ ;
+
+       if ( up->iModemSilentCount < iModemStateTimeout[up->iModemState] / iModemSilentTimeout[up->iModemState] ) {
+#ifdef DEBUG
+               if ( debug ) {
+                       printf( "refclock_jjy.c : modem_esc_silent : call modem_esc_escape\n" ) ;
+               }
+#endif
+               modem_esc_escape( peer, pp, up ) ;
+               up->iModemSilentTimer = 0 ;
+               return STAY_MODEM_STATE ;
        }
-       sCmd[1] = 0 ;
 
 #ifdef DEBUG
        if ( debug ) {
-               printf ( "jjy_poll_echokeisokuki_lt2000 (refclock_jjy.c) : send '%s'\n", sCmd ) ;
+               printf( "refclock_jjy.c : modem_esc_silent : call modem_esc_disc\n" ) ;
        }
 #endif
-
-       if ( write ( pp->io.fd, sCmd, 1 ) != 1  ) {
-               refclock_report ( peer, CEVNT_FAULT ) ;
-       }
+       return modem_esc_disc( peer, pp, up ) ;
 
 }
+/******************************/
+static int
+modem_esc_disc ( struct peer *peer, struct refclockproc *pp, struct jjyunit *up )
+{
 
-/**************************************************************************************************/
+       char    *pCmd ;
+       int     iCmdLen ;
 
-static void
-jjy_poll_citizentic_jjy200 ( int unit, struct peer *peer )
-{
+       DEBUG_MODEM_PRINTF( "modem_esc_disc" ) ;
 
-       /* Do nothing ( up->bPollFlag is set by the jjy_poll ) */
+       /* Disconnect */
+       pCmd = "ATH0\r\n" ;
 
-}
+       /* Send command */
+       iCmdLen = strlen( pCmd ) ;
+       if ( write( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
+               refclock_report( peer, CEVNT_FAULT ) ;
+       }
 
-/**************************************************************************************************/
+       jjy_write_clockstats( peer, JJY_CLOCKSTATS_MARK_SEND, pCmd ) ;
 
-static void
-jjy_poll_tristate_gpsclock01  ( int unit, struct peer *peer )
-{
-#ifdef DEBUG
-       static const char *sFunctionName = "jjy_poll_tristate_gpsclock01" ;
-#endif
+       return CHANGE_MODEM_STATE ;
 
-       struct jjyunit      *up;
-       struct refclockproc *pp;
+}
 
-       const char      *pCmd ;
-       int     iCmdLen ;
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    jjy_write_clockstats                                                                   ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
 
-       pp = peer->procptr;
-       up = pp->unitptr ;
+static void
+jjy_write_clockstats ( struct peer *peer, int iMark, const char *pData )
+{
 
-       if ( ( pp->sloppyclockflag & CLK_FLAG1 ) == 0 ) {
-               up->linecount = 1 ;
-       }
+       char    sLog [ 100 ] ;
+       char    *pMark ;
+       int     iMarkLen, iDataLen ;
 
-#ifdef DEBUG
-       if ( debug ) {
-               printf ( "%s (refclock_jjy.c) : flag1=%X CLK_FLAG1=%X up->linecount=%d\n",
-                       sFunctionName, pp->sloppyclockflag, CLK_FLAG1,
-                       up->linecount ) ;
+       switch ( iMark ) {
+       case JJY_CLOCKSTATS_MARK_JJY :
+               pMark = "JJY " ;
+               break ;
+       case JJY_CLOCKSTATS_MARK_SEND :
+               pMark = "--> " ;
+               break ;
+       case JJY_CLOCKSTATS_MARK_RECEIVE :
+               pMark = "<-- " ;
+               break ;
+       case JJY_CLOCKSTATS_MARK_INFORMATION :
+               pMark = "--- " ;
+               break ;
+       case JJY_CLOCKSTATS_MARK_ATTENTION :
+               pMark = "=== " ;
+               break ;
+       case JJY_CLOCKSTATS_MARK_WARNING :
+               pMark = "-W- " ;
+               break ;
+       case JJY_CLOCKSTATS_MARK_ERROR :
+               pMark = "-X- " ;
+               break ;
+       default :
+               pMark = "" ;
+               break ;
        }
-#endif
 
-       /*
-        * Send a first command
-        */
+       iDataLen = strlen( pData ) ;
+       iMarkLen = strlen( pMark ) ;
+       strcpy( sLog, pMark ) ; /* Harmless because of enough length */
+       printableString( sLog+iMarkLen, sizeof(sLog)-iMarkLen, pData, iDataLen ) ;
 
 #ifdef DEBUG
        if ( debug ) {
-               printf ( "%s (refclock_jjy.c) : send '%s'\n",
-                        sFunctionName,
-                        tristate_gpsclock01_command_sequence[up->linecount].commandLog ) ;
+               printf( "refclock_jjy.c : clockstats : %s\n", sLog ) ;
        }
 #endif
-
-       pCmd =  tristate_gpsclock01_command_sequence[up->linecount].command ;
-       iCmdLen = tristate_gpsclock01_command_sequence[up->linecount].commandLength ;
-       if ( write ( pp->io.fd, pCmd, iCmdLen ) != iCmdLen ) {
-               refclock_report ( peer, CEVNT_FAULT ) ;
-       }
+       record_clock_stats( &peer->srcadr, sLog ) ;
 
 }
 
-/**************************************************************************************************/
+/*################################################################################################*/
+/*################################################################################################*/
+/*##                                                                                           ##*/
+/*##    printableString                                                                                ##*/
+/*##                                                                                           ##*/
+/*################################################################################################*/
+/*################################################################################################*/
 
 static void
-printableString ( char *sOutput, int iOutputLen, char *sInput, int iInputLen )
+printableString ( char *sOutput, int iOutputLen, const char *sInput, int iInputLen )
 {
        const char      *printableControlChar[] = {
                        "<NUL>", "<SOH>", "<STX>", "<ETX>",