; 国民機起動音発生装置 PiPo Ver.6.2+ ; 製作 : 爆竹銃 ; http://baku.homeunix.net ; http://bakutek.net ;@bakuchikujuu ; 最終更新 :2016-08-24 ;200X 初代 ; いろんなサンプルをパッチワークで繋ぎつつうりうり改造 ;2006-07-31 Ver.4 ; Ver.3まではループでタイミングを合わせていたが、 ; 色々面倒が多いので割り込み利用に(ほぼ)作り直した ;2016-05-04 ;発音前無音時間を指定できるようにした ;ピとポの周期が1usずれていたのを修正(ずれてたが、内蔵OSCの誤差±1%に埋もれる程度) ;2016-08-24 ;先の改造で練り込んでしまったバグを修正 list P=PIC12F615 include "P12F615.INC" __CONFIG _CP_OFF & _BOR_ON & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSCIO & _IOSCFS_8MHZ #define PI_TMR1L 0x18 ; (65536-250+12) #define PI_TMR1H 0xfe #define PO_TMR1L 0x24 #define PO_TMR1H 0xfc #define WAIT10ms_TMR1L 0xfc ;10ms周期割り込み用 #define WAIT10ms_TMR1H 0xd8 ;(65536-10000+12) #define MODE_BEEP 0 ; beep音発生 mode=&b0000 0001 #define MODE_WAIT 1 ; beep equ 5 ; GPIO5 BEEP出力 input equ 4 ; GPIO4 スルーBEEP入力 fire equ 2 ; GPIO2 テスト再生 wait_before_beep equ 0 ;ピポ前に待つ:flags[0]=1, ピポ後に待つ:flags[0]=0 CBLOCK 0x40 w_save ; W待避用 status_save ; STATUS待避用 counter4wait ; ループでのWAIT用 mode ; 「状態」 flags ;各種設定 beep_state ; BEEPはH?L? beep_counter_h ;波数カウント用 beep_counter_l ; beep_counter_h_ad ;波数カウント用 A/D変換結果 beep_counter_l_ad ; wait_counter_h ;無音時間待ちカウント用 wait_counter_l ; adcon_channel ;A/Dチャンネル指定 adcon_h ;A/D結果 adcon_l ; set_TMR1L ; 割り込み時に再セットするTMR1の値 set_TMR1H ENDC ;いちいちmovlw, movwfとかは面倒だよな movlf MACRO literal, filereg movlw literal movwf filereg ENDM ;使用例 ; movlf 0x01, mode movff MACRO filereg_src, filereg_dist movf filereg_src, W movwf filereg_dist ENDM ; ;16bit decfscもどき(0ではなく、-1でループ(等)脱出) ; ■使用例: ; movlf 0x04, h ; movlf 0x00, l ; loop ; call hoge ; decfscw h,l ; goto loop ; ; DECrement F, Skip if Carry (Word) decfscw MACRO h, l movlw 0x01 subwf l, f btfss STATUS, C subwf h, f btfss STATUS, C ENDM ; ■使用例: ; decfsncw h,l ; clrf flag ; DECrement F, Skip if NonCarry (Word) decfsncw MACRO h, l movlw 0x01 subwf l, f btfss STATUS, C subwf h, f btfss STATUS, C ENDM ;割り込み時レジスタ待避 save_reg MACRO ;W,STATUSレジスタ退避 movwf w_save swapf STATUS, W bcf STATUS, RP0 ;割り込み前にバンク切り替えしてるかも movwf status_save ENDM load_reg MACRO ;W,STATUSレジスタ復帰 swapf status_save, W movwf STATUS swapf w_save, f swapf w_save, W ENDM ; ============================================== org 0 goto initialize org 4 goto interrupt ; //////////////////////////////////////////////////////////////// initialize banksel GPIO clrf GPIO clrwdt ;割り込み関連初期化 banksel PIE1 movlf b'00000001', PIE1 ;TMR1割り込み Enable movlf b'00011111', TRISIO ;GPIO[0:4]=input, GPIO5=output movlf b'00010100', WPU ;WeekPullup movlf b'00000000', OPTION_REG ;bit7 /GPPU 0 Weak pull-ups on GPIO movlf b'00010011', ANSEL ;GPIO 0,1をアナログ入力, ADCclk=Fosc/8 ; BANK 0 -------------------------------- banksel T1CON movlf b'00000001', T1CON ;TMR1 1:1 movlf b'01000000', INTCON ; Peripheral Interrupt Enable movlf b'00000000', CMCON0 ;コンパレータ無効 ;準備 ;ちょいと(100ms)待つ movlf 0x00, wait_counter_h movlf d'10', wait_counter_l call wait_by_timer ;無音時間は、発音前?後? clrf flags btfsc GPIO, input ;inputが、Lに落ちて、いない、なら (オープンかH) bcf flags, wait_before_beep ;発音後に待つよ btfss GPIO, input ;inputが、Hで、なければ bsf flags, wait_before_beep ;発音前に待つよ ; ---------------------------------------------------------------- pipo ;ちょいと(100ms)待つ movlf 0x00, wait_counter_h movlf d'10', wait_counter_l call wait_by_timer ;発振前無音時間 btfsc flags, wait_before_beep ;発音後無音モードでは、下記処理を飛ばす call silent_wait ;無音時間 movlf 0x00, beep_state ; beep初期値 clrf mode bsf mode, MODE_BEEP ; ピポ音長さ読み込み movlf 0, adcon_channel call adcon10bit movff adcon_h, beep_counter_h_ad movff adcon_l, beep_counter_l_ad movff beep_counter_h_ad, beep_counter_h movff beep_counter_l_ad, beep_counter_l pi ; *"Pi" ------------------------------------------------ movlf PI_TMR1H, set_TMR1H movlf PI_TMR1L, set_TMR1L movff set_TMR1L, TMR1L movff set_TMR1H, TMR1H bcf PIR1,TMR1IF bsf INTCON, GIE pi_loop btfss mode, MODE_BEEP goto po goto pi_loop ; *"Po" ------------------------------------------------ po clrf mode bsf mode, MODE_BEEP movff beep_counter_h_ad, beep_counter_h movff beep_counter_l_ad, beep_counter_l bcf STATUS, C rrf beep_counter_h, f ; カウント数半減 rrf beep_counter_l, f ;タイマーセット movlf PO_TMR1H, set_TMR1H movlf PO_TMR1L, set_TMR1L movff set_TMR1L, TMR1L movff set_TMR1H, TMR1H bcf PIR1,TMR1IF bsf INTCON, GIE po_loop btfss mode, MODE_BEEP goto po_end goto po_loop po_end ;BEEP発音終了 bcf INTCON, GIE ;割り込み禁止 bcf GPIO, beep ;とりあえず、出力OFF btfsc flags, wait_before_beep goto donot_beep_thru ;発音前無音モードでは、inputがGNDに落ちているので、下記処理を飛ばす ; BEEP出力を入力に合わせる btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep donot_beep_thru ;発振後無音時間 btfss flags, wait_before_beep ;発音前無音モードでは、下記処理を飛ばす call silent_wait ;無音時間 bcf INTCON, GIE ;割り込み禁止 ;BEEPスルー状態へ移行 btfss flags, wait_before_beep ;発音前無音モードでは、スルーしない goto beep_thru_loop goto eloop ;end of main //////////////////////////////////////////////// ;無音時間 ---------------------------------------- ;最大で10230ms silent_wait movlf 1, adcon_channel call adcon10bit movff adcon_h, wait_counter_h movff adcon_l, wait_counter_l wait_by_timer clrf mode bsf mode, MODE_WAIT movlf WAIT10ms_TMR1H, set_TMR1H movlf WAIT10ms_TMR1L, set_TMR1L movff set_TMR1L, TMR1L movff set_TMR1H, TMR1H bcf PIR1,TMR1IF bsf INTCON, GIE btfss mode, MODE_WAIT goto $+2 goto $-2 return ;end of silent_wait -------------------------------- ;*A/D変換10bit精度 ------------------------------------------------ ; adcon_channelにポート番号を入れてcall ; adcon_h, adcon_lに結果が入る ; ■使用例: ; movlf adcon_channel, 0 ; call adcon10bit adcon10bit bcf STATUS, C rlf adcon_channel, f rlf adcon_channel, W iorlw b'10000001' ; 右詰, A/D_ON movwf ADCON0 movlf 3, counter4wait ;wait 20us call wait bsf ADCON0, GO btfsc ADCON0, GO_DONE goto $-1 movff ADRESH, adcon_h banksel ADRESL movf ADRESL, W banksel adcon_l movwf adcon_l #ifdef debug movlf 0x80, adcon_l movlf 0x00, adcon_h #endif return ; end of adcon10bit ------------------------------------------------ ; *WAIT -------------------------------------------------------- ; (counter4wait-1)*5 + 8 サイクル時間待ち ; movlw, movwfを入れれば、(X-1)*5+10 ; ■使用例: ; movlf d'10', counter4wait ; call wait wait ;2 (call) goto $+1 ;2 ;2 decfsz counter4wait, f ;1 ;2(脱出時) goto wait ;2 return ;2 ; end of wait ------------------------------------------------ ; *割り込み部分(主処理?)-------------------------------- interrupt save_reg ; 割り込み発生からここまで12サイクル nop movf set_TMR1L, W ;タイマー再セット movwf TMR1L movf set_TMR1H, W movwf TMR1H bcf PIR1, TMR1IF btfsc mode, MODE_BEEP ; ここで、割り込み発生から 18サイクル goto intsub_beep btfsc mode, MODE_WAIT goto intsub_wait ; BEEP! ------------------------------------------------ intsub_beep ;割り込み発生から20サイクル経過 ; BEEP出力操作 movlw 0x01 ;1 xorwf beep_state, f ;1 btfsc beep_state, 0 ;1 ;2 goto set_BEEP_H ;2 goto set_BEEP_L ;2 set_BEEP_H nop ;1 bsf GPIO, beep ;1 goto end_set_BEEP ;2 set_BEEP_L bcf GPIO, beep ;1 goto end_set_BEEP ;2 end_set_BEEP ;計17サイクル nop ;波数カウント decfsncw beep_counter_h, beep_counter_l ;5 clrf mode ;1 減算でキャリー有りなら、「状態」変更 ;計6サイクル load_reg ;4 retfie ;計6サイクル@復帰処理 ; intsub_wait ;カウントダウン movlw 0x01 ;1 subwf wait_counter_l, f ;1 btfss STATUS, C ;1 ;2 subwf wait_counter_h, f ;1 btfss STATUS, C ;1 ;2 clrf mode ;1 減算でキャリー有りなら、「状態」変更 ;計6サイクル load_reg retfie ;計6サイクル@復帰処理 ; end of interrupt ------------------------------------------------ ; BEEPスルーしないループ ------------------------------------------------- eloop btfsc GPIO, fire ; テスト発音ボタンが押されたら、ループ脱出 goto eloop goto pipo ; BEEPスルーループ ------------------------------------------------- beep_thru beep_thru_loop btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfss GPIO, input bsf GPIO, beep btfsc GPIO, input bcf GPIO, beep btfsc GPIO, fire ; テスト発音ボタンが押されたら、ループ脱出 goto beep_thru_loop goto pipo end