Music Player for ARCH-PRO

Dependencies:   GT20L16J1Y_font TinyJpgDec mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GSDPlayer.cpp Source File

GSDPlayer.cpp

00001 // --------------------------------------------------------
00002 //  GSDPlayer (c) CopYright 2013-2014 Goji.   goji2100.com
00003 // --------------------------------------------------------
00004 
00005 #include "mbed.h"
00006 #include "mainconf.h"
00007 
00008 #include "SDFileSystem.h"
00009 #include "TinyJpgDec.h"
00010 
00011 #include "mGTFT.h"
00012 #include "mGTP.h"
00013 #include "GT20L16J1Y_font.h"
00014 
00015 
00016 /* SDFileSystem.cpp change
00017  -----------------------------------------------------------------------
00018 144:    _spi.frequency(16000000);
00019 210:    _spi.frequency(24000000); // Set to 1MHz for data transfer
00020 */
00021 
00022 
00023 //#define Level_Indicator 4000  // for Level Indicator
00024 //#define Test                  // for Simple Player
00025 
00026 #define FILESYS "sd"
00027 #if defined(_ARCH_PRO)
00028   SDFileSystem sd(P0_9,  P0_8,  P0_7,  P0_6,  FILESYS); // Arch Pro SPI1SD
00029   #define BUFF_SIZE (512 * 4)               // WAV file buffer size
00030   #define LLow    1
00031   #define LHigh   0
00032   PwmOut  Line_R(P2_0), Line_L(P2_1);       // PWM_1, PWM_2
00033   BusOut  TFTBus(D8, D9, D2, D3, D4, D5, D6, D7);
00034 #else
00035 #endif
00036 
00037 Serial pc(USBTX, USBRX);
00038 DigitalOut statLED1(LED1), statLED2(LED2), statLED3(LED3), statLED4(LED4);
00039 
00040 #define PWM_CLKMHZ  24  // 24MHz
00041 Ticker Tick_Timer;
00042 
00043 volatile uint16_t ps_stat = 0;      // Player status
00044 uint16_t tp_stat = 0, tp_statN = 0;
00045 #define PS_PLAY     BIT1(15)
00046 #define PS_PAUSE    BIT1(14)
00047 #define PS_FFR      BIT1(13)
00048 #define PS_FFF      BIT1(12)
00049 #define PS_SEEK     BIT1(11)
00050 #define PS_FR       BIT1(10)
00051 #define PS_FF       BIT1( 9)
00052 #define PS_VDOWN    BIT1( 8)
00053 #define PS_VUP      BIT1( 7)
00054 #define PS_EOR      BIT1( 6)   // End of Root
00055 #define PS_EOD      BIT1( 5)   // End of DIR
00056 #define PS_EOF      BIT1( 4)   // Eod of File
00057 
00058 #define SWBuff()    { if (buffNX==0) { buffNW=0,buffNX=1; } else { buffNW=1,buffNX=0; } buffLN[buffNX]=buffGP=0; }
00059 volatile int32_t buffNW, buffNX, buffLN[2], buffGP;
00060 unsigned char Wave_buff[2][BUFF_SIZE];
00061 #define _WS16(n,v)  *(short*         )&Wave_buff[n][v]
00062 #define _WU16(n,v)  *(unsigned short*)&Wave_buff[n][v]
00063 #define _WU32(n,v)  *(unsigned long* )&Wave_buff[n][v]
00064 uint8_t  Wave_CHs, Wave_Bits;
00065 uint32_t Wave_BPS, Wave_Size, Wave_Rlen, Wave_Play, Wave_FPos;
00066 uint16_t Wave_Prid;
00067 
00068 volatile uint16_t Pwm_Ratio, Line_Vols = 16, Line_Vol = 160;
00069 
00070 #if defined(Level_Indicator)
00071 volatile uint32_t Pwm_cnt = 0;
00072 volatile uint16_t Pwm_aveL = 0, Pwm_aveR = 0;
00073 #endif
00074 
00075 void PwmLR_Out16(int16_t lv, int16_t rv)
00076 {
00077     int16_t lw = ((lv + 32768) / Pwm_Ratio);
00078     int16_t rw = ((rv + 32768) / Pwm_Ratio);
00079 //  if (lw >= LPC_PWM1->MR0) lw = LPC_PWM1->MR0;
00080 //  if (rw >= LPC_PWM1->MR0) rw = LPC_PWM1->MR0;
00081   #if defined(_ARCH_PRO)
00082     LPC_PWM1->MR1 = lw;
00083     LPC_PWM1->MR2 = rw;
00084     if (Line_Vols)
00085         LPC_PWM1->LER |= ((1 << 1) | (1 << 2));
00086   #else
00087     LPC_PWM1->MR6 = lw;
00088     LPC_PWM1->MR5 = rw;
00089     if (Line_Vols)
00090         LPC_PWM1->LER |= ((1 << 6) | (1 << 5));
00091   #endif
00092   #if defined(Level_Indicator)
00093     Pwm_cnt++;
00094     Pwm_aveL = (Pwm_aveL + ((uint16_t)(lv) + 32768) >> 8) / 2;
00095     Pwm_aveR = (Pwm_aveR + ((uint16_t)(rv) + 32768) >> 8) / 2;
00096   #endif
00097 }
00098 
00099 
00100 void ISR_Tick(void)
00101 {
00102     if (!(ps_stat & PS_PAUSE) && (buffGP < buffLN[buffNW])) {
00103         statLED2 = LHigh;
00104         PwmLR_Out16(_WS16(buffNW, buffGP), _WS16(buffNW, buffGP + 2));
00105         buffGP += 4;
00106         if ((buffGP >= buffLN[buffNW]) && (buffNX != -1)) SWBuff();
00107         statLED2 = LLow;
00108     }
00109 }
00110 
00111 
00112 extern TFT_INFO TFT_info;
00113 int32_t Last_Err;
00114 
00115 GT20L16J1Y_FONT font(p11, p12, p13, P0_16);
00116 void draw_kanji(int x1, int y1, uint16_t c1, uint16_t c2)
00117 {
00118     for (int x = 0; x < 32; x++)
00119         for (int y = 0, m = 0x01; y < 8; y++, m <<= 1)
00120             TFT_setPixel(x1 + x%16,  y1 + y + (8 * (x >> 4)), ((font.bitmap[x] & m) ? c1 : c2));
00121 }
00122 
00123 
00124 uint16_t bmpXsize, bmpYsize;
00125 
00126 void BMP24Bits(int16_t x1, int16_t y1, char *fn)
00127 {
00128     uint8_t rbuff[64];
00129 
00130     FILE *fp = fopen(fn, "rb");
00131     if (!fp) {
00132         pc.printf("open error\n");
00133         return;
00134     }
00135 
00136     fread(rbuff, 1, (14 + 40), fp);
00137     bmpXsize = *(uint16_t*)&rbuff[18];
00138     bmpYsize = *(uint16_t*)&rbuff[22];
00139 
00140     if ((bmpXsize > TFT_MAX_X) ||
00141         (bmpYsize > TFT_MAX_Y) ||
00142         (rbuff[28] != 24)) {
00143         pc.printf("format error\n");
00144         return;
00145     }
00146 
00147     int dummy = (bmpXsize * 3) % 4;
00148     for (int z = 0, y = y1; z < bmpYsize; z++, y--) {
00149         TFT_setXY(x1, y);
00150         for (int i = 0; i < bmpXsize; i++) {
00151             fread(rbuff, 1, 3, fp);
00152             TFT_wr_data((uint16_t)(
00153                 ((rbuff[2] & 0xF8) << 8) |      // R
00154                 ((rbuff[1] & 0xFC) << 3) |      // G
00155                 ((rbuff[0]       ) >> 3) ));    // B
00156         }
00157         if (dummy) fread(rbuff, 1, dummy, fp);
00158     }
00159     fclose(fp);
00160 }
00161 
00162 
00163 FILE *jfp;
00164 UINT jpeg_input(JDEC *jd, BYTE *buff, UINT ndata)
00165 {
00166     if (buff) {
00167         int n = fread(buff, 1, ndata, jfp);
00168         return(n == -1 ? 0 : n);
00169     }
00170     return(fseek(jfp, ndata, SEEK_CUR) == -1 ? 0 : ndata);
00171 }
00172 
00173 int16_t Cover_tlx, Cover_tly;
00174 
00175 UINT jpeg_output(JDEC *jd, void *bitmap, JRECT *rect)
00176 {
00177     WORD *src = (WORD *)bitmap;
00178 
00179     int x0 = rect->left;
00180     int x1 = rect->right;
00181     int y0 = rect->top;
00182     int y1 = rect->bottom;
00183     int w = x1 - x0 + 1;
00184 
00185     if (x0 >= TFT_MAX_X || y0 >= TFT_MAX_Y) return 1;
00186     if (x1 >= TFT_MAX_X) x1 = TFT_MAX_X - 1;
00187     if (y1 >= TFT_MAX_Y) y1 = TFT_MAX_Y - 1;
00188 
00189     for (int y = y0; y <= y1; y++) {
00190         TFT_setXY(Cover_tlx + x0, Cover_tly + y);
00191         WORD *p = src + w * (y - y0);
00192         for (int x = x0; x <= x1; x++)
00193             TFT_wr_data(*p++);
00194     }
00195     return 1;
00196 }
00197 
00198 
00199 #define MM_TLX      0
00200 #define MM_TLY      (TFT_MAX_Y - bmpYsize)
00201 #define MM_YH       bmpYsize
00202 
00203 #define MM_FR       80
00204 #define MM_PLAY     (MM_FR   + 50)
00205 #define MM_FF       (MM_PLAY + 54)
00206 #define MM_FFE      (MM_FF   + 50)
00207 #define MM_VUPD     (TFT_MAX_X - 58)
00208 
00209 #define MM_VUP      (TFT_MAX_Y - bmpYsize)
00210 #define MM_VDWN     (TFT_MAX_Y - (bmpYsize / 2))
00211 
00212 uint16_t tp_menu()
00213 {
00214     int16_t wposX, wposY;
00215 
00216     if (TPC_getXY(&wposX, &wposY) == 2) {
00217         if (wposY < MM_TLY) return(PS_SEEK);
00218         if (wposX < MM_FR ) return(0);
00219         if      (wposX < MM_PLAY) return(PS_FFR);
00220         else if (wposX < MM_FF  ) return(PS_PAUSE);
00221         else if (wposX < MM_FFE ) return(PS_FFF);
00222         else if (wposY < MM_VDWN) return(PS_VUP);
00223         else if (wposY > MM_VDWN) return(PS_VDOWN);
00224     }
00225     return(0);
00226 }
00227 
00228 //#define SEEK_Dump() 
00229 #define SEEK_Dump() pc.printf("%d - (%8d - %d = %8d) = %8d(%8d)\n", Wave_Size,Wave_FPos,Wave_Play,Wave_FPos-Wave_Play,Wave_Rlen,Wave_Rlen-(Wave_Size-(Wave_FPos-Wave_Play)))
00230 
00231 uint16_t event_chk()
00232 {
00233     static uint16_t stepS  = 0, timep, barp, bcp;
00234     static int16_t  tp_cnt = 0;
00235 
00236     int16_t px, py;
00237     uint16_t statN = 0, tw, barl, bc;
00238     char times[8];
00239 
00240     while (1) {
00241         switch (stepS) {
00242             case  0:
00243             case 50:
00244                 tw = (Wave_FPos - Wave_Play) / (Wave_BPS * 4);   // (Wave_FPos * 8) / (Wave_BPS * 16 * 4)
00245                 if (tw != timep) {
00246                     timep = tw;
00247                     sprintf(times, "%02d:%02d", (timep / 60), (timep % 60));
00248                     TFT_drawText( 28, (TFT_MAX_Y - 1) - 6 - (bmpYsize / 2), (uint8_t*)times, WHITE, BLACK);
00249                     barp = 0;
00250                 }
00251                 stepS += 10;
00252                 break;
00253 
00254             case 10:
00255             case 60:
00256                 barl = (((Wave_FPos - Wave_Play) / 1000) * TFT_MAX_X) / (Wave_Size / 1000);
00257                 bc = (ps_stat & PS_PAUSE) ? YELLOW : BLUE;
00258                 if ((stepS >= 50) || (barp != barl) || (bcp != bc)) {
00259                     TFT_fillRectangle(  0, (TFT_MAX_Y - 1) - bmpYsize - 2, barl, (TFT_MAX_Y - 1) - bmpYsize, bc, bc);
00260                     if (barl < (TFT_MAX_X - 1))
00261                         TFT_fillRectangle(barl, (TFT_MAX_Y - 1) - bmpYsize - 2, (TFT_MAX_X - 1), (TFT_MAX_Y - 1) - bmpYsize, BLACK, BLACK);
00262                     barp = barl;
00263                     bcp = bc;
00264                 }
00265                 if (stepS > 50) stepS += 10;
00266                 else stepS = 20;
00267                 break;
00268 
00269             case 70:
00270                 if (TPC_getXY(&px, &py) == 2) {
00271                     if (px < ((320 * 1) / 10)) px = ((320 * 1) / 10);
00272                     if (px > ((320 * 9) / 10)) px = ((320 * 9) / 10);
00273                     if (px < ((320 * 1) / 7)) {
00274                         if (Wave_FPos < (Wave_BPS * 2 * 2 * 2)) {
00275                             SEEK_Dump();
00276                             statN = PS_FFR;
00277                             tp_cnt = 0;
00278                             stepS = 0;
00279                             break;
00280                         }
00281                         Wave_FPos = Wave_Play;
00282                         Wave_Rlen = Wave_Size;
00283                     } else if (px >= ((320 * 9) / 10)) {
00284                         Wave_FPos = Wave_Play + Wave_Size;
00285                         Wave_Rlen = 0;
00286                     } else {
00287                         uint64_t pr = (px - ((320 * 1) / 10)) * 1000 / (((320 * 8) / 10));
00288                         Wave_FPos = ((Wave_Size * pr) / 1000);
00289                         if (Wave_FPos > (Wave_Play + Wave_Size)) Wave_FPos = Wave_Size + Wave_Play;
00290                         if (Wave_FPos < Wave_Play) Wave_FPos = Wave_Play;
00291                         Wave_Rlen = Wave_Size - (Wave_FPos - Wave_Play);
00292                     }
00293                 } else {
00294                     tp_cnt++;
00295                     if (tp_cnt > 100) {
00296                         if (Wave_FPos < Wave_Size + Wave_Play) {
00297                             Wave_FPos &= (uint64_t)-BUFF_SIZE;
00298                             if (Wave_FPos < Wave_Play) Wave_FPos = Wave_Play;
00299                             Wave_Rlen = Wave_Size - (Wave_FPos - Wave_Play);
00300                         }
00301                         SEEK_Dump();
00302                         statN = PS_SEEK;
00303                         tp_cnt = 0;
00304                         stepS = 0;
00305                         break;
00306                     }
00307                 }
00308                 stepS = 50;
00309                 break;
00310 
00311             case 20:
00312                 if (tp_stat != 0) {
00313                     stepS = 22;
00314                     break;
00315                 }
00316                 tp_stat = tp_menu();
00317                 tp_cnt = 0;
00318                 if (tp_stat & PS_SEEK) {
00319                     ps_stat |= PS_PAUSE;
00320                     stepS = 50;
00321                     SEEK_Dump();
00322                     break;
00323                 }
00324                 if (tp_stat == 0) stepS = 0;
00325                 else stepS = 22;
00326                 break;
00327 
00328             case 22:
00329                 tp_statN = tp_menu();
00330                 if (tp_statN == 0) {
00331                     tp_cnt = 0;
00332                     tp_stat = 0;
00333                     stepS = 0;
00334                     break;
00335                 }
00336                 if (tp_stat == tp_statN) {
00337                     if (tp_cnt != -1) tp_cnt++;
00338                     stepS = 24;
00339                     break;
00340                 }
00341                 tp_cnt = 0;
00342                 tp_stat = tp_statN;
00343                 stepS = 22;
00344                 break;
00345 
00346             case 24:
00347                 if (tp_cnt > 1) {
00348                     if (tp_stat & PS_VUP) {
00349                         if (tp_cnt == 3) statN = tp_stat;
00350                         if (tp_cnt >= 5) tp_cnt = 0;
00351                     } else if (tp_stat & PS_VDOWN) {
00352                         if (tp_cnt == 2) statN = tp_stat;
00353                         if (tp_cnt >= 3) tp_cnt = 0;
00354                     } else {
00355                         statN = tp_stat;
00356                         tp_cnt = -1;
00357                     }
00358                 }
00359                 stepS = 0;
00360                 break;
00361 
00362             default:
00363                 stepS = 0;
00364                 break;
00365         }
00366         if (stepS < 50) break;
00367     }
00368     return(statN);
00369 }
00370 
00371 
00372 void poll()
00373 {
00374     uint16_t statN;
00375     char stext[8];
00376 
00377     if ((statN = event_chk()) == 0) return;
00378     if (statN & PS_PAUSE) { ps_stat ^= PS_PAUSE; return; }
00379     if (statN & (PS_FFR | PS_FFF | PS_SEEK)) { ps_stat |= statN; return; }
00380     if (statN & (PS_VUP | PS_VDOWN)) {
00381         if (statN & PS_VUP) {
00382             if (Line_Vols < 32) { Line_Vol -= (Line_Vols >= 16 ? 10 : 40); Line_Vols++; }
00383         } else {
00384             if (Line_Vols >  0) { Line_Vol += (Line_Vols >  16 ? 10 : 40); Line_Vols--; }
00385         }
00386         sprintf(stext, "%2d", Line_Vols);
00387         TFT_drawText((TFT_MAX_X - 76), (TFT_MAX_Y - 1) - 6 - (bmpYsize / 2), (uint8_t*)stext, WHITE, BLACK);
00388         Pwm_Ratio = ((65536 / PWM_CLKMHZ) / Wave_Prid) + Line_Vol;
00389     }
00390     return;
00391 }
00392 
00393 
00394 DIR  *dp;
00395 FILE *fp;
00396 struct dirent *p;
00397 
00398 int Open_Wave(char *path)
00399 {
00400     fp = fopen(path, "rb");
00401     if (fp == NULL)  return (Last_Err = -3);    // can't open
00402 
00403     buffLN[0] = fread(Wave_buff[0], 1, BUFF_SIZE, fp);
00404     if (buffLN[0] < 46) return (Last_Err = -4); // invalid file
00405 
00406     // "RIFF", (long)File size, "WAVE"
00407     if ((_WU32(0, 0) != 0x46464952) ||
00408         (_WU32(0, 8) != 0x45564157))
00409         return (Last_Err = -5);  // invalid file
00410 
00411     buffGP = 12;
00412     while (buffGP < BUFF_SIZE) {
00413         unsigned long tagn = _WU32(0, buffGP);
00414         unsigned long tagl = _WU32(0, buffGP + 4);
00415         buffGP += 8;
00416 
00417         if (tagn == 0x20746D66) {   // "fmt "
00418             Wave_CHs  = _WU16(0, buffGP + 2);
00419             Wave_BPS  = _WU32(0, buffGP + 4);
00420             Wave_Bits = _WU32(0, buffGP +14);
00421             Wave_Prid = 2000000 / Wave_BPS;
00422             if (Wave_Prid & 1) Wave_Prid++;
00423             Wave_Prid >>= 1;
00424         }
00425 
00426         // "fact" 0x74636166)
00427         // "LIST" 0x74636166)
00428         if (tagn != 0x61746164) {   // !"data"
00429             buffGP += tagl;
00430             continue;
00431         }
00432 
00433         if ((Wave_BPS == 24000) ||
00434             (Wave_BPS == 32000) ||
00435             (Wave_BPS == 44100) ||
00436             (Wave_BPS == 48000)) {
00437             Wave_Size = tagl;
00438             return 0;
00439         }
00440         break;
00441     }
00442     return (Last_Err = -6);  // invalid file
00443 }
00444 
00445 
00446 int music_nw, music_nx;
00447 
00448 int Play_Wave()
00449 {
00450     int32_t getln;
00451 
00452     if (((buffNX != -1) && (buffLN[buffNX] == 0)) ||(ps_stat & (PS_SEEK | PS_FFR))) {
00453         statLED1 = LHigh;
00454         if (ps_stat & (PS_SEEK | PS_FFR)) {
00455             if (fseek(fp, Wave_FPos, SEEK_SET) == -1) {
00456                 ps_stat |= PS_EOF;
00457                 buffNX = -1;
00458                 return (Last_Err = -7); // read error
00459             }
00460             Wave_Rlen = Wave_Size - (Wave_FPos - Wave_Play);
00461             ps_stat &= ~PS_FFR;
00462         }
00463 
00464         if (Wave_FPos <= Wave_Play)
00465             getln = ((BUFF_SIZE - Wave_Play) > Wave_Rlen) ? Wave_Rlen : (BUFF_SIZE - Wave_Play);
00466         else
00467             getln = (Wave_Rlen > BUFF_SIZE) ? BUFF_SIZE : Wave_Rlen;
00468         if (getln && (buffNX != -1)) {
00469             if (fread(Wave_buff[buffNX], 1, getln, fp) != getln) {
00470                 ps_stat |= PS_EOF;
00471                 buffNX = -1;
00472                 return (Last_Err = -7); // read error
00473             }
00474             buffLN[buffNX] = getln & -4;
00475             Wave_FPos += getln;
00476             if (Wave_Rlen > getln) Wave_Rlen -= getln; else Wave_Rlen = 0;
00477 
00478             if (ps_stat & PS_SEEK) {
00479                 buffLN[buffNW] = buffLN[buffNX];
00480                 SWBuff();
00481                 ps_stat &= ~(PS_SEEK | PS_PAUSE);
00482             }
00483         }
00484         statLED1 = LLow;
00485 
00486         if (Wave_Rlen == 0) {
00487             buffNX = -1;
00488             ps_stat |= PS_EOF;
00489             wait_ms(50);
00490             return(0);
00491         }
00492         return getln;
00493     }
00494 
00495     if (ps_stat & PS_PAUSE) return(1);
00496     return 0;
00497 }
00498 
00499 
00500 #if defined(Test)
00501 int main()
00502 {
00503     if (Open_Wave("/" FILESYS "/music/01.wav")) error("open error\n");
00504 
00505     Pwm_Ratio = ((65535 / PWM_CLKMHZ) / Wave_Prid) + Line_Vol;
00506     buffNW = 0, buffNX = 1;
00507     buffLN[buffNX] = 0;
00508 
00509     Line_R.period_us(Wave_Prid);
00510     Line_L.period_us(Wave_Prid);
00511     Tick_Timer.attach_us(&ISR_Tick, Wave_Prid);
00512 
00513     pc.printf("start\n");
00514     while (1) {
00515         if (buffLN[buffNX] == 0) {
00516             if (fread(Wave_buff[buffNX], 1, BUFF_SIZE, fp) != BUFF_SIZE) break;
00517             if (Wave_Size >= BUFF_SIZE) Wave_Size -= BUFF_SIZE; else break;
00518             buffLN[buffNX] = BUFF_SIZE;
00519         }
00520     }
00521     Tick_Timer.detach();
00522     fclose(fp);
00523     pc.printf("stop\n");
00524 }
00525 
00526 #else
00527 
00528 int main()
00529 {
00530     char path[256], msc_file[256], stext[20];
00531 
00532     pc.baud(115200);
00533     TFT_init();
00534     TPC_Init();
00535     TFT_clearScreen(GRAY);
00536 
00537     while (1) {
00538 
00539         // Open Music Directory
00540         // ---------------------
00541         if (sd.disk_initialize()) return -1;
00542 
00543         BMP24Bits(0, (TFT_MAX_Y - 1), "/" FILESYS "/images/Play.bmp");
00544         dp = 0, music_nw = 1, music_nx = 1;
00545 
00546         while (1) {
00547 
00548             // Get Music file(.wav)
00549             // ---------------------
00550             {
00551                 int i;
00552 
00553                 if (music_nw >= music_nx) {
00554                     if (dp) closedir(dp);
00555                     dp = opendir("/" FILESYS "/music");
00556                     if (dp == NULL) {
00557                         pc.printf("\n" "/" FILESYS "/music/ open error.\n");
00558                         return 0;
00559                     }
00560                     music_nw = 0;
00561                 }
00562 
00563                 if ((p = readdir(dp)) == NULL) break;
00564                 for (i = 0; p->d_name[i]; i++)
00565                     msc_file[i] = p->d_name[i];
00566                 msc_file[i] = '\0';
00567 
00568                 if (msc_file[i - 4] == '.') msc_file[i - 4] = '\0';
00569                 if (strcmp(p->d_name + (i - 3), "wav") != 0) {
00570                     pc.printf("Skip - music/%s\n", p->d_name);
00571                     continue;
00572                 }
00573 
00574                 if (++music_nw < music_nx) continue;
00575                 music_nx++;
00576             }
00577 
00578             // View Navigate(Play time, Sound volume)
00579             // ---------------------------------------
00580             {
00581                 snprintf(path, sizeof path, "/" FILESYS "/music/%s", msc_file);
00582                 pc.printf("Play - %s\n", path);
00583 
00584                 TFT_fillRectangle(  0,   0, 319, 239 - bmpYsize, GRAY,  GRAY);
00585                 TFT_drawText( 28, 239 - 6 - (bmpYsize / 2), (uint8_t*)"00:00", WHITE, BLACK);
00586                 sprintf(stext, "%2d", Line_Vols);
00587                 TFT_drawText(244, 239 - 6 - (bmpYsize / 2), (uint8_t*)stext, WHITE, BLACK);
00588                 TFT_fillRectangle(  0, 239 - bmpYsize - 2, 319, 239 - bmpYsize, BLACK, BLACK);
00589             }
00590 
00591             // View Image
00592             // -----------
00593             {
00594                 JDEC jdec;
00595                 WORD work[4000/sizeof(WORD)];
00596 
00597                 snprintf(path, sizeof path, "/" FILESYS "/music/%s" ".jpg", msc_file);
00598                 pc.printf("jpg - %s\n", path);
00599                 jfp = fopen(path, "rb");
00600                 if (!jfp) jfp = fopen("/" FILESYS "/images/NoImage.jpg", "rb");
00601                 if (jfp) {
00602                     JRESULT r = jd_prepare(&jdec, jpeg_input, work, sizeof(work), jfp);
00603                     if (r == JDR_OK) {
00604                         uint16_t ww = jdec.width & 0x3FF;   // struct jdec ???
00605                         uint16_t wh = jdec.width >> 16;     // ..
00606                         Cover_tlx = (ww < 170) ? ((176 - ww) / 2) : 4;
00607                         Cover_tly = (wh < 180) ? ((188 - wh) / 2) : 4;
00608                         r = jd_decomp(&jdec, jpeg_output, 0);
00609                       #if (0)
00610                         TFT_drawLine(Cover_tlx + 1, Cover_tly + wh, Cover_tlx + ww, Cover_tly + wh, WHITE);
00611                         TFT_drawLine(Cover_tlx + ww, Cover_tly + 1, Cover_tlx + ww, Cover_tly + wh, WHITE);
00612                       #endif
00613                     }
00614                     fclose(jfp);
00615                 }
00616             }
00617 
00618             // View Song title
00619             // ----------------
00620             {
00621                 int l = 0;
00622                 char msc_Text[256];
00623 
00624                 snprintf(path, sizeof path, "/" FILESYS "/music/%s" ".txt", msc_file);
00625                 pc.printf("txt - %s\n", path);
00626 
00627                 fp = fopen(path, "r");
00628                 if (fp) {
00629                     l = fread(msc_Text, 1, 256, fp);
00630                     fclose(fp);
00631                 }
00632 
00633                 if (l > 4)
00634                      msc_Text[l] = '\0';
00635                 else snprintf(msc_Text, sizeof(msc_Text), "||%s||", msc_file);
00636                 pc.printf("%02d - %s\n\n", music_nw, msc_Text);
00637 
00638                 int  ps, pl = 0;
00639                 int  px = 176, py = Cover_tly + 2;
00640                 uint8_t ws[2];
00641                 ws[1] = '\0';
00642 
00643                 for (ps = 0; ps < 256; ps++) {
00644                     if (msc_Text[ps] == '|') {
00645                         if (++pl > 2) break;
00646                         py += 20;
00647                         px = 176;
00648                         continue;
00649                     }
00650                     if (msc_Text[ps] & 0x80) {  // KANJI ?
00651                         font.read((msc_Text[ps] << 8)| msc_Text[ps + 1]);
00652                         draw_kanji(px, py, ((pl == 2) ? WHITE : DWHITE), GRAY);
00653                         px += 16;
00654                         ps++;
00655                     } else {
00656                         ws[0] = msc_Text[ps];
00657                         TFT_drawText(px, py + 2, ws, ((pl == 2) ? WHITE : DWHITE), GRAY);
00658                         px += 8;
00659                     }
00660                 }
00661             }
00662 
00663             // Play Music
00664             // -----------
00665             {
00666                 snprintf(path, sizeof path, "/" FILESYS "/music/%s" ".wav", msc_file);
00667                 int rc = Open_Wave(path);
00668                 if (rc) {
00669                     if (fp != NULL) fclose(fp);
00670                     pc.printf(" rc=%d, Last_Err=%d\n", rc, Last_Err);
00671                     Last_Err = 0;
00672                     continue;
00673                 }
00674 
00675                 uint16_t tw = Wave_Size / (Wave_BPS * 4);
00676                 sprintf(stext, "%02d %2dks %02d:%02d", music_nw, (Wave_BPS / 1000), (tw / 60), (tw % 60));
00677                 TFT_drawText(214, (222 - bmpYsize), (uint8_t*)stext, BLACK, GRAY);
00678 
00679                 Wave_Play = buffGP;
00680                 Wave_FPos = BUFF_SIZE;
00681                 Wave_Rlen = Wave_Size - (Wave_FPos - Wave_Play);
00682                 buffNW = 0, buffNX = 1;
00683                 buffLN[buffNX] = 0;
00684 
00685                 Last_Err = 0;
00686                 ps_stat  = PS_PLAY;
00687 
00688                 Pwm_Ratio = ((65535 / PWM_CLKMHZ) / Wave_Prid) + Line_Vol;
00689                 Line_R.period_us(Wave_Prid);
00690                 Line_L.period_us(Wave_Prid);
00691                 Tick_Timer.attach_us(&ISR_Tick, Wave_Prid); // Play!
00692  
00693                 while (!(ps_stat & PS_EOF) && (ps_stat & PS_PLAY) && (Last_Err == 0)) {
00694 
00695                   #if defined(Level_Indicator)
00696                     uint16_t yl0 = 0, yr0 = 0, yl, yr;
00697                     if (Pwm_cnt > Level_Indicator) {
00698                         yl = 238 - (((Pwm_aveL - 64) * (bmpYsize - 2)) / 200);
00699                         yr = 238 - (((Pwm_aveR - 64) * (bmpYsize - 2)) / 200);
00700                         Pwm_cnt = 0;
00701                         if (yl > 237) yl = 238;
00702                         if (yr > 237) yr = 238;
00703                         yl0 = (yl > yl0) ? yl : ((yl0 + yl) / 2);
00704                         yr0 = (yr > yr0) ? yr : ((yr0 + yl) / 2);
00705                         TFT_fillRectangle(MM_VUPD + 5, MM_VUP + 1, MM_VUPD +  7, yl0, BLACK, BLACK);
00706                         TFT_fillRectangle(MM_VUPD + 9, MM_VUP + 1, MM_VUPD + 11, yr0, BLACK, BLACK);
00707                         if (yl0 < 238) TFT_fillRectangle(MM_VUPD + 5, yl0, MM_VUPD +  7, 238, YELLOW, YELLOW);
00708                         if (yr0 < 238) TFT_fillRectangle(MM_VUPD + 9, yr0, MM_VUPD + 11, 238, YELLOW, YELLOW);
00709                     }
00710                   #endif
00711 
00712                     if (Play_Wave()) {
00713 
00714                         statLED4 = LHigh;
00715                         if (ps_stat & PS_PAUSE) wait_ms(5);
00716                         poll();
00717                         statLED4 = LLow;
00718 
00719                         if (ps_stat & PS_FFF) {
00720                             buffNX = -1;
00721                             break;
00722                         }
00723 
00724                         if (ps_stat & PS_FFR) {
00725                             if (Wave_FPos < (Wave_BPS * 2 * 2 * 2)) {
00726                                 buffNX = -1;
00727                                 if (music_nx > music_nw)
00728                                     music_nx = (music_nw > 1) ? music_nw - 1 : 1;
00729                                 break;
00730                             } else
00731                                 Wave_FPos = Wave_Play;
00732                         }
00733                     }
00734                 }
00735 
00736                 Tick_Timer.detach();
00737                 fclose(fp);
00738                 pc.printf("Close stat=%04X, %d - %d\n", ps_stat, Wave_Rlen, Last_Err);
00739                 ps_stat  = 0;
00740                 Last_Err = 0;
00741             }
00742         }
00743         closedir(dp);
00744     }
00745 }
00746 #endif