// ver.0.1.09 상황 : 패턴 선택에선 전체곡 한번재생, 반복재생의 경우가 제대로 작동한다.

// 패턴을 바꾸면 처음부터 노래를 재생하는 현상은 
// VNC1L에 명령을 내릴때, 패턴이 바뀜에 따라 전에 수신받은 명령을 초기화하고
// 새로 받은 명령에 따라 새로 작업을 수행하기 때문에 생김

#include <mega128.h>
#include <delay.h>
#include <stdio.h>

#define min_vol 5
#define max_vol 50

//------------------------------------------------------------------------------------------//
typedef unsigned char    UINT8;
typedef unsigned int    UINT16;
typedef signed char        INT8;
typedef signed int        INT16;
//------------------------------------------------------------------------------------------//
#define GLCD_DAT        PORTA
#define GLCD_RS         PORTC.5        // H : Data, L : Command
#define GLCD_RW         PORTC.4        // H : Read, L : Write
#define GLCD_EN         PORTC.3        // H Active
#define GLCD_RST        PORTC.2        // Low Reset
#define GLCD_PSB        PORTC.0        // H : Parallel, L : Serial
//------------------------------------------------------------------------------------------//
void GlcdCmd ( UINT8 cmd )
{
    GLCD_RS  = 0;
    GLCD_RW  = 0;

    GLCD_EN  = 1;
    delay_us(1);
    GLCD_DAT = cmd;
    delay_us(1);
    GLCD_EN  = 0;
    delay_us(1);

    delay_us(72);
}
//------------------------------------------------------------------------------------------//
void GlcdData ( UINT8 dat )
{
    GLCD_RS  = 1;
    GLCD_RW  = 0;

    GLCD_EN  = 1;
    delay_us(1);
    GLCD_DAT = dat;
    delay_us(1);
    GLCD_EN  = 0;
    delay_us(1);

    delay_us(72);
}
//------------------------------------------------------------------------------------------//
void GlcdInit ( void )
{
    delay_ms(40);

    // LCD Reset
    //////////////////////////////////////
    GLCD_RST = 0;
    delay_us( 3 );
    GLCD_RST = 1;
    
    // Setting PSB
    //////////////////////////////////////
    GLCD_PSB = 1;
    
    // GLCD Init
    //////////////////////////////////////
    // Basic Instruction
    GlcdCmd( 0x30 );        // Function Set,    DL = 1, RE = 0
    delay_us(100);
    GlcdCmd( 0x30 );        // Function Set,    DL = 1, RE = 0
    delay_us(40);
    GlcdCmd( 0x08 );        // Display Status,    D = 0, C = 0, B = 0
    delay_us(100);
    GlcdCmd( 0x01 );        // Clear
    delay_ms(10);
    GlcdCmd( 0x06 );        // Entry Mode Set,    I/D = 1, S = 0

/*
    // Extended Instruction
    GlcdCmd( 0x36 );        // Extended Function Set,            DL = 1, RE = 1, G = 1
    GlcdCmd( 0x02 );        // Scroll Or RAM Address Select,    SR = 0
    GlcdCmd( 0x06 );        // Reverse,                            R1 = 1, R0 = 0
*/
}
//------------------------------------------------------------------------------------------//
// 0행 ~ 3행, 0열 ~ 15열
UINT8 glcd_gotoxy ( UINT8 x, UINT8 y )
{
    if( (x > 15) || (y > 3) ) return 0;

    switch( y )
    {
        case 0:    GlcdCmd( 0x80 | x );    break;
        case 1:    GlcdCmd( 0x90 | x );    break;
        case 2:    GlcdCmd( 0x88 | x );    break;    // LCD 데이터시트
        case 3:    GlcdCmd( 0x98 | x );    break;    // LCD 데이터시트
        // case 2:    GlcdCmd( 0xA0 | x );    break;    // ST7920 데이터시트
        // case 3:    GlcdCmd( 0xB0 | x );    break;    // ST7920 데이터시트
    }
    
    return 1;
}
//------------------------------------------------------------------------------------------//
void glcd_puts ( UINT8 *str )
{
    UINT8 i = 0;
    
    while(1)
    {
        if( str[i] == 0 ) break;
        GlcdData( str[i] );
        i++;    
    }
}
//------------------------------------------------------------------------------------------//
void glcd_putsf ( UINT8 flash *str )
{
    UINT8 i = 0;
    
    while(1)
    {
        if( str[i] == 0 ) break;
        GlcdData( str[i] );
        i++;    
    }
}

void send2vnc(char flash *cmd)
{
  while( *cmd) putchar(*cmd++);
  putchar(0x0d);
}

void send2vol(char flash *cmd,unsigned char vv)
{
  while( *cmd) putchar(*cmd++);
  putchar(vv);
  putchar(0x0d);
}

//------------------------------------------------------------------------------------------//
int mode = 0 , in_mp3_screen_mode = 0 , home_screen = 1; 
// mode = 홈화면에서 모드 선택할 때 필요한것 , 이 변수에 의해서 모드가 바뀜
// in_mp3_screen_mode = mp3화면에서 모드 선택할 때 필요한것 , 이 변수에 의해서 mp3내의 재생패턴 , 리스트 표현방식이 바뀜
// home_screen = 홈화면 인에이블 , 최초의 화면 표시를 할 수 있도록 한다.

int mode_select_enable = 1 , in_mp3_screen_mode_select = 0 , home_menu_select_enable = 1 , MP3_enable = 0;
// mode_select_enable = 각 모드마다 작동하는 방향을 기술한다.
// in_mp3_screen_mode_select = in_mp3_screen_mode 를 사용할 수 있게 하는 변수, 이 변수가 0이면 in_mp3_screen_mode 사용불가
// home_menu_select_enable = mode 변수를 사용할 수 있게 함
// MP3_enable = mp3기능을 사용할 수 있게 만들어 주는 변수임

int exit = 0 , Enter_key = 0;

void system_init (); // 초기 시스템 설정
void mode_select (); // 모드값계산 설정
void lcd_home_display (); // 홈화면에서 lcd에 뿌려주는 화면
void MP3_function_display (); // mp3화면에서 lcd에 뿌려주는 화면
void mode_enable (); // mp3 , 녹음기능 활성화시키는 함수
void key_init (); // 키 설정
void USART_init(); // USART 설정

void volume_funtion (); // ver0.1.09에서 추가

void patern (); // ver0.1.05에서 추가
int patern_mode = 0 , patern_enable = 0, patern_select_enable = 0; //ver0.1.05에서 추가

unsigned char vol=0;

void main ( void )
{
    
    DDRD = 0xf0;
    DDRA = 0xff;    // GLCD DATA
    DDRC = 0x3D;    // GLCD CON        PC.1 : SW 입력
    
    PORTB = 0x00;
    DDRB = 0x00;    // MP3 구동스위치를 위한 설정
    
    PORTE=0x02;     // 통신을 위한 설정
    DDRE=0x00;      // 통신을 위한 설정
    
    USART_init ();                  // USART 기본 설정   

    GlcdInit();     // GLCD 설정
    delay_ms(100);  // GLCD 초기화 딜레이
    
    GlcdCmd( 0x0C );        // Display Status,    D = 1, C = 0, B = 0 , GLCD 초기화

    glcd_gotoxy( 2, 1 );            // GLCD에 홈화면 좌표 설정함
    glcd_putsf( "Blueyak" );        // 따옴표에 있는 글씨 출력하기
    
    delay_ms(5000);                 // 5초 동안 화면에 BlueYak
    
    vol=15;
 
    send2vol("vsv ",vol);  
    send2vnc("vra");
    send2vnc("vp");
    
    while(1)
    {
        system_init ();
        key_init ();
        mode_enable ();
        
        volume_funtion ();
        
        if(mode_select_enable == 1)mode_select ();
                                                      
        if ( home_screen == 1 ) lcd_home_display ();
        if ( MP3_enable == 1 ) MP3_function_display ();
        if ( patern_enable == 1 ) patern ();     
    }
}
//------------------------------------------------------------------------------------------//

//------------------------------------------------------------------------------------------//
void system_init ()
{
     if( mode < 0 ) mode = 2;
     if( mode > 2 ) mode = 0;
     
     if( in_mp3_screen_mode < 0 ) in_mp3_screen_mode = 5;
     if( in_mp3_screen_mode > 5 ) in_mp3_screen_mode = 0;
     
     if( patern_mode < 0 ) patern_mode = 3;
     if( patern_mode > 3 ) patern_mode = 0;
     
}

void USART_init ()
{
    UCSR0A=0x00; // 초기값 

    UCSR0B=0x18; // 송수신 인에이블
    UCSR0C=0x06; // 전송데이터 8비트 설정
    UBRR0H=0x00; // 0 
    UBRR0L=0x67; // 103
}

void key_init ()
    if ( PIND.2 == 0 ) Enter_key = 1; 
    else if ( PIND.2 == 1 ) Enter_key = 0;
    
    if ( PIND.3 == 0 ) exit = 1 , PORTD.5 = 1;
    else if ( PIND.3 == 1 ) exit = 0;
}

void mode_select ()
{
    if ( home_menu_select_enable == 1 && in_mp3_screen_mode_select == 0 && patern_select_enable == 0)
    {
        if ( PIND.0 == 0 ) mode = mode - 1;
        else if ( PIND.1 == 0 ) mode = mode + 1;
    }
    
    if ( in_mp3_screen_mode_select == 1 && home_menu_select_enable == 0 && patern_select_enable == 0 )
    {
        if ( PIND.0 == 0 ) in_mp3_screen_mode = in_mp3_screen_mode - 1;  
        else if ( PIND.1 == 0 ) in_mp3_screen_mode = in_mp3_screen_mode + 1;
    }
    
    if( in_mp3_screen_mode_select == 0 && home_menu_select_enable == 0 && patern_select_enable == 1)
    {
        if ( PIND.0 == 0 ) patern_mode = patern_mode - 1; 
        else if ( PIND.1 == 0 ) patern_mode = patern_mode + 1;   
    }
     
    while(1)
    {
        if( PIND.0 == 1 && PIND.1 == 1 ) break;
    }                                     
}

void mode_enable ()
{
    if ( home_screen == 1 && mode == 0 && Enter_key == 1 ) MP3_enable = 1;
    if ( Enter_key == 1 && in_mp3_screen_mode == 2 ) patern_enable = 1;
}

void lcd_home_display () // depth 1
{       
    glcd_gotoxy ( 0 , 3 );
    glcd_putsf ("  Press Enter  ");
              //0123456789012345
    if( mode == 0 )
    {
        glcd_gotoxy ( 0 , 1 );
        glcd_putsf ("      MP3       ");
                 // 0123456789012345
    }
    
    if( mode == 1 )
    {
        glcd_gotoxy ( 0 , 1 );
        glcd_putsf ("Text (Add after)");
                 // 0123456789012345
    }
    
    if( mode == 2 )
    {
        glcd_gotoxy ( 0 , 1 );
        glcd_putsf ("Alarm(Add after)");
                 // 0123456789012345
    }

void MP3_function_display () // depth 2
        //////////////////////////////////////////////////////////////////////
        
        // 홈화면으로 루트복귀
    if( exit == 1 ) MP3_enable = 0, home_screen = 1 , home_menu_select_enable = 1 , in_mp3_screen_mode_select = 0 , in_mp3_screen_mode = 0; 
    
        //////////////////////////////////////////////////////////////////////
    else  
    {
        home_screen = 0;
        home_menu_select_enable = 0;
        
        //////////////////////////////////////////////////////////////////////
        
        // depth 2 = mp3 화면의 하위메뉴 모드 선택 인에이블
        
        in_mp3_screen_mode_select = 1;
        
        //////////////////////////////////////////////////////////////////////
            
            glcd_gotoxy ( 0 , 0 );
            glcd_putsf ("      Menu      ");
                  //0123456789012345    
                         
            if( in_mp3_screen_mode == 0 )
            {
                glcd_gotoxy ( 0 , 1 );
                glcd_putsf ("      List      ");
                          //0123456789012345
                          
                if( PIND.2 == 0 )
                {
                    delay_ms(200);
                    
                    send2vnc("dir");
                    
                    
                    
                    delay_ms(200);
                }
            }  
        
            if ( in_mp3_screen_mode == 1 )
            {
                glcd_gotoxy ( 0 , 1 );
                glcd_putsf ("  Folder List   ");
            } 
        
            if ( in_mp3_screen_mode == 2 )
            {
                glcd_gotoxy ( 0 , 1 );
                glcd_putsf (" Patern Select  ");
            }  
            
            if ( in_mp3_screen_mode == 3 )
            {
                glcd_gotoxy ( 0 , 1 );
                glcd_putsf ("  Play / Pause  ");
                    
                if( Enter_key == 1 )
                {
                    delay_ms(200);
                    send2vnc("vp");
                    delay_ms(200);
                }
                
            } 
            
            if ( in_mp3_screen_mode == 4 )
            {
                glcd_gotoxy ( 0 , 1 );
                glcd_putsf ("    Play Back   ");
                           //0123456789012345
                
                if( Enter_key == 1 )
                {
                    delay_ms(200);
                    send2vnc("vsb");
                    send2vnc("vsb");
                    send2vnc("vsb");
                    delay_ms(200);
                }
            } 
            
            if ( in_mp3_screen_mode == 5 )
            {
                glcd_gotoxy ( 0 , 1 );
                glcd_putsf ("  Play Forward  ");
                           //0123456789012345
                           
                if( Enter_key == 1 )
                {
                    delay_ms(200);
                    send2vnc("vsf");
                    delay_ms(200);
                }
            }  
            
                      
    }
}

void patern () // depth 3
{   

    if( exit == 1 ) delay_ms(150) , patern_select_enable = 0 , patern_enable = 0 , MP3_enable = 1 , in_mp3_screen_mode_select = 1 , in_mp3_screen_mode = 2;
    
    else 
    {                                             
        in_mp3_screen_mode_select = 0;
        MP3_enable = 0; 
        
        ///////////////////////////////////
        
        // depth 3 패턴 선택 인에이블
        
        patern_select_enable = 1 ;
        
        ///////////////////////////////////
        
        delay_ms(100);
        
        
        /*
        patern_mode = 0 , 모든노래 한번만 재생
        patern_mode = 1 , 모든노래 무한 재생
        patern_mode = 2 , 한곡 한번만 재생
        patern_mode = 3 , 한곡 무한 재생
        */
                                                                
        if ( patern_mode == 0 ) 
        {
            glcd_gotoxy ( 0 , 1 ) , glcd_putsf ("all song onetime");
        
            if ( Enter_key == 1 )
            {
                send2vnc ("vp");
                delay_ms(10);
                
                PORTB.7 = 0;
                
                send2vnc ("v3a");
            }
        }
                                                                   
        else if ( patern_mode == 1 ) 
        {       
            glcd_gotoxy ( 0 , 1 ) , glcd_putsf ("all song repeat ");
             
            if( Enter_key == 1 )
            {
                send2vnc ("vp");
                delay_ms(10);
                
                PORTB.6 = 0;
                
                send2vnc ("vra");   
            }
        }
        else if ( patern_mode == 2 )  
        {
            glcd_gotoxy ( 0 , 1 ) , glcd_putsf ("one song onetime");
        
            if( Enter_key == 1 )
            {
                send2vnc ("vp");
                delay_ms(10);
                
                PORTB.5 = 1;
                
                send2vnc ("vpf");
                
            }
        }
        else if ( patern_mode == 3 ) 
        {
            glcd_gotoxy ( 0 , 1 ) , glcd_putsf ("one song repeat ");
        
            if( Enter_key == 1 ) 
            {
                send2vnc ("vp");
                delay_ms(10);
                
                PORTB.4 = 1;
                
                send2vnc ("vrf");
            }
        }    
    } 
}

void volume_funtion ()
{
     //volume control
 
     if ((PINB & 0x04)==0) {   // smaller   
            
        delay_ms(200);      
        PORTB=0x0; 
        
        vol=vol+5;
        if (vol>max_vol) vol=max_vol;
      
        send2vol("vsv ",vol);  
        delay_ms(200);      
     }  
  
     if ((PINB & 0x02)==0) {   //louder
            
        delay_ms(200);
        PORTB=0x0;       
        
        vol=vol-5;
        if (vol<min_vol) vol=min_vol;
        
        send2vol("vsv ",vol);
        delay_ms(200);      
     }    
}

///////////////////////////////////////////////////////

지금까지 짠 프로그램으로는 GLCD에서 이전곡, 다음곡 버튼을 눌러서 노래를 바꾸는 것과
볼륨제어, 전체곡 반복재생, 전체곡 한번재생의 패턴선택을 할 수 있게까지 만들었음.

그래서 이제부턴 곡정보와 파일의 장소를 읽어와서 GLCD에 표시하려고 하는데, 말처럼 쉽지가 않음.
VNC1L의 메뉴얼을 읽고 'DIR' 이란 명령이 파일의 장소를 읽는다는 것까진 알아냈는데

이건 하이퍼 터미널 상에서만 해당하는 내용으로, 실제로 사용하고 있는 컴파일러인 코드비전에선
이 명령어가 작동하지 않음을 알아냈음.

즉, 무언가 함수가 필요하다는 말인데, 그 함수를 어떻게 짜야할지도 모르겠네?

사실 위에 있는 코드중에서 send2vnc라는 함수나 send2vol이란 함수는 내가 짠게 아니라서 말이지.

형들 헬프