nlgplay for mbed

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 
00008 #include "mbed.h"
00009 #include "SDFileSystem.h"
00010 #include "lcd.h"
00011 
00012 #define USE_NBV3
00013 #define USE_FASTIO
00014 
00015 #define NBCTRL_VER "Ver 1.13"
00016 
00017 #pragma O3
00018 #pragma Otime
00019 
00020 
00021 // (pinname, mode)
00022 DigitalIn sw_play(dp24, PullUp);
00023 DigitalIn sw_next(dp10, PullUp);
00024 DigitalIn sw_prev(dp9, PullUp);
00025 
00026 // LED 
00027 DigitalOut led1(LED1, 0);
00028 DigitalOut led2(LED2, 0);
00029 
00030 // SPI: MOSI, MISO, SCLK, CS
00031 SDFileSystem sd(dp2, dp1, dp6, dp25, "sd"); 
00032 
00033 //
00034 // nlg_emb.c
00035 //
00036 
00037 #define CMD_PSG  0x00
00038 #define CMD_OPM  0x01
00039 #define CMD_OPM2 0x02
00040 #define CMD_IRQ  0x80
00041 
00042 #define CMD_CTC0 0x81
00043 #define CMD_CTC3 0x82
00044 
00045 #define NLG_VER (110)
00046 #define NLG_BASECLK (4000000)
00047 
00048 FILE *nlg_file;
00049 
00050 char nlg_title[65];
00051 int  nlg_baseclk;
00052 int  nlg_tick;
00053 int  nlg_length;
00054 int  nlg_loop_ptr;
00055 int  nlg_version;
00056 
00057 int  nlg_ctc0;
00058 int  nlg_ctc3;
00059 
00060 #define _WAIT for(int wcnt=0; wcnt < 2; wcnt++)
00061 
00062 #ifndef USE_FASTIO
00063 // 通常IO
00064 
00065 #define RCK io04 // pin4 , P0_11
00066 #define SCK io03 // pin17, P1_8
00067 #define DBS io01 // pin13, P1_4
00068 #define CTS io02 // pin26, P0_3
00069 
00070 #define IO_A0 io05
00071 #define IO_WR io06
00072 
00073 // (pinname, initial value)
00074 DigitalOut io01(dp13, 0); // P1_4
00075 DigitalOut io02(dp26, 0); // P0_3
00076 DigitalOut io03(dp17, 0); // P1_8
00077 DigitalOut io04(dp4, 0); // P0_11
00078 
00079 DigitalOut io05(dp18, 0); // P1_9
00080 DigitalOut io06(dp11, 0); // P1_2
00081 
00082 void ioInit()
00083 {
00084 }
00085 
00086 // 16bit output
00087 void ioShiftOut(unsigned int data)
00088 {
00089     int i;
00090     
00091     for(i = 0; i < 8; i++)
00092     {
00093         /* 2ビット分のデータをそれぞれ出力 */
00094         if (data & 0x80)
00095             CTS = 1;
00096         else
00097             CTS = 0;
00098         
00099         if (data & 0x8000)
00100             DBS = 1;
00101         else
00102             DBS = 0;
00103         
00104         data <<= 1;
00105 
00106         SCK = 1;
00107         // _WAIT;
00108         SCK = 0;
00109         // _WAIT;
00110     }
00111 
00112     RCK = 1;
00113     // _WAIT;
00114     RCK = 0;
00115     // _WAIT;
00116 }
00117 #else
00118 
00119 // 高速IO
00120 
00121 #define RCK IO_04
00122 #define SCK IO_03
00123 #define DBS IO_01
00124 #define CTS IO_02
00125 
00126 
00127 #define IO_A0 io05
00128 #define IO_WR io06
00129 
00130 DigitalOut io01(dp13, 0); // P1_4
00131 DigitalOut io02(dp26, 0); // P0_3
00132 DigitalOut io03(dp17, 0); // P1_8
00133 DigitalOut io04(dp4, 0); // P0_11
00134 
00135 DigitalOut io05(dp18, 0); // P1_9
00136 DigitalOut io06(dp11, 0); // P1_2
00137 
00138 
00139 #define IO_01 (1<<4)  // DBS P1_4
00140 #define IO_02 (1<<3)  // CTS P0_3
00141 #define IO_03 (1<<8)  // SCK P1_8
00142 #define IO_04 (1<<11) // RCK P0_11
00143 
00144 
00145 void ioInit()
00146 {    
00147     // 出力
00148     LPC_GPIO0->DIR |= (IO_02 | IO_04);
00149     LPC_GPIO1->DIR |= (IO_01 | IO_03);
00150 }
00151 
00152 // 16bit output
00153 void ioShiftOut(unsigned int data)
00154 {
00155     int i;
00156      
00157     for(i = 0; i < 8; i++)
00158     {
00159         /* 2ビット分のデータをそれぞれ出力 */
00160         if (data & 0x80)
00161             LPC_GPIO0->DATA |= CTS;
00162         else
00163             LPC_GPIO0->DATA &= ~CTS;
00164         
00165         if (data & 0x8000)
00166             LPC_GPIO1->DATA |= DBS;
00167         else
00168             LPC_GPIO1->DATA &= ~DBS;
00169         
00170         data <<= 1;
00171 
00172         LPC_GPIO1->DATA |= SCK;
00173         LPC_GPIO1->DATA &= ~SCK;
00174     }
00175 
00176     LPC_GPIO0->DATA |= RCK;
00177     LPC_GPIO0->DATA &= ~RCK;
00178 
00179 }
00180 
00181 #endif
00182 
00183 
00184 /* 制御信号定義 */
00185 #define CS_PSG (1 << 1)
00186 #define CS_FM1 (1 << 2)
00187 #define CS_FM2 (1 << 3)
00188 #define A0     (1 << 4)
00189 #define WR     (1 << 5)
00190 #define ICL    (1 << 6)
00191 
00192 /* アクティブローの制御信号 */
00193 #define ACTLOW (CS_PSG | CS_FM1 | CS_FM2 | WR | ICL)
00194 
00195 #ifdef USE_NBV3
00196 /* NBV3 16bit出力 */
00197 void regOutBase(int addr, int data, int select)
00198 {
00199     /* アドレスを出力 */
00200     /* A0をローにして待つ */
00201     IO_A0 = 0;
00202     ioShiftOut((addr << 8) | (ACTLOW & ~(select | WR)));
00203     ioShiftOut((addr << 8) | (ACTLOW));
00204     
00205     
00206     /* チップ側の処理を待つ */
00207     
00208     /* データを出力 */
00209     /* A0をハイにして待つ */
00210     IO_A0 = 1;
00211     ioShiftOut((data << 8) | (ACTLOW & ~(select | WR)));
00212     ioShiftOut((data << 8) | (ACTLOW));
00213 
00214     /* 処理を待つ */
00215 }
00216 #else
00217 /* NBV2互換出力 */
00218 void regOutBase(int addr, int data,int select)
00219 {
00220     /* アドレスを出力 */
00221     /* A0をローにして待つ */
00222     ioShiftOut((addr << 8) | (ACTLOW));
00223     ioShiftOut((addr << 8) | (ACTLOW & ~(select | WR)));
00224     ioShiftOut((addr << 8) | (ACTLOW));
00225     
00226     /* チップ処理待ち */        
00227     
00228     /* データを出力 */
00229     /* A0をハイにして待つ */
00230     ioShiftOut((data << 8) | A0 | (ACTLOW));
00231     ioShiftOut((data << 8) | A0 | (ACTLOW & ~(select | WR)));
00232     ioShiftOut((data << 8) | A0 | (ACTLOW));
00233 
00234     /* チップ処理待ち */
00235 }
00236 #endif
00237 
00238 /* PSG出力 */
00239 void regPSGOut(int addr, int data)
00240 {
00241     regOutBase(addr, data, CS_PSG);
00242 }
00243 
00244 /* FM2出力 */
00245 void regFM2Out(int addr, int data)
00246 {
00247     regOutBase(addr, data, CS_FM2);
00248 }
00249 
00250 /* FM音源にデータを出力 */
00251 void regFMOut(int addr,int data)
00252 {
00253     regOutBase(addr, data, CS_FM1);
00254 }
00255 
00256 /* ボード消音 */
00257 void boardMute(void)
00258 {
00259     int i;
00260     
00261     /* PSG初期化 */
00262     regPSGOut(0x00,0);
00263     regPSGOut(0x01,0);
00264     
00265     regPSGOut(0x06, 0x00);
00266     regPSGOut(0x07, 0x3f); // ALL OFF
00267     regPSGOut(0x08, 0x00); // CH.A 0
00268     regPSGOut(0x09, 0x00); // CH.B 0
00269     regPSGOut(0x0a, 0x00); // CH.C 0
00270     
00271     /* MUTE(disable) */
00272     for(i = 0x20; i < 0x28; i++)
00273     {
00274         regFMOut(i, 0x00);
00275         regFM2Out(i, 0x00);
00276     }
00277     
00278     // KEYOFF
00279     for(i = 0x00; i < 0x08; i++)
00280     {
00281         regFMOut(0x08, i & 0x07);
00282         regFM2Out(0x08, i & 0x07);
00283     }
00284     
00285     // FORCE RELEASE
00286     for(i= 0x00; i < 0x20; i++)
00287     {
00288         regFMOut(0xE0 + i, 0x0f);        
00289         regFM2Out(0xE0 + i, 0x0f);
00290     }
00291 }
00292 
00293 
00294 /* ボード初期化 */
00295 void boardInit(void)
00296 {
00297     wait_ms(20);
00298     /* ICLのみをLOW(アクティブ)にする */
00299     ioShiftOut(ACTLOW & ~(ICL));    
00300     wait_ms(150);
00301     
00302     /* 元に戻す */
00303     ioShiftOut(ACTLOW);
00304     wait_ms(10);
00305 }
00306 
00307 typedef unsigned char  byte;
00308 typedef unsigned short word;
00309 typedef unsigned long  dword;
00310 
00311 
00312 // 変数読み出し(WORD)
00313 word ReadWORD(byte *p)
00314 {
00315     return
00316         ((word)p[0]) |
00317         ((word)p[1])<<8;
00318 }
00319 
00320 // 変数読み出し(DWORD)
00321 dword ReadDWORD(byte *p)
00322 {
00323     return
00324         ((dword)p[0]) |
00325         ((dword)p[1])<<8 |
00326         ((dword)p[2])<<16 |
00327         ((dword)p[3])<<24;
00328 }
00329 
00330 // NLGファイルを開く
00331 int OpenNLG(const char *file)
00332 {    
00333     byte nlg_hdr[0x60];
00334 
00335     nlg_file = fopen(file, "rb");
00336         
00337     if (!nlg_file)
00338     {
00339         printf("File open error:%s\n", file);
00340         return -1;
00341     }
00342         
00343     fread(nlg_hdr, 0x60, 1, nlg_file);
00344     
00345     if (memcmp(nlg_hdr, "NLG1", 4) != 0)
00346     {
00347         printf("Unknown format!\n");
00348         fclose(nlg_file);
00349         return -1;
00350     }
00351     
00352     nlg_version = ReadWORD(nlg_hdr + 4);
00353 
00354     memcpy(nlg_title, nlg_hdr + 8, 64);
00355     nlg_title[64]=0;
00356 
00357     nlg_baseclk = ReadDWORD(nlg_hdr + 72);
00358     nlg_tick = ReadDWORD(nlg_hdr + 76);
00359 
00360     nlg_length = ReadDWORD(nlg_hdr + 88);
00361     nlg_loop_ptr = (long)ReadDWORD(nlg_hdr + 92);
00362     
00363     fseek(nlg_file, 0x60, SEEK_SET);
00364     
00365     nlg_ctc0 = nlg_ctc3 = 0;
00366     
00367     return 0;
00368 }
00369 
00370 #if 0
00371 
00372 
00373 // 変数書き出し(WORD)
00374 inline void WriteWORD(byte *p,word val)
00375 {
00376     p[0] = (val & 0xff);
00377     p[1] = ((val>>8) & 0xff);
00378 }
00379 
00380 // 変数書き出し(DWORD)
00381 inline void WriteDWORD(byte *p,dword val)
00382 {
00383     p[0] = (val & 0xff);
00384     p[1] = ((val>>8) & 0xff);
00385     p[2] = ((val>>16) & 0xff);
00386     p[3] = ((val>>24) & 0xff);
00387 }
00388 
00389 // 書き込み用NLGファイルを開く
00390 int CreateNLG(const char *file)
00391 {
00392     byte hdr[0x80];
00393     
00394     nlg_file = fopen(file, "wb");
00395     
00396     if (!nlg_file)
00397     {
00398         printf("File open error:%s\n", file);
00399         return -1;
00400     }
00401     
00402     memset(hdr, 0, 0x80);
00403     memcpy(hdr,"NLG1",4);
00404     
00405     WriteWORD(hdr + 4, NLG_VER); // Version
00406     WriteDWORD(hdr + 72, NLG_BASECLK); // BaseCLK
00407     WriteDWORD(hdr + 76, 0); // Tick
00408     WriteDWORD(hdr + 88, 0); // Length
00409     WriteDWORD(hdr + 92, 0); // Loop Pointer
00410     
00411     fwrite(hdr, 0x60, 1, nlg_file);
00412 
00413     nlg_ctc0 = nlg_ctc3 = 0;
00414 
00415     return 0;
00416 }
00417 
00418 
00419 // コマンドの書き込み
00420 void WriteNLG_CMD(int cmd)
00421 {
00422     if (!nlg_file)
00423         return;
00424     
00425     fputc(cmd, nlg_file);
00426 }
00427 
00428 // CTC定数の書き込み
00429 void WriteNLG_CTC(int cmd,int ctc)
00430 {
00431     if (!nlg_file)
00432         return;
00433 
00434     fputc(cmd, nlg_file);
00435     fputc(ctc, nlg_file);
00436 }
00437 
00438 // データの書き込み
00439 void WriteNLG_Data(int cmd,int addr,int data)
00440 {
00441     if (!nlg_file)
00442         return;
00443 
00444     fputc(cmd, nlg_file);
00445     fputc(addr, nlg_file);
00446     fputc(data, nlg_file);
00447 }
00448 
00449 #endif
00450 
00451 // ファイルを閉じる
00452 void CloseNLG(void)
00453 {
00454     if (!nlg_file)
00455         return;
00456 
00457     fclose(nlg_file);
00458 
00459 #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler
00460     free(nlg_file);
00461 #endif
00462 
00463     nlg_file = NULL;
00464 }
00465 
00466 // データの読み出し
00467 inline int ReadNLG(void)
00468 {
00469     return fgetc(nlg_file);
00470 }
00471 
00472 // ファイルポインタの位置を取得
00473 inline long TellNLG(void)
00474 {
00475     return ftell(nlg_file);
00476 }
00477 
00478 // ファイルポインタの位置を設定
00479 inline void SeekNLG(long pos)
00480 {
00481     fseek(nlg_file, pos, SEEK_SET);
00482 }
00483 
00484 // タイトルの取得
00485 inline char *GetTitleNLG(void)
00486 {
00487     return nlg_title;
00488 }
00489 
00490 // ティックの取得
00491 inline int GetTickNLG(void)
00492 {
00493     return nlg_tick;
00494 }
00495 
00496 // Set Tick
00497 inline void SetTick(void)
00498 {
00499     nlg_tick = ((nlg_ctc0 * 256) * nlg_ctc3);
00500     // printf("nlg_tick=%d\n", nlg_tick);
00501 }
00502 
00503 // CTC0値の設定
00504 void SetCTC0_NLG(int value)
00505 {
00506     nlg_ctc0 = value;
00507     SetTick();
00508 }
00509 
00510 // CTC3値の設定
00511 void SetCTC3_NLG(int value)
00512 {
00513     nlg_ctc3 = value;
00514     SetTick();
00515 }
00516 
00517 // 曲の長さを得る
00518 int GetLengthNLG(void)
00519 {
00520     return nlg_length;
00521 }
00522 
00523 // ループポインタを得る
00524 int GetLoopPtrNLG(void)
00525 {
00526     return nlg_loop_ptr;
00527 }
00528 
00529 // ベースクロックを得る
00530 int GetBaseClkNLG(void)
00531 {
00532     return nlg_baseclk;
00533 }
00534 
00535 #define CMD_PSG  0x00
00536 #define CMD_OPM  0x01
00537 #define CMD_OPM2 0x02
00538 #define CMD_IRQ  0x80
00539 
00540 #define CMD_CTC0 0x81
00541 #define CMD_CTC3 0x82
00542 
00543 
00544 /* 単位を扱いやすいように */
00545 typedef unsigned char byte;
00546 typedef unsigned short word;
00547 typedef unsigned long dword;
00548 
00549 /* NLGを処理するための構造体 */
00550 typedef struct
00551 {
00552     int base_clk;
00553     int clk_per_sample;
00554     
00555     int freeze;
00556     int total_samples;
00557         
00558     int total_sec;
00559 
00560     int current_samples;
00561     int tick;
00562     int tick_sec;
00563     
00564     int irq_count;
00565     int irq_loop;
00566     long loop_address;
00567     
00568     int irq_counter;
00569     int irq_counter2;
00570     
00571 } NLG_R;
00572 
00573 
00574 /* 初期化 */
00575 int initNLG(NLG_R *np, const char *nlg_name)
00576 {
00577     if (OpenNLG(nlg_name) < 0)
00578         return -1;
00579     
00580     np->base_clk = GetBaseClkNLG();
00581     
00582     /* printf("Title:%s %d %d %dsec %d\n",
00583            GetTitleNLG(),
00584            GetBaseClkNLG(),
00585            GetTickNLG(),
00586            GetLengthNLG(),
00587            GetLoopPtrNLG());
00588     */
00589     
00590     np->total_samples = 0;
00591     np->current_samples = 0;
00592         
00593     np->total_sec = 0;
00594     
00595     np->tick = 0;
00596     np->tick_sec = 0;
00597     
00598     np->freeze = 0;
00599     
00600     np->irq_count = 0;
00601     np->irq_loop = GetLoopPtrNLG();
00602     np->loop_address = -1;
00603     
00604     np->irq_counter = 0;
00605     np->irq_counter2 = 0;
00606 
00607     return 0;
00608 }
00609 
00610 /* PSGへの出力 */
00611 void WritePSG(int addr,int value)
00612 {
00613     regPSGOut(addr, value);
00614 }
00615 
00616 /* FM1への出力 */
00617 void WriteOPM(int addr,int value)
00618 {
00619     regFMOut(addr, value);
00620 }
00621 
00622 /* FM2への出力 */
00623 void WriteOPM2(int addr,int value)
00624 {
00625     regFM2Out(addr, value);
00626 }
00627 
00628 // stop flag
00629 bool g_stop = false;
00630 bool g_prev = false;
00631 
00632 void DispNLG(NLG_R *np)
00633 {
00634     // printf("Time %02d:%02d\r",np->total_sec / 60, np->total_sec % 60);
00635     // fflush(stdout);
00636     
00637     char buf[16];
00638     sprintf(buf, "%02d:%02d",
00639         np->total_sec / 60, 
00640         np->total_sec % 60);
00641     
00642     lcd_setCursor(3,1);
00643     lcd_printStr(buf);
00644 }
00645 
00646 // wait until release buttons
00647 void waitButtonRelease(void)
00648 {
00649     while(!sw_next || !sw_play || !sw_prev);
00650 }
00651 
00652 // wait until press buttons
00653 void waitButtonPress(void)
00654 {
00655     while(sw_next && sw_play && sw_prev);
00656 }
00657 
00658 /* NLGの再生 */
00659 int PlayNLG(NLG_R *np, int sec)
00660 {
00661     int cmd;
00662     int addr, data;
00663     int result = 0;
00664     
00665     int tick;
00666     int total_us = 0;
00667     int us_tick = np->base_clk / 1000000;
00668     
00669     printf("start play\n");
00670     Timer t;
00671     
00672     t.start();
00673     total_us = 0;
00674     
00675     // wait until release buttons
00676     waitButtonRelease();
00677     
00678     DispNLG(np);
00679 
00680     while(np->total_sec < sec && !g_stop)
00681     {
00682         // push next
00683         if (!sw_next)
00684             break;
00685         
00686         // push prev
00687         if (!sw_prev)
00688         {
00689             g_prev = true;
00690             break;
00691         }
00692 
00693         // push play
00694         if (!sw_play)
00695         {
00696             g_stop = true;
00697             break;
00698         }
00699 
00700         /* ウエイトの処理 */
00701         while (np->tick >= us_tick)
00702         {
00703             int us = np->tick / us_tick;
00704             np->tick -= (us * us_tick);
00705             
00706             // 次のタイミングまで待つ
00707             while(t.read_us() < total_us + us);
00708             
00709             total_us += us;
00710             
00711             // 1秒ごとにリセットする
00712             if (total_us >= 1000000)
00713             {
00714                 total_us -= t.read_us();
00715                 t.reset();
00716             }
00717             // DELAY_NEXT(us);
00718             
00719             // printf("delay : %dus\n",us);
00720         }
00721         
00722         /* コマンドの読み出し */
00723         cmd = ReadNLG();
00724         if (cmd == EOF)
00725         {
00726             if (np->loop_address >= 0)
00727             {
00728                 SeekNLG(np->loop_address);
00729                 cmd = ReadNLG();
00730             }
00731             else
00732             {           
00733                 result = EOF;
00734                 break;
00735             }
00736         }
00737         
00738         /* コマンドの処理 */
00739         switch (cmd)
00740         {
00741             case CMD_PSG:
00742                 addr = ReadNLG();
00743                 data = ReadNLG();
00744                 WritePSG(addr, data);
00745                 break;
00746             case CMD_OPM:
00747                 addr = ReadNLG();
00748                 data = ReadNLG();
00749                 WriteOPM(addr, data);
00750                 break;
00751             case CMD_OPM2:
00752                 addr = ReadNLG();
00753                 data = ReadNLG();
00754                 WriteOPM2(addr, data);
00755                 break;
00756             case CMD_IRQ:
00757                 tick = GetTickNLG();
00758                 np->tick_sec += tick;
00759                 np->tick += tick;
00760                 np->irq_count++;
00761                 if (np->irq_count == np->irq_loop)
00762                 {
00763                     /* ループ位置の設定 */
00764                     np->loop_address = TellNLG();
00765                     np->loop_address -= 1;
00766                 }
00767                 np->irq_counter++;
00768                 if (np->irq_counter >= 48)
00769                 {
00770                     np->irq_counter = 0;
00771                     led1 = !led1;
00772 
00773                     np->irq_counter2++;
00774                     if (np->irq_counter2 >= 4)
00775                     {
00776                         np->irq_counter2 = 0;
00777                         led2 = !led2;
00778                     }
00779                 }
00780             break;
00781             case CMD_CTC0:
00782                 SetCTC0_NLG(ReadNLG());
00783             break;
00784             case CMD_CTC3:
00785                 SetCTC3_NLG(ReadNLG());
00786             break;
00787                 
00788         }
00789         /* 秒情報の表示 */
00790         while (np->tick_sec >= np->base_clk)
00791         {
00792             np->tick_sec -= np->base_clk;
00793             np->total_sec++;
00794 
00795             DispNLG(np);            
00796         }
00797     }
00798     
00799     return result;
00800 }
00801 
00802 NLG_R n;
00803 
00804 int nlg_play(const char *nlg_file)
00805 {
00806     printf("nlg_play:%s\n",nlg_file);
00807 
00808        /* NLGの初期化 */
00809     if (initNLG(&n, nlg_file) < 0)
00810     {
00811         lcd_printStrY(1, " ERROR!!");
00812         printf("Failed to init.\n");
00813         return -1;
00814     }
00815 
00816     printf("Play..\n");
00817     
00818     /* 再生する */
00819     PlayNLG(&n, 360);
00820     
00821     /* mute */
00822     boardMute();
00823     
00824     /* NLGファイルを閉じる */
00825     CloseNLG();
00826     
00827     return 0;
00828 }
00829 
00830 void error_sdcard(void)
00831 {
00832     lcd_printStr2("SD CARD", "ERROR!");
00833     
00834     while(1);
00835 }
00836 
00837 int get_nlg_file(char *dest, int index)
00838 {
00839     char *cwd = "/sd/";
00840     int count = -1;
00841     DIR *dir = opendir(cwd); 
00842 
00843     dest[0] = 0;
00844     
00845     if (dir == NULL)
00846     {
00847         return -1;
00848     } 
00849     struct dirent *dent;
00850     
00851     while(1)
00852     {
00853         dent = readdir(dir);
00854         if (!dent)
00855             break;
00856 
00857         // resource or hidden file
00858         if (dent->d_name[0] == '.')
00859             continue;
00860             
00861         char *ext = strrchr(dent->d_name, '.');
00862         if (!ext)
00863             continue;
00864 
00865         if (strcasecmp(ext, ".nlg") != 0)
00866             continue;
00867         
00868         if (count < 0)
00869             count = 0;
00870 
00871         count++;
00872         
00873         if (index < 0)
00874             continue;
00875         
00876         if (count <= index)
00877             continue;         
00878         
00879         strcpy(dest, dent->d_name);
00880         break;
00881     }
00882     closedir(dir);
00883     return count;
00884 }
00885 
00886 //
00887 // COM mode
00888 //
00889 void loop_for_com()
00890 {
00891     Serial pc(USBTX, USBRX);
00892     
00893     lcd_printStrY(1,"COM MODE");
00894 
00895     pc.printf("com_mode\n");
00896     
00897     while(1)
00898     {
00899         unsigned char sw, adr, val;
00900         
00901         sw = pc.getc();
00902         if (sw == 0x00)
00903             continue;
00904             
00905         adr = pc.getc();
00906         val = pc.getc();
00907         switch(sw)
00908         {
00909             case 1:
00910                 regFMOut(adr, val);
00911             break;
00912             case 2:
00913                 regFM2Out(adr, val);
00914             break;
00915             case 3:
00916                 regPSGOut(adr, val);
00917             break;
00918             case 0x0f:
00919                 pc.baud(9600 * val);
00920             break;
00921         }
00922 
00923         // pc.printf("sw = %02x, adr = %02x, val = %02x\n", sw, adr, val);
00924     }
00925 }
00926 
00927 //
00928 // title
00929 //
00930 void putTitle()
00931 {
00932         lcd_printStr2("NBCTRL", NBCTRL_VER);
00933         wait(1.5);
00934 }
00935 
00936 // 情報の表示
00937 void show_info(int files)
00938 {
00939     char buf[16];
00940 
00941     Timer t;
00942     int result_us = 0;
00943     t.reset();
00944     t.start();
00945             
00946     // actual timing
00947     regFMOut(0x20, 0x00);
00948     
00949     result_us = t.read_us();
00950     t.stop();
00951     
00952     printf("result_us=%dus\n", result_us);            
00953     sprintf(buf, "R:%dus", result_us); 
00954     lcd_printStrY(1, buf);
00955     wait(3);
00956             
00957     sprintf(buf, "%8s", __DATE__); 
00958     lcd_printStrYscr(1, buf);
00959     wait(3);
00960 
00961     if (files < 0)
00962         lcd_printStrY(1, "NO FILES");
00963     else
00964     {
00965         char buf[16];
00966         sprintf(buf, "%3dfiles", files);    
00967         lcd_printStrY(1, buf);
00968     }
00969     wait(3);
00970     lcd_cls();
00971 }
00972 
00973 //
00974 // main 
00975 //
00976 int main() 
00977 {
00978     bool info_mode = false;
00979     bool com_mode = false;
00980 
00981     int files = 0;
00982     
00983     char file[32];
00984     char path[48];
00985     
00986     ioInit();
00987     
00988     wait_ms(20);
00989 
00990     // reset SHIFT REGISTER
00991     ioShiftOut((0xFF << 8) | (ACTLOW));
00992     
00993     // モード
00994     if (!sw_next)
00995         info_mode = true;
00996     if (!sw_prev)
00997         com_mode = true;
00998     
00999     // 初期化とタイトル表示
01000     lcd_init();
01001     putTitle();
01002     
01003     // ボードの初期化
01004     boardInit();
01005 
01006     // 通信モードに移行    
01007     if (com_mode)
01008             loop_for_com();
01009         
01010     files = get_nlg_file(file, -1);
01011     
01012     // エラー表示
01013     if (files < 0)
01014         error_sdcard();
01015     
01016     // 情報モード
01017     if (info_mode)
01018         show_info(files);
01019 
01020     
01021     bool repeat_flag = false;
01022     int idx = 0;
01023     while(files > 0)
01024     {
01025         char buf[16];
01026         
01027         get_nlg_file(file, idx);
01028         
01029         sprintf(path, "/sd/%s", file);
01030         printf("path=%s\n",path);
01031         
01032         lcd_cls();
01033         lcd_printStrY(0, file);
01034 
01035         sprintf(buf, "%2d ", idx + 1);
01036         lcd_printStrY(1, buf);
01037 
01038         nlg_play(path);
01039         
01040         // wait for chattering
01041         wait(0.25);
01042 
01043         // wait release        
01044         waitButtonRelease();
01045                 
01046         // if play button is pressed
01047         if (g_stop)
01048         {
01049             g_stop = false;
01050             g_prev = false;                
01051 
01052             lcd_printStrY(1, "  STOP  ");
01053 
01054             // wait any button is pressed
01055             waitButtonPress();
01056             
01057             // 
01058             if (!sw_prev) {
01059                 lcd_printStrY(1, "  PREV  ");
01060                 g_prev = true;
01061             }
01062             if (!sw_play)
01063             {
01064                 lcd_printStrY(1, "  PLAY  ");
01065                 repeat_flag = true;
01066             }
01067             if (!sw_next)
01068             {
01069                 lcd_printStrY(1, "  NEXT  ");
01070                 repeat_flag = false;
01071             }
01072             
01073             // wait release
01074             waitButtonRelease();
01075             
01076             // reset board
01077             boardInit();
01078         }
01079         
01080         // play prev or next song
01081         if (g_prev)
01082         {
01083             g_prev = false;
01084 
01085             if (idx - 1 >= 0)
01086                 idx--;
01087             else
01088                 idx = files - 1;
01089 
01090             continue;
01091         }
01092         
01093         if (!repeat_flag) 
01094         {
01095             if (idx + 1 < files)
01096                 idx++;
01097             else
01098                 idx = 0;
01099         }
01100         repeat_flag = false;
01101     }
01102 }