;***** Sound.sub ********************************************************** ; ; サウンド・サブルーチン (Sound_Init, Sound_Play) ; ; ( coding: Ver. 0.00 2011/11/06 by M.Yamamoto ) ; coding: Ver. 1.00 2011/11/08 初期バージョン ; update: Ver. 1.01 2011/11/09 最適化 (旧 code 残) ; update: Ver. 1.02 2011/11/09 旧 code 削除 ; update: Ver. 1.03 2011/11/09 コメントの強化 ; update: Ver. 1.04 2013/10/02 システムクロックの引き継ぎ ; bugfix: Ver. x.xx ; ;******************************************************* PicAsm 0230 ****** ; オリジナルは、サイト "電子工作etc" の "簡易電子メトロノーム(http://www8.plala.or.jp/InHisTime/page195.html)" ; で紹介されている HEXファイル(http://www8.plala.or.jp/InHisTime/PIC-156/metronome.hex) 中にあり、プログラムは ; mikroC PRO で作成されていて、そこで使用されているサウンド関数(Sound_Init,Sound_Play)そのものである。 ; その HEXファイルを "帝" で逆アセンブルして得られたアセンブルリストから、サウンド関数部分を抽出して再編集した。 ; オリジナルのコードでは、呼ばれた Sound_Play サブルーチンからは後1レベルのみのサブルーチンコールで済ましてい ; るために、32 / 32bit 除算ルーチン等のコードでは、かなり冗長なコードとなってそのサイズを肥大化している。 ; そこで全体のコードを最適化するにあたって、冗長なコードを改善するためにもう1レベルのサブルーチンコールを許す ; ことにした。したがってスタックがその分圧迫されるので、使用時にはそのことの考慮が必要である。 ; 参考: オリジナルのコードサイズ = 726 Words, 最適化後のコードサイズ = 431 Words ;========================================================================== ; ポートとピンを指定してサウンドを初期化する ;========================================================================== ;入力レジスタ: port_x: 5:PORTA, 6:PORTB, 7:PORTC, 8:PORTD, 9:PORTE ; port_bit: 0:bit0, 1:bit1, 2:bit2, 3:bit3, 4:bit4, 5:bit5, 6:bit6, 7:bit7 ;出力レジスタ: sound01: port_x の Copy 例. h'06' ; (Sound_Playに sound02: 出力 bit 位置 (反転値) h'f7' = b'11110111' (port_bit = h'03') ; 引き継ぐ) sound03: 出力 bit 位置 h'08' = b'00001000' (port_bit = h'03') Sound_Init bcf STATUS,RP0 ;バンク 0 bcf STATUS,RP1 movf port_x,W movwf sound01 ;保存 movlw h'01' ;bit 位置の初期値 = b'00000001' movwf sound02 movf port_bit,W ;W レジスタ = ループカウンタ sinit_01 btfsc STATUS,Z ;Z = 0 か? goto sinit_02 ;No rlf sound02,F ;1 bit 左にシフト bcf sound02,0 ;廻り込んだ C bit をクリア addlw h'ff' goto sinit_01 sinit_02 movf sound02,W movwf sound03 ;保存 comf sound02,F ;反転値保存 movlw h'80' ;バンク 1 指定 addwf port_x,W movwf FSR ;TRISx のアドレス movf sound02,W andwf INDF,F ;Sound 出力ポートの設定 bcf FSR,7 ;PORTx のアドレス movf sound02,W andwf INDF,F ;Sound 出力ポートに "0" 出力 return ;========================================================================== ; 出力周波数と出力時間を指定しサウンドを鳴らす ;========================================================================== ;入力変数: sys_clk: システムクロック(KHz) ... sp_sub_01 内で使用 ;入力レジスタ: freq_lo: low Sound出力周波数(Hz) ; freq_hi: high ; time_lo: low Sound出力時間(ms) ; time_hi: high ;内部使用レジスタ: sound00: work00 ; sound01: ポートアドレス (5:PORTA, 6:PORTB, 7:PORTC, 8:PORTD, 9:PORTE) ; sound02: Sound出力ポートの bit 位置 (反転値) ; sound03: Sound出力ポートの bit 位置 ; sound04: work04 ; sound05: work05 ; sound06: work06 ; sound07: work07 ; sound08: work08 ; sound09: work09 ; sound0a: work0a ; sound0b: work0b ; sound0c: work0c ; sound70: work70 ; sound71: work71 ; sound72: work72 ; sound73: work73 ; sound74: work74 ; sound75: work75 ; sound76: work76 ; sound77: work77 ; sound78: work78 ; sound79: work79 ; sound7a: work7a ; sound7b: work7b ; sound7c: work7c Sound_Play call sp_sub_01 ;使用クロック: KHz で指定 ;(sound73,72,71,70) movlw h'e8' ;low d'1000' movwf sound74 movlw h'03' ;high d'1000' movwf sound75 clrf sound76 clrf sound77 ; 使用クロック(KHz) x 1000 call sp_sub_02 ;乗算-1: (sound73,72,71,70) x (sound77,76,75,74) ; = (sound7b,7a,79,78,73,72,71,70) movf freq_lo,W ;low Sound出力周波数(Hz) movwf sound74 movf freq_hi,W ;high Sound出力周波数(Hz) movwf sound75 clrf sound76 clrf sound77 ;(使用クロック(KHz) x 1000) / Sound出力周波数(Hz) call sp_sub_03 ;除算-1: (sound73,72,71,70) / (sound77,76,75,74) ; = (sound73,72,71,70) … (sound7b,7a,79,78) rrf sound73,F ;(sound73,72,71,70) / 8 rrf sound72,F rrf sound71,F rrf sound70,F bcf sound73,7 rrf sound73,F rrf sound72,F rrf sound71,F rrf sound70,F bcf sound73,7 rrf sound73,F rrf sound72,F rrf sound71,F rrf sound70,F bcf sound73,7 movf sound70,W ;(除算-1の答 >> 3) を退避 (sound71,70) → (sound05,04) movwf sound04 ; movf sound71,W ; movwf sound05 ; call sp_sub_01 ;使用クロック: KHz で指定 ;(sound73,72,71,70) movf time_lo,W ;low Sound出力時間(ms) movwf sound74 movf time_hi,W ;high Sound出力時間(ms) movwf sound75 clrf sound76 clrf sound77 ; 使用クロック(KHz) x Sound出力時間(ms) call sp_sub_02 ;乗算-2: (sound73,72,71,70) x (sound77,76,75,74) ; = (sound7b,7a,79,78,73,72,71,70) movf sound04,W ;(除算-1の答 >> 3) を復帰 (sound05,04) → (sound75,74) movwf sound74 movf sound05,W movwf sound75 clrf sound76 clrf sound77 movlw h'03' addlw h'00' ;W レジスタ = ループカウンタ splay_01 btfsc STATUS,Z ;Z = 0 か ? goto splay_02 ;No rlf sound74,F ;(sound77,76,75,74) x 2 ^ 3 rlf sound75,F rlf sound76,F rlf sound77,F bcf sound74,0 addlw h'ff' goto splay_01 ; (使用クロック(KHz) x Sound出力時間(ms)) / ((除算-1の答 >> 3) << 3) splay_02 call sp_sub_03 ;除算-2: (sound73,72,71,70) / (sound77,76,75,74) ; = (sound73,72,71,70) … (sound7b,7a,79,78) movf sound70,W movwf sound08 ;除算-2の答の退避 (sound0b,0a,09,08) movf sound71,W movwf sound09 ; movf sound72,W movwf sound0a ; movf sound73,W movwf sound0b ; movlw h'0a' ;d'10' movwf sound74 movlw h'00' movwf sound75 movf sound04,W ;(除算-1の答 >> 3) を復帰 (sound05,04) → (sound71,70) movwf sound70 movf sound05,W movwf sound71 ; (除算-1の答 >> 3) / 10 call sp_sub_04 ;除算-3: (sound71,70) / (sound75,74) ; = (sound71,70) … (sound79,78) movf sound70,W movwf sound04 ;除算-3の答の退避 (sound05,04) movf sound71,W movwf sound05 ; movlw h'00' subwf sound71,W btfss STATUS,Z goto splay_03 movlw h'03' subwf sound70,W splay_03 btfsc STATUS,C goto splay_04 return splay_04 movf sound01,W ;ポートアドレス: (5:PORTA, 6:PORTB) movwf FSR ;を設定 splay_05 movf sound0b,W sublw h'00' btfss STATUS,Z ;sound0b = h'00' か ? goto splay_06 ;No movf sound0a,W sublw h'00' btfss STATUS,Z ;sound0a = h'00' か ? goto splay_06 ;No movf sound09,W sublw h'00' btfss STATUS,Z ;sound09 = h'00' か ? goto splay_06 ;No movf sound08,W sublw h'00' splay_06 btfsc STATUS,C ;sound0a < h'00' か ? goto splay_13 ;No movf sound03,W ;Sound出力ポートの bit 位置 iorwf INDF,F ;"1" 出力 movf sound05,W btfsc STATUS,Z goto splay_09 clrf sound06 clrf sound07 splay_07 movf sound06,W subwf sound07,W btfss STATUS,Z goto splay_08 movf sound05,W subwf sound06,W splay_08 btfsc STATUS,C goto splay_09 clrf sound0c call sp_sub_05 ;ウェイト incf sound06,F btfsc STATUS,Z incf sound07,F goto splay_07 splay_09 movf sound04,W movwf sound0c call sp_sub_05 ;ウェイト movf sound02,W ;Sound出力ポートの bit 位置 (反転値) andwf INDF,F ;"0" 出力 movf sound05,W btfsc STATUS,Z goto splay_12 clrf sound06 clrf sound07 splay_10 movf sound06,W subwf sound07,W btfss STATUS,Z goto splay_11 movf sound05,W subwf sound06,W splay_11 btfsc STATUS,C goto splay_12 clrf sound0c call sp_sub_05 ;ウェイト incf sound06,F btfsc STATUS,Z incf sound07,F goto splay_10 splay_12 movf sound04,W movwf sound0c call sp_sub_05 ;ウェイト movlw h'01' subwf sound08,F btfss STATUS,C subwf sound09,F btfss STATUS,C subwf sound0a,F btfss STATUS,C subwf sound0b,F goto splay_05 splay_13 movf sound02,W ;Sound出力ポートの bit 位置 (反転値) andwf INDF,F ;"0" 出力 return ;========================================================================== ; 使用クロック: KHz で指定 sp_sub_01 bcf STATUS,RP0 ;バンク 0 bcf STATUS,RP1 movlw low sys_clk ; movwf sound70 movlw high sys_clk ; movwf sound71 clrf sound72 clrf sound73 return ;========================================================================== ; 32bit x 32bit = 64bit 乗算ルーチン ; (sound73,72,71,70) x (sound77,76,75,74) = (sound7b,7a,79,78,73,72,71,70) ; 被乗数 sound70: 最下位 例. h'40' d'8000' → 答 h'00' d'8000000' ; sound71: h'1f' → (下位 h'12' ; sound72: h'00' → 32bit) h'7a' ; sound73: 最上位 h'00' → h'00' ; 乗数 sound74: 最下位 h'e8' d'1000' → 変更なし ; sound75: h'03' → 変更なし ; sound76: h'00' → 変更なし ; sound77: 最上位 h'00' → 変更なし ; 答 sound78: ; (上位 sound79: ; 32bit) sound7a: ; sound7b: 最上位 ; カウンタsound7c: h'22' d'34' → h'00' sp_sub_02 bcf STATUS,RP0 ;バンク 0 bcf STATUS,RP1 movlw h'22' ;d'34' movwf sound7c clrf sound78 clrf sound79 clrf sound7a clrf sound7b s02_01 decf sound7c,F btfsc STATUS,Z ;Z = 0 か ? goto s02_04 ;No bcf STATUS,C ;C = 0 s02_02 rrf sound7b,F rrf sound7a,F rrf sound79,F rrf sound78,F rrf sound73,F rrf sound72,F rrf sound71,F rrf sound70,F btfss STATUS,C ;C = 1 か ? goto s02_01 ;No decf sound7c,F btfsc STATUS,Z ;Z = 0 か ? goto s02_03 ;No call sp_sub_02a goto s02_02 s02_03 call sp_sub_02a s02_04 return sp_sub_02a movf sound74,W addwf sound78,F movf sound75,W btfsc STATUS,C ;C = 0 か ? incfsz sound75,W ;No addwf sound79,F movf sound76,W btfsc STATUS,C ;C = 0 か ? incfsz sound76,W ;No addwf sound7a,F movf sound77,W btfsc STATUS,C ;C = 0 か ? incfsz sound77,W ;No addwf sound7b,F return ;========================================================================== ; 32bit / 32bit = 32bit … 32bit 除算ルーチン ; (sound73,72,71,70) / (sound77,76,75,74) = (sound73,72,71,70) … (sound7b,7a,79,78) ; 被除数 sound70: 最下位 例. h'00' d'8000000' → 答 h'c1' d'4545' ; sound71: h'12' → h'11' ; sound72: h'7a' → h'00' ; sound73: 最上位 h'00' → h'00' ; 除数 sound74: 最下位 h'e0' d'1760' → 変更なし ; sound75: h'06' → 変更なし ; sound76: h'00' → 変更なし ; sound77: 最上位 h'00' → 変更なし ; 余り sound78: 最下位 → h'20' d'800' ; sound79: → h'03' ; sound7a: → h'00' ; sound7b: 最上位 → h'00' ; カウンタsound7c: h'07' d'07' → h'00' ; ワーク sound00: sp_sub_03 bcf STATUS,RP0 ;バンク 0 bcf STATUS,RP1 clrf sound7b clrf sound7a clrf sound79 clrf sound78 clrf sound00 rlf sound73,W rlf sound78,F movf sound74,W call sp_sub_03s rlf sound73,F movlw h'07' movwf sound7c s03_01 rlf sound73,W call sp_sub_03r movf sound74,W btfss sound73,0 goto s03_02 call sp_sub_03s goto s03_03 s03_02 call sp_sub_03a s03_03 rlf sound73,F decfsz sound7c,F goto s03_01 rlf sound72,W call sp_sub_03r movf sound74,W btfss sound73,0 goto s03_04 call sp_sub_03s goto s03_05 s03_04 call sp_sub_03a s03_05 rlf sound72,F movlw h'07' movwf sound7c s03_06 rlf sound72,W call sp_sub_03r movf sound74,W btfss sound72,0 goto s03_07 call sp_sub_03s goto s03_08 s03_07 call sp_sub_03a s03_08 rlf sound72,F decfsz sound7c,F goto s03_06 rlf sound71,W call sp_sub_03r movf sound74,W btfss sound72,0 goto s03_09 call sp_sub_03s goto s03_10 s03_09 call sp_sub_03a s03_10 rlf sound71,F movlw h'07' movwf sound7c s03_11 rlf sound71,W call sp_sub_03r movf sound74,W btfss sound71,0 goto s03_12 call sp_sub_03s goto s03_13 s03_12 call sp_sub_03a s03_13 rlf sound71,F decfsz sound7c,F goto s03_11 rlf sound70,W call sp_sub_03r movf sound74,W btfss sound71,0 goto s03_14 call sp_sub_03s goto s03_15 s03_14 call sp_sub_03a s03_15 rlf sound70,F movlw h'07' movwf sound7c s03_16 rlf sound70,W call sp_sub_03r movf sound74,W btfss sound70,0 goto s03_17 call sp_sub_03s goto s03_18 s03_17 call sp_sub_03a s03_18 rlf sound70,F decfsz sound7c,F goto s03_16 btfsc sound70,0 goto s03_19 call sp_sub_02a ; s03_19 return sp_sub_03r rlf sound78,F rlf sound79,F rlf sound7a,F rlf sound7b,F rlf sound00,F return sp_sub_03s subwf sound78,F movf sound75,W btfss STATUS,C incfsz sound75,W subwf sound79,F movf sound76,W btfss STATUS,C incfsz sound76,W subwf sound7a,F movf sound77,W btfss STATUS,C incfsz sound77,W subwf sound7b,F clrw btfss STATUS,C movlw h'01' subwf sound00,F return sp_sub_03a addwf sound78,F movf sound75,W btfsc STATUS,C incfsz sound75,W addwf sound79,F movf sound76,W btfsc STATUS,C incfsz sound76,W addwf sound7a,F movf sound77,W btfsc STATUS,C incfsz sound77,W addwf sound7b,F clrw btfsc STATUS,C movlw h'01' addwf sound00,F return ;========================================================================== ; 16bit / 16bit = 16bit … 16bit 除算ルーチン ; (sound71,70) / (sound75,74) = (sound71,70) … (sound79,78) ; 被除数 sound70: 下位 例. h'78' d'1912' → 答 h'bf' d'191' ; sound71: 上位 h'07' → h'00' ; 除数 sound74: 下位 h'0a' d'10' → 変更なし ; sound75: 上位 h'00' → 変更なし ; 余り sound78: 下位 → h'02' d'2' ; sound79: 上位 → h'00' ; カウンタsound7c: h'10' d'16' → h'00' sp_sub_04 bcf STATUS,RP0 ;バンク 0 bcf STATUS,RP1 clrf sound78 clrf sound79 movlw h'10' movwf sound7c ;ループカウンタ = 16 s04_01 rlf sound71,W rlf sound78,F rlf sound79,F movf sound74,W subwf sound78,F movf sound75,W btfss STATUS,C ;C = 1 か ? incfsz sound75,W ;No subwf sound79,F btfsc STATUS,C ;C = 0 か ? goto s04_02 ;No movf sound74,W addwf sound78,F movf sound75,W btfsc STATUS,C ;C = 0 か ? incfsz sound75,W ;No addwf sound79,F bcf STATUS,C s04_02 rlf sound70,F rlf sound71,F decfsz sound7c,F ;ループカウンタ - 1 = 0 か ? goto s04_01 ;No return ;========================================================================== ; ウェイト・ルーチン sp_sub_05 bcf STATUS,RP0 ;バンク 0 bcf STATUS,RP1 decf sound0c,F decf sound0c,F s05_01 movf sound0c,W sublw h'00' btfsc STATUS,C ;C = 0 か ?, h'00' < W goto s05_02 ;No decf sound0c,F nop nop nop goto s05_01 s05_02 nop nop nop nop nop return ;=============================================================== end ======