damuboのブログ

damuboのブログ

生き物ってすごい。モノづくりなんかもねっ

やっとのことで・・・

MIDI Trigger Converterのプログラムを発掘したのでご紹介します。

 

商用利用される場合はご連絡下さい。それ以外ではご自由にどうぞ。

(申し訳ございませんがサポートは期待されないでください、汗)

 

(ブログにコピーするときに、

文字化けしているかもしれないのでそのままでは動作しません。

修正をお願いいたします。

<、>、はそれぞれ小文字に変換してください。)

 

; =========================== ここから ===============================
    LIST      P=16F84
    #include <p16F84.inc>
    LIST r=dec        ;10進数を定数とする

    __CONFIG _CP_OFF & _HS_OSC & _PWRTE_ON & _WDT_OFF
;_CP_OFF コードプロテクトしない
;_HS_OSC 4MHz~20MHz(水晶振動子orセラミック振動子  4MHzで計算
;_PWRTE_ON パワーアップタイマ有効
;_WDT_OFF ウォッチドックタイマ無効
;---------------------------------------------------------------
;アドレスに名前を付ける
;
; GPR 0x0C~0x4F     を使用可能(SFR 0x00~0x0Bまではシステム用)
;---------------------------------------------------------------
temp2        equ    0x0E
temp        equ 0x10
xmit        equ 0x11
i            equ 0x12
j            equ 0x13
k            equ 0x14
rmit        equ 0x18
statusData    equ 0x19
noteData    equ 0x1A
veloData    equ 0x1B
triger0        equ 0x20
triger1        equ 0x21
triger2        equ 0x22
triger3        equ 0x23
triger4        equ 0x24
triger5        equ 0x25
triger6        equ 0x26
triger7        equ 0x27
INDEX        equ    0x28
statusLED    equ 0x2F
statusLED2    equ 0x2E
;***************************************************************
;リセットベクタ
;***************************************************************
        org    0
        goto    start
;***************************************************************
;割り込みベクタ
;***************************************************************
        org    4
;***************************************************************
;スタート
;***************************************************************
start
;---------------------------------------------------------------
;ポートの設定
;---------------------------------------------------------------
        clrf    PORTA
        clrf    PORTB
        bsf    STATUS,RP0        ;ページを1に切り替え
        movlw    B'00000001'
        movwf    TRISA        ;portA(bit0~4)を0Bitのみ入力に設定 H=入力 (bit4のみ=オープンドレイン)
        movlw    B'00000000'
        movwf    TRISB        ;portB(bit0~7)を全て出力に設定
        ;portAのbit0をMIDIの入力に
        ;portAのbit2をMIDIの出力に
        ;portAのbit3をstatusLEDに
        ;portBはトリガ主力用に
;---------------------------------------------------------------
;変数初期化
;---------------------------------------------------------------
        bcf    STATUS,RP0    ;ページを0に切り替え
        bsf PORTA,2        ;ストップビットを初期状態?
        bcf PORTA,3        ;statusLED消灯
        movlw    0x00
        movwf    triger0        ;Snare_Drum
        movwf    triger1        ;Stick
        movwf    triger2        ;Kick_Drum
        movwf    triger3        ;Cymbal1
        movwf    triger4        ;Low_Tom
        movwf    triger5        ;High_Tom
        movwf    triger6        ;Closed_HiHat
        movwf    triger7        ;Open_HiHat
        movlw    0xFF
        movwf     statusLED
        bsf PORTA,3        ;statusLED点灯
;***************************************************************
;メイン
;***************************************************************
main
        ;startbitの検出
        btfss    PORTA,0        ;1μs    1(2) fのbビット目が1だったら次命令スキップ
        goto status_get        ;3μs
        ;----------MIDIスルーのテスト--↓---------
;        btfsc    PORTA,0        ;1μs    1(2) fのbビット目がLoだったら次命令スキップ
;        goto led_
;        call    getmidi
;        goto throughout
        ;-------------------------↑---------
        ;トリガー出力
        movlw    0            ;1μs
        movwf    temp        ;2
        bcf        STATUS,C    ;3 キャリークリア
        rrf        triger0,f    ;4 PORTAの内容を右に1ビットシフトして最下位(bit0)のあふれをSTATUSのCに入れる
        rrf        temp,f        ;5
        rrf        triger1,f    ;6
        rrf        temp,f        ;7 
        rrf        triger2,f    ;8
        rrf        temp,f        ;9
        rrf        triger3,f    ;10
        rrf        temp,f        ;11
        rrf        triger4,f    ;12
        rrf        temp,f        ;13
        rrf        triger5,f    ;14
        rrf        temp,f        ;15
        rrf        triger6,f    ;16
        rrf        temp,f        ;17
        rrf        triger7,f    ;18
        rrf        temp,w        ;19
        ;トリガーを出力 20μS+2μS = 32μS以下だけどギリギリかな?
        movwf    TRISB        ;20

        ;startbitの検出
        btfss    PORTA,0        ;1μs    1(2) fのbビット目が1だったら次命令スキップ
        goto status_get        ;3μs

        movlw    20            ;Y = 3*X + 1
        movwf    temp    ;3*5+3 = 18μs
main1
        ;startbitの検出
        btfss    PORTA,0        ;1μs    1(2) fのbビット目が1だったら次命令スキップ
        goto status_get        ;3μs
        decfsz    temp,f
        goto    main1

        ;最終的なトリガーは
        ; (22+22*20)μS~(22+22*20)×7μS = 462μS~3234μS = 0.0005~0.003s
        ;
        ;LEDを点滅がしている時は待機中
led_
        decfsz    statusLED,w
        goto    led_on
led_off
        bcf PORTA,3        ;statusLED消灯
        decfsz    statusLED2,w
        goto    led_on1
led_off1
        movlw    0xFF
        movwf     statusLED
        goto led_on2
led_on
        decf statusLED,f

        bsf PORTA,3        ;statusLED点灯
        movlw    0xFF
        movwf     statusLED2
led_on1    
        decf statusLED2,f
led_on2
        goto main            ;2
status_get
        ;ステータスをゲット
        call    getmidi        ;4μs    getmidi関数を呼び込み(midi信号を受け取る)
                            ;    rmitにデータが入る
        btfss    statusData,7        ;5μs    1(2) fのbビット目が1だったら次命令スキップ
        goto data_byte        ;7μs
status_byte
                            ;Microsoft GS Wavetable SW Synth ドラムセット 0x99 or 0x89
        movlw    0x01        ;5
        movwf    statusLED    ;6
        movlw    0xFF        ;7
        movwf    statusLED2    ;8
        bcf PORTA,3            ;9        statusLED消灯
        movfw    statusData    ;10μs
        sublw    0x99        ;11μs    ノートオン
        btfsc    STATUS,Z    ;12μs    1(2)
        goto note_on        ;14μs    2
        movfw    statusData    ;14μs
        sublw    0x89        ;15μs    ノートオフ
        btfsc    STATUS,Z    ;16μs    1(2)
        goto note_off        ;18μs    2
                            ;ドラムセットのノートオン、オフ以外はスルー出力
                            ; それでも32μs以上は無理
                            ;
throughout
        bsf        PORTA,2        ;RA2をmidi出力
        movfw    statusData
        movwf    xmit
        call    sendmidi    ;sendmidi関数を呼び込み(midi信号を送る)
        movfw    noteData
        movwf    xmit
        call    sendmidi    ;sendmidi関数を呼び込み(midi信号を送る)
        movfw    veloData
        movwf    xmit
        call    sendmidi    ;sendmidi関数を呼び込み(midi信号を送る)

        goto main            ;        2
data_byte
                            ;いきなりデーターバイト = ステータスがなければ無視 取りこぼしetc?
        goto main
;---------------------------------------------------------------
;SUBルーチン
;---------------------------------------------------------------
note_off                ;18μs
        ;とりあえずノートオフは無視
        goto main
note_on
                            ;14μs
        org 0x0200                 ;TABLE_LOOKUPルーチンのアドレス0x200H
TABLE_LOOKUP
        movlw    31
        subwf    noteData,w        ;
        andlw    B'00011111'

         movwf   INDEX           ;Wレジスタよりインデックス値
        movlw   LOW(TABLE)      ;テーブル開始の下位アドレス
        addwf   INDEX,F         ;下位アドレスとインデックスを加算
        movlw   HIGH(TABLE)     ;テーブル開始の上位アドレス
        movwf   PCLATH          ;上位アドレスをPCLATHに代入
        btfsc   STATUS,C        ;キャリフラグが1なら
        incf    PCLATH,F        ;上位アドレス(PCLATH)へ桁上がりあり
        movfw   INDEX         ;インデックスをWレジスタへ
        movwf   PCL                ; ↑ ジャンプテーブルへ飛ぶ     テーブルのgotoで
;---------------------------------------------------------------
TABLE
    ;ノートナンバーは31から考慮 0~31 b'00011111'
        goto    Sticks            ;31        1
;        goto    Square_Click    ;32        
;        goto    Metronome_Click    ;33        
;        goto    Metronome_Bell    ;34        
        goto    Sticks            ;32        2
        goto    Sticks            ;33        3
        goto    Sticks            ;34        4
        goto    Kick_Drum2        ;35        5
        goto    Kick_Drum1        ;36        6
        goto    Side_Stick        ;37        7
        goto    Snare_Drum1        ;38        8
        goto    Hand_Clap        ;39        9
        goto    Snare_Drum2        ;40        10
        goto    Low_Tom2        ;41        11
        goto    Closed_HiHat    ;42        12
        goto    Low_Tom1        ;43        13
        goto    Pedal_HiHat        ;44        14
        goto    Mid_Tom2        ;45        15
        goto    Open_HiHat        ;46        16
        goto    Mid_Tom1        ;47        17
        goto    High_Tom2        ;48        18
        goto    Crash_Cymbal1    ;49        19
        goto    High_Tom1        ;50        20
;        goto    Ride_Cymbal1    ;51
;        goto    Chinese_Cymbal    ;52
;        goto    Ride_Bell        ;53
        goto    Crash_Cymbal1    ;51        21
        goto    Crash_Cymbal1    ;52        22
        goto    Crash_Cymbal1    ;53        23
;        goto    Tambourine        ;54
        goto    Snare_Drum1        ;54        24
;        goto    Splash_Cymbal    ;55    
        goto    Crash_Cymbal1    ;55        25
;        goto    Cowbell            ;56
        goto    High_Tom1        ;50        26
;        goto    Crash_Cymbal2    ;57
        goto    Crash_Cymbal1    ;55        27
;        goto    Vibra_Slap        ;58
;        goto    Ride_Cymbal2    ;59
        goto    Crash_Cymbal1    ;55        28
        goto    Crash_Cymbal1    ;55        29
;        goto    High_Bongo        ;60
;        goto    Low_Bongo        ;61
        goto    High_Tom1        ;50        30
        goto    Low_Tom1        ;43        31
;        goto    Mute_HighConga    ;62    
;        goto    Open_HighConga    ;63
        goto    High_Tom1        ;50        32
        goto    Low_Tom1        ;43        33
;        goto    Low_Conga        ;64        34
;        goto    High_Timbale    ;65        35
;        goto    Low_Timbale        ;66        36
;        goto    High_Agogo        ;67        37
    org 0x0280
Sticks        ;NO.31
        movlw    0x7f
        movwf    triger1
        goto    main
        movlw    0xff        ;1μs    max 3+4+7*5=42μs  +ここ以前の17μs = 59μsで取りこぼすかもね?
        movwf    triger1        ;2μs
        bsf        veloData,0    ;3μs
Sticks1
        rlf        veloData,f    ;1μs
        btfsc    STATUS,C    ;2μs  1(2) STATUSのCが0ならば、gotoをスキップ、1ならばgoto
        goto    main        ;4μs
        rrf        triger1,f    ;4μs
        goto    Sticks1        ;5μs
Side_Stick    ;NO.37    
        goto    Sticks        ;5μs
Snare_Drum1    ;NO.38    
        movlw    0x7f
        movwf    triger0
        goto    main
        movlw    0xff        ;1μs    max 3+4+7*5=42μs  +ここ以前の17μs = 59μsで取りこぼすかもね?
        movwf    triger0        ;2μs
        bsf        veloData,0    ;3μs
Snare_Drum11
        rlf        veloData,f    ;1μs
        btfsc    STATUS,C    ;2μs  1(2) STATUSのCが0ならば、gotoをスキップ、1ならばgoto
        goto    main        ;4μs
        rrf        triger0,f    ;4μs
        goto    Snare_Drum11;5μs
Snare_Drum2    ;NO.40    
        goto    Snare_Drum1    ;2μs
Kick_Drum2    ;NO.35    
        movlw    0x7f
        movwf    triger2
        goto    main
        movlw    0xff        ;1μs    max 3+4+7*5=42μs  +ここ以前の17μs = 59μsで取りこぼすかもね?
        movwf    triger2        ;2μs
        bsf        veloData,0    ;3μs
Kick_Drum21
        rlf        veloData,f    ;1μs
        btfsc    STATUS,C    ;2μs  1(2) STATUSのCが0ならば、gotoをスキップ、1ならばgoto
        goto    main        ;4μs
        rrf        triger2,f    ;4μs
        goto    Kick_Drum21    ;5μs
Kick_Drum1    ;NO.36    
        goto    Kick_Drum2    ;2μs
Low_Tom2    ;NO.41    
        movlw    0x7f
        movwf    triger4
        goto    main
        movlw    0xff        ;1μs    max 3+4+7*5=42μs  +ここ以前の17μs = 59μsで取りこぼすかもね?
        movwf    triger4        ;2μs
        bsf        veloData,0    ;3μs
Low_Tom21
        rlf        veloData,f    ;1μs
        btfsc    STATUS,C    ;2μs  1(2) STATUSのCが0ならば、gotoをスキップ、1ならばgoto
        goto    main        ;4μs
        rrf        triger4,f    ;4μs
        goto    Low_Tom21    ;5μs
Low_Tom1    ;NO.43    
        goto Low_Tom2
Mid_Tom2    ;NO.45    
        goto Low_Tom2
Mid_Tom1    ;NO.47    
        movlw    0x7f
        movwf    triger5
        goto    main
        movlw    0xff        ;1μs    max 3+4+7*5=42μs  +ここ以前の17μs = 59μsで取りこぼすかもね?
        movwf    triger5        ;2μs
        bsf        veloData,0    ;3μs
Mid_Tom11
        rlf        veloData,f    ;1μs
        btfsc    STATUS,C    ;2μs  1(2) STATUSのCが0ならば、gotoをスキップ、1ならばgoto
        goto    main        ;4μs
        rrf        triger5,f    ;4μs
        goto    Mid_Tom11    ;5μs
High_Tom2    ;NO.48    
        goto    Mid_Tom1    ;2μs

High_Tom1    ;NO.50    
        goto    Mid_Tom1    ;2μs
Closed_HiHat;NO.42    
        movlw    0x7f
        movwf    triger6
        goto    main
        movlw    0xff        ;1μs    max 3+4+7*5=42μs  +ここ以前の17μs = 59μsで取りこぼすかもね?
        movwf    triger6        ;2μs
        bsf        veloData,0    ;3μs
Closed_HiHat1
        rlf        veloData,f    ;1μs
        btfsc    STATUS,C    ;2μs  1(2) STATUSのCが0ならば、gotoをスキップ、1ならばgoto
        goto    main        ;4μs
        rrf        triger6,f    ;4μs
        goto    Closed_HiHat1;5μs
Pedal_HiHat    ;NO.44    
        goto    Closed_HiHat;2μs
Open_HiHat    ;NO.46    
        movlw    0x7f
        movwf    triger7
        goto    main
        movlw    0xff        ;1μs    max 3+4+7*5=42μs  +ここ以前の17μs = 59μsで取りこぼすかもね?
        movwf    triger7        ;2μs
        bsf        veloData,0    ;3μs
Open_HiHat1
        rlf        veloData,f    ;1μs
        btfsc    STATUS,C    ;2μs  1(2) STATUSのCが0ならば、gotoをスキップ、1ならばgoto
        goto    main        ;4μs
        rrf        triger7,f    ;4μs
        goto    Open_HiHat1    ;5μs
Crash_Cymbal1;NO.49    
        movlw    0x7f
        movwf    triger3
        goto    main
        movlw    0xff        ;1μs    max 3+4+7*5=42μs  +ここ以前の17μs = 59μsで取りこぼすかもね?
        movwf    triger3        ;2μs
        bsf        veloData,0    ;3μs
Crash_Cymbal11
        rlf        veloData,f    ;1μs
        btfsc    STATUS,C    ;2μs  1(2) STATUSのCが0ならば、gotoをスキップ、1ならばgoto
        goto    main        ;4μs
        rrf        triger3,f    ;4μs
        goto    Crash_Cymbal11;5μs
Ride_Cymbal1;NO.51    
        goto    Crash_Cymbal1;2μs
Hand_Clap    ;NO.39    
        goto    Crash_Cymbal1;2μs
Tambourine    ;NO.54    
        goto    Crash_Cymbal1;2μs
;---------------------------------------------------------------
;ウエイト 1=1/40000=0.25μs 1命令4クロック=1μS   20μs程度
;---------------------------------------------------------------
wait_loop
        movlw    5            ;Y = 3*X + 3  (return含む)
        movwf    temp2    ;3*5+3 = 18μs
wait_loop1
        decfsz    temp2,f
        goto    wait_loop1
        return
;---------------------------------------------------------------
;                MIDI ショートメッセージ入力ルーチン
;---------------------------------------------------------------
;   スタートビットは論理0、ストップビットは論理1
;   5mAのカレントループとし論理0が電流が流れている状態
;
; 初めがHI? startbit(LO) → 0bit→1、2、3、4、5、6、7bit stopbit(HI)
;
;    start 0 1 2 3  4 5 6 7  stop      ←0bitが先に来る
; ――――――__ ― ― ― ― ― ― ― ―  ――――――
;
;4MHzバージョン
;1/40000=0.25μs 1命令4クロック=1μS 1命令サイクル1μs
;MIDI 1bit=32μS
;
;    bcf        STATUS,RP0    ;STATUSの 5をクリア(0) → バンク0
;
;    call    getmidi        ;2μs    getmidi関数を呼び込み(midi信号を受け取る)
;        statusData
;        noteData
;        veloData    にデータが入る
getmidi
    ;____________startbit_______________
    btfsc    PORTA,0    ;2μs    1(2) fのbビット目がゼロだったら次命令スキップ
    goto    getmidi
startb_0
    movlw 9            ;Y = 3 * X + 1
                    ;X=9  28μs消費
    movwf temp
loop_01
    decfsz temp,f 
    goto loop_01        ;end delay
    movlw 8            ; midi信号は8ビット
                    ;31μs    1
    movwf j            ;32μs    1
    ;____________ここまでは_______________
getloop_0
                    ;8Bit巡回シフト命令で1バイトを入力
    rrf PORTA,w        ;PORTAの内容を右に1ビットシフトして最下位(bit0)のあふれをSTATUSのCに入れる 答えはWに
                    ;1μs    1
    rrf statusData,f        ;STATUSのCとrmitの内容を合せて右に1ビットシフト
                    ;2μs    1
    movlw 8            ;Y = 3 * X + 1    X=8  27μs消費
    movwf temp
loop_02
    decfsz temp,f    ; 1*(X-1)+2
    goto loop_02        ; 2*(X-1)
    nop                ;28μs
    nop                ;29μs
    decfsz j,f        ;30μs    1(2)
    goto getloop_0    ;32μs    2
    nop                ;32μs    1
stopb_0
    ;____________stopbit_______________
                    ;ストップビットが来たらリターン
loop_03
    btfss    PORTA,0    ;fのbビット目が1だったら次命令スキップ
    goto    loop_03
;    return            ;2μs
getmidi_1
    ;____________startbit_______________
    btfsc    PORTA,0    ;2μs    1(2) fのbビット目がゼロだったら次命令スキップ
    goto    getmidi_1
startb_1
    movlw 10        ;Y = 3 * X + 1
                    ;X=10  31μs消費
    movwf temp
loop_11
    decfsz temp,f 
    goto loop_11        ;end delay
    movlw 8            ; midi信号は8ビット
                    ;31μs    1
    movwf j            ;32μs    1
    ;____________ここまでは_______________
getloop_1
                    ;8Bit巡回シフト命令で1バイトを入力
    rrf PORTA,w        ;PORTAの内容を右に1ビットシフトして最下位(bit0)のあふれをSTATUSのCに入れる 答えはWに
                    ;1μs    1
    rrf noteData,f        ;STATUSのCとrmitの内容を合せて右に1ビットシフト
                    ;2μs    1
    movlw 8            ;Y = 3 * X + 1    X=8  27μs消費
    movwf temp
loop_12
    decfsz temp,f    ; 1*(X-1)+2
    goto loop_12        ; 2*(X-1)
    nop                ;28μs
    nop                ;29μs
    decfsz j,f        ;30μs    1(2)
    goto getloop_1    ;32μs    2
    nop                ;32μs    1
stopb_1
    btfss    noteData,7    ;fのbビット目が1だったら次命令スキップ
    goto    loop_13

    movfw    noteData    ;ステータスバイトだった(取りこぼしてずれた???)
    movwf    statusData
    goto    loop_03
    ;____________stopbit_______________
                    ;ストップビットが来たらリターン
loop_13
    btfss    PORTA,0    ;fのbビット目が1だったら次命令スキップ
    goto    loop_13
;    return            ;2μs
getmidi_2
    ;____________startbit_______________
    btfsc    PORTA,0    ;2μs    1(2) fのbビット目がゼロだったら次命令スキップ
    goto    getmidi_2
startb_2
    movlw 10        ;Y = 3 * X + 1
                    ;X=10  31μs消費
    movwf temp
loop_21
    decfsz temp,f 
    goto loop_21        ;end delay
    movlw 8            ; midi信号は8ビット
                    ;31μs    1
    movwf j            ;32μs    1
    ;____________ここまでは_______________
getloop_2
                    ;8Bit巡回シフト命令で1バイトを入力
    rrf PORTA,w        ;PORTAの内容を右に1ビットシフトして最下位(bit0)のあふれをSTATUSのCに入れる 答えはWに
                    ;1μs    1
    rrf veloData,f        ;STATUSのCとrmitの内容を合せて右に1ビットシフト
                    ;2μs    1
    movlw 8            ;Y = 3 * X + 1    X=9  25μs消費
    movwf temp
loop_22
    decfsz temp,f    ; 1*(X-1)+2
    goto loop_22        ; 2*(X-1)
    nop                ;28μs
    nop                ;29μs
    decfsz j,f        ;30μs    1(2)
    goto getloop_2    ;32μs    2
    nop                ;32μs    1
stopb_2
    btfss    veloData,7    ;fのbビット目が1だったら次命令スキップ
    goto    loop_23

    movfw    veloData    ;ステータスバイトだった(取りこぼしてずれた???)
    movwf    statusData
    goto    loop_03
    ;____________stopbit_______________
                    ;ストップビットが来たらリターン
loop_23
    btfss    PORTA,0    ;fのbビット目が1だったら次命令スキップ
    goto    loop_23
    return            ;2μs
;---------------------------------------------------------------
;                      MIDI バイト出力ルーチン
;---------------------------------------------------------------
;自作電子楽器ノブログ http://toucylab.exblog.jp/4256675/ さんの流用です
;
;    bcf STATUS,RP0    ; STATUSの 5をクリア(0) → バンク0
;    bsf PORTA,2        ;RA2をmidi出力
;
;    movlw 90h        ; ノートオン、チャンネル1
;    movwf xmit        ;xmitに10010000(Ox90)を格納
;    call sendmidi    ;sendmidi関数を呼び込み(midi信号を送る)
;のように使用します
;
;4MHzバージョン
;ウエイト 1=1/40000=0.25μs 1命令4クロック=1μS
;MIDIは1ビット32μS = 1/31250bit (31.25Kbit/sec)
;    なので32μSでループを終らせる
;
; 1バイト出力するのに 32μS * 10bit ≒ 320μS
; したがって1MIDIショートメッセージ(3バイト)でおよそ1ms必要
;
sendmidi

starta_
    bcf PORTA,2        ; スタートビット
    
    movlw 7        ;Y = 3 * X + 1    X=7  22μs消費
    movwf temp
loop1_
    decfsz temp,f
    goto loop1_        ;end delay
    nop                ;23μs
    
    movlw 8            ; midi信号は8ビット
                    ;24μs
    movwf j            ;25μs

sendloop_
    rrf xmit,f        ; xmitの内容を右に1ビットシフトしてSTATUSのCに入れる
                    ;26μs
    btfsc STATUS,C    ; STATUSのCが0ならば、gotoをスキップ、1ならばgoto
                    ;27μs
    goto send1_        ;29μs

send0_
    nop                ;29μs
    nop                ;30μs
    nop                ;31μs
    bcf PORTA,2        ;0ビットを送る     32μs
    goto endloop_    ;2μs

send1_
    nop                ;30μs
    nop                ;31μs
    bsf PORTA,2        ;1ビットを送る     32μs
    nop                ;1μs
    nop                ;2μs

endloop_
    nop                ;3μs
    movlw 6            ;Y = 3 * X + 1    X=6  19μs消費
    movwf temp
loop2_
    decfsz temp,f    ; 1*(X-1)+2
    goto loop2_        ; 2*(X-1)

    decfsz j,f        ;23μs
    goto sendloop_    ;25μs

stopb_
    nop                ;28μs
    nop                ;29μs
    nop                ;30μs
    nop                ;31μs
    bsf PORTA,2        ; ストップビット     32μs
    movlw 9        ; Y = 3 * X + 1 + 2(return)
                    ;X=9  30μs消費
    movwf temp
loop3_
    decfsz temp,f 
    goto loop3_        ; end delay
    return            ;2μs以上( call + α )を他で消費するのでちょうど?
;---------------------------------------------------------------
        END
; プログラムの終了をアセンブラに指示する
; =========================== ここまで ===============================