![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
firmware of NBCTRLV1 / AYC01
Dependencies: SDFileSystemEx mbed
Diff: main.cpp
- Revision:
- 0:722cc5360dc3
- Child:
- 1:29f0e76a9999
diff -r 000000000000 -r 722cc5360dc3 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Feb 08 05:49:26 2016 +0000 @@ -0,0 +1,1419 @@ +// +// NLGPLAY : NLG file player for mbed +// +// example to write : +// ./lpc21isp -bin file.bin /dev/cu.usbserial-??? 115200 12000 +// +// 20151008: updated. +// + +#include <stdio.h> + +#include "mbed.h" +#include "SDFileSystem.h" +#include "lcd.h" + +#include "nlg_mini.h" + +// SPIモード +// #define USE_SPI + +#ifdef TARGET_LPC1114 +// 高速I/Oモード(LPC1114専用) +#define USE_FASTIO +#endif + +// ピンアサイン切り替え +#include "pindef.h" + + +#define PRG_NAME "NLGPLAY" +#define PRG_VER_BASE "V1.22" + +#ifndef USE_SPI +#define PRG_VER PRG_VER_BASE +#else +#define PRG_VER PRG_VER_BASE "S" +#endif + + +//#pragma O3 +//#pragma Otime + + + +// (pinname, mode) +DigitalIn sw_play(DP_PLAY, PullUp); +DigitalIn sw_next(DP_NEXT, PullUp); +DigitalIn sw_prev(DP_PREV, PullUp); + +#define MAX_PATH 128 +#define MAX_FILENAME 64 +#define MAX_DIR 64 + +// Global Variable +struct +{ + bool stop; + bool prev; + bool one_mode; + + int idx; + int max_entries; + + char playlist[MAX_FILENAME]; + char file[MAX_FILENAME]; + char cwd[MAX_DIR]; + + NLG_CTX nlg; + int total_sec; +} g; + +// キーコード +#define SW_PLAY 1 +#define SW_NEXT 2 +#define SW_PREV 4 + + +// ボタンが離されるのを待つ +void wait_key_up(void) +{ + while(!sw_next || !sw_play || !sw_prev); +} + +// ボタンの入力を待つ +void wait_key_down(void) +{ + while(sw_next && sw_play && sw_prev); +} + +// キー入力 +int get_key(void) +{ + int key = 0; + + if (!sw_next) + key |= SW_NEXT; + if (!sw_play) + key |= SW_PLAY; + if (!sw_prev) + key |= SW_PREV; + return key; +} + +// キー開放待ち +void wait_relkey(void) +{ + wait_key_up(); + wait(0.1); +} + +// キー待ち +int wait_anykey(void) +{ + wait_key_down(); + int key = get_key(); + + wait(0.1); + wait_relkey(); + + return key; +} + +// LED +DigitalOut led1(LED1, 0); +DigitalOut led2(LED2, 0); + +// SPI: MOSI, MISO, SCLK, CS +SDFileSystem sd(DP_MOSI, DP_MISO, DP_SCLK, DP_SCS, "sd"); + +// LCD +LCD lcd; + +#define _WAIT for(int wcnt=0; wcnt < 2; wcnt++) + + +//////////////// +// 高速IO + +#define DBS IO_01 // DATA +#define CTS IO_02 // CTRL +#define RCK IO_04 // LATCH +#define SCK IO_03 // SCLK + + +DigitalOut io01(DP_IO01, 0); // P1_4 +DigitalOut io02(DP_IO02, 0); // P0_3 +DigitalOut io03(DP_IO03, 0); // P1_8 +DigitalOut io04(DP_IO04, 0); // P0_11 + +#if 0 +// NBV3での試し機能 +#define IO_A0 io05 +#define IO_WR io06 + +DigitalOut io05(DP_IO05, 0); // P1_9 +DigitalOut io06(DP_IO06, 0); // P1_2 + +#endif + +#define IO_01 (1 << 4) // DBS P1_4 +#define IO_02 (1 << 3) // CTS P0_3 +#define IO_03 (1 << 8) // SCK P1_8 +#define IO_04 (1 << 11) // RCK P0_11 + +#ifdef USE_FASTIO + +// ポート出力 +#define DATA_HI LPC_GPIO1->DATA |= DBS +#define DATA_LO LPC_GPIO1->DATA &= ~DBS +#define CTRL_HI LPC_GPIO0->DATA |= CTS +#define CTRL_LO LPC_GPIO0->DATA &= ~CTS +#define SCK_HI LPC_GPIO1->DATA |= SCK +#define SCK_LO LPC_GPIO1->DATA &= ~SCK +#define RCK_HI LPC_GPIO0->DATA |= RCK +#define RCK_LO LPC_GPIO0->DATA &= ~RCK + +// 出力設定 +#define PORT_DIR LPC_GPIO0->DIR |= (IO_02 | IO_04); \ + LPC_GPIO1->DIR |= (IO_01 | IO_03) + +#else + +// ポート出力 +#define DATA_HI io01 = 1 +#define DATA_LO io01 = 0 +#define CTRL_HI io02 = 1 +#define CTRL_LO io02 = 0 +#define SCK_HI io03 = 1 +#define SCK_LO io03 = 0 +#define RCK_HI io04 = 1 +#define RCK_LO io04 = 0 + +// 出力設定 +#define PORT_DIR + +#endif + +SPI *spi; + +// I/O初期化 +void ioInit() +{ + // SPIインスタンスの取得 + spi = sd.getSPI(); + // 出力 + PORT_DIR; +} + + +#ifndef USE_SPI +// 8x2ビットモード + +#define SHIFTOUT io8x2Out + +// 8bit 出力 +void byteOut(unsigned char data) +{ + int i; + + for(i = 0; i < 8; i++) + { + if (data & 0x80) + DATA_HI; + else + DATA_LO; + + data <<= 1; + + SCK_HI; + SCK_LO; + } +} + +// 8x2ビット出力 or 16bit出力選択可能 +void io8x2Out(unsigned int ctrl, unsigned int data) +{ + int i; + // シフトレジスタ直列モード + if (g.one_mode) + { + // データ順 + // <- CCCCCCCC76543210 + + byteOut(ctrl); + byteOut(data); + + // ラッチ + RCK_HI; + RCK_LO; + } + else + { + // シフトレジスタ並列モード + for(i = 0; i < 8; i++) + { + /* 2ビット分のデータをそれぞれ出力 */ + if (ctrl & 0x80) + CTRL_HI; + else + CTRL_LO; + + if (data & 0x80) + DATA_HI; + else + DATA_LO; + + ctrl <<= 1; + data <<= 1; + // シフトクロック + SCK_HI; + SCK_LO; + } + + // ラッチ + RCK_HI; + RCK_LO; + } +} + +#else + +// 16bitモード +#define SHIFTOUT io16Out + + + +// 16bit 出力 +void io16Out(unsigned char ctrl, unsigned char data) +{ + spi->write(ctrl); + spi->write(data); + + // byteOut(ctrl); + // byteOut(data); + + // LATCH + RCK_HI; + RCK_LO; +} + +#endif + +/* 制御信号定義 */ +#define CS_FM3 (1 << 0) +#define CS_PSG (1 << 1) +#define CS_FM1 (1 << 2) +#define CS_FM2 (1 << 3) +#define A0 (1 << 4) +#define WR (1 << 5) +#define ICL (1 << 6) +#define CTL (1 << 7) + + +/* アクティブローの制御信号 */ +#define ACTLOW (CS_PSG | CS_FM1 | CS_FM2 | CS_FM3 | WR | ICL) + + +/* NBV2互換出力 */ +void regOutBase(int addr, int data, int select) +{ + /* アドレスを出力 */ + /* A0をローにして待つ */ + int ctrl = ACTLOW; + + /* 裏レジスタ */ + if (addr >= 0x100) + ctrl |= CTL; + addr &= 0xff; + + SHIFTOUT(ctrl, 0x00); + SHIFTOUT(ctrl & ~(select | WR), addr); + SHIFTOUT(ctrl, addr); + + /* チップ処理待ち */ + + /* データを出力 */ + /* A0をハイにして待つ */ + ctrl |= A0; + SHIFTOUT(ctrl, 0x00); + SHIFTOUT(ctrl & ~(select | WR), data); + SHIFTOUT(ctrl, data); + + /* チップ処理待ち */ +} + +/* 出力 */ +#define regPSGOut(addr, data) regOutBase(addr, data, CS_PSG) +#define regFMOut(addr, data) regOutBase(addr, data, CS_FM1) +#define regFM2Out(addr, data) regOutBase(addr, data, CS_FM2) + +/* 音源出力 */ +#define WritePSG regPSGOut +#define WriteOPM regFMOut +#define WriteOPM2 regFM2Out + + +/* ミュート */ +void boardMute(void) +{ + int i; + + /* PSG初期化 */ + regPSGOut(0x00,0); + regPSGOut(0x01,0); + + regPSGOut(0x06, 0x00); + regPSGOut(0x07, 0x3f); // ALL OFF + regPSGOut(0x08, 0x00); // CH.A 0 + regPSGOut(0x09, 0x00); // CH.B 0 + regPSGOut(0x0a, 0x00); // CH.C 0 + + /* MUTE(disable) */ + for(i = 0x20; i < 0x28; i++) + { + regFMOut(i, 0x00); + regFM2Out(i, 0x00); + } + + // KEYOFF + for(i = 0x00; i < 0x08; i++) + { + regFMOut(0x08, i & 0x07); + regFM2Out(0x08, i & 0x07); + } + + // FORCE RELEASE + for(i= 0x00; i < 0x20; i++) + { + regFMOut(0xE0 + i, 0x0f); + regFM2Out(0xE0 + i, 0x0f); + } + + // OPLL ミュート + for(i= 0x00; i <= 0x08; i++) + { + regFMOut(0x20 + i, 0x00); + regFMOut(0x30 + i, 0x0f); + regFM2Out(0x20 + i, 0x00); + regFM2Out(0x30 + i, 0x0f); + } + +} + +/* ボード初期化 */ +void boardInit(void) +{ + wait_ms(20); + /* ICLのみをLOW(アクティブ)にする */ + SHIFTOUT(ACTLOW & ~(ICL), 0); + wait_ms(150); + + /* 元に戻す */ + SHIFTOUT(ACTLOW, 0); + wait_ms(10); +} + +////////////////////////////////////////// + +// 表示 +void dispTime() +{ + char buf[16]; + sprintf(buf, "%02d:%02d", + g.total_sec / 60, + g.total_sec % 60); + + lcd.setCursor(3,1); + lcd.printStr(buf); +} + +#define WAIT_US 10000 // 10ms +#define SEC_US 1000000 // 1sec +#define NEXT_MAX_US 300000 // 300ms + +/* NLGの再生 */ +int PlayNLG_Loop(void) +{ + int cmd; + int addr, data; + + int result = 0; + + int us = 0; + int diff_us = 0; + + int count_us = 0; + int total_us = 0; + + // NEXTボタンのカウンタ + int next_count = 0; + + bool wait_skip = false; + + + // GetTickUsNLG + int tick_us = GetTickUsNLG(&g.nlg); + + // printf("tick_us:%d\n", tick_us); + + g.total_sec = 0; + + // タイマースタート + Timer t; + t.start(); + + // 表示 + dispTime(); + + // LED消灯 + led1 = 0; + led2 = 0; + + // LEDカウンタ + int led_cnt1 = 0; + int led_cnt2 = 0; + + // ループ + while(!g.stop) + { + /* ウエイトの処理 */ + while (count_us >= WAIT_US) + { + // ボタンチェック + if (!sw_next) + { + // NEXTが押されている + if (next_count < NEXT_MAX_US) + next_count += count_us; + else + { + // 早送り + next_count = NEXT_MAX_US; + wait_skip = true; + } + } + else + { + // NEXTが離されている + wait_skip = false; + + // 一瞬だけボタンが押された場合、次の曲へ + if (next_count > 0 && next_count < NEXT_MAX_US) + { + next_count = 0; + goto song_end; + } + + // 早送りの終了 + if (next_count == NEXT_MAX_US) + { + next_count = 0; + } + } + // PREVが押された + if (!sw_prev) + { + g.prev = true; + goto song_end; + } + + // PLAYが押された + if (!sw_play) + { + g.stop = true; + goto song_end; + } + + // スキップでなければ次のタイミングまで待つ + while(!wait_skip && (us = t.read_us()) + diff_us < count_us); + + // タイマーリセット + if (!wait_skip) + t.reset(); + + // 差分を計算 + diff_us += us; + while(diff_us >= count_us) + diff_us -= count_us; + + // 積算する + total_us += count_us; + count_us = 0; + + // 1秒で積算カウントをリセットする + if (total_us >= SEC_US) + { + while(total_us >= SEC_US) + { + g.total_sec++; + total_us -= SEC_US; + } + // 表示 + dispTime(); + } + } + + /* コマンドの読み出し */ + cmd = ReadNLG(&g.nlg); + if (cmd == EOF) + { + result = EOF; + break; + } + + if (cmd < 0x80) + { + addr = ReadNLG(&g.nlg); + data = ReadNLG(&g.nlg); + + // 裏レジスタ + if (cmd >= 0x40) + addr |= 0x100; + + switch(cmd & 0x3f) + { + case CMD_PSG: + WritePSG(addr, data); + break; + case CMD_FM1: + WriteOPM(addr, data); + break; + case CMD_FM2: + WriteOPM2(addr, data); + break; + } + } + else + { + /* コマンドの処理 */ + switch (cmd) + { + case CMD_IRQ: + count_us += tick_us; + + // LED1 + led_cnt1++; + if (led_cnt1 >= 48) + { + led_cnt1 = 0; + led1 = !led1; + } + + // LED2 + led_cnt2++; + if (led_cnt2 >= 192) + { + led_cnt2 = 0; + led2 = !led2; + } + break; + case CMD_CTC0: + data = ReadNLG(&g.nlg); + SetCTC0_NLG(&g.nlg, data); + tick_us = GetTickUsNLG(&g.nlg); + // printf("CTC0:%d tick_us:%d\n", data, tick_us); + + break; + case CMD_CTC3: + data = ReadNLG(&g.nlg); + SetCTC3_NLG(&g.nlg, data); + tick_us = GetTickUsNLG(&g.nlg); + // printf("CTC3:%d tick_us:%d\n", data, tick_us); + break; + } + } + } + +song_end: + + return result; +} + + +// ファイルを再生する +int play_file(const char *filename) +{ + /* NLGファイルを開く */ + if (OpenNLG(&g.nlg, filename) < 0) + { + return -1; + } + + /* 再生する */ + PlayNLG_Loop(); + + /* NLGファイルを閉じる */ + CloseNLG(&g.nlg); + + return 0; +} + +// error_sdcard() +// エラー! +void error_sdcard(void) +{ + lcd.printStr2("SD CARD", "ERROR!"); + + while(1); +} + +// COM mode +void loop_for_com(void) +{ + int sw, val; + int adr = 0x00; + int baud = 9600; + char buf[16]; + Serial pc(DP_TX, DP_RX); + + lcd.cls(); + lcd.printStrY(0, "COM MODE"); + + sprintf(buf, "%-8d", baud); + lcd.printStrY(1, buf); + + pc.printf("COM\n"); + + // タイマースタート + Timer t; + t.start(); + + while(1) + { + + sw = pc.getc(); + + // 0は同期リセット + if (sw == 0x00) + continue; + + if (sw >= 1 && sw <= 3) + { + adr = pc.getc(); + val = pc.getc(); + } + + switch(sw) + { + case 1: + regFMOut(adr, val); + break; + case 2: + regFM2Out(adr, val); + break; + case 3: + regPSGOut(adr, val); + break; + case 0x0f: + // 通信速度設定 + val = pc.getc(); + baud = (9600 * val); + sprintf(buf, "%-8d", baud); + lcd.printStrY(1, buf); + + pc.baud(baud); + break; + case 0x10: + // + val = pc.getc(); + val = (val * 10000); + while(t.read_us() < val); + pc.putc('.'); + t.reset(); + break; + case 0x11: + t.reset(); + break; + } + + // pc.printf("sw = %02x, adr = %02x, val = %02x\n", sw, adr, val); + } +} + + +// chk_isdir +// ディレクトリか否か +// return : bool +// false if not directory + +bool chk_isdir(const char *cwd, const char *dir) +{ + char tmp[256]; + sprintf(tmp,"%s/%s", cwd, dir); + + DIR *dp = opendir(tmp); + if (!dp) + return false; + + closedir(dp); + return true; +} + +#define EXT_LIST ".lst" +#define EXT_NLG ".nlg" + +// get_fileentry +// index : index of list , -1 = return number of entries +// is_mode : 0 = normal mode +// mode = MODE_GETDIR | MODE_GETLIST | MODE_FILE +// return : int +// -1 = not found or error + +#define MODE_FILE 0 +#define MODE_GETDIR 1 +#define MODE_GETLIST 2 + +int get_fileentry(int index, int mode) +{ + // return -1 if entry is zero. + int count = 0; + DIR *dp = opendir(g.cwd); + + g.file[0] = 0; + + if (!dp) + return -1; + + struct dirent *dent = NULL; + + while(1) + { + // エントリの読み出し + dent = readdir(dp); + + // 失敗 + if (!dent) + break; + + // リソースか隠しファイル + if (dent->d_name[0] == '.') + continue; + + // 拡張子の取得 + char *ext = strrchr(dent->d_name, '.'); + + switch(mode) + { + // ディレクトリモード + case MODE_GETDIR: + // ディレクトリでなければ継続 + if (!chk_isdir(g.cwd, dent->d_name)) + continue; + break; + + // プレイリストモード + case MODE_GETLIST: + // リストでなければ無視 + if (!ext || strcasecmp(ext, EXT_LIST) != 0) + continue; + break; + + // ファイルモード + case MODE_FILE: + // NLGファイルでなければ継続 + if (!ext || strcasecmp(ext, EXT_NLG) != 0) + continue; + break; + } + + // カウントアップ + count++; + + // カウントモードかカウントがindex未満で継続 + if (index < 0 || count <= index) + continue; + + // ファイル名をコピーして終了 + strcpy(g.file, dent->d_name); + break; + + } + closedir(dp); + return count; +} + + +// +// タイトル表示 +// +int putTitle() +{ + int count_ms = 0; + int diff_us = 0; + int us = 0; + int key = get_key(); + + // キー入力時はキャンセル + if (key) + return key; + + lcd.printStr2(PRG_NAME, PRG_VER); + Timer t; + t.start(); + + // 1500msまでループする + while(count_ms < 1500) + { + while((us = t.read_us()) + diff_us < 1000); + t.reset(); + + // キー入力があれば終了 + key = get_key(); + if (key) + return key; + + // 差分を現在の時間に足して次の差分を作る + diff_us += us; + + while(diff_us >= 1000) + { + count_ms++; + diff_us -= 1000; + } + } + + return 0; +} + +// 情報の表示 +void show_info(int files) +{ + char buf[16]; + + Timer t; + int result_us = 0; + t.reset(); + t.start(); + + // 実際の書き込み時間を計測する + regFMOut(0x20, 0x00); + regFMOut(0x20, 0x00); + regFMOut(0x20, 0x00); + regFMOut(0x20, 0x00); + regFMOut(0x20, 0x00); + + // 経過時間を得る + result_us = t.read_us(); + t.stop(); + + // 平均値 + result_us /= 5; + + // 結果表示 + printf("result_us=%dus\n", result_us); + sprintf(buf, "R:%dus", result_us); + lcd.printStrY(1, buf); + wait(3); + + // コンパイル時の日付 + sprintf(buf, "%8s", __DATE__); + lcd.printStrYscr(1, buf); + wait(3); + + if (files < 0) + lcd.printStrY(1, "NO FILES"); + else + { + sprintf(buf, "%3dfiles", files); + lcd.printStrY(1, buf); + } + wait(3); + lcd.cls(); +} + +// ビットテスト + +void bit_test() +{ + char buf[9]; + lcd.printStrY(0, "BIT_TEST"); + + wait_key_up(); + + int pin = 0; + int mode = 0; + char sig; + + while(1) + { + // 表示 + if (mode & 1) + sig = 'C'; // コントロール + else + sig = 'D'; // データ + + if (mode & 2) + strcpy(buf,"00"); + else + sprintf(buf, "%c%d", sig, pin); + + lcd.printStrY(1, buf); + + // 出力 + if (mode & 2) + { + SHIFTOUT(0xff, 0x00); + } + else + { + int bit = (1 << pin); + if (mode & 1) + SHIFTOUT(0xff & ~(bit), 0); // コントロール + else + SHIFTOUT(0xff, bit); // データ + } + + // キー待ち + int key = wait_anykey(); + + // 再生 + if (key & SW_PLAY) + { + mode ^= 2; + continue; + } + // 次 + if (key & SW_NEXT) + { + pin++; + if (pin > 7) + { + pin = 0; + mode = (mode + 1) & 1; + } + } + // 前 + if (key & SW_PREV) + { + pin--; + if (pin < 0) + { + pin = 7; + mode = (mode - 1) & 1; + } + } + } +} + +// +// ファイル選択表示 +void disp_filesel(int mode) +{ + char buf[16]; + + char *mode_name; + switch(mode) + { + case MODE_GETLIST: + mode_name = "LIST SEL"; + break; + case MODE_GETDIR: + mode_name = "DIR SEL"; + break; + default: + mode_name = "FILE SEL"; + } + + strncpy(buf, g.file, 8); + buf[8] = 0; + + // 表示 + lcd.printStr2(buf, mode_name); +} + +// +// ファイル/ディレクトリ選択 +// mode = MODE_GETLIST | MODE_GETDIR | MODE_FILE +// +int file_select(int mode) +{ + // ファイル数を得る + int files = get_fileentry(-1, mode); + + // 最大エントリー + g.max_entries = files - 1; + + // ファイル名の取得 + get_fileentry(g.idx, mode); + + // 表示 + disp_filesel(mode); + + // リリース待ち + wait_relkey(); + + while(1) + { + // ファイル名の取得 + get_fileentry(g.idx, mode); + + // 表示 + disp_filesel(mode); + + // キー待ち + int key = wait_anykey(); + + // 次のエントリ + if (key & SW_NEXT) + { + if (g.idx < g.max_entries) + g.idx++; + else + g.idx = 0; + } + + // 前のエントリ + if (key & SW_PREV) + { + if (g.idx > 0) + g.idx--; + else + g.idx = g.max_entries; + } + // 再生ボタンを押した + if (key & SW_PLAY) + break; + } + + return g.idx; +} + +// get_playlist() +// index = リスト位置, -1でエントリ数を返す +int get_playlist(int index) +{ + int count = 0; + FILE *fp = fopen(g.playlist, "r"); + + g.file[0] = 0; + + // プレイリストが開けない + if (!fp) + return -1; + + while(1) + { + // プレイリストから一行読み込む + char *p = fgets(g.file, MAX_FILENAME, fp); + + // EOFなので終了 + if (!p) + break; + + // サイズ + int len = strlen(g.file); + + // CR/LFをトリムする + while(len > 0 && (unsigned char)g.file[len - 1] < 0x20) + { + g.file[len - 1] = 0x00; + len--; + } + + // 空行は飛ばす + if (!len) + continue; + + count++; + + // カウントモードかカウントがindex未満で継続 + if (index < 0 || count <= index) + continue; + else + break; + } + + // プレイリストを閉じる + fclose(fp); + +#if defined(__MICROLIB) && defined(__ARMCC_VERSION) + free(fp); +#endif + + return count; +} + + +// グローバル変数初期化 +void init_globe(void) +{ + memset(&g, 0, sizeof(g)); + strcpy(g.cwd,"/sd"); +} + +// パスの作成 +void make_path(char *path, const char *dir, const char *file) +{ + sprintf(path, "%s/%s", dir, file); +} + +// 再生モード +void play_mode(void) +{ + int files = -1; + + // プレイリストモードか否か + if (g.playlist[0]) + files = get_playlist(-1); + else + files = get_fileentry(-1, MODE_FILE); + + // エラー表示 + if (files < 0) + error_sdcard(); + + g.max_entries = files - 1; + + bool repeat_flag = false; + + // ファイルが無い + if (files < 1) + { + lcd.cls(); + lcd.printStrY(0, "NO FILES"); + wait(1); + } + + // 再生モードループ + while(1) + { + char path[MAX_PATH]; + char buf[16]; + + // プレイリストかどうか? + if (g.playlist[0]) + get_playlist(g.idx); + else + get_fileentry(g.idx, MODE_FILE); + + // フルパスを作成 + make_path(path, g.cwd, g.file); + + // 曲番号 + sprintf(buf, "%2d ", g.idx + 1); + + // ファイル名名表示 + lcd.cls(); + lcd.printStrY(0, g.file); + lcd.printStrY(1, buf); + + // 再生開始 + play_file(path); + + // ミュート + boardMute(); + + // キー開放待ち + wait_relkey(); + + + // 再生ボタンが押された + if (g.stop) + { + // ストップ表示 + lcd.printStrY(1, " STOP "); + + g.stop = false; + g.prev = false; + g.total_sec = 0; + + // ボード初期化 + boardInit(); + + // ファイル選択 + file_select(MODE_FILE); + continue; + } + + // 前の曲を再生 + if (g.prev) + { + g.prev = false; + + // 同じ曲を再生 + if (g.total_sec >= 2) + continue; + + if (g.idx > 0) + g.idx--; + else + g.idx = g.max_entries; + + continue; + } + + // 繰り返しではない + if (!repeat_flag) + { + if (g.idx < g.max_entries) + g.idx++; + else + g.idx = 0; + } + repeat_flag = false; + } +} + + + +// +// メニュー選択 +// +#define MENU_FILE 0 +#define MENU_DIR 1 +#define MENU_LIST 2 +#define MENU_INFO 3 +#define MENU_COM 4 +#define MENU_TEST 5 +#define MENU_SMODE 6 +#define MENU_MAX 6 + +// メニュー文字列 +const char *menu_modes[] = +{ + "FILE", // 0 + "DIR", // 1 + "LIST", // 2 + "INFO", // 3 + "COM", // 4 + "TEST", // 5 + "Sx16", // 6 +}; + +// メニュー選択表示 +void menu_disp(int sel) +{ + char buf[16]; + + // 表示 + lcd.printStrY(0, "MENU SEL"); + sprintf(buf, "%02d %-4s", sel, menu_modes[sel]); + lcd.printStrY(1, buf); +} + +// モード選択 +int menu_select() +{ + int count = 0; + + // 初期表示 + menu_disp(0); + + // リリース待ち + wait_key_up(); + + while(1) + { + // キー待ち + int key = wait_anykey(); + + // 次 + if (key & SW_NEXT) + { + if (count < MENU_MAX) + count++; + else + count = 0; + } + // 前 + if (key & SW_PREV) + { + if (count > 0) + count--; + else + count = MENU_MAX; + } + // 再生 + if (key & SW_PLAY) + break; + + // 表示 + menu_disp(count); + } + + return count; +} + +// メニューモード +void menu_mode(void) +{ + int files = 0; + char path[MAX_PATH]; + + menu_start: + + // ボードの初期化 + boardInit(); + + int sw = menu_select(); + switch(sw) + { + // ファイル選択 + case MENU_FILE: + file_select(MODE_FILE); + break; + // ディレクトリ選択 + case MENU_DIR: + file_select(MODE_GETDIR); + // パスを結合し、インデックスを初期化 + make_path(path, g.cwd, g.file); + strcpy(g.cwd, path); + g.idx = 0; + break; + // プレイリスト選択 + case MENU_LIST: + file_select(MODE_GETLIST); + break; + // 情報モード + case MENU_INFO: + files = get_fileentry(-1, MODE_FILE); + show_info(files); + goto menu_start; + // 通信モード + case MENU_COM: + loop_for_com(); + break; + // テストモード + case MENU_TEST: + bit_test(); + break; + // ストレートモード + case MENU_SMODE: + g.one_mode = true; + lcd.printStr2("","Sx16 ON"); + wait(0.5); + goto menu_start; + } +} + +// +// main +// +int main() +{ + // 初期化 + init_globe(); + + // I/O初期化 + ioInit(); + + // 立ち上がり待ち + wait_ms(20); + + // シフトレジスタの初期化 + SHIFTOUT(0xFF, 0xFF); + + // LCD初期化 + lcd.init(); + + // タイトル表示 + int key = putTitle(); + + // NEXTボタンでメニュー表示 + if (key & SW_NEXT) + menu_mode(); + + // 再生モード + play_mode(); +}