firmware of NBCTRLV1 / AYC01

Dependencies:   SDFileSystemEx mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //
00002 // NLGPLAY : NLG file player for mbed
00003 //
00004 // example to write :
00005 // ./lpc21isp -bin file.bin /dev/cu.usbserial-??? 115200 12000
00006 //
00007 // 20151008: updated.
00008 // 20160418: imporved file/dir selector
00009 // improved init sequence
00010 //
00011 
00012 #include <stdio.h>
00013 
00014 #include "mbed.h"
00015 #include "SDFileSystem.h"
00016 #include "lcd.h"
00017 
00018 #include "nlg_mini.h"
00019 
00020 // SPIモード
00021 // #define USE_SPI
00022 
00023 #ifdef TARGET_LPC1114
00024 // 高速I/Oモード(LPC1114専用)
00025 #define USE_FASTIO
00026 #endif
00027 
00028 // ピンアサイン切り替え
00029 #include "pindef.h"
00030 
00031 
00032 #define PRG_NAME "NLGPLAY"
00033 #define PRG_VER_BASE "V1.30"
00034 
00035 #ifndef USE_SPI
00036 #define PRG_VER PRG_VER_BASE
00037 #else
00038 #define PRG_VER PRG_VER_BASE "S"
00039 #endif
00040 
00041 
00042 //#pragma O3
00043 //#pragma Otime
00044 
00045 
00046 
00047 // (pinname, mode)
00048 DigitalIn sw_play(DP_PLAY, PullUp);
00049 DigitalIn sw_next(DP_NEXT, PullUp);
00050 DigitalIn sw_prev(DP_PREV, PullUp);
00051 
00052 #define MAX_PATH 128
00053 #define MAX_FILENAME 64
00054 #define MAX_DIR 64
00055 
00056 // Global Variable
00057 struct
00058 {
00059   bool stop;
00060   bool prev;
00061   bool one_mode;
00062 
00063   int idx;
00064   int max_entries;
00065 
00066   char playlist[MAX_FILENAME];
00067   char file[MAX_FILENAME];
00068   char cwd[MAX_DIR];
00069 
00070   NLG_CTX nlg;
00071   int total_sec;
00072 } g;
00073 
00074 // キーコード
00075 #define SW_PLAY 1
00076 #define SW_NEXT 2
00077 #define SW_PREV 4
00078 
00079 
00080 // ボタンが離されるのを待つ
00081 void wait_key_up(void)
00082 {
00083     while(!sw_next || !sw_play || !sw_prev);
00084 }
00085 
00086 // ボタンの入力を待つ
00087 void wait_key_down(void)
00088 {
00089     while(sw_next && sw_play && sw_prev);
00090 }
00091 
00092 // キー入力
00093 int get_key(void)
00094 {
00095   int key = 0;
00096   
00097   if (!sw_next)
00098     key |= SW_NEXT;
00099   if (!sw_play)
00100     key |= SW_PLAY;
00101   if (!sw_prev)
00102     key |= SW_PREV;
00103   return key;
00104 }
00105 
00106 // キー開放待ち
00107 void wait_relkey(void)
00108 {
00109   wait_key_up();
00110   wait(0.1);
00111 }
00112 
00113 // キー待ち
00114 int wait_anykey(void)
00115 {
00116     wait_key_down();
00117     int key = get_key();
00118 
00119     wait(0.1);
00120     wait_relkey();
00121 
00122     return key;
00123 }
00124 
00125 // LED
00126 DigitalOut led1(LED1, 0);
00127 DigitalOut led2(LED2, 0);
00128 
00129 // SPI: MOSI, MISO, SCLK, CS
00130 SDFileSystem sd(DP_MOSI, DP_MISO, DP_SCLK, DP_SCS, "sd");
00131 
00132 // LCD
00133 LCD lcd;
00134 
00135 #define _WAIT for(int wcnt=0; wcnt < 2; wcnt++)
00136 
00137 
00138 ////////////////
00139 // 高速IO
00140 
00141 #define DBS IO_01 // DATA
00142 #define CTS IO_02 // CTRL
00143 #define RCK IO_04 // LATCH
00144 #define SCK IO_03 // SCLK
00145 
00146 
00147 DigitalOut io01(DP_IO01, 0); // P1_4
00148 DigitalOut io02(DP_IO02, 0); // P0_3
00149 DigitalOut io03(DP_IO03, 0); // P1_8
00150 DigitalOut io04(DP_IO04, 0); // P0_11
00151 
00152 #if 0
00153 // NBV3での試し機能
00154 #define IO_A0 io05
00155 #define IO_WR io06
00156 
00157 DigitalOut io05(DP_IO05, 0); // P1_9
00158 DigitalOut io06(DP_IO06, 0); // P1_2
00159 
00160 #endif
00161 
00162 #define IO_01 (1 << 4)  // DBS P1_4
00163 #define IO_02 (1 << 3)  // CTS P0_3
00164 #define IO_03 (1 << 8)  // SCK P1_8
00165 #define IO_04 (1 << 11) // RCK P0_11
00166 
00167 #ifdef USE_FASTIO
00168 
00169 // ポート出力
00170 #define DATA_HI LPC_GPIO1->DATA |= DBS
00171 #define DATA_LO LPC_GPIO1->DATA &= ~DBS
00172 #define CTRL_HI LPC_GPIO0->DATA |= CTS
00173 #define CTRL_LO LPC_GPIO0->DATA &= ~CTS
00174 #define SCK_HI LPC_GPIO1->DATA |= SCK
00175 #define SCK_LO LPC_GPIO1->DATA &= ~SCK
00176 #define RCK_HI LPC_GPIO0->DATA |= RCK
00177 #define RCK_LO LPC_GPIO0->DATA &= ~RCK
00178 
00179 // 出力設定
00180 #define PORT_DIR  LPC_GPIO0->DIR |= (IO_02 | IO_04); \
00181  LPC_GPIO1->DIR |= (IO_01 | IO_03)
00182 
00183 #else
00184 
00185 // ポート出力
00186 #define DATA_HI io01 = 1
00187 #define DATA_LO io01 = 0
00188 #define CTRL_HI io02 = 1
00189 #define CTRL_LO io02 = 0
00190 #define SCK_HI io03 = 1
00191 #define SCK_LO io03 = 0
00192 #define RCK_HI io04 = 1
00193 #define RCK_LO io04 = 0
00194 
00195 // 出力設定
00196 #define PORT_DIR 
00197 
00198 #endif
00199 
00200 SPI *spi;
00201 
00202 // I/O初期化
00203 void ioInit()
00204 {
00205   // SPIインスタンスの取得
00206   spi = sd.getSPI();
00207   // 出力
00208   PORT_DIR;
00209 }
00210 
00211 
00212 #ifndef USE_SPI
00213 // 8x2ビットモード
00214 
00215 #define SHIFTOUT io8x2Out
00216 
00217 // 8bit 出力
00218 void byteOut(unsigned char data)
00219 {
00220     int i;
00221 
00222     for(i = 0; i < 8; i++)
00223     {
00224         if (data & 0x80)
00225             DATA_HI;
00226         else
00227             DATA_LO;
00228 
00229         data <<= 1;
00230         
00231         SCK_HI;
00232         SCK_LO;
00233     }
00234 }
00235 
00236 // 8x2ビット出力 or 16bit出力選択可能
00237 void io8x2Out(unsigned int ctrl, unsigned int data)
00238 {
00239     int i;
00240     // シフトレジスタ直列モード
00241     if (g.one_mode)
00242     {
00243         // データ順
00244         // <- CCCCCCCC76543210
00245         
00246         byteOut(ctrl);
00247         byteOut(data);
00248                 
00249         // ラッチ
00250         RCK_HI;
00251         RCK_LO;
00252     }
00253     else 
00254     {
00255     // シフトレジスタ並列モード
00256         for(i = 0; i < 8; i++)
00257         {
00258             /* 2ビット分のデータをそれぞれ出力 */
00259             if (ctrl & 0x80)
00260                 CTRL_HI;
00261             else
00262                 CTRL_LO;
00263     
00264             if (data & 0x80)
00265                 DATA_HI;
00266             else
00267                 DATA_LO;
00268     
00269             ctrl <<= 1;
00270             data <<= 1;
00271             // シフトクロック
00272             SCK_HI;
00273             SCK_LO;
00274         }
00275     
00276         // ラッチ
00277         RCK_HI;
00278         RCK_LO;
00279     }
00280 }
00281 
00282 #else
00283 
00284 // 16bitモード
00285 #define SHIFTOUT io16Out
00286 
00287 
00288 
00289 // 16bit 出力
00290 void io16Out(unsigned char ctrl, unsigned char data)
00291 {
00292     spi->write(ctrl);
00293     spi->write(data);
00294 
00295     // byteOut(ctrl);
00296     // byteOut(data);
00297 
00298     // LATCH
00299     RCK_HI;
00300     RCK_LO;
00301 }
00302 
00303 #endif
00304 
00305 /* 制御信号定義 */
00306 #define CS_FM3 (1 << 0)
00307 #define CS_PSG (1 << 1)
00308 #define CS_FM1 (1 << 2)
00309 #define CS_FM2 (1 << 3)
00310 #define A0     (1 << 4)
00311 #define WR     (1 << 5)
00312 #define ICL    (1 << 6)
00313 #define CTL    (1 << 7)
00314 
00315 
00316 /* アクティブローの制御信号 */
00317 #define ACTLOW (CS_PSG | CS_FM1 | CS_FM2 | CS_FM3 | WR | ICL)
00318 
00319 
00320 /* NBV2互換出力 */
00321 void regOutBase(int addr, int data, int select)
00322 {
00323     /* アドレスを出力 */
00324     /* A0をローにして待つ */
00325     int ctrl = ACTLOW;
00326     
00327     /* 裏レジスタ */
00328     if (addr >= 0x100)
00329         ctrl |= CTL;
00330     addr &= 0xff;
00331   
00332     SHIFTOUT(ctrl, 0x00);
00333     SHIFTOUT(ctrl & ~(select | WR), addr);
00334     SHIFTOUT(ctrl, addr);
00335 
00336     /* チップ処理待ち */
00337 
00338     /* データを出力 */
00339     /* A0をハイにして待つ */
00340     ctrl |= A0;
00341     SHIFTOUT(ctrl, 0x00);
00342     SHIFTOUT(ctrl & ~(select | WR), data);
00343     SHIFTOUT(ctrl, data);
00344 
00345     /* チップ処理待ち */
00346 }
00347 
00348 /* 出力 */
00349 #define regPSGOut(addr, data) regOutBase(addr, data, CS_PSG)
00350 #define regFMOut(addr, data) regOutBase(addr, data, CS_FM1)
00351 #define regFM2Out(addr, data) regOutBase(addr, data, CS_FM2)
00352 
00353 /* 音源出力 */
00354 #define WritePSG regPSGOut
00355 #define WriteOPM regFMOut
00356 #define WriteOPM2 regFM2Out
00357 
00358 
00359 /* ミュート */
00360 void boardMute(void)
00361 {
00362     int i;
00363 
00364     /* PSG初期化 */
00365     regPSGOut(0x00,0);
00366     regPSGOut(0x01,0);
00367 
00368     regPSGOut(0x06, 0x00);
00369     regPSGOut(0x07, 0x3f); // ALL OFF
00370     regPSGOut(0x08, 0x00); // CH.A 0
00371     regPSGOut(0x09, 0x00); // CH.B 0
00372     regPSGOut(0x0a, 0x00); // CH.C 0
00373 
00374     /* MUTE(disable) */
00375     for(i = 0x20; i < 0x28; i++)
00376     {
00377         regFMOut(i, 0x00);
00378         regFM2Out(i, 0x00);
00379     }
00380 
00381     // KEYOFF
00382     for(i = 0x00; i < 0x08; i++)
00383     {
00384         regFMOut(0x08, i & 0x07);
00385         regFM2Out(0x08, i & 0x07);
00386     }
00387 
00388     // FORCE RELEASE
00389     for(i= 0x00; i < 0x20; i++)
00390     {
00391         regFMOut(0xE0 + i, 0x0f);
00392         regFM2Out(0xE0 + i, 0x0f);
00393     }
00394 
00395     // OPLL ミュート
00396     for(i= 0x00; i <= 0x08; i++)
00397     {
00398         regFMOut(0x20 + i, 0x00);
00399         regFMOut(0x30 + i, 0x0f);
00400         regFM2Out(0x20 + i, 0x00);
00401         regFM2Out(0x30 + i, 0x0f);
00402     }
00403 
00404 }
00405 
00406 /* ボード初期化 */
00407 void boardInit(void)
00408 {
00409     wait_ms(20);
00410     /* ICLのみをLOW(アクティブ)にする */
00411     SHIFTOUT(ACTLOW & ~(ICL), 0);
00412     wait_ms(150);
00413 
00414     /* 元に戻す */
00415     SHIFTOUT(ACTLOW, 0);
00416     wait_ms(10);
00417 }
00418 
00419 //////////////////////////////////////////
00420 
00421 // 表示
00422 void dispTime()
00423 {
00424     char buf[16];
00425     sprintf(buf, "%02d:%02d",
00426         g.total_sec / 60,
00427         g.total_sec % 60);
00428 
00429     lcd.setCursor(3,1);
00430     lcd.printStr(buf);
00431 }
00432 
00433 #define WAIT_US 10000 // 10ms
00434 #define SEC_US 1000000 // 1sec
00435 #define NEXT_MAX_US 300000 // 300ms
00436 
00437 /* NLGの再生 */
00438 int PlayNLG_Loop(void)
00439 {
00440     int cmd;
00441     int addr, data;
00442 
00443     int result = 0;
00444 
00445     int us = 0;
00446     int diff_us = 0;
00447 
00448     int count_us = 0;
00449     int total_us = 0;
00450 
00451     // NEXTボタンのカウンタ
00452     int next_count = 0;
00453 
00454     bool wait_skip = false;
00455 
00456 
00457     // GetTickUsNLG
00458     int tick_us = GetTickUsNLG(&g.nlg);
00459 
00460     // printf("tick_us:%d\n", tick_us);
00461 
00462     g.total_sec = 0;
00463 
00464     // タイマースタート
00465     Timer t;
00466     t.start();
00467 
00468     // 表示
00469     dispTime();
00470 
00471     // LED消灯
00472     led1 = 0;
00473     led2 = 0;
00474 
00475     // LEDカウンタ
00476     int led_cnt1 = 0;
00477     int led_cnt2 = 0;
00478 
00479     // ループ
00480     while(!g.stop)
00481     {
00482         /* ウエイトの処理 */
00483         while (count_us >= WAIT_US)
00484         {
00485             // ボタンチェック
00486             if (!sw_next)
00487             {
00488                 // NEXTが押されている
00489                 if (next_count < NEXT_MAX_US)
00490                     next_count += count_us;
00491                 else
00492                 {
00493                     // 早送り
00494                     next_count = NEXT_MAX_US;
00495                     wait_skip = true;
00496                 }
00497             }
00498             else
00499             {
00500                 // NEXTが離されている
00501                 wait_skip = false;
00502 
00503                 // 一瞬だけボタンが押された場合、次の曲へ
00504                 if (next_count > 0 && next_count < NEXT_MAX_US)
00505                 {
00506                     next_count = 0;
00507                     goto song_end;
00508                 }
00509 
00510                 // 早送りの終了
00511                 if (next_count == NEXT_MAX_US)
00512                 {
00513                     next_count = 0;
00514                 }
00515             }
00516             // PREVが押された
00517             if (!sw_prev)
00518             {
00519                 g.prev = true;
00520                 goto song_end;
00521             }
00522 
00523             // PLAYが押された
00524             if (!sw_play)
00525             {
00526                 g.stop = true;
00527                 goto song_end;
00528             }
00529 
00530             // スキップでなければ次のタイミングまで待つ
00531             while(!wait_skip && (us = t.read_us()) + diff_us < count_us);
00532 
00533             // タイマーリセット
00534             if (!wait_skip)
00535                 t.reset();
00536 
00537             // 差分を計算
00538             diff_us += us;
00539             while(diff_us >= count_us)
00540               diff_us -= count_us;
00541 
00542             // 積算する
00543             total_us += count_us;
00544             count_us = 0;
00545 
00546             // 1秒で積算カウントをリセットする
00547             if (total_us >= SEC_US)
00548             {
00549                 while(total_us >= SEC_US)
00550                 {
00551                     g.total_sec++;
00552                     total_us -= SEC_US;
00553                 }
00554                 // 表示
00555                 dispTime();
00556             }
00557         }
00558 
00559         /* コマンドの読み出し */
00560         cmd = ReadNLG(&g.nlg);
00561         if (cmd == EOF)
00562         {
00563             result = EOF;
00564             break;
00565         }
00566         
00567         if (cmd < 0x80)
00568         {
00569             addr = ReadNLG(&g.nlg);
00570             data = ReadNLG(&g.nlg);
00571             
00572             // 裏レジスタ
00573             if (cmd >= 0x40)
00574                 addr |= 0x100;
00575             
00576             switch(cmd & 0x3f)
00577             {
00578             case CMD_PSG:
00579                 WritePSG(addr, data);
00580                 break;
00581             case CMD_FM1:
00582                 WriteOPM(addr, data);
00583                 break;
00584             case CMD_FM2:
00585                 WriteOPM2(addr, data);
00586                 break;
00587             }
00588         }
00589         else
00590         {
00591             /* コマンドの処理 */
00592             switch (cmd)
00593             {
00594                 case CMD_IRQ:
00595                     count_us += tick_us;
00596         
00597                     // LED1
00598                     led_cnt1++;
00599                     if (led_cnt1 >= 48)
00600                     {
00601                         led_cnt1 = 0;
00602                         led1 = !led1;
00603                     }
00604 
00605                     // LED2
00606                     led_cnt2++;
00607                     if (led_cnt2 >= 192)
00608                     {
00609                         led_cnt2 = 0;
00610                         led2 = !led2;
00611                     }
00612                 break;
00613                 case CMD_CTC0:
00614                     data = ReadNLG(&g.nlg);
00615                     SetCTC0_NLG(&g.nlg, data);
00616                     tick_us = GetTickUsNLG(&g.nlg);
00617                     // printf("CTC0:%d tick_us:%d\n", data, tick_us);
00618         
00619                 break;
00620                 case CMD_CTC3:
00621                     data = ReadNLG(&g.nlg);
00622                     SetCTC3_NLG(&g.nlg, data);
00623                     tick_us = GetTickUsNLG(&g.nlg);
00624                     // printf("CTC3:%d tick_us:%d\n", data, tick_us);
00625                 break;
00626             }
00627         }
00628     }
00629 
00630 song_end:
00631 
00632     return result;
00633 }
00634 
00635 
00636 // ファイルを再生する
00637 int play_file(const char *filename)
00638 {
00639     /* NLGファイルを開く */
00640     if (OpenNLG(&g.nlg, filename) < 0)
00641     {
00642         return -1;
00643     }
00644 
00645     /* 再生する */
00646     PlayNLG_Loop();
00647 
00648     /* NLGファイルを閉じる */
00649     CloseNLG(&g.nlg);
00650 
00651     return 0;
00652 }
00653 
00654 // error_sdcard()
00655 // エラー!
00656 void error_sdcard(void)
00657 {
00658     lcd.printStr2("SD CARD", "ERROR!");
00659 
00660     while(1);
00661 }
00662 
00663 // COM mode
00664 void loop_for_com(void)
00665 {
00666     int sw, val;
00667     int adr = 0x00;
00668     int baud = 9600;
00669     char buf[16];
00670     Serial pc(DP_TX, DP_RX);
00671 
00672     lcd.cls();
00673     lcd.printStrY(0, "COM MODE");
00674 
00675     sprintf(buf, "%-8d", baud);
00676     lcd.printStrY(1, buf);
00677 
00678     pc.printf("COM\n");
00679 
00680     // タイマースタート
00681     Timer t;
00682     t.start();
00683 
00684     while(1)
00685     {
00686 
00687         sw = pc.getc();
00688 
00689         // 0は同期リセット
00690         if (sw == 0x00)
00691             continue;
00692 
00693         if (sw >= 1 && sw <= 3)
00694         {
00695           adr = pc.getc();
00696           val = pc.getc();
00697         }
00698 
00699         switch(sw)
00700         {
00701             case 1:
00702                 regFMOut(adr, val);
00703             break;
00704             case 2:
00705                 regFM2Out(adr, val);
00706             break;
00707             case 3:
00708                 regPSGOut(adr, val);
00709             break;
00710             case 0x0f:
00711                 // 通信速度設定
00712                 val = pc.getc();
00713                 baud = (9600 * val);
00714                 sprintf(buf, "%-8d", baud);
00715                 lcd.printStrY(1, buf);
00716 
00717                 pc.baud(baud);
00718             break;
00719             case 0x10:
00720                 //
00721                 val = pc.getc();
00722                 val = (val * 10000);
00723                 while(t.read_us() < val);
00724                 pc.putc('.');
00725                 t.reset();
00726             break;
00727             case 0x11:
00728                 t.reset();
00729             break;
00730         }
00731 
00732         // pc.printf("sw = %02x, adr = %02x, val = %02x\n", sw, adr, val);
00733     }
00734 }
00735 
00736 
00737 // chk_isdir
00738 // ディレクトリか否か
00739 // return : bool
00740 // false if not directory
00741 
00742 bool chk_isdir(const char *cwd, const char *dir)
00743 {
00744     char tmp[256];
00745     sprintf(tmp,"%s/%s", cwd, dir);
00746 
00747     DIR *dp = opendir(tmp);
00748     if (!dp)
00749       return false;
00750 
00751     closedir(dp);
00752     return true;
00753 }
00754 
00755 #define EXT_LIST ".lst"
00756 #define EXT_NLG ".nlg"
00757 
00758 // get_fileentry
00759 // index : index of list , -1 = return number of entries
00760 // is_mode : 0 = normal mode
00761 // mode = MODE_GETDIR | MODE_GETLIST | MODE_FILE
00762 // return : int
00763 // -1 = not found or error
00764 
00765 #define MODE_FILE 0
00766 #define MODE_GETDIR 1
00767 #define MODE_GETLIST 2
00768 
00769 int get_fileentry(int index, int mode)
00770 {
00771     // return -1 if entry is zero.
00772     int count = 0;
00773     DIR *dp = opendir(g.cwd);
00774 
00775     g.file[0] = 0;
00776 
00777     if (!dp)
00778         return -1;
00779 
00780     struct dirent *dent = NULL;
00781 
00782     while(1)
00783     {
00784         // エントリの読み出し
00785         dent = readdir(dp);
00786 
00787         // 失敗
00788         if (!dent)
00789             break;
00790 
00791         // リソースか隠しファイル
00792         if (dent->d_name[0] == '.')
00793             continue;
00794 
00795         // 拡張子の取得
00796         char *ext = strrchr(dent->d_name, '.');
00797 
00798         switch(mode)
00799         {
00800           // ディレクトリモード
00801           case MODE_GETDIR:
00802             // ディレクトリでなければ継続
00803             if (!chk_isdir(g.cwd, dent->d_name))
00804                 continue;
00805           break;
00806 
00807           // プレイリストモード
00808           case MODE_GETLIST:
00809             // リストでなければ無視
00810             if (!ext || strcasecmp(ext, EXT_LIST) != 0)
00811               continue;
00812           break;
00813 
00814           // ファイルモード
00815           case MODE_FILE:
00816             // NLGファイルでなければ継続
00817             if (!ext || strcasecmp(ext, EXT_NLG) != 0)
00818                 continue;
00819           break;
00820         }
00821 
00822         // カウントアップ
00823         count++;
00824 
00825         // カウントモードかカウントがindex未満で継続
00826         if (index < 0 || count <= index)
00827             continue;
00828 
00829         // ファイル名をコピーして終了
00830         strcpy(g.file, dent->d_name);
00831         break;
00832 
00833     }
00834     closedir(dp);
00835     return count;
00836 }
00837 
00838 
00839 //
00840 // タイトル表示
00841 //
00842 int putTitle()
00843 {
00844     int count_ms = 0;
00845     int diff_us = 0;
00846     int us = 0;
00847     int key = get_key();
00848 
00849     // キー入力時はキャンセル
00850     if (key)
00851       return key;
00852 
00853     lcd.printStr2(PRG_NAME, PRG_VER);
00854     Timer t;
00855     t.start();
00856 
00857     // 1500msまでループする
00858     while(count_ms < 1500)
00859     {
00860       while((us = t.read_us()) + diff_us < 1000);
00861       t.reset();
00862 
00863       // キー入力があれば終了
00864       key = get_key();
00865       if (key)
00866         return key;
00867 
00868       // 差分を現在の時間に足して次の差分を作る
00869       diff_us += us;
00870 
00871       while(diff_us >= 1000)
00872       {
00873         count_ms++;
00874         diff_us -= 1000;
00875       }
00876     }
00877 
00878     return 0;
00879 }
00880 
00881 // 情報の表示
00882 void show_info(int files)
00883 {
00884     char buf[16];
00885 
00886     Timer t;
00887     int result_us = 0;
00888     t.reset();
00889     t.start();
00890 
00891     // 実際の書き込み時間を計測する
00892     regFMOut(0x20, 0x00);
00893     regFMOut(0x20, 0x00);
00894     regFMOut(0x20, 0x00);
00895     regFMOut(0x20, 0x00);
00896     regFMOut(0x20, 0x00);
00897 
00898     // 経過時間を得る
00899     result_us = t.read_us();
00900     t.stop();
00901 
00902     // 平均値
00903     result_us /= 5;
00904 
00905     // 結果表示
00906     printf("result_us=%dus\n", result_us);
00907     sprintf(buf, "R:%dus", result_us);
00908     lcd.printStrY(1, buf);
00909     wait(3);
00910 
00911     // コンパイル時の日付
00912     sprintf(buf, "%8s", __DATE__);
00913     lcd.printStrYscr(1, buf);
00914     wait(3);
00915 
00916     if (files < 0)
00917         lcd.printStrY(1, "NO FILES");
00918     else
00919     {
00920         sprintf(buf, "%3dfiles", files);
00921         lcd.printStrY(1, buf);
00922     }
00923     wait(3);
00924     lcd.cls();
00925 }
00926 
00927 // ビットテスト
00928 
00929 void bit_test()
00930 {
00931     char buf[9];
00932     lcd.printStrY(0, "BIT_TEST");
00933 
00934     wait_key_up();
00935 
00936     int pin = 0;
00937     int mode = 0;
00938     char sig;
00939 
00940     while(1)
00941     {
00942         // 表示
00943         if (mode & 1)
00944           sig = 'C'; // コントロール
00945         else
00946           sig = 'D'; // データ
00947 
00948         if (mode & 2)
00949           strcpy(buf,"00");
00950         else
00951           sprintf(buf, "%c%d", sig, pin);
00952 
00953         lcd.printStrY(1, buf);
00954 
00955         // 出力
00956         if (mode & 2)
00957         {
00958             SHIFTOUT(0xff, 0x00);
00959         }
00960         else
00961         {
00962             int bit = (1 << pin);
00963             if (mode & 1)
00964               SHIFTOUT(0xff & ~(bit), 0); // コントロール
00965             else
00966               SHIFTOUT(0xff, bit); // データ
00967         }
00968 
00969         // キー待ち
00970         int key = wait_anykey();
00971 
00972         // 再生
00973         if (key & SW_PLAY)
00974         {
00975           mode ^= 2;
00976           continue;
00977         }
00978         // 次
00979         if (key & SW_NEXT)
00980         {
00981           pin++;
00982           if (pin > 7)
00983           {
00984               pin = 0;
00985               mode = (mode + 1) & 1;
00986           }
00987         }
00988         // 前
00989         if (key & SW_PREV)
00990         {
00991           pin--;
00992           if (pin < 0)
00993           {
00994               pin = 7;
00995               mode = (mode - 1) & 1;
00996           }
00997         }
00998     }
00999 }
01000 
01001 //
01002 // ファイル選択表示
01003 void disp_filesel(int mode)
01004 {
01005   char buf[16];
01006   char buf_mode[16];
01007   
01008   char *mode_name;
01009   switch(mode)
01010   {
01011     case MODE_GETLIST:
01012       mode_name = "LIST";
01013     break;
01014     case MODE_GETDIR:
01015       mode_name = "DIR ";
01016     break;
01017     default:
01018       mode_name = "FILE";
01019   }
01020 
01021   sprintf(buf_mode, "%s %03d", mode_name, g.idx + 1);
01022   strncpy(buf, g.file, 8);
01023   buf[8] = 0;
01024 
01025   // 表示
01026   lcd.printStr2(buf, buf_mode);
01027 }
01028 
01029 //
01030 // ファイル/ディレクトリ選択
01031 // mode = MODE_GETLIST | MODE_GETDIR | MODE_FILE
01032 //
01033 int file_select(int mode)
01034 {
01035     // ファイル数を得る
01036     int files = get_fileentry(-1, mode);
01037 
01038     // 最大エントリー
01039     g.max_entries = files - 1;
01040 
01041     // ファイル名の取得
01042     get_fileentry(g.idx, mode);
01043 
01044     // 表示
01045     disp_filesel(mode);
01046 
01047     // リリース待ち
01048     wait_relkey();
01049 
01050     while(1)
01051     {
01052         // ファイル名の取得
01053         get_fileentry(g.idx, mode);
01054 
01055         // 表示
01056         disp_filesel(mode);
01057 
01058         // キー待ち
01059         int key = wait_anykey();
01060 
01061         // 次のエントリ
01062         if (key & SW_NEXT)
01063         {
01064             if (g.idx < g.max_entries)
01065                 g.idx++;
01066             else
01067                 g.idx = 0;
01068         }
01069 
01070         // 前のエントリ
01071         if (key & SW_PREV)
01072         {
01073             if (g.idx > 0)
01074                 g.idx--;
01075             else
01076                 g.idx = g.max_entries;
01077         }
01078         // 再生ボタンを押した
01079         if (key & SW_PLAY)
01080             break;
01081     }
01082 
01083     return g.idx;
01084 }
01085 
01086 // get_playlist()
01087 // index = リスト位置, -1でエントリ数を返す
01088 int get_playlist(int index)
01089 {
01090     int count = 0;
01091     FILE *fp = fopen(g.playlist, "r");
01092 
01093     g.file[0] = 0;
01094 
01095     // プレイリストが開けない
01096     if (!fp)
01097         return -1;
01098 
01099     while(1)
01100     {
01101         // プレイリストから一行読み込む
01102         char *p = fgets(g.file, MAX_FILENAME, fp);
01103 
01104         // EOFなので終了
01105         if (!p)
01106             break;
01107 
01108         // サイズ
01109         int len = strlen(g.file);
01110 
01111         // CR/LFをトリムする
01112         while(len > 0 && (unsigned char)g.file[len - 1] < 0x20)
01113         {
01114             g.file[len - 1] = 0x00;
01115             len--;
01116         }
01117 
01118         // 空行は飛ばす
01119         if (!len)
01120             continue;
01121 
01122         count++;
01123 
01124         // カウントモードかカウントがindex未満で継続
01125         if (index < 0 || count <= index)
01126             continue;
01127         else
01128             break;
01129     }
01130 
01131     // プレイリストを閉じる
01132     fclose(fp);
01133 
01134 #if defined(__MICROLIB) && defined(__ARMCC_VERSION)
01135     free(fp);
01136 #endif
01137 
01138     return count;
01139 }
01140 
01141 
01142 // グローバル変数初期化
01143 void init_globe(void)
01144 {
01145   memset(&g, 0, sizeof(g));
01146   strcpy(g.cwd,"/sd");
01147 }
01148 
01149 // パスの作成
01150 void make_path(char *path, const char *dir, const char *file)
01151 {
01152   sprintf(path, "%s/%s", dir, file);
01153 }
01154 
01155 // 再生モード
01156 void play_mode(void)
01157 {
01158   int files = -1;
01159 
01160   // プレイリストモードか否か
01161   if (g.playlist[0])
01162       files = get_playlist(-1);
01163   else
01164       files = get_fileentry(-1, MODE_FILE);
01165 
01166   // エラー表示
01167   if (files < 0)
01168       error_sdcard();
01169 
01170   g.max_entries = files - 1;
01171 
01172   bool repeat_flag = false;
01173 
01174   // ファイルが無い
01175   if (files < 1)
01176   {
01177       lcd.cls();
01178       lcd.printStrY(0, "NO FILES");
01179       wait(1);
01180   }
01181 
01182   // 再生モードループ
01183   while(1)
01184   {
01185       char path[MAX_PATH];
01186       char buf[16];
01187 
01188       // プレイリストかどうか?
01189       if (g.playlist[0])
01190           get_playlist(g.idx);
01191       else
01192           get_fileentry(g.idx, MODE_FILE);
01193 
01194       // フルパスを作成
01195       make_path(path, g.cwd, g.file);
01196 
01197       // 曲番号
01198       sprintf(buf, "%2d ", g.idx + 1);
01199 
01200       // ファイル名名表示
01201       lcd.cls();
01202       lcd.printStrY(0, g.file);
01203       lcd.printStrY(1, buf);
01204 
01205       // 再生開始
01206       play_file(path);
01207 
01208       // ミュート
01209       boardMute();
01210 
01211       // キー開放待ち
01212       wait_relkey();
01213 
01214 
01215       // 再生ボタンが押された
01216       if (g.stop)
01217       {
01218           // ストップ表示
01219           lcd.printStrY(1, "  STOP  ");
01220 
01221           g.stop = false;
01222           g.prev = false;
01223           g.total_sec = 0;
01224 
01225           // ボード初期化
01226           boardInit();
01227 
01228           // ファイル選択
01229           file_select(MODE_FILE);
01230           continue;
01231       }
01232 
01233       // 前の曲を再生
01234       if (g.prev)
01235       {
01236           g.prev = false;
01237 
01238           // 同じ曲を再生
01239           if (g.total_sec >= 2)
01240             continue;
01241 
01242           if (g.idx > 0)
01243               g.idx--;
01244           else
01245               g.idx = g.max_entries;
01246 
01247           continue;
01248       }
01249 
01250       // 繰り返しではない
01251       if (!repeat_flag)
01252       {
01253           if (g.idx < g.max_entries)
01254               g.idx++;
01255           else
01256               g.idx = 0;
01257       }
01258       repeat_flag = false;
01259   }
01260 }
01261 
01262 
01263 
01264 //
01265 // メニュー選択
01266 //
01267 #define MENU_FILE 0
01268 #define MENU_DIR 1
01269 #define MENU_LIST 2
01270 #define MENU_INFO 3
01271 #define MENU_COM 4
01272 #define MENU_TEST 5
01273 #define MENU_SMODE 6
01274 #define MENU_MAX 6
01275 
01276 // メニュー文字列
01277 const char *menu_modes[] =
01278 {
01279   "FILE", // 0
01280   "DIR",  // 1
01281   "LIST", // 2
01282   "INFO", // 3
01283   "COM",  // 4
01284   "TEST", // 5
01285   "Sx16", // 6
01286 };
01287 
01288 // メニュー選択表示
01289 void menu_disp(int sel)
01290 {
01291   char buf[16];
01292 
01293   // 表示
01294   lcd.printStrY(0, "MENU SEL");
01295   sprintf(buf, "%02d %-4s", sel, menu_modes[sel]);
01296   lcd.printStrY(1, buf);
01297 }
01298 
01299 // モード選択
01300 int menu_select()
01301 {
01302     int count = 0;
01303 
01304     // 初期表示
01305     menu_disp(0);
01306 
01307     // リリース待ち
01308     wait_key_up();
01309 
01310     while(1)
01311     {
01312         // キー待ち
01313         int key = wait_anykey();
01314 
01315         // 次
01316         if (key & SW_NEXT)
01317         {
01318             if (count < MENU_MAX)
01319                 count++;
01320             else
01321                 count = 0;
01322         }
01323         // 前
01324         if (key & SW_PREV)
01325         {
01326             if (count > 0)
01327                 count--;
01328             else
01329                 count = MENU_MAX;
01330         }
01331         // 再生
01332         if (key & SW_PLAY)
01333             break;
01334 
01335         // 表示
01336         menu_disp(count);
01337     }
01338 
01339     return count;
01340 }
01341 
01342 // メニューモード
01343 void menu_mode(void)
01344 {
01345   int files = 0;
01346   char path[MAX_PATH];
01347 
01348   menu_start:
01349 
01350   // ボードの初期化
01351   boardInit();
01352 
01353   int sw = menu_select();
01354   switch(sw)
01355   {
01356     // ファイル選択
01357     case MENU_FILE:
01358       file_select(MODE_FILE);
01359     break;
01360     // ディレクトリ選択
01361     case MENU_DIR:
01362         file_select(MODE_GETDIR);
01363         // パスを結合し、インデックスを初期化
01364         make_path(path, g.cwd, g.file);
01365         strcpy(g.cwd, path);
01366         g.idx = 0;
01367     break;
01368     // プレイリスト選択
01369     case MENU_LIST:
01370         file_select(MODE_GETLIST);
01371     break;
01372     // 情報モード
01373     case MENU_INFO:
01374           files = get_fileentry(-1, MODE_FILE);
01375           show_info(files);
01376           goto menu_start;
01377     // 通信モード
01378     case MENU_COM:
01379       loop_for_com();
01380     break;
01381     // テストモード
01382     case MENU_TEST:
01383       bit_test();
01384     break;
01385     // ストレートモード
01386     case MENU_SMODE:
01387         g.one_mode = true;
01388         lcd.printStr2("","Sx16 ON");
01389         wait(0.5);
01390         goto menu_start;
01391     }
01392 }
01393 
01394 //
01395 // main
01396 //
01397 int main()
01398 {
01399     // 初期化
01400     init_globe();
01401 
01402     // I/O初期化
01403     ioInit();
01404 
01405     // シフトレジスタの初期化
01406     SHIFTOUT(ACTLOW & ~(ICL), 0x00);
01407 
01408     // 立ち上がり待ち
01409     wait_ms(20);
01410 
01411     // LCD初期化
01412     lcd.init();
01413 
01414     // ICLなどをHにする
01415     SHIFTOUT(ACTLOW, 0x00);
01416     
01417     // 消音する
01418     boardMute();
01419 
01420     // タイトル表示
01421     int key = putTitle();
01422     
01423 
01424     // NEXTボタンでメニュー表示
01425     if (key & SW_NEXT)
01426       menu_mode();
01427 
01428     // 再生モード
01429     play_mode();
01430 }