;            プログラム名　　Trans.asm
;
;ラジコンのサーボモータを利用したシステムの送信側のＰＩＣの制御プログラムである。
;     　　　　　　　　　　　　　　　　　　　　　　　　　　　   2000,3/28～　　金野
;　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　2000,4,6  完成
;母プログラムは　sosin　である。
;　　　　　　　アナログ端子　４チャンネル。ただし、開放端でも可。
;　　　　　　　デジタル端子　４チャンネル。ただし、開放端でも可。
;　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　
;回路での設定条件
;（１）使用する発振素子はセラミックオシレータ１０．０ＭＨｚとする。
;
;プログラムの流れ概要
;（１）可変抵抗のアナログ電圧を測定し、その値をシリアルデータとして、送信出力する。
;（２）１０ＭＨｚクロックで、１命令実行時間約０．４マイクロ秒（多分４サイクル）
;（３）取り込んだ可変抵抗の電圧値は、約２０ｍ秒毎に、送信する。（ラジコンの規格に準拠させる）
;　　　Futaba の規格は２０ｍ秒毎であるが、１０ｍ秒でも良さそうである。３月２９日そうしてみる。
;（４）送信データはＲＳ＿２３２Ｃ規格に準拠させる。
;　　　その順列　１スタートビット＋８データビット＋１ストップビット＝１０ビット
;（５）送信されるデータは、０から２５５の整数値。
;（６）１ビットの送信時間長は　約５マクロ秒とする。約２００，０００ボーとなる。
;　　　従って１データ＝１バイト（１０ビット）の送信時間は　約５０マイクロ秒となる。
;
;アセンブル時の注意
;（１）定数はリテラル値扱いである。厳重に留意しておくこと。
;（２）Radix は Decimal とする。暗黙数値は１０進数と見なす。
;（３）アセンブルした出力ファイルは　INHX32 形式に指定すべし

  LIST P=PIC16C711       ;使用するプロセッサを指定する
  #INCLUDE "P16C711.INC" ;上記プロセッサのためのインクルードファイルを
                         ;呼び出し結合する
;ＰＩＣの初期設定 
  __CONFIG  _WDT_OFF & _XT_OSC &_BODEN_OFF
                          ;ＰＩＣはマイクロコントローラモード
                          ;これでポートＣその他の端子がＩ／Ｏポートとなる。
                          ;ウオッチドックタイマーはオフ
                          ;発振はクリスタル方式
                          ;ブラウンアウトはオフ。（オンでは規定電圧以下となるとリセット）

;************************************************************************************************ 
;変数	
   CBLOCK h'000C'     ;このディレクチブと下のENDCの間に使用する変数名を定義できる
                      ;数値は使用するプロセッサの一般目的レジスタの開始番地とする　　
        temp0         ;一時的カウンタ変数
        temp1         ;
        temp2         ;
        temp3         ;
        Tr_data       ;送信するデータを入れる変数。
        Sw_data       ;４つのスイッチが接続されたデジタル端子の入力電圧レベルを示す変数。
                      ;第０，１，２，３ビット目に、順次スイッチ１，２，３，４の状態を示すために、
                      ;スイッチオンの時＝１，スイッチオフの時＝０　を代入しておく。
        delay_cntr    ;シリアル送信パルス長設定（遅延）用カウンタ
        bit_cntr      ;転送したビット数
        xmt_byte      ;転送するバイト
   ENDC

  ;各使用端子に名称を定義する。
   #define   RS_232C_out  PORTB,0  ;ＲＳ＿２３２Ｃ規格の信号を出力する端子の命名 
   #define   Trigger      PORTB,1  ;トリガー信号出力端子として使用 
   #define   Switch1      PORTB,7  ;１番目のスイッチが接続されたデジタル入力端子の命名
   #define   Switch2      PORTB,6  ;２番目の　　　　同上
   #define   Switch3      PORTB,5  ;３番目の　　　　同上
   #define   Switch4      PORTB,4  ;４番目の　　　　同上

;定数
AD_channel    equ        4  ;ＡＤチャンネル数。
;data_int0     equ      200  ;約２０ｍ秒（規格に準拠して）毎に、
data_int0     equ      100  ;約１０ｍ秒（規格に準拠して）毎に、
data_int1     equ       78  ;データ群を送信するための２組の時間定数
pulsewidth    equ      120  ; 

;************************************************************************************************
          org     0                
start
     ;各ポートの初期設定  
          call     port_initial

     ;ＡＤの初期設定    
          call     AD_initial

execute
          bsf      Trigger       ;モニター用トリガ端子をＨレベルとする。
     ;アナログ端子での計測と得られたデータの送信  
        ;ＡＮ０端子
          bcf      ADCON0,CHS1   ;ＡＮ０端子の選択。
          bcf      ADCON0,CHS0   ;
          call     adwait        ;チャンネルが安定するまで待機
          call     AD_convert    ;ＡＤ変換を行う。
          call     data_trans    ;データの送信を行う。          
          bcf      Trigger       ;モニター用トリガ端子をＬレベルとする。
        ;ＡＮ１端子
          bcf      ADCON0,CHS1   ;ＡＮ１端子の選択。
          bsf      ADCON0,CHS0   ;
          call     adwait        ;チャンネルが安定するまで待機
          call     AD_convert    ;ＡＤ変換を行う。
          call     data_trans    ;データの送信を行う。          
        ;ＡＮ２端子
          bsf      ADCON0,CHS1   ;ＡＮ２端子の選択。
          bcf      ADCON0,CHS0   ;
          call     adwait        ;チャンネルが安定するまで待機
          call     AD_convert    ;ＡＤ変換を行う。
          call     data_trans    ;データの送信を行う。
        ;ＡＮ３端子       
          bsf      ADCON0,CHS1   ;ＡＮ３端子の選択。
          bsf      ADCON0,CHS0   ;
          call     adwait        ;チャンネルが安定するまで待機
          call     AD_convert    ;ＡＤ変換を行う。
          call     data_trans    ;データの送信を行う。

     ;デジタル端子での各スイッチの状態認識とその状態データの送信
          clrf     Sw_data        ;00000000 としておく。スイッチは全てオフと見なしておく。
          call     digital_delay  ;遅延ループ。
        ;スイッチ１端子
          btfsc    Switch1        ;スイッチ１がオンの時は、
          bsf      Sw_data,0      ;Sw_data の第０ビットを　１とする。
        ;スイッチ２端子
          btfsc    Switch2        ;スイッチ２がオンの時は、
          bsf      Sw_data,1      ;Sw_data の第１ビットを　１とする。
        ;スイッチ３端子
          btfsc    Switch3        ;スイッチ３がオンの時は、
          bsf      Sw_data,2      ;Sw_data の第２ビットを　１とする。
        ;スイッチ４端子
          btfsc    Switch4        ;スイッチ４がオンの時は、
          bsf      Sw_data,3      ;Sw_data の第３ビットを　１とする。

          movf     Sw_data,0      ;
          movwf    Tr_data        ;
          call     data_trans     ;
          call     data_delay    ;
          goto     execute       ;１バイトの送信を終了したので、繰り返す。

     ;エンドレスとしておく。

;*************　初期設定ルーチン集  **************************************************************
;ポートの初期設定
port_initial 
  ;ＲＡポートの設定。
  ;　　ＲＡ０　　ＡＤ端子に設定。使用
  ;　　ＲＡ１　　ＡＤ端子に設定。使用
  ;　　ＲＡ２　　ＡＤ端子に設定。使用
  ;　　ＲＡ３　　ＡＤ端子に設定。使用
  ;　　ＲＡ４　　当面デジタル出力端子とし、未使用としておく。
          bsf     STATUS,RP0        ;バンク１に移る
          movlw   b'00'             ;ＲＡ０～ＲＡ３端子をＡＤ端子として設定し、同時に、参照電圧は
          movwf   ADCON1            ;電源電圧となる。
          movlw   b'01111'          ;アナログ入力チャンネルは対応するＴＲＩＳビットを
          movwf   TRISA             ;入力ビットとして選択しておかなければならないので。
          bcf     STATUS,RP0        ;バンク０に戻る

  ;ＲＢポートの設定。
  ;　　ＲＢ０　　ＲＳ＿２３３２Ｃ規格出力端子として使用
  ;　　ＲＢ１　　トリガーとして使用　　　　　出力端子
  ;　　ＲＢ２　　未使用　　　　　　　　　　　同上
  ;　　ＲＢ３　　未使用　　　　　　　　　　　同上
  ;　　ＲＢ４　　スイッチ４と接続して使用　　入力端子
  ;　　ＲＢ５　　スイッチ３と接続して使用　　同上
  ;　　ＲＢ６　　スイッチ２と接続して使用　　同上
  ;　　ＲＢ７　　スイッチ１と接続して使用　　同上
          clrf    PORTB             ;PORTB のラッチデータをクリア
          bsf     STATUS,RP0        ;バンク選択ビットを１とし、バンク１に移る
          movlw   b'11110000'       ;Ｗに２進数の 11110000 を入れる
          movwf   TRISB             ;ＢポートのステータスレジスタTRISBに上の値を代入。
          bcf     STATUS,RP0        ;バンク０に戻しておく。
          return

;ＡＤコンバータの初期設定　　関係するレジスタ ADCON0
AD_initial                          ;ADCON0=(ADCS1,ADCS0, ,CHS1,CHS0,GO/DONE, ,ADON)
          bsf     ADCON0,ADCS1      ;ＡＤ変換クロック　(ADCS1,ADCS0)    
          bcf     ADCON0,ADCS0      ;                  (    0,    0)   ２＊Fosc
                                    ;                  (    0,    1)   ８＊Fosc
                                    ;                  (    1,    0) ３２＊Fosc
                                    ;                  (    1,    1)   ＲＣ 
                                    ;変換クロックは小さい程良いが、必要最低時間があるので
                                    ;マニュアルの表を参照して決定すること
                                    ; (CHS1,CHS0) ＡＤ変換する入力端子の設定ビット
                                    ;例　=(   0,   0) ＡＮ０端子を選択
                                    ; GO/DONE　　（入出力兼用）  (（（  
                                    ;     ＡＤ変換を開始させる。GO(or DONE) を 1 とする
                                    ;     ＡＤ変換完了した。    GO(or DONE) が 0 となる
          bsf     ADCON0,ADON       ;ＡＤ変換器をオン。

          return
;************************************************************************************************
;ＡＤ端子の設定後、正確なＡＤ変換値を得るため、若干時間待機させる（チャージング時間の保証）。
;
adwait    movlw   30               ;１０では小さいようである。
          movwf   temp0            ;３０より大きい方が安定性が高いかもしれない。
loop_wait decfsz  temp0,1          ;
          goto    loop_wait
          return

;************************************************************************************************ 
;ＡＤ変換を行う
AD_convert
          bsf      ADCON0,GO     ;ＡＤ変換開始。
loop_ad   btfsc    ADCON0,GO     ;変換完了
          goto     loop_ad       ;まで待機。
          movf     ADRES,0       ;変換値を
          movwf    Tr_data       ;変数 Tr_data に代入する。  
          return

;************************************************************************************************ 
;１０ｍ秒毎にデータを送信するための時間幅を設定するルーチンである。
data_delay
          movlw    data_int0     ;定数 data_int0 の値をＷレジスタに取り込み、
          movwf    temp0         ;temp0 に代入する。
          movlw    data_int1     ;定数 data_int1 の値をＷレジスタに取り込み、
          movwf    temp1         ;temp1 に代入する。
loop_del  decfsz   temp0,1       ;temp0 を－１し、まだ０となっていなければ、
          goto     loop_del      ;繰り返す。
          movlw    data_int0     ;定数 data_int0 の値をＷレジスタに取り込み、
          movwf    temp0         ;temp0 に代入する。
          decfsz   temp1,1       ;temp1 を－１し、まだ０となっていなければ、
          goto     loop_del      ;繰り返す。
          return

;************************************************************************************************ 
;デジタル端子の状態変数を送信する際の時間遅延　約８０マイクロ秒　をはかるルーチンである。
digital_delay
          movlw    60            ;
          movwf    temp0         ;
dig_loop  decfsz   temp0,1       ;
          goto     dig_loop      ;
          return

;************************************************************************************************ 
;ＲＳ－２３２Ｃシリアルデータとして出力する。
data_trans
          comf     Tr_data,0     ;Tr_data の内容の補数をＷレジスタに取り込み
          movwf    xmt_byte      ;xmt_byte に代入する

again     bsf      RS_232C_out   ;最初に、ＲＳ－２３２Ｃ出力端子をＨレベルとし、
          nop                    ;スタートビットとして、送信開始。
          nop                    ;パルス幅調整用ｎｏｐ命令
          nop
          nop
          nop
          nop
          nop 
          movlw    8             ;Ｗレジスタに数値８をセット。１バイト長８ビットの宣言
          movwf    bit_cntr      ;Ｗレジスタの内容を bit_cntr に代入。
          movf     xmt_byte,0    ;転送すべきバイト内容をＷレジスタに取り込む

xmit      rrf      xmt_byte,1    ;データを右回転させる。第０ビットはキャリービットに入る。
          btfsc    STATUS,C      ;キャリービットの内容の補数（内容が１ならば０，０ならば１）を
          bcf      RS_232C_out   ;
          btfss    STATUS,C      ;RS_232C_out に代入する。
          bsf      RS_232C_out   ;ビットデータの送信。
          nop                    ;パルス幅調整用ｎｏｐ命令
          nop
          nop
          nop
          nop
          nop
          decfsz   bit_cntr,1    ;bit_cntr を－１し、まだ０となっていなければ、
          goto     xmit          ;次のビットの送信を繰り返す。
          bcf      RS_232C_out   ;RS_232C_out の出力レベルをＬとし、ストップビットとする。
          return

;************************************************************************************************ 

         END




