' ' ************************************************* ' * * ' * EasyMP3 + SD/MMC MP3プレーヤー プログラム * ' * * ' * AVR is using ATmega644P * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2008. 4.22 * ' ************************************************* ' ' Ver 01.01 初回公開バージョン ' ' $regfile = "M644PDEF.DAT" $crystal = 19660800 ' $hwstack = 128 $swstack = 128 $framesize = 128 ' ' Vs_so Alias Pina.0 'VS1011B SO 端子接続ポート Vs_si Alias Porta.1 'VS1011B SI 端子接続ポート Vs_sclk Alias Porta.2 'VS1011B SCLK 端子接続ポート Vs_xcs Alias Porta.3 'VS1011B XCS 端子接続ポート Vs_xreset Alias Porta.4 'VS1011B XRESET 端子接続ポート Vs_xdcs Alias Porta.5 'VS1011B XDCS 端子接続ポート Vs_dreq Alias Pina.6 'VS1011B DREQ 端子接続ポート ' Sd_cs Alias Portb.4 'SD/MMCカード /CS 端子接続ポート Sd_cd Alias Pinb.2 'SD/MMCカード CARD DETECT 端子接続ポート Sd_cdpu Alias Portb.2 'プルアップ用 Sd_wp Alias Pinb.3 'SD/MMCカード WRITE PROTECT 端子接続ポート Sd_wppu Alias Portb.3 'プルアップ用 ' Sw_pi Alias Pinc 'スイッチ接続ポート Sw_po Alias Portc 'プルアップ用 ' ' Dim Fbuff(512) As Byte '音声データ用バッファ。 Dim Buffpoi As Word '音声データ用バッファ・ポインタ。 Dim Vsctemp As Byte 'VS1011Bへのコマンド送信用、テンポラリ。 Dim Vscadr As Byte 'VS1011Bへのコマンド送信用、アドレス。 Dim Vscpar1 As Byte 'VS1011Bへのコマンド送信用、パラメータ上位8bit。 Dim Vscpar2 As Byte 'VS1011Bへのコマンド送信用、パラメータ下位8bit。 Dim Volume As Byte '音量。 Dim Voltemp As Byte '音量のテンポラリ。 ' Dim Keycun As Byte 'キー入力チェック用タイマーカウンター。 Dim Keyflg As Byte 'キー入力検出フラグ。 Dim Keydat As Byte 'キー入力データ。 Dim Keytmp As Byte 'キー入力用テンポラリ。 ' Dim Playsta As Byte '再生状態。 Dim Playmax As Word '総曲数。 Dim Playno As Word '再生曲番号。 Dim Fname As String * 12 '再生曲ファイル名。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Tempw1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Tempw2 As Word '汎用テンポラリ変数 Word型 No.2 Dim Tempw3 As Word '汎用テンポラリ変数 Word型 No.3 Dim Temps1 As Single '汎用テンポラリ変数 Single型 No.1 Dim Temps2 As Single '汎用テンポラリ変数 Single型 No.2 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 ' ' Config Vs_so = Input 'VS1011B用ポートの入出力方向を設定。 Config Vs_si = Output Config Vs_sclk = Output Config Vs_xcs = Output Config Vs_xreset = Output Config Vs_xdcs = Output Config Vs_dreq = Input ' Vs_xreset = 0 'VS1011Bをハードウェア・リセット。 Vs_xcs = 1 'VS1011Bのコマンド・チップ・セレクト端子を[H]にセット。 Vs_xdcs = 1 'VS1011Bのデータ・チップ・セレクト端子を[H]にセット。 Vs_sclk = 0 'VS1011Bのシリアル・クロック端子を[L]にセット。 ' Config Sd_cd = Input 'SD/MMCカード用ポートの入出力方向を設定。 Set Sd_cdpu 'プルアップ。 Config Sd_wp = Input Set Sd_wppu 'プルアップ。 ' Config Sw_po = Input 'スイッチ接続ポートの入出力方向を設定。 Sw_po = &HFF 'プルアップ。 ' Set Portb.0 '未使用ポート・プルアップ。 Set Portb.1 Set Portd.0 Set Portd.1 ' Config Lcdmode = Port 'LCDを4ビットのポートモードに設定。 Config Lcdbus = 4 'LCDデータバスを4bitに設定。 Config Lcdpin = Pin , Db4 = Pord.4 , Db5 = Pord.5 'LCDのポート割り当て。 Config Lcdpin = Pin , Db6 = Pord.6 , Db7 = Pord.7 Config Lcdpin = Pin , E = Pord.3 , Rs = Pord.2 Config Lcd = 16 * 2 'LCD表示を16文字2行に設定。 ' Cursor Off 'LCDのカーソルを設定。 Cls 'LCD表示をすべて消去。 ' ' * SDカードとAVR-DOSの制御プログラムを組み込む * ' $include "Config_MMC_EasyMP3.bas" 'SD/MMCカードのピン設定プログラムを組み込む。 ' If Gbdriveerror <> 0 Then Goto Driveerr 'If 初期化でエラーが発生した? Then ' $include "CONFIG_AVR-DOS_JP.bas" 'AVR-DOSの設定プログラムを組み込む。 ' Temp1 = Initfilesystem(1) 'ファイル・システムを初期化する。 If Temp1 > 0 Then Goto Avrdoserr 'If AVR-DOSエラーが発生した? Then ' ' * A/D・Timerの初期設定 * ' Config Adc = Single , Prescaler = Auto 'A/Dコンバータの設定。 Start Adc 'A/Dコンバータに電源を供給。 ' Config Timer0 = Timer , Prescale = 1024 , Clear Timer = 1 'Timer0 キー入力用。 Ocr0a = 191 'タイマー 100Hz,10mS Config Timer1 = Timer , Prescale = 1024 , Clear Timer = 1 'Timer1 再生時間表示用。 Compare1a = 1919 'タイマー 10Hz,100mS ' ' * VS1011Bの初期設定 * ' Waitms 10 Vs_xreset = 1 'VS1011Bのハードウェア・リセットを解除。 Waitms 10 ' Vscadr = &H00 : Vscpar1 = &H08 : Vscpar2 = &H00 'VS1011Bの動作モードを設定。(VS1002ネイティブ・モード) Gosub Vscomtx Waitms 2 Vscadr = &H03 : Vscpar1 = &H9B : Vscpar2 = &HF7 'VS1011Bの動作クロックを設定。(14.318MHz/2000+&H8000) Gosub Vscomtx Waitms 10 ' Tempw1 = Getadc(7 , &H20) 'A/D CH.7を変換。 Gosub Volset 'VS1011Bに音量値を設定。 ' ' ********************** ' * メイン・プログラム * ' ********************** ' ' * MP3の総曲数を確認 * ' Playmax = 0 'ディレクトリを調べて、総曲数を確認。 Tempstr = Dir( "*.mp3") While Len(tempstr) > 0 Playmax = Playmax + 1 Tempstr = Dir() Wend ' If Playmax = 0 Then Goto Notfound 'If MP3ファイルが無い? Then Cls Lcd "No. Total: " '総曲数を表示。 Locate 1 , 14 Lcd Playmax Playno = 1 Playsta = 0 '再生状態 = 停止 Locate 2 , 11 Lcd "STOP " ' ' * キー入力 * ' Playmd01: Gosub Keyin 'キー入力をチェック。 If Keyflg = 0 Then Goto Playmd02 'If キー入力有り? Else Keyflg = 0 If Keydat.0 = 1 Then Goto Playmd11 'If 前曲キー? Then If Keydat.1 = 1 Then Goto Playmd12 'If 次曲キー? Then If Keydat.2 = 1 Then Goto Playmd13 'If 再生キー? Then If Keydat.4 = 1 Then Goto Playmd14 'If 停止キー? Then Goto Playmd02 ' Playmd11: '前曲キー Playno = Playno - 1 If Playno = 0 Then Playno = Playmax 'If 最前曲? Then If Playsta = 0 Then Gosub Musnds 'If 再生停止中? Then Goto Playmd02 ' Playmd12: '次曲キー Playno = Playno + 1 If Playno > Playmax Then Playno = 1 'If 最終曲? Then If Playsta = 0 Then Gosub Musnds 'If 再生停止中? Then Goto Playmd02 ' Playmd13: '再生キー Playsta = 1 Goto Playmd02 ' Playmd14: '停止キー Playsta = 0 Locate 2 , 11 Lcd "STOP " ' ' Playmd02: If Playsta = 0 Then Goto Playmd01 'If 再生停止中? Then ' ' * 再生開始 * ' If Playno > Playmax Then Playno = 1 'If 再生する曲が無くなった? Then Gosub Musnds '曲番号とファイル名を表示。 ' Vscadr = &H00 : Vscpar1 = &H08 : Vscpar2 = &H04 'VS1011Bをソフトウェア・リセット Gosub Vscomtx Waitms 2 ' Open Fname For Binary As #1 '再生するファイルを開く。 While Eof(#1) = 0 '曲の終わりまで繰り返し。 Get #1 , Fbuff(1) , , 512 'データを512バイト読み込む。 Buffpoi = 1 For Temp1 = 1 To 16 '32バイト×16ブロックの繰り返し。 Do : Loop Until Vs_dreq = 1 'VS1011Bの[DREQ]端子が[H]になるまで待つ。 Vs_xdcs = 0 'VS1011Bの[XDCS]端子を[L]にする。(データポートへアクセス) For Temp2 = 1 To 32 '32バイトを連続送信。 Shiftout Vs_si , Vs_sclk , Fbuff(buffpoi) , 1 Buffpoi = Buffpoi + 1 Next Temp2 Vs_xdcs = 1 'VS1011Bの[XDCS]端子を[H]にする。 Gosub Keyin 'キー入力をチェック。 Next Temp1 ' ' * 再生時間を表示 * ' If Tifr1.ocf1a = 0 Then Goto Playmd03 'If 100mS 経過した? Else Set Tifr1.ocf1a 'Timer1 比較A一致フラグをリセット。 Vscadr = &H04 'VS1011Bから、再生時間を読み込む。 Gosub Vscomrx Tempw3 = Makeint(vscpar2 , Vscpar1) '2つのバイト変数をワード変数に変換。 Tempw1 = Tempw3 / 60 '再生時間変換 秒 -> 分:秒。 Tempw2 = Tempw1 * 60 Tempw2 = Tempw3 - Tempw2 Tempstr = Str(tempw1) Locate 2 , 11 'LCDに分:秒を表示。 Lcd Format(tempstr , " ") ; ":"; Tempstr = Str(tempw2) Lcd Format(tempstr , "00") ' Playmd03: Gosub Volset 'VS1011Bに音量値を設定。 ' If Keyflg = 0 Then Goto Playmd04 'If キー入力有り? Else If Keydat.3 <> 1 Then Exit While 'If ポーズ・キー? Else Keyflg = 0 'ポーズ・キーの処理。 Playmd05: Gosub Keyin 'キー入力をチェック。 If Keyflg = 0 Then Goto Playmd05 'If キー入力有り? Else If Keydat.3 <> 1 Then Exit While 'If ポーズ・キー? Else Keyflg = 0 ' Playmd04: Wend Close #1 'ファイルを閉じる。 ' If Keyflg = 1 Then Goto Playmd01 'If キー入力有り? Then Playno = Playno + 1 '次曲を再生。 Goto Playmd01 End ' ' ************************* ' * キー入力 サブルーチン * (Keyflg = 1 キー入力有り) ' ************************* (Keydat = キーデータ) ' Keyin: If Tifr0.ocf0a = 0 Then Return 'If Timer0が10mSカウント終了? Else Set Tifr0.ocf0a 'Timer1 比較A一致フラグをリセット。 ' If Keycun < 5 Then Goto Keyin01 'If キー入力チェック開始待ち(50mS)? Then If Keycun = 5 Then Goto Keyin02 'If キー入力チェック開始? Then If Keycun < 7 Then Goto Keyin01 'If チャタリング チェック期間? Then If Keycun = 7 Then Goto Keyin04 'If キー入力再確認? Then ' Gosub Keyport 'キーオフを確認 If Keydat = 0 Then Goto Keyin05 'If キーオフ? Then Return ' Keyin01: 'キー入力チェック開始待ち(50mS) Keycun = Keycun + 1 Return ' Keyin02: 'キー入力チェック開始 Gosub Keyport 'キー接続ポートからデータ入力 If Keydat <> 0 Then Goto Keyin03 'If キー入力有り? Then Keyin05: Keycun = 0 Return ' Keyin03: 'キー入力有り Keytmp = Keydat Goto Keyin01 ' Keyin04: 'キー入力再確認 Gosub Keyport 'キー接続ポートからデータ入力 If Keydat <> Keytmp Then Goto Keyin05 'If キー入力エラー? Then Keyflg = 1 Goto Keyin01 ' ' ********************************************** ' * キー接続ポートからのデータ入力サブルーチン * (Keydat = キー入力ポートのデータ) ' ********************************************** ' Keyport: Keydat = Not Sw_pi Return ' ' ***************************************** ' * 曲番号とファイル名を表示 サブルーチン * ' ***************************************** ' Musnds: Locate 1 , 4 '再生する曲番号を表示。 Lcd Spc(3) Locate 1 , 4 Lcd Playno ' Temp1 = 1 '再生曲番号から、再生するファイル名を検索。 Fname = Dir( "*.mp3") While Temp1 <> Playno Temp1 = Temp1 + 1 Fname = Dir() Wend ' Lowerline 'LCDの2行目に、再生するファイル名を表示。 Lcd Spc(9) Locate 2 , 2 Temp1 = Len(fname) 'ファイル名の拡張子部分を除去。 Temp1 = Temp1 - 4 Tempstr = Left(fname , Temp1) Lcd Tempstr Return ' ' ************************* ' * 音量設定 サブルーチン * ' ************************* ' Volset: Volume = Adch '前回のA/D変換値を読み込む。 Set Adcsra.adsc 'A/D変換開始。 Shift Volume , Right , 1 'ボリューム値を1/2 If Volume = Voltemp Then Return 'If ボリューム値が変化した? Else Voltemp = Volume Temps1 = Volume + 1 Temps2 = Log(temps1) '自然対数に変換。 Temps2 = Temps2 * 50 Temp1 = Int(temps2) '整数部分を取り出し。 Temp1 = 242 - Temp1 Vscadr = &H0B : Vscpar1 = Temp1 : Vscpar2 = Temp1 'VS1011Bに音量値を設定。 Gosub Vscomtx Waitus 100 Return ' ' ***************************************** Vscadr = コマンド・レジスタのアドレス ' * VS1011B コマンド書き込み サブルーチン * Vscpar1 = コマンド・パラメータ上位8bit ' ***************************************** Vscpar2 = コマンド・パラメータ下位8bit ' Vscomtx: Do : Loop Until Vs_dreq = 1 'VS1011Bの[DREQ]端子が[H]になるまで待つ。 Vs_xcs = 0 'VS1011Bの[XCS]端子を[L]にする。(コマンドへアクセス) Vsctemp = &H02 Shiftout Vs_si , Vs_sclk , Vsctemp , 1 'VS1011Bへのコマンド書き込み命令 [02]。 Shiftout Vs_si , Vs_sclk , Vscadr , 1 'VS1011Bのコマンド・アドレス・レジスタを指定。 Shiftout Vs_si , Vs_sclk , Vscpar1 , 1 'VS1011Bのコマンド・パラメータ上位8bit 。 Shiftout Vs_si , Vs_sclk , Vscpar2 , 1 'VS1011Bのコマンド・パラメータ下位8bit 。 Vs_xcs = 1 'VS1011Bの[XCS]端子を[H]にする。 Return ' ' ***************************************** Vscadr = コマンド・レジスタのアドレス ' * VS1011B コマンド読み込み サブルーチン * 読み込みデータの上位8bit = Vscpar1 ' ***************************************** 読み込みデータの下位8bit = Vscpar2 ' Vscomrx: Do : Loop Until Vs_dreq = 1 'VS1011Bの[DREQ]端子が[H]になるまで待つ。 Vs_xcs = 0 'VS1011Bの[XCS]端子を[L]にする。(コマンドへアクセス) Vsctemp = &H03 Shiftout Vs_si , Vs_sclk , Vsctemp , 1 'VS1011Bへのコマンド読み込み命令 [03]。 Shiftout Vs_si , Vs_sclk , Vscadr , 1 'VS1011Bのコマンド・アドレス・レジスタを指定。 Shiftin Vs_so , Vs_sclk , Vscpar1 , 1 '読み込みデータの上位8bit 。 Shiftin Vs_so , Vs_sclk , Vscpar2 , 1 '読み込みデータの下位8bit 。 Vs_xcs = 1 'VS1011Bの[XCS]端子を[H]にする。 Return ' ' * SDカード エラー * ' Driveerr: Cls Waitms 200 Lcd "SDカード エラー!" Lowerline Lcd "SDカード ガ アリマセン!" Wait 1 Goto Driveerr ' ' * AVR-DOS エラー * ' Avrdoserr: Cls Lcd "AVR-DOS Error! " ; Temp1 End ' ' * MP3ファイルが無いエラー * ' Notfound: Cls Lcd "MP3ファイル ガ アリマセン" End