#author("2022-01-10T13:12:43+09:00","","") #author("2022-01-12T09:46:40+09:00","","") ~ 演出機器を自動的に動作させるクリックとして使われるタイムコードについて書きたいと思います。 ----- ~目次 #contents() ~ *タイムコードとは [#hacee6f1] 本来は動画を扱うための物ですが、舞台やイベントの現場では機器の動作を同期させたり定時動作を自動化するための汎用制御信号として用います。規格名は「SMPTE12M」に定義される「LTC(Linear Time Code)」と呼ばれる物です。「SMPTE」とは「Society of Motion Pictures an Television Engineers(米国映画テレビ技術者協会)」のことであり、日本語では「エス・エム・ピー・ティー・イー」又は「シンプティ」と読みます。 &br; 規格の目的は動画のフレームのタイムアドレスを表す物です。動画は言わば超高速紙芝居ですが、何番目の画像かを時刻表現に近い形式で表します。ですから、演出器具を動かすためのクリックでもなければ、時刻を表すための物でもありません。性質上、その様に使えるだけです。 &br; 信号の電気的特性は、映像用の磁気テープでは音声トラックに書かれていたこともあり、一般的な音声信号とほぼ同等に扱うことが出来ます。 ~ 注意ですが、世間でタイムコードと呼ばれるシステムはこれだけではありません。動画に全く関係無いところで全く違うタイムコードが使われていることもあります。所構わず「タイムコードすなわちLTC」として話を進めると事故の基になります。 ~ 以下は、「[[%%%SMPTEデジタル規格集3=TC,SDTIほか=(宇野潤三訳、兼六館出版、ISBN4-87462-045-0)%%%:https://www.amazon.co.jp/SMPTE%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E8%A6%8F%E6%A0%BC%E9%9B%86%E3%80%883%E3%80%89TC%E3%80%81SDTI%E3%81%BB%E3%81%8B-%E5%AE%87%E9%87%8E-%E6%BD%A4%E4%B8%89/dp/4874620655/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=3GR0N4Z6ZUSWT&keywords=SMPTE%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E8%A6%8F%E6%A0%BC%E9%9B%86%EF%BC%93&qid=1641600695&sprefix=smpte%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E8%A6%8F%E6%A0%BC%E9%9B%863%2Caps%2C201&sr=8-1]]」を参考にしています。 ~ なお、LTCは地上波デジタルテレビ放送が始まる前の地上波アナログテレビ放送の時代に策定された物です。この記事はLTCについてですから、テレビ放送についての情報は地上波アナログテレビ放送を前提とした物になります。 **フレームのタイムアドレス [#ea1b4e42] 「動画は超高速紙芝居」と書きましたが、動画は静止画を一定の間隔で差し替えることで動いているように見せる手法です。動画をスロー再生する(静止画を切り替える間隔を長くする)とカクカクと動きが飛び々々に見えると思いますが、静止画を切り替える間隔を一定以上に短くすると滑らかに動いている様に錯覚することが動画の原理です。 &br; 撮った動画を単に放映するだけなら不要なことかもしれませんが、動画の構成や編集が複雑になってきますと静止画単位で管理した方がよくなってきて、それぞれにナンバリングをする様になったのだと思います。 ~ 動画では静止画単位をフレームと呼びますが、それぞれに重複しないアドレス(ナンバー)を割付け、記録媒体にフレームの画像情報と並列に記録します。この様式が「タイムコード」であり、それぞれのフレームを表す物がタイムアドレスとなります。 &br; タイムアドレスがあると便利ですが、最初のフレームから単に連番を付けるだけでは桁数が多くなって管理が簡単とは言えません。動画は時間に対して一定の動作をしますので「何分何秒目」と表した方が直感的にわかりやすいので時刻表現に近い形としたのだと思います。一般的には「何時:何分:何秒:何フレーム」と表します。最後の「何フレーム」は1秒の間のフレームの通し番号です。「0時0分0秒0フレーム」から始まり「23時59分59秒29(24,23)フレーム」までカウントできます。 *動画のフォーマット [#k93fc5f7] そもそもが動画を静止画単位で管理するためのナンバリングですから、動画のフォーマットの基本を理解しておくべきです。 &br; LTCを理解するためには次の二つが重要です。 **フレームレート [#hd016adc] 1秒間に静止画が何枚あるか、という単位です。これが何種類もあります。単位表記は「fps」です。「フレーム・パー・セコンド( Frames par Second )」の略です。1秒間のフレーム数を表します。つまり、フレームレートとは何fpsであるか、という意味です。 ~ 主だったフレームレートは次の通りです。 -''30fps'' &br; モノクロNTSCで用いられる。 -''29.97fps'' &br; カラーNTSCで用いられる。 &br; テレビ放送において、それ以前のモノクロテレビでも観られるカラー放送(もちろんモノクロで映ります)が出来ないかというニーズに応えた結果この様な中途半端なフレームレートが出来ました。モノクロ放送の上位互換としてカラー化するにはカラーバースト信号と呼ばれる基準信号をフレーム毎に入れないといけないのですが、PALでは信号の隙間に巧く入れられたものの、NTSCではどうしても無理なためフレームの時間長を1.001倍したのです。 -''25fps'' &br; PAL(モノクロ/カラー双方)で用いられる。 -''24fps'' &br; フィルム映画で用いられる。 &br; タイムコードはフィルムにも焼き付けられることがあります。 ~ 【用語解説】NTSC(エヌティーエスシー)やPAL(パル)とはテレビ送信の規格。NTSCは主にアメリカ合衆国やカナダ、日本などで用いられ、PALは主にヨーロッパや旧ソビエト連邦圏で用いられています。 **ドロップフレーム(DF) / ノンドロップフレーム(NDF) [#a948d7e3] -''ドロップフレーム(DF)'' &br; フレームを落とす(ドロップ)という言葉のままです。1.001倍とはいえ累積誤差を無視出来ないこともあるので、29.97fpsにおいて1時間毎の帳尻を合わせようとする方法です。0分を含む10分目の頭以外、毎分0秒の頭2フレームを落とす方法です。勘違いされやすいのですが、動画の静止画を削除するのではなく、動画はそのままにナンバリングのカウントを飛ばします(落とします)。 &br; 例えば、9分59秒29フレームの次は10分0秒0フレームですが、10分59秒29フレームの次は11分0秒2フレームです。 -''ノンドロップフレーム(NDF)'' &br; 時間の累積誤差は気にせず、規定フレーム数を1秒とする考え方です。NTSCにおいてカラー(29.97fps)でもモノクロ(30fps)でも30フレームを1秒とカウントする考え方です。カラーでも短時間の動画ではこの方法を使うことも多いようです。 *SMPTE12MとLTC [#g347244f] 最も古く、現在でも基本となっているタイムコードの規格が「SMPTE12M」です。この中に「LTC (Linear Time Code)」が定義されています。 &br; LTCはフレームと並列で保存される80bit長のデジタル符号です。規格の主な内容は80bitのデータフォーマット、変調方式、電気的特性です。規格から計算される物ですが、ビットレート(送信速度)も重要な情報です。 **電気的特性 [#f039a8b0] +4dB音声LINE信号に近似し互換性があります。 -信号波形は短形波(振幅誤差=5%未満、立ち上がり下がり時間=波長の10%未満) -出力インピーダンス25-50Ω、入力インピーダンス1kΩ (音声LINE信号と同等) -電圧振幅1~2vp-p(信号レベル+3~+8dBに相当[+4dBは1.23vp-p]) -信号様式は平衡型信号でも不平衡信号でも可 (音声LINE信号と同等) -推奨コネクタは、平衡信号なら3ピンのXLRコネクタ(1-GND、2,3-平衡信号)、不平衡信号ならBNCコネクタ(メス) &br;※ 下記変調方式の特性により平衡信号における極性はそれほど気にしなくても良い。 **変調方式 [#q1dfb9c1] デジタル信号は0か1かの数値を表し、電気的には数値が0なら電圧が0v、数値が1なら電圧が規定値とするのが基本です。しかし、このまま長距離の送受信は出来ませんので、戻すことを前提に装置が送受信しやすい電気的な変更を加えます。これを「変調」と呼びます。 &br; LTCではデジタル符号変調方式の一つである「差動バイフェーズ」を使います。 ***差動バイフェーズ [#r910c715] 単線で表現します。クロックなどの制御信号線はありません。 &br; 単位時間内の電圧変化の回数で0か1を表現します。電圧値ではありません。 &br; 以下には「電圧が反転」とする文言がありますが、規定値プラスだった電圧が規定値マイナスへ、規定値マイナスだった電圧が規定値プラスに変化することを表しています。 -''数値が0ならば'' &br; 1) 単位時間の始まりで信号の電圧が反転 &br; 2) 単位時間の終わり(次のビットの単位時間の始まり)で電圧が反転 -''数値が1ならば'' &br; 1) 単位時間の始まりで信号の電圧が反転 &br; 2) 単位時間の半分で電圧が反転 &br; 3) 単位時間の終わり(次のビットの単位時間の始まり)で電圧が反転 ~ 文章ではイメージしにくいかもしれませんが、単位時間の始まりと終わりで必ず電圧が反転し、1の場合だけ単位時間の半分で電圧の反転が追加されます。 **ビットレート [#od0440c0] シリアルなデジタル信号ですから送信速度も大事な設定値です。 &br; 1フレームの送信時間と80bitの送信時間が等しいので、タイムコードのビットレートはフレームレートに比例します。 -''30fps'' &br; 80bit x 30fps = 2,400bps -''29.97fps'' &br; 80bit x 29.97fps = 2,397.6bps &br; ※ 規格の意図は1フレームの時間長が30fpsの1.001倍なので、29.97fpsで計算すると厳密には誤差が出る。 -''25fps'' &br; 80bit x 25fps = 2,000bps -''24fps'' &br; 80bit x 24fps = 1,940bps **データフォーマット [#g765c387] ***データの内容 [#p90049c6] 80bitのデジタル符号で表します。実際の順番はバラバラですが、大雑把に分類すると次の情報が記されます。 -''タイムアドレス'' &br; 時、分、秒、フレームを表します。 &br; 数値表現は2桁のBCDです。%%%[[BCDとは「二進化十進数:https://ja.wikipedia.org/wiki/%E4%BA%8C%E9%80%B2%E5%8C%96%E5%8D%81%E9%80%B2%E8%A1%A8%E7%8F%BE]]」%%%と呼ばれる数値表現方法です。 -''フラグピット'' &br; 機能の設定のON/OFFを表します。フラグには4種類あります。 -''バイナリグループ'' &br; 文字情報や日付などを送るための枠。情報の内容はフラグビットのBGFによって定義される。 &br; 演出機器の制御では読み飛ばしされるのが普通。 -''同期ワード'' &br; 80bitのタイムコードの末尾を示すコード。固定値。 ***データのフォーマット [#y4914ca2] 80bitの内訳は次の通りです。 ~''データフォーマット表'' |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |CENTER:|LEFT:|LEFT:|LEFT:|LEFT:|c |0|>|フレームの&br;1の位|0bit目|BCD表記&br;数値範囲0-9| |1|~|~|1bit目|~| |2|~|~|2bit目|~| |3|~|~|3bit目|~| |4|>|>|第1&br;バイナリグループ|使用しない場合=0&br;使用する場合は&br;それぞれの設定値| |5|~|~|~|~| |6|~|~|~|~| |7|~|~|~|~| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |8|>|フレームの&br;10の位|0bit目|BCD表記&br;数値範囲0-2| |9|~|~|1bit目|~| |10|NTSCモノクロ 30fps|>|未定義|通常=0| |~|NTSCカラー 29.97fps|>|ドロップフレームフラグ|DF=1 / NDF=0| |~|PAL 25fps|>|未定義|通常=0| |~|フィルム 24fps|>|未定義|通常=0| |11|NTSCモノクロ 30fps|>|未定義|通常=0| |~|NTSCカラー 29.97fps|>|カラーフレームフラグ|カラー=1 / モノクロ=0| |~|PAL 25fps|>|カラーフレームフラグ|カラー=1 / モノクロ=0| |~|フィルム 24fps|>|未定義|通常=0| |12|>|>|第2&br;バイナリグループ|使用しない場合=0&br;使用する場合は&br;モードによる設定値| |13|~|~|~|~| |14|~|~|~|~| |15|~|~|~|~| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |16|>|秒の1の位|0bit目|BCD表記&br;数値範囲0-9| |17|~|~|1bit目|~| |18|~|~|2bit目|~| |19|~|~|3bit目|~| |20|>|>|第3&br;バイナリグループ|使用しない場合=0&br;使用する場合は&br;モードによる設定値| |21|~|~|~|~| |22|~|~|~|~| |23|~|~|~|~| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |24|>|秒の10の位|0bit目|BCD表記&br;数値範囲0-5| |25|~|~|1bit目|~| |26|~|~|2bit目|~| |27|NTSCモノクロ 30fps|>|極性補正フラグ|計算により定義| |~|NTSCカラー 29.97fps|~|~|~| |~|PAL 25fps|>|バイナリグループフラグ0|設定値は別表| |~|フィルム 24fps|>|極性補正フラグ|計算により定義| |28|>|>|第4&br;バイナリグループ|使用しない場合=0&br;使用する場合は&br;モードによる設定値| |29|~|~|~|~| |30|~|~|~|~| |31|~|~|~|~| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |32|>|分の1の位|0bit目|BCD表記&br;数値範囲0-9| |33|~|~|1bit目|~| |34|~|~|2bit目|~| |35|~|~|3bit目|~| |36|>|>|第5&br;バイナリグループ|使用しない場合=0&br;使用する場合は&br;モードによる設定値| |37|~|~|~|~| |38|~|~|~|~| |39|~|~|~|~| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |40|>|分の10の位|0bit目|BCD表記&br;数値範囲0-5| |41|~|~|1bit目|~| |42|~|~|2bit目|~| |43|NTSCモノクロ 30fps|>|バイナリグループフラグ0|設定値は別表| |~|NTSCカラー 29.97fps|~|~|~| |~|PAL 25fps|>|バイナリグループフラグ2|~| |~|フィルム 24fps|>|バイナリグループフラグ0|~| |44|>|>|第6&br;バイナリグループ|使用しない場合=0&br;使用する場合は&br;モードによる設定値| |45|~|~|~|~| |46|~|~|~|~| |47|~|~|~|~| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |48|>|時の1の位|0bit目|BCD表記&br;数値範囲0-9| |49|~|~|1bit目|~| |50|~|~|2bit目|~| |51|~|~|3bit目|~| |52|>|>|第7&br;バイナリグループ|使用しない場合=0&br;使用する場合は&br;モードによる設定値| |53|~|~|~|~| |54|~|~|~|~| |55|~|~|~|~| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |56|>|時の10の位|0bit目|BCD表記&br;数値範囲0-2| |57|~|~|1bit目|~| |58|NTSCモノクロ 30fps|>|バイナリグループフラグ1|設定値は別表| |~|NTSCカラー 29.97fps|~|~|~| |~|PAL 25fps|~|~|~| |~|フィルム 24fps|~|~|~| |59|NTSCモノクロ 30fps|>|バイナリグループフラグ2|設定値は別表| |~|NTSCカラー 29.97fps|~|~|~| |~|PAL 25fps|>|極性補正フラグ|計算により定義| |~|フィルム 24fps|>|バイナリグループフラグ2|設定値は別表| |60|>|>|第8&br;バイナリグループ|使用しない場合=0&br;使用する場合は&br;モードによる設定値| |61|~|~|~|~| |62|~|~|~|~| |63|~|~|~|~| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |64|同期ワード|0bit目|固定値|=0| |65|~|1bit目|~|=0| |66|~|2bit目|~|=1| |67|~|3bit目|~|=1| |68|~|4bit目|~|=1| |69|~|5bit目|~|=1| |70|~|6bit目|~|=1| |71|~|7bit目|~|=1| |CENTER:BGCOLOR(gray):COLOR(white):''ビット''|>|>|CENTER:BGCOLOR(gray):COLOR(white):''名 称''|CENTER:BGCOLOR(gray):COLOR(white):''補 足''| |72|同期ワード|8bit目|固定値|=1| |73|~|9bit目|~|=1| |74|~|10bit目|~|=1| |75|~|11bit目|~|=1| |76|~|12bit目|~|=1| |77|~|13bit目|~|=1| |78|~|14bit目|~|=0| |79|~|15bit目|~|=1| -ドロップフレームフラグ:ビット10 &br; ドロップフレームのタイムコードなら常に1にします。変則ですが、フレームレートが29.97fpsでもタイムアドレスのカウントがノンドロップフレームなら0で良いのだと思う。 -バイナリグループフラグ0,1,2(BGF0,BGF1,BGF2):ビット27,43,58,59 &br; バイナリーグループはタイムコード内に様々な情報を付加する機能で、その意味合いを表すのがバイナリーグループフラグですが、演出機器を汎用的に動かす用法において使うとは思えません。 &br; 使用しないなら、BGF0=0、BGF1=0、BGF2=0 とすべてのフラグを0にするのが一般的(らしい)。 &br; 上表に「設定値は別表」と書いてありますが記載しません。原本の書籍には記載あります。 -極性補正フラグ:ビット27,59 &br; パリティビットの様なものですが、データ補正用ではなく、差動バイフェーズの位相を安定させるためのもの。 &br; 通常のパリティビットはデータワードを2進数で見たときに含まれる1の数が奇数か偶数かのフラグですが、LTCでは極性補正フラグを除く0-63bitの内に含まれる「0」の数が奇数であれば極性補正フラグを「1」とし偶数なら「0」とする。 &br; ただし、このフラグは複数のLTCソースを切り替えて用いる際に同期ワードの読み取りを安定させる目的なので、複数を使わないなら「0」固定でも良いらしい。 *microchip社のPIC16マイコンでタイムコード機器を作る [#p90c572c] 今はmicrochip社のPIC16マイコン以外にも安価で優秀なマイコンが数多くありますが、マイコンを使い始めた当初、私にも理解出来て安価に開発環境を整えられたマイコンがこれだったので今も愛用しています。当時はCコンパイラが大変高価だったため、その名残で未だにアセンブラで書いています。 &br; PICマイコンは拡張ミッドレンジ16系を用います。上位機種に比べて処理能力や機能は劣りますが、今はRaspberryPiと組み合わせて使うことが多く、お互いにお互いの弱点を補ってくれるので不足はありません。今回のLTCを扱う上ではとても便利です。 ~ それでは基本となる処理方針を考えていきましょう。 &br; LTCの実態である差動バイフェースはシリアル信号の一種ですが、これを専門的に扱うモジュールもライブラリもPIC16系にはありません。高級OSにおけるデバイスドライバに相当する部位から書くのですが、シリアル信号では基底クロックの精度と汎用性が重要になりますから、クロックソースをどうやって作るかを考えてみます。 **タイムコードのクロックソース [#v3acfe00] LTCは1,940~2,400bpsの差動バイフェーズ信号です。これに用いる基底クロックをPIC内で作ります。基底クロックは差動バイフェーズの性質上送信速度の倍ですから3,880~4,800Hzです。 &br; マイコンに与えるクロック(Fosc)は32MHzとします。8MHzの水晶発振子を用い内部の4倍PLLで32HMzとします。1命令クロックはパイプラインの都合でFosc/4となり8MHzです。 &br; 基底クロックはPIC内のタイマであるTMR1をコンペアモードで起こします。コンペアモードとは、命令クロックでカウントされるTMR1とCCPxレジスタの値が一致すると割り込みを発生し、TMR1をクリアする機能なので、設定周期を発生させるのに便利な機能です。 ***基本的な考え方 [#w1a181a8] 高度な分周機能を持ったPLLを用いれば簡単なことですが、8MHzのタイマの単純なカウントだけで必要な基底クロックを起こすにはちょっとした小細工をします。 &br; PICのコンペアモードは、CCPxレジスタに値を設定しておけば、TMR1の値がこれと同じになった瞬間にフラグ(一致フラグ)が立つ機能です。通常はCCPxを一定値で使いますが、一致回数に対し一定の周期でCCPxレジスタの値を増減すれば長い目で見ると辻褄を合わせられます。クロック周期の増減は0.5%未満なので、波形の立ち上がり立下り誤差に吸収される程度だと思います。 ***フレームレート毎の補正の仕方 [#ccda614d] LTCは1時間単位で帳尻が合うことを前提にしていますのでその様に計算します。PICマイコンの1時間当たりの総クロックカウント数と、LTCの基底クロックを起こすTMR1の総クロックカウント数が同じになるようなCCPxレジスタの増減規則を見つけたいと思います。 -''1時間あたりのPICマイコンのクロックカウント数'' &br; まずは目標値である1時間あたりのPICマイコンのクロックカウント数を出します。 &br;[Fosc/4 = 8MHz] × [60秒] × [60分] = [1時間あたりクロックカウント数 = 28,800,000,000] ~ -''基底クロックのためのTMR1のカウント標準値と補正:30fpsの場合'' &br;[1フレームのビット数 = 80bit] × [基底クロック倍数 = 2倍] × [フレームレート = 30fps] × [60秒] × [60分] = [1時間あたりの基底クロック数 = 17,280,000] &br;[1時間あたりクロックカウント数 = 28,800,000,000] ÷ [1時間あたりの基底クロック数 = 17,280,000] = [CCPxにレジスタに与えるカウント標準値 = 1,666] ・[余り(誤差1) = 11,520,000] ~ 余りを帳消しにする補正を考えます。 &br;[1時間あたりの基底クロック数 = 17,280,000] ÷ [余り(誤差1) = 11,520,000] = [1.500] → 切り上げ → [補正周期1 = 2] &br;[1時間あたりの基底クロック数 = 17,280,000] mod [補正周期1 = 2] = [余り(誤差2) = 2,880,000] &br;[1時間あたりの基底クロック数 = 17,280,000] ÷ [余り(誤差2) = 2,880,000] = [6.00] → 余り無し → [補正周期2 = 6] &br; 補正周期とは、CCPxにレジスタに与えるカウント標準値を補正する基底クロックの周期です。この場合補正値は1としています。 &br; CCPxにレジスタに与えるカウント標準値を基底クロックのカウント2回に1回、6回に1回+1(1,667)するのです。2回と6回では倍数/約数の関係で位相が合ってしまいますから、偶数目で2回周期とし、奇数目で6回周期を取ればいいでしょう。 ~ 総カウント数が一致するので1時間あたりの誤差は無いとなります。 &br; [CCPxにレジスタに与えるカウント標準値 = 1,666] &br; [補正周期1 = 2] &br; [補正周期2 = 6] -''基底クロックのためのTMR1のカウント標準値と補正:29.97fpsの場合'' &br; フレームレートは29.97fpsですが、正しくは[30÷1.001]fpsです。表記は29.97fpsとし計算値は[30÷1.001]fpsを使います。 &br;[1フレームのビット数 = 80bit] × [基底クロック倍数 = 2倍] × [フレームレート = 29.97fps] × [60秒] × [60分] = [1時間あたりの基底クロック数 = 17,262,737.262737300] &br;[1時間あたりクロックカウント数 = 28,800,000,000] ÷ [1時間あたりの基底クロック数 = 17,262,737.262737300] = [CCPxにレジスタに与えるカウント標準値 = 1,666] ・[余り(誤差1) = 5,754,246] ~ 余りを帳消しにする補正を考えます。 &br;[1時間あたりの基底クロック数 = 17,262,737.262737300] ÷ [余り(誤差1) = 5,754,246] = [3.0・・・03] → 切り上げ → [補正周期1 = 4] &br;[1時間あたりの基底クロック数 = 17,262,737.262737300] mod [補正周期1 = 4] = [余り(誤差2) = 1,438,561.438554800] &br;[1時間あたりの基底クロック数 = 17,262,737.262737300] ÷ [余り(誤差2) = 1,438,561.438554800] = [12.000000000055400] → 切り上げ→ [補正周期2 = 13] &br;[1時間あたりの基底クロック数 = 17,262,737.262737300] mod [補正周期2 = 13] = [余り(誤差3) = 110,658.5721903900] &br;[1時間あたりの基底クロック数 = 17,262,737.262737300] ÷ [余り(誤差3) = 110,658.5721903900] = [156.00000000936500] → 切り上げ→ [補正周期3 = 157] &br;[1時間あたりの基底クロック数 = 17,262,737.262737300] mod [補正周期3 = 157] = [余り(誤差4) = 704.83166340147700] &br;[1時間あたりの基底クロック数 = 17,262,737.262737300] ÷ [余り(誤差4) = 704.83166340147700] = [24,492.00023084700] → 切り上げ→ [補正周期4 = 24,493] &br;[1時間あたりの基底クロック数 = 17,262,737.262737300] mod [補正周期4 = 24,493]] = [余り(誤差5) = 0.028770218230306500] ~ 誤差が1未満になりましたのでここまで &br; 誤差 = 0.028770218230306500 / 28,800,000,000 (水晶発振子の精度からしてもこれ以上頑張っても意味がない) &br; [CCPxにレジスタに与えるカウント標準値 = 1,666] &br; [補正周期1 = 4] &br; [補正周期2 = 13] &br; [補正周期3 = 157] &br; [補正周期4 = 24,493] -''基底クロックのためのTMR1のカウント標準値と補正:25fpsの場合'' &br;[1フレームのビット数 = 80bit] × [基底クロック倍数 = 2倍] × [フレームレート = 25fps] × [60秒] × [60分] = [1時間あたりの基底クロック数 = 14,400,000] &br;[1時間あたりクロックカウント数 = 28,800,000,000] ÷ [1時間あたりの基底クロック数 = 14,400,000] = [CCPxにレジスタに与えるカウント標準値 = 2,000] ・[余り(誤差1) 無し] ~ 補正の必要はありません。 &br;[CCPxにレジスタに与えるカウント標準値 = 2,000] -''基底クロックのためのTMR1のカウント標準値と補正:24fpsの場合'' &br;[1フレームのビット数 = 80bit] × [基底クロック倍数 = 2倍] × [フレームレート = 24fps] × [60秒] × [60分] = [1時間あたりの基底クロック数 = 13,824,000] &br;[1時間あたりクロックカウント数 = 28,800,000,000] ÷ [1時間あたりの基底クロック数 = 13,824,000] = [CCPxにレジスタに与えるカウント標準値 = 2,083] ・[余り(誤差1) = 4,608,000] ~ 余りを帳消しにする補正を考えます。 &br;[1時間あたりの基底クロック数 = 17,280,000] ÷ [余り(誤差1) = 4,608,000] = [3.00] → 余り無し → [補正周期1 = 3] ~ [CCPxにレジスタに与えるカウント標準値 = 2,083] &br; [補正周期1 = 3] ~ クロックはすべての基本ですから、出来るだけ正確を目指したいものです。 **差動バイフェーズのデコード [#v459e4cb] 受信ではLTCを10バイトのデータにすることが最初の作業でしょう。 &br; そのためにもビットを正確に受信しなければなりません。 ***差動バイフェーズのビット受信 [#t2a53a7f] ソフトウェア的に処理し、対応範囲を24~30fpsとします。 &br; 差動バイフェーズは値が一定でも信号が常に反転していますから、PICではI/O入力の変化割り込みを用いるのが最適でしょう。その名の通り、I/Oの入力が変化すると割り込みが発生する機能です。 &br; PIC内での処理ですから、波長の長短は秒数よりも上記のカウンタのカウント数で考えた方が近道です。可能ならば24fpsでも30fpsでも同じ処理で済ませたいので検討します。 -''入力が反転したら計測タイマをクリアする'' &br; 変化割り込みを利用し、その瞬間のタイマのカウント数を取得し、カウンタをクリアします。 -''波長による識別'' &br; 周期は精度が出ているものとしますが、波形の立ち上がり立下りは周期の10%未満となっているので、PICのI/Oによる検知はその分ズレる可能性があります。 &br; 各条件での波長をタイマーのカウント数で表します(PIC16系/Fosc=32MHz) |COLOR(white):BGCOLOR(gray):CENTER:符号|>|>|COLOR(white):BGCOLOR(gray):CENTER:24fps|>|>|COLOR(white):BGCOLOR(gray):CENTER:30fps| |~|COLOR(white):BGCOLOR(gray):CENTER:-10%|COLOR(white):BGCOLOR(gray):CENTER:0%|COLOR(white):BGCOLOR(gray):CENTER:+10%|COLOR(white):BGCOLOR(gray):CENTER:-10%|COLOR(white):BGCOLOR(gray):CENTER:0%|COLOR(white):BGCOLOR(gray):CENTER:+10%| |CENTER:|RIGHT:|RIGHT:|RIGHT:|RIGHT:|RIGHT:|RIGHT:|c |0|3,787|4,166|4,583|''3,029''|3,332|3,666| |1|1,893|2,083|''2,292''|1,514|1,666|1,833| ~ 符号0ならば3,029~4,583です。符号1ならば、2回続けてが条件になりますが、1,514~2,292です。 &br; 表の太字にもなりますが、フレームレートに関わらず符号0の最短波長と符号1の最長波長は被りません。デコード処理は24~30fpsで定数も含めて共通化出来るということです。 &br; 精度やノイズ耐性を上げるなら設定されたフレームレートに合わせて許容範囲を絞ればいい。 ***ビットデータを格納し、タイムコードとして扱える様にする [#oe74f476] ビットデータを得たなら一時スタックレジスタに保存する。 -''シフトレジスタに保存'' &br; 10バイトの一時スタックレジスタを用意し、ビット情報の受信があれば、10バイト全体を左シフトし、受信したビット情報を最下位ビットに書き込む。 &br; ビット受信の度にこれを延々繰り返す。 -''同期ワードを確認する'' &br; ビットを書き込んだら下位2バイトをチェックする。同期ワードは 0b0011111111111101(0x3FFD) なので一致するか確認する。 &br; 一致すれば同期ワードなので、パケット受信が成立となる。 &br; 受信データを次の処理に引き継いで差動バイフェーズのデコードは一区切り。 ~ 受け取るのは時刻の刻みにも等しい物なので、正しい長さの信号であるかを評価する意味はあまり無いと思う。同期ワードが出現した瞬間に受信したデータに書かれた時刻が真であるとして良いと思う。 ----- ~ ・・・以下、まとめ中。