firmware of NBCTRLV1 / AYC01
Dependencies: SDFileSystemEx mbed
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 }
Generated on Wed Jul 20 2022 14:46:06 by 1.7.2