Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: SDFileSystemEx mbed
Revision 0:722cc5360dc3, committed 2016-02-08
- Comitter:
- bkc_mbed
- Date:
- Mon Feb 08 05:49:26 2016 +0000
- Child:
- 1:29f0e76a9999
- Commit message:
- ver 1.22
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystemEx.lib Mon Feb 08 05:49:26 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/bkc_mbed/code/SDFileSystemEx/#3701e9942a16
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lcd.cpp Mon Feb 08 05:49:26 2016 +0000
@@ -0,0 +1,148 @@
+/*
+ * lcd.cpp : AQM0802A mini library
+ *
+ * Based on LCD module "AQM0802A-RN-GBW" sample program
+ * Copyright (c) 2013 Yoshihiro TSUBOI
+ *
+ * Original Arduino version was developed by
+ * Copyright (c) 2013 Masahiro WAKAYAMA at SWITCH SCIENCE
+ *
+ * Released under the MIT License: http://mbed.org/license/mit
+ *
+ */
+
+#include "mbed.h"
+
+#include "lcd.h"
+#include "pindef.h"
+
+LCD::LCD()
+{
+ i2c = new I2C(DP_SDA, DP_SCL); // sda, scl
+}
+
+#define LCD_ADDR 0x7C
+
+void LCD::cmd(char x)
+{
+ char data[2];
+ data[0] = 0x00; // CO = 0,RS = 0
+ data[1] = x;
+ i2c->write(LCD_ADDR, data, 2);
+}
+
+void LCD::contdata(char x)
+{
+ char data[2];
+ data[0] = 0xC0; //0b11000000 CO = 1, RS = 1
+ data[1] = x;
+ i2c->write(LCD_ADDR, data, 2);
+}
+
+void LCD::lastdata(char x)
+{
+ char data[2];
+ data[0] = 0x40; //0b11000000 CO = 0, RS = 1
+ data[1] = x;
+ i2c->write(LCD_ADDR, data, 2);
+}
+
+
+void LCD::setContrast(unsigned char c) {
+ cmd(0x39);
+ cmd(0x70 | (c & 0x0f)); // contrast Low
+ cmd(0x5C | ((c >> 4) & 0x03)); // contast High/icon/power
+ cmd(0x38);
+}
+
+void LCD::init() {
+ int cont = 0;
+ wait(0.04);
+ // LCD initialize
+ cmd(0x38); // function set
+ cmd(0x39); // function set
+ cmd(0x04); // EntryModeSet
+ cmd(0x14); // interval osc
+ cmd(0x70 | (cont & 0xF)); // contrast Low
+ cmd(0x5C | ((cont >> 4) & 0x3)); // contast High/icon/power
+ cmd(0x6C); // follower control
+ wait(0.2);
+ cmd(0x38); // function set
+ cmd(0x0C); // Display On
+ cmd(0x01); // Clear Display
+ wait(0.2); // need additional wait to Clear Display
+
+ setContrast(36);
+}
+
+
+// 文字と空白で1行を埋める
+void LCD::printStrFill(const char *s)
+{
+ int idx = 0;
+ for(idx = 0; idx < 8; idx++)
+ {
+ if(idx < 7) {
+ contdata(*s);
+ } else {
+ lastdata(*s);
+ }
+ if (*s) s++;
+ }
+}
+
+void LCD::printStr(const char *s)
+{
+ int idx = 0;
+ while(*s && idx < 8) {
+ if(*(s + 1)) {
+ contdata(*s);
+ } else {
+ lastdata(*s);
+ }
+ s++;
+ idx++;
+ }
+}
+
+void LCD::setCursor(unsigned char x,unsigned char y)
+{
+ cmd(0x80 | (y * 0x40 + x));
+}
+
+void LCD::printStrY(int y,const char *s)
+{
+ setCursor(0, y);
+ printStrFill(s);
+}
+
+void LCD::printStrYscr(int y,const char *s)
+{
+ int cnt = strlen(s) - 7;
+ if (cnt <= 0)
+ cnt = 1;
+
+ for(int i = 0; i < cnt; i++)
+ {
+ setCursor(0, y);
+ printStr(s + i);
+ wait(0.5);
+ }
+}
+
+
+void LCD::printStr2(const char *s, const char *s2)
+{
+ setCursor(0,0);
+ printStrFill(s);
+ setCursor(0,1);
+ printStrFill(s2);
+}
+
+void LCD::cls(void)
+{
+ setCursor(0, 0);
+ printStrFill("");
+ setCursor(0, 1);
+ printStrFill("");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lcd.h Mon Feb 08 05:49:26 2016 +0000
@@ -0,0 +1,27 @@
+#ifndef __LCD_H__
+#define __LCD_H__
+
+#include "mbed.h"
+
+class LCD {
+public:
+ LCD();
+
+ void printStr(const char *s);
+ void setContrast(unsigned char c);
+ void setCursor(unsigned char x,unsigned char y);
+ void cls(void);
+ void init(void);
+ void printStr2(const char *s, const char *s2);
+ void printStrY(int y,const char *s);
+ void printStrYscr(int y,const char *s);
+
+protected:
+ void cmd(char x);
+ void contdata(char x);
+ void lastdata(char x);
+ void printStrFill(const char *s);
+ I2C *i2c;
+};
+
+#endif
--- /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();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Feb 08 05:49:26 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/6473597d706e \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nlg_mini.cpp Mon Feb 08 05:49:26 2016 +0000
@@ -0,0 +1,149 @@
+
+//
+// nlg_mini.cpp
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nlg_mini.h"
+
+/* 単位を扱いやすいように */
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long dword;
+
+// 変数読み出し(WORD)
+word ReadWORD(byte *p)
+{
+ return
+ ((word)p[0]) |
+ ((word)p[1])<<8;
+}
+
+// 変数読み出し(DWORD)
+dword ReadDWORD(byte *p)
+{
+ return
+ ((dword)p[0]) |
+ ((dword)p[1])<<8 |
+ ((dword)p[2])<<16 |
+ ((dword)p[3])<<24;
+}
+
+// NLGファイルを開く
+int OpenNLG(NLG_CTX *np, const char *filename)
+{
+ byte hdr[0x60];
+
+ np->fp = fopen(filename, "rb");
+
+ // ファイルが開けない
+ if (!np->fp)
+ return NLG_FILEERR;
+
+ // ヘッダ部分の読み込み
+ fread(hdr, 0x60, 1, np->fp);
+
+ // IDの確認
+ if (memcmp(hdr, "NLG1", 4) != 0)
+ {
+ CloseNLG(np);
+ return NLG_UNK_FORMAT;
+ }
+
+ // バージョン
+ np->version = ReadWORD(hdr + 4);
+
+ // クロック
+ np->baseclk = ReadDWORD(hdr + 72);
+
+ // ティック
+ np->tick = ReadDWORD(hdr + 76);
+ np->tick_us = np->tick / 4;
+
+ // 長さ
+ np->length = ReadDWORD(hdr + 88);
+
+ // 位置
+ fseek(np->fp, 0x60, SEEK_SET);
+
+ // CTC初期化
+ np->ctc0 = np->ctc3 = 0;
+
+ return NLG_OK;
+}
+
+// ファイルを閉じる
+void CloseNLG(NLG_CTX *np)
+{
+ if (!np->fp)
+ return;
+
+ fclose(np->fp);
+
+#if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler
+ free(np->fp);
+#endif
+
+ np->fp = NULL;
+}
+
+// データの読み出し
+int ReadNLG(NLG_CTX *np)
+{
+ return fgetc(np->fp);
+}
+
+// ファイルポインタの位置を取得
+long TellNLG(NLG_CTX *np)
+{
+ return ftell(np->fp);
+}
+
+// ファイルポインタの位置を設定
+void SeekNLG(NLG_CTX *np, long pos)
+{
+ fseek(np->fp, pos, SEEK_SET);
+}
+
+// ティック(us)の取得
+int GetTickUsNLG(NLG_CTX *np)
+{
+ return np->tick_us;
+}
+
+// Set Tick
+// (CTC0 * 64us) * CTC3
+static inline void SetTickNLG(NLG_CTX *np)
+{
+ np->tick = ((np->ctc0 * 256) * np->ctc3);
+ np->tick_us = np->tick / 4;
+}
+
+// CTC0値の設定
+void SetCTC0_NLG(NLG_CTX *np, int value)
+{
+ np->ctc0 = value;
+ SetTickNLG(np);
+}
+
+// CTC3値の設定
+void SetCTC3_NLG(NLG_CTX *np, int value)
+{
+ np->ctc3 = value;
+ SetTickNLG(np);
+}
+
+// 曲の長さを得る
+int GetLengthNLG(NLG_CTX *np)
+{
+ return np->length;
+}
+
+// ベースクロックを得る
+int GetBaseClkNLG(NLG_CTX *np)
+{
+ return np->baseclk;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nlg_mini.h Mon Feb 08 05:49:26 2016 +0000
@@ -0,0 +1,57 @@
+//
+// nlg_mini.h
+//
+
+#ifndef __NLG_MINI_H__
+#define __NLG_MINI_H__
+
+#define CMD_PSG 0x00
+#define CMD_OPM 0x01
+#define CMD_OPM2 0x02
+#define CMD_FM1 0x01
+#define CMD_FM2 0x02
+
+
+#define CMD_IRQ 0x80
+
+#define CMD_CTC0 0x81
+#define CMD_CTC3 0x82
+
+#define NLG_VER (110)
+#define NLG_BASECLK (4000000)
+
+#define NLG_OK (0)
+#define NLG_FILEERR (-1)
+#define NLG_UNK_FORMAT (-2)
+
+
+/* NLGを処理するための構造体 */
+typedef struct
+{
+ FILE *fp;
+
+ int version;
+
+ int baseclk;
+ int tick;
+ int tick_us;
+
+ int length;
+
+ int ctc0;
+ int ctc3;
+
+} NLG_CTX;
+
+int OpenNLG(NLG_CTX *np, const char *filename);
+void CloseNLG(NLG_CTX *np);
+int ReadNLG(NLG_CTX *np);
+long TellNLG(NLG_CTX *np);
+void SeekNLG(NLG_CTX *np, long pos);
+int GetTickUsNLG(NLG_CTX *np);
+void SetCTC0_NLG(NLG_CTX *np, int value);
+void SetCTC3_NLG(NLG_CTX *np, int value);
+int GetLengthNLG(NLG_CTX *np);
+int GetBaseClkNLG(NLG_CTX *np);
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pindef.h Mon Feb 08 05:49:26 2016 +0000 @@ -0,0 +1,68 @@ +#ifndef __PINDEF_H__ +#define __PINDEF_H__ + +#ifdef TARGET_LPC1114 + +// NBCTRLV1 / AYC01 + +// BUTTON +#define DP_PLAY dp24 +#define DP_NEXT dp10 +#define DP_PREV dp9 + +// SPI +#define DP_MOSI dp2 +#define DP_MISO dp1 +#define DP_SCLK dp6 +#define DP_SCS dp25 + +// IO +#define DP_IO01 dp13 // P1_4 +#define DP_IO02 dp26 // P0_3 +#define DP_IO03 dp17 // P1_8 +#define DP_IO04 dp4 // P0_11 +#define DP_IO05 dp18 // P1_9 +#define DP_IO06 dp11 // P1_2 + +// I2C +#define DP_SDA dp5 +#define DP_SCL dp27 + +// SERIAL +#define DP_TX USBTX +#define DP_RX USBRX + +#else + +//// TG-LPC11U35 + +// BUTTON +#define DP_PLAY p20 +#define DP_NEXT p19 +#define DP_PREV p18 + +// SPI +#define DP_MOSI p5 +#define DP_MISO p6 +#define DP_SCLK p7 +#define DP_SCS p8 + +// IO +#define DP_IO01 p21 +#define DP_IO02 p23 +#define DP_IO03 p24 +#define DP_IO04 p25 +#define DP_IO05 p26 +#define DP_IO06 p30 + +// I2C +#define DP_SDA p28 +#define DP_SCL p27 + +// SERIAL +#define DP_TX p9 +#define DP_RX p10 + +#endif + +#endif \ No newline at end of file