☆debug_printfの%dで マイナスの表示

vxsnprintf.c

#if X86
unsigned int xput_n(char *buf, char *fmt, unsigned long long vv, int width, unsigned int zeroflag, unsigned int buf_size)
#else
/*                        ここで、unsigned long 符号無しで宣言されているため、マイナスがなくなる。
unsigned int xput_n(char *buf, char *fmt, unsigned long vv, int width, unsigned int zeroflag, unsigned int buf_size)
*/
unsigned int xput_n(char *buf, char *fmt, long vv, int width, unsigned int zeroflag, unsigned int buf_size)
#endif
  
    case 'd':
        base = 10;
                if ( vv < 0 )
                {
                  negativeflag = 1;
                  vv=-vv;
                }
        vvd = (long long)vv;
        /*
                if (vvd < 0) {
            vv = -vvd;
            negativeflag = 1;
        }
                 */
        break;


// vxsnprintf
int vxsnprintf(char *buf, int buf_size, char *fmt, va_list args)

            case 'd':
#ifdef X86
                size = xput_n(buf, fmt, (long long)va_arg(args, long), n, zeroflag, buf_size);
#else   
                size = xput_n(buf, fmt, (long)va_arg(args, long), n, zeroflag, buf_size);           
#endif
===============================================================================

☆LとRの両方のチャンネル出力

PA2/TIOA10_0 is OUTPUT

(1)wav_config.h

/* wav file stereo setting */
                             /* changed to 1 */
#define WAV_STEREO_LEFT      (1U)             /* 0 : "L" channel output disable  */
                                              /* 1 : "L" channel output enable   */

#define WAV_STEREO_RIGHT     (1U)             /* 0 : "R" channel output disable  */
                                              /* 1 : "R" channel output enable   */


(2)pwm_config.h
/* the PWM channel related to base timer channel specifications */
#ifndef MB9BF618T
#define CFG_PWM0     (BASETIMER_CH5)
#else

#define CFG_PWM0     (BASETIMER_CH8)
/* add */
#define CFG_PWM1     (BASETIMER_CH10)

#endif



(3)pwm.h

#if defined(CFG_PWM1)

  .............
/* add */
#ifdef MB9BF618T
    #if (CFG_PWM1 == BASETIMER_CH8)
        #define PWM_USE_BASETIMER_CH8
    #endif
    #if (CFG_PWM1 == BASETIMER_CH9)
        #define PWM_USE_BASETIMER_CH9
    #endif
    #if (CFG_PWM1 == BASETIMER_CH10)
        #define PWM_USE_BASETIMER_CH10
    #endif
    #if (CFG_PWM1 == BASETIMER_CH11)
        #define PWM_USE_BASETIMER_CH11
    #endif
#endif

#endif /* defined(CFG_PWM1) */



(4)pwm.c
#ifdef PWM_USE_BASETIMER_CH10
    /* set extended port function registers of PWM ch.10  */
    /* add TIOA10_0 PA2 */
    FM3_GPIO->EPFR12 = (FM3_GPIO->EPFR12& 0xFF00FFFF) | 0x00040000;
//    GPIO->EPFR12 = (GPIO->EPFR12& 0xFF00FFFF) | 0x00000000;

    /* set port function registers of PWM ch.10 */
    bFM3_GPIO_PFRA_P2 = 1;           /* peripheral function(TIOA0) */
#endif /* #ifdef PWM_USE_BASETIMER_CH10 */

/* change */
#if defined(PWM_USE_BASETIMER_CH10) || defined(PWM_USE_BASETIMER_CH11)
    /* set base timer io select register of PWM ch.10/11 */
    FM3_BTIOSEL8B->BTSEL89AB = (FM3_BTIOSEL8B->BTSEL89AB & 0x0F); /* I/O mode 0 */
#endif /* defined(PWM_USE_BASETIMER_CH10) || defined(PWM_USE_BASETIMER_CH11) */

===================================================================================


☆MDFをFatFsに置き換える  
内容は、とりあえずコンパイルとリンカーのエラーをなくした程度のもので、動作は保証せず。
その他、ff.c ff.h ffconf.h integer.h diskio.h が必要。
FatFsのオプション設定は 読み込みのみ、セクター512のみ、ロングファイル名未使用の 最小構成。 
Makefile の CSRC に ff.c を加えて、 LDFLAGS から -lMDF_minimum_ARMv7M を削除してコンパイル&リンクすると、、出力(hexコード)が数十Kバイトぐらい 小さくなるみたい。

usbhost_demoapp.c

/* write sector to PBR */
static FS_INT usbhost_demoapp_write(FS_VOID* pDevinfo, FS_DWORD Start, FS_DWORD Cnt, char* pData);


/* for ff ***********************************************************/
#include "diskio.h"    FM3 SD card  fatFs  用のものを そのまま使用させて頂いた。
#include "ff.h"

static volatile DSTATUS Stat = STA_NOINIT;    /* Physical drive status */

static    uint16_t s_bytes_per_sector;  /* bytes per sector */
static    uint32_t s_bytes_per_block;   /* bytes per block */
static    uint32_t s_max_lba;           /* max logical block address */

FATFS Fatfs[2];        /* File system object for each logical drive */
FIL   File_Obj[2];       /* 0番目を使用する */

static void init_fatfs(BYTE drv);
static void init_fatfs2(BYTE drv);

static FRESULT scan_files(char* path0 );

#define USE_F_READ 1
/* for ff ***********************************************************/


MDFの関数(FS_で始まるもの。MDFそのもの。)をFatFs(F_で始まるもの。)の関数に置き換える。
制御ルーチンは、MDF用のをそのまま使っているので、MDFの制御部分(usbhost_demoapp_MDF_openその他)は残すこと。
FatFsの ディスクの初期化は なにをすれば よくわからなかったので、 USBメモリーディスクのdbrの読み込み(セクターとブロックの設定)まで おこなっている。
MDF_initの場所で、fatFsのf_mountをおこなっている。
FatFsのF_readは、MDFと同じ USBメモリーディスクのPBRの読み込みにしてみた。
USBが抜かれたときに、usbhost_demoapp_MDF_closeがよばれて処理するところが 何故か 動いていないみたいである。

/************************************/
/*  modified for fsfat               */
/************************************/
static void usbhost_demoapp_joystick_psw2_process(void)
{
    FS_INT ret;

    debug_printf("+usbhost_demoapp_joystick_psw2_process\n");

    /* if wav play stage is initial stage to show WAV output is stopped, then start play wav file */
    if (s_WavPlayStage == WAVPLAY_STAGE_INIT)
    {


        /* open file */
        ret = (FS_INT) f_open(  &File_Obj[0] ,(const char *)s_WavFileName_table[s_WavFileId] , FA_READ);
        ////ret = FS_open((const char *)s_WavFileName_table[s_WavFileId], O_RDONLY, ATTR_NORMAL);

        /* file wav is not existed */
        if (FR_NO_FILE == ret)
        {
             debug_printf("-this wav file is not existed\n");
            /*  this wav file is not existed\n  */
        }
        /* open file error */
        else if (ret != FR_OK)
        {
             debug_printf("-open file error: ret= %d\n", (int)ret);
            /* open file error */
        }

        /* open file successfully */
        else
        {
            debug_printf("+open file successfully\n");
            /* get wav file no for file operation */

            /*********************************************/
            /*                                           */
            /* This line below must be think again !     */
            s_FileNo = s_WavFileId;

            /* set wav play stage to analyze */
            s_WavPlayStage = WAVPLAY_STAGE_ANALYZE;

            /* fill wav buffer */

            usbhost_demoapp_fill_wav_buf_ff();
       }
    }
    /* if WAV output is playing, then stop play wav file */
    else
    {
         debug_printf(" if WAV output is playing, then stop play wav file\n");
         usbhost_demoapp_stop_wav_ff();

    }
}


static void usbhost_demoapp_fill_wav_buf(void)
{
    /* buffer for read wav file */
    static uint8_t s_wav_read_buffer[DATA_BLOCK_SIZE];
    /* actual length when read wav file */
    static FS_DWORD s_wav_read_length = 0;
    /* header size of wav file:from start of file to offset of data of data chunk */
    static uint8_t  wav_header_length = 0;

    uint16_t wav_fill_buf_size;           /* fill buffer size  */
    uint16_t wav_empty_buf_size;          /* buffer empty size */
    uint32_t file_eof_flg = FALSE;        /* end of file flag  */
    FS_INT ret;
    int i;


    /* debug_printf("(usbhost_demoapp_fill_wav_buf)\n"); */

    /* if wav play stage is not initial stage */
    if (s_WavPlayStage != WAVPLAY_STAGE_INIT)
    {
        /* if buffer for read wav file is empty, to do below */
        if (s_WavReadBufferIsEmpty == TRUE)
        {
            /* read 1 block data for wav file */
            ret= f_read( &File_Obj[0], s_wav_read_buffer, DATA_BLOCK_SIZE , &s_wav_read_length);

            ////ret = FS_read(s_FileNo, s_wav_read_buffer, DATA_BLOCK_SIZE, &s_wav_read_length);


            /* reached file end, then stop play wav file. this is not read file error */
            if( s_wav_read_length < DATA_BLOCK_SIZE )
            ////if (FS_ERR_EOF == ret)
            {
                file_eof_flg = TRUE;
            }
            /* read file error */
            else if (ret !=  FR_OK)
            {
                file_eof_flg = TRUE;  // to call stop_wav
                s_wav_read_length = 0;
                debug_printf("-read file error: %d\n", ret);
               
            }
            /* read file successfully */
            else
            {
                /* set flag to indicate buffer for read wav file contains data */
                s_WavReadBufferIsEmpty = FALSE;
            }
        }
    }

    /* if wav file need analyze */
    if (s_WavPlayStage == WAVPLAY_STAGE_ANALYZE)
    {
        /* wav header must bigger or equal to 44 bytes */
        if (s_wav_read_length >= WAV_HEADER_LENGTH)
        {
            /* analyze WAV file header */
            if (WAV_Analyze(s_wav_read_buffer, &wav_header_length, &s_WavHeaderInfo) == WAV_RET_OK)
            {
                     debug_printf(" s_wav_read_length %d\n", s_wav_read_length);
                    /* update index of current WAV file */
                    s_CurrentWavFileIndex = wav_header_length;

                    /* get fill buffer size */
                    wav_fill_buf_size = (uint16_t)(s_wav_read_length - wav_header_length);



                    /* fill data buffer with specified WAV data from offset of data chunk */
                    (void)WAV_FillBuffer(&s_wav_read_buffer[wav_header_length], wav_fill_buf_size);

                    /* set flag to indicate buffer for read wav file is empty */
                    s_WavReadBufferIsEmpty = TRUE;

                    /* set wav play stage to playing stage */
                    s_WavPlayStage = WAVPLAY_STAGE_PLAYING;

                    /* update index of current WAV file */
                    s_CurrentWavFileIndex += wav_fill_buf_size;


        /* When start up, fill ring buffer */
         for(i=0;i<10;++i)   // for(i=0;i<(WAV_BUFFER_SIZE/DATA_BLOCK_SIZE);++i)
         {
           if( (WAV_BUFFER_SIZE - s_CurrentWavFileIndex)  > DATA_BLOCK_SIZE)
           {
              /* read 1 block data for wav file */
              ret= f_read( &File_Obj[0], s_wav_read_buffer, DATA_BLOCK_SIZE , &s_wav_read_length);
              if(ret==FR_OK)
              {
                    /* get fill buffer size */
                    wav_fill_buf_size = (uint16_t)s_wav_read_length;

                    /* fill data buffer with specified WAV data */
                    (void)WAV_FillBuffer(s_wav_read_buffer, wav_fill_buf_size);

                    /* set flag to indicate buffer for read wav file is empty */
                    s_WavReadBufferIsEmpty = TRUE;

                    /* update index of current WAV file */
                    s_CurrentWavFileIndex += wav_fill_buf_size;
              }else break;
          }

        }




                    /* start individual timer of specified channel */
                    (void)TIMER_Start(TIMER_CH1);

                    /* start WAV output operation */
                    (void)WAV_Start();

            }
            else
            {
                /* stop play wav file */

                usbhost_demoapp_stop_wav_ff();

                debug_printf(" analyze WAV file header error\n");
            }
        }
        else
        {
            debug_printf("  WAV file header size is too little\n");
        }
    }
    /* if wav file is playing */
    else if (s_WavPlayStage == WAVPLAY_STAGE_PLAYING)
    {
         /* get buffer empty size */
        (void)WAV_GetBufferEmptySize(&wav_empty_buf_size);

        /* there is no remain data */
        if (file_eof_flg == TRUE)
        {
            /* only invalid data in buffer , stop play wav file */
            if (WAV_BUFFER_SIZE - wav_empty_buf_size < (((s_WavHeaderInfo.FmtChunk.BitsWidth) / 8U) * (s_WavHeaderInfo.FmtChunk.Channels)))
            {

                usbhost_demoapp_stop_wav_ff();
   
           }
           else
           {
             /* Last Datas will be lost !  Waht to do....... */
              最後の残りのデータをリングバッファに送っていないよ! 未完成。
           }
        }
        else
        {
            /* if buffer empty size is greater than data block size, then to do below */
            if (wav_empty_buf_size >= DATA_BLOCK_SIZE)
            {
                /* if buffer for read wav file contains data, to do below */
                if (s_WavReadBufferIsEmpty != TRUE)
                {
                    /* get fill buffer size */
                    wav_fill_buf_size = (uint16_t)s_wav_read_length;

                    /* fill data buffer with specified WAV data */
                    (void)WAV_FillBuffer(s_wav_read_buffer, wav_fill_buf_size);

                    /* set flag to indicate buffer for read wav file is empty */
                    s_WavReadBufferIsEmpty = TRUE;

                    /* update index of current WAV file */
                    s_CurrentWavFileIndex += wav_fill_buf_size;
                }
            }
        }
    }
    else
    {
    }

    return;
}



static void usbhost_demoapp_stop_wav(void)
{
    FS_INT ret;

    /* close file */
    ret= f_close( &File_Obj[0] );
   

    /* close error */
    if (ret != FR_OK)
    {
         debug_printf("-fclose error of ff %d\n", ret);
        /* close file error */
    }
    else
    {
        debug_printf("+fclose of ff \n");

        /* stop individual timer of specified channel */
        (void)TIMER_Stop(TIMER_CH1);
        /* change to stop Timer at first */

        /* finish process of WAV output */
        (void)WAV_Finish();

        /* stop individual timer of specified channel */
       /*  (void)TIMER_Stop(TIMER_CH1);  */

        /* WAV playing flag initialize */
        s_WavPlayStage = WAVPLAY_STAGE_INIT;

        /* set flag to indicate buffer for read wav file to empty */
        s_WavReadBufferIsEmpty = TRUE;
    }
}

static uint8_t usbhost_demoapp_MDF_open(void)
{
/******************************************************
               MDF device function are defined HERE!
*******************************************************/

    FS_FUNCNAME ram_func = {
        usbhost_demoapp_read,
        usbhost_demoapp_write,
        NULL,
        NULL,
        NULL
    };
    uint8_t drive_info;
    FS_INT fs_ret;

    uint8_t ret = TRUE;

    /* read dbr for single LUN device */
    usbhost_demoapp_read_dbr(s_MscDeviceAddr, 0);
                                          /* LUN=0 */

#ifdef USE_F_READ
     init_fatfs(0);
    
#else
    /*  start MDF\n  */
    /* start MDF */
    fs_ret = FS_startMDF();
    if (fs_ret != 0)
    {
        debug_printf("-start MDF error error: %d\n", fs_ret);
        /* start MDF error */
        FS_endMDF();
        /*  end MDF\n  */

        ret = FALSE;
    }
    else
    {
         debug_printf("+FS_startMDF\n");
        /* drive initialize */
        fs_ret = FS_initDrv("MSC", &ram_func, (void *)&drive_info);
        if (fs_ret != 0)
        {
             debug_printf("-drive initialize error(usbhost_demoapp_MDF_open): %d\n", fs_ret);

            FS_endMDF();

            /*  end MDF\n  */

            ret = FALSE;
        }
        else  debug_printf("+FS_initDrv\n");
    }

#endif

    return (ret);
}

/**
* @brief            usb host sample application close MDF
*
* @param            none
* @return           none
*
**/
static void usbhost_demoapp_MDF_close(void)
{
    FS_INT fs_ret;

#ifdef USE_F_READ
    /* This is NOT realy called ??? */
    init_fatfs2(0);
#else
    /* end task */
    fs_ret = FS_endTask();
    if (fs_ret != 0)
    {
        debug_printf("-end task error: %d\n", fs_ret);
    }

    /* end drive */
    fs_ret = FS_endDrv("MSC");
    if (fs_ret != 0)
    {
        debug_printf("-end drive error: %d\n", fs_ret);
    }

    /* end MDF */
    FS_endMDF();

    debug_printf("-end MDF\n");

#endif



}

static void usbhost_demoapp_msc_disconnect_callback(uint8_t MscDevAddr)
{
/******************************************************
  When dis-connected, this will be called !
*******************************************************/

    /* reset msc device address */
    s_MscDeviceAddr = 0;

    /* clear medium connect flag */
    s_IsMediumConnect = FALSE;

    /* set MDF stage */
    s_MDFStage = MDF_STAGE_CLOSE;

#ifdef USE_F_READ
   /* reset Stat for FF */
   Stat = STA_NOINIT;
   /*********************/
#endif
    return;
}

static FS_INT usbhost_demoapp_read_dbr(uint8_t DevAddr, uint8_t Lun)
{
    uint16_t bytes_per_sector;  /* bytes per sector */
    uint32_t bytes_per_block;   /* bytes per block */
    uint32_t max_lba;           /* max logical block address */
    uint8_t  buffer[512];       /* buffer for temp  */

    FS_INT ret = 0;

    /* read first block from USB MSC device */
    if (USBH_MSC_Read(DevAddr, Lun, 0, 1, buffer) != USBH_MSC_RET_OK)
    {
        debug_printf("-USB host MSC read mbr data error\n");
        ret=-1;
    }

   
    /* set Dbr Offset to zero */
    s_DbrOffset = 0;

    /* if signature is 0x55AA and JMP instruction is not 0xEB or 0xE9, */
    /* the first block is a valid mbr, */
    /* then find the Dbr Offset */
    if ((buffer[510] == 0x55) && (buffer[511] == 0xAA) &&
        (buffer[0] != 0xEB) && (buffer[0] != 0xE9))
    {
        /* set Dbr Offset */
        s_DbrOffset = (((uint32_t)buffer[0x1C6] << 0)  |
                       ((uint32_t)buffer[0x1C7] << 8)  |
                       ((uint32_t)buffer[0x1C8] << 16) |
                       ((uint32_t)buffer[0x1C9] << 24));
        /* read dbr data from USB MSC device */
        if( USBH_MSC_Read(DevAddr, Lun, s_DbrOffset, 1, buffer) != USBH_MSC_RET_OK) ret +=-2;
    }

    bytes_per_sector = (uint16_t)buffer[0x0C] << 8 | (uint16_t)buffer[0x0B];
    /* read USB MSC device capacity */
    if (USBH_MSC_ReadCapacity(DevAddr, Lun, &max_lba, &bytes_per_block) != USBH_MSC_RET_OK)
    {
        debug_printf("-USB host MSC read capacity error\n");
        ret -=-4;
    }
    s_BlocksPerSector = bytes_per_sector/bytes_per_block;

#ifdef USE_F_READ
    s_bytes_per_sector = bytes_per_sector;
    s_bytes_per_block = bytes_per_block;
    s_max_lba = max_lba;
#endif

    return ret;
}

/************************************/
/*  new add for fsfat               */
/************************************/

/*--------------------------------------------------------------------------

   Public Functions

----------------------------------------------------------------------------*/
static void init_fatfs(
    BYTE drv        /* Physical drive number (0) */
)
{

    f_mount( drv , &Fatfs[0]);
    debug_printf("+fmount of ff \n");

}

static void init_fatfs2(
    BYTE drv        /* Physical drive number (0) */
)
{

    f_mount( drv , NULL);
    debug_printf("+set fmount NULL \n");

}


/*-----------------------------------------------------------------------*/
/* MISC                                                                  */
/*-----------------------------------------------------------------------*/
指定したディレクトリーの中のファイル名称(短いファイル名称)を調べて表示する関数。 合計99までにしてある。
static FRESULT scan_files (
    char* path        /* Pointer to the path name working buffer */
)
{
    DIR dirs;
        FILINFO Finfo;
    FRESULT res;
    int  i;
   
    if ((res = f_opendir(&dirs, path)) == FR_OK)
        {
       
               /* 99 ko made SAGASU ! */
               for(i=0;i<99;++i)
               {
                 res = f_readdir(&dirs, &Finfo);
                 if( (res != FR_OK) || (Finfo.fname[0]==0))
                 {
                   debug_printf("-f_readdir of ff error %d\n", res);
                   break;
                 }
                 if( Finfo.fname[0]=='.')
                 {
                    debug_printf("-fname is dot \n");
                    continue;
                 }

                 if(Finfo.fattrib & AM_DIR)
                 {
                   debug_printf("No. %d , Directory, %s\n",i , Finfo.fname);
                 }
                 else
                 {
                   debug_printf("No. %d , File, %s\n",i , Finfo.fname);
                 }

               }

         }
         else
         {
            debug_printf("-f_opendir of ff error %d\n", res);

         }


    return res;
}

ファイルを再生する順番がよく分からないので、ファイル名称(8文字)の頭から1ないし2文字の数字(1から99)をつけて、数の小さいものから再生するように並びかえるプログラムを追加した。

以下は、FatFs に 最小限 必要な関数たち。
/*-----------------------------------------------------------------------*/
/* Initialize disk drive                                                 */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
    BYTE drv        /* Physical drive number (0) */
)
{
        FS_INT ret0 = 0;

    if (drv) return STA_NOINIT;            /* Supports only drive 0 */
        else if (s_IsMediumConnect == FALSE) return RES_NOTRDY; /* no connection */
    else if (Stat & STA_NODISK) return Stat;    /* Is card existing in the soket? */

       /* read dbr for single LUN device */
       if( (ret0=usbhost_demoapp_read_dbr(s_MscDeviceAddr, 0)) != 0 )
       {
           debug_printf("-usbhost_demoapp_read_dbr error %d\n", ret0);

       }
       else
       {
         Stat &= ~STA_NOINIT;
         debug_printf("+ disk_initialize was called from ff. \n");
       }

       return Stat;
}


/*-----------------------------------------------------------------------*/
/* Get disk status                                                       */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
    BYTE drv        /* Physical drive number (0) */
)
{
    if (drv) return STA_NOINIT;        /* Supports only drive 0 */
        else if( s_IsMediumConnect == FALSE ) return STA_NODISK;  /* No connection */


    return Stat;    /* Return disk status */
}

/*-----------------------------------------------------------------------*/
/* Read sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
    BYTE drv,        /* Physical drive number (0) */
    BYTE *buff,        /* Pointer to the data buffer to store read data */
    DWORD sector,    /* Start sector number (LBA) */
    BYTE count        /* Number of sectors to read (1..128) */
)
{



    if (drv || !count) return RES_PARERR;        /* Check parameter */
    else if (s_IsMediumConnect == FALSE) return RES_NOTRDY; /* no connection */
    else if (Stat & STA_NOINIT) return RES_NOTRDY;    /* Check if drive is ready */

    /* read sector from USB MSC device */
    if (USBH_MSC_RET_OK != USBH_MSC_Read(s_MscDeviceAddr,
                                         0,
                                         (FS_DWORD)sector * s_BlocksPerSector+ s_DbrOffset,
                                         (FS_DWORD)count * s_BlocksPerSector,
                                         (char *)buff))
    {
        return RES_ERROR;
    }
    else return RES_OK;


}


/*-----------------------------------------------------------------------*/
/* Write sector(s)                                                       */
/*-----------------------------------------------------------------------*/
動作未検証もの。
DRESULT disk_write (
    BYTE drv,            /* Physical drive number (0) */
    const BYTE *buff,    /* Ponter to the data to write */
    DWORD sector,        /* Start sector number (LBA) */
    BYTE count            /* Number of sectors to write (1..128) */
)
{

    if (drv || !count) return RES_PARERR;        /* Check parameter */
    else if (s_IsMediumConnect == FALSE) return RES_NOTRDY; /* no connection */
    else if (Stat & STA_NOINIT) return RES_NOTRDY;    /* Check if drive is ready */


    
    if (USBH_MSC_RET_OK != USBH_MSC_Write(s_MscDeviceAddr,
                                         0,
                                         (FS_DWORD)sector * s_BlocksPerSector+ s_DbrOffset,
                                         (FS_DWORD)count * s_BlocksPerSector,
                                         (char *)buff))
    {
        return RES_ERROR;
    }
    else return RES_OK;
  
}


/*-----------------------------------------------------------------------*/
/* Miscellaneous drive controls other than data read/write               */
/*-----------------------------------------------------------------------*/
動作未検証もの。
DRESULT disk_ioctl (
    BYTE drv,        /* Physical drive number (0) */
    BYTE ctrl,        /* Control command code */
    void *buff        /* Pointer to the conrtol data */
)
{
    DRESULT res;
    BYTE n, csd[16], *ptr = buff;
    WORD csize;
    DWORD *dp, st, ed;


    if (drv) return RES_PARERR;                    /* Check parameter */
    if (Stat & STA_NOINIT) return RES_NOTRDY;    /* Check if drive is ready */

    res = RES_ERROR;

    switch (ctrl) {


    case GET_SECTOR_COUNT :    /* Get drive capacity in unit of sector (DWORD) */
        *(WORD*)buff = s_max_lba ;
        res = RES_OK;
        break;

    case GET_SECTOR_SIZE :    /* Get sector size in unit of byte (WORD) */
        *(WORD*)buff = s_bytes_per_sector;
        res = RES_OK;
        break;

    case GET_BLOCK_SIZE :    /* Get erase block size in unit of sector (DWORD) */
        *(WORD*)buff = s_bytes_per_block;
        res = RES_OK;
        break;


    default:
        res = RES_PARERR;
    }



    return res;
}

/*-----------------------------------------------------------------------*/
/* Device Timer Driven Function                                          */
/*-----------------------------------------------------------------------*/
/* This function must be called from timer interrupt routine in period
/  of 1 ms to generate card control timing.
*/
/*** 以下の関数の機能(USBメモリーの有無、抜き差し検出)は  USBHost callback function  の中の処理でおこなうようにする。  */
//void disk_timerproc (void)



====================================================================================


☆周波数の設定

timer.c
STATUS TIMER_SetCh1Cycle(uint32_t Cycle)

   /* calculating the reload value */
    value = (uint32_t)TIMER_PER_CLOCK * (uint32_t)Cycle;

    switch( Cycle )
    {
       case 22:  value = 1632;  //   72000000Hz/44100Hz 正確には一致しない だいたい同じ
                 break;
       case 20:  value = 1500;  // =72000000Hz/48000Hz
                 break;
       case 31:  value = 2250;  // =72000000Hz/32000Hz
                 break;

       default: break;
    }

=================================================================================
☆JOYSTICKのボタン・キー入力の変更

P7D/CN2-29
PF0/CN2-30
に、JOYSTICのPSW2とleftを割り付ける。

(1)joystick_config.h   ディレクトリーled_swの中にある。
/* the data registers related to joystick specifications */

/*
#define JOYSTICK_RIGHT_PDR  (bFM3_GPIO_PDIR3_P1)  */  /* data register of right button  */


/* key1 and key2 */
#define JOYSTICK_PSW2_PDR   (bFM3_GPIO_PDIR7_PD)   /* data register of PSW2 button  */
#define JOYSTICK_LEFT_PDR   (bFM3_GPIO_PDIRF_P0)    /* data register of left button   */



/* the direction registers related to joystick specifications */
/*
#define JOYSTICK_RIGHT_DDR  (bFM3_GPIO_DDR3_P1)    */ /* direction register of right button  */


/* key1 and key2 */
#define JOYSTICK_PSW2_DDR   (bFM3_GPIO_DDR7_PD)     /* direction register of PSW2 button  */
#define JOYSTICK_LEFT_DDR   (bFM3_GPIO_DDRF_P0)      /* direction register of left button   */

(2)usbhost_demoapp.c
static void usbhost_demoapp_joystick_process(void)
{
#if 1

if 1 else 文の elseの位置を、joystick のボタンbuttonキーの応答にも動くように、 変更する。
//#else
    /* if psw2 button of joystick has been detected, then do process for psw2 button */
    if (s_IsJoystickButtonDetected[JOYSTICK_BUTTON_PSW2] == TRUE)
    {

    /* if left button of joystick has been detected, then do process for left button */
    if (s_IsJoystickButtonDetected[JOYSTICK_BUTTON_LEFT] == TRUE)
    {

   }
#else


=================================================================================
☆TDA1543のDACへの出力の追加

TIOA01_2/P53/CN2-22   LRCK 
タイマーCH1の、4MHzの発振を元に、PLLと分割とカウンターを使って出力。理論上、44100Hzの周波数は、少しずれる。

SCK1_1 /P13/CN1-42     BCK相当の信号。 
SOT1_1 /P12/CN1-41     DATA
SPIモードで、SCK1_1から固定周波数3MHz?のクロックで、SOT1_1から(8ビット+8ビット)を LとR 合計2回分送っている。 

(1)usbhost_demoapp.c

DAC出力用のポートの設定
void init_dac(void)
{
  /* TIOA01_2/P53 (CN2-22) for DAC LRCK */  注意:P56のCH9から P53 CH1へ変更した。
  FM3_GPIO->PFR5_f.P3    = 1; // peripheral function on P53
  FM3_GPIO->EPFR04_f.TIOA1E0 = 1; // enable TIOA01_2 on P53
  FM3_GPIO->EPFR04_f.TIOA1E1 = 1; // enable TIOA01_2 on P53

  /* setup Multi Function Serial unit 1 (MFS1) as CSIO (SPI) mode
   for serial interface 16-bit digital audio DAC
   P12/SOT1_1 (CN1-41) ---> DAC_SDAT
   P13/SCK1_1 (CN1-42) ---> DAC_SCLK  */

  FM3_GPIO->PFR1_f.P2 = 1; // peripheral function on P12
  FM3_GPIO->PFR1_f.P3 = 1; // peripheral function on P13
  FM3_GPIO->ADE_f.AN2 = 0; // P12/AN02 as digital pin
  FM3_GPIO->ADE_f.AN3 = 0; // P13/AN03 as digital pin  
  FM3_GPIO->EPFR07_f.SOT1B1 = 1; // enable SOT1_1 on P12
  FM3_GPIO->EPFR07_f.SCK1B1 = 1; // enable SCK1_1 on P13

 /* setup for CSIO (SPI) mode  *//* ch 1 has No fifo  */
  FM3_MFS1_CSIO->SCR        = 0x00; // disable Tx and Rx
  FM3_MFS1_CSIO->ESCR= 0x00;  // 8bit, not wait
  FM3_MFS1_CSIO->SMR        = 0x40; // select CSIO mode
  FM3_MFS1_CSIO->SCR_f.SPI  = 1;    // SPI mode
  FM3_MFS1_CSIO->SMR_f.SCINV= 1;    // SPI mode (II)
  FM3_MFS1_CSIO->SMR_f.BDS  = 1;    // MSB first
  FM3_MFS1_CSIO->SMR_f.SCKE = 1;    // SCK out enable
  FM3_MFS1_CSIO->SMR_f.SOE  = 1;    // Serial data out enable


  /* --------------------------------- */
  /*   fs=48Khz 32slots => 1.536Mhz         */
  FM3_MFS1_CSIO->BGR        = 23;   // SCK = 72 [MHz] / (23+1) = 3 [MHz]
  FM3_MFS1_CSIO->SCR_f.TXE  = 1;    // enable Tx
}


/* add */
    init_dac();

    /* timer module initialize */
    TIMER_Init();


(2)wav.c
static uint8_t            s_WavDataBuf[WAV_BUFFER_SIZE];/* data buffer                */

/*  add */
int16_t LRch0[5];  /* global, 2 3 buffer */   LRch0[2]とLRch0[3]に出力データをためてから、1タイミングおくれてDACへ出力する。
static int16_t bit_shift0, bit_shift1;   /* I2Sフォーマットの最後のLSBをLRCK変化後に出力させるため、データを1ビットシフトさせる。前のデータのシフト分を これに記憶しておく。


STATUS WAV_Start(void)
{
    uint8_t ret = WAV_RET_ILLEGAL_ERROR;           /* return value */

    /* WAV output status is analyzed status */
    if (s_WavStatus == WAV_STATUS_ANALYZE)
    {

/* add */
bit_shift0=0;
bit_shift1=0;
LRch0[0]=0; LRch0[1]=0; LRch0[2]=0; LRch0[3]=0;


STATUS WAV_UpdateWavOnDuty(void)
{
    uint8_t  loop_cnt;                     /* loop counter */
    uint16_t data[2] = {0, 0};             /* temp data    */
    uint8_t  ret = WAV_RET_ILLEGAL_ERROR;  /* return value */

if( FM3_GPIO->PDIR5_f.P3 == 0)  /* Low , Lch Output */
{
  /* WAV output status is outputing status */
    if (s_WavStatus == WAV_STATUS_OUTPUTING)
    {
        /* WAV data is enough */
        if ((WAV_BUFFER_SIZE - s_BufEmptySize) >= (((s_WavFmtInfo.BitsWidth) / 8U) * (s_WavFmtInfo.Channels)))
        {
            /* set On-Duty of PWM using for WAV output */
            for (loop_cnt = 0; loop_cnt < s_WavFmtInfo.Channels; loop_cnt++)
            {
                /* significant bits per sample is 8 bits */
                if (s_WavFmtInfo.BitsWidth == BITSWIDTH_8BIT)
                {
                    /* get 1 byte On-Duty data from data buffer */
                    data[loop_cnt] = s_WavDataBuf[s_BufReadIndex];



          LRch0[loop_cnt + 2]=s_WavDataBuf[s_BufReadIndex];
          LRch0[loop_cnt + 2] = (LRch0[loop_cnt + 2] << 8);       


                    /* convert On-Duty data from 8 bits to 16 bits */
                    data[loop_cnt] = (data[loop_cnt] << 8);

                    /* update read index */
                    if ((s_BufReadIndex + 1) < WAV_BUFFER_SIZE)
                    {
                        s_BufReadIndex++;
                    }
                    else
                    {
                        s_BufReadIndex = (s_BufReadIndex + 1) - WAV_BUFFER_SIZE;
                    }

                    /* empty size of data buffer increment */
                    s_BufEmptySize++;
                }
               /* significant bits per sample is 8 bits */

                else
                {
                    /* get 2 bytes On-Duty data from data buffer */
                    /* 16bit adjustment method :  [-32768, +32767] -> [0, 65535] */
                    if ((s_BufReadIndex + 1) < WAV_BUFFER_SIZE)
                    {
                        data[loop_cnt] = (uint16_t)((int16_t)MAKEHWORD(s_WavDataBuf[s_BufReadIndex + 1],
                                                                       s_WavDataBuf[s_BufReadIndex]) + SIGNED_16BIT_MIN_NUM);

               LRch0[loop_cnt+2]=MAKEHWORD(s_WavDataBuf[s_BufReadIndex + 1], s_WavDataBuf[s_BufReadIndex]);
                  
                    }
                    else
                    {
                        data[loop_cnt] = (uint16_t)((int16_t)MAKEHWORD(s_WavDataBuf[(s_BufReadIndex + 1) - WAV_BUFFER_SIZE],
                                                                       s_WavDataBuf[s_BufReadIndex]) + SIGNED_16BIT_MIN_NUM);

               LRch0[loop_cnt +2]=MAKEHWORD(s_WavDataBuf[(s_BufReadIndex + 1) - WAV_BUFFER_SIZE],s_WavDataBuf[s_BufReadIndex]);
              
                    }

                    /* update read index */
                    if ((s_BufReadIndex + 2) < WAV_BUFFER_SIZE)
                    {
                        s_BufReadIndex += 2;
                    }
                    else
                    {
                        s_BufReadIndex = (s_BufReadIndex + 2) - WAV_BUFFER_SIZE;
                    }

                    /* update empty size of data buffer */
                    s_BufEmptySize += 2;
                }
            }
            /* wav file is monaural */
            if (s_WavFmtInfo.Channels == CHANNELS_MONAURAL)
            {
                /* set On-Duty of ch.1 PWM */
                (void)PWM_SetOnDuty(s_UsePwmChannel[LEFT_CHANNEL], data[0]);
            }
            /* wav file is stereo */
            else
            {
#if (WAV_STEREO_LEFT == 1)
                /* set On-Duty of left channel PWM */
                (void)PWM_SetOnDuty(s_UsePwmChannel[LEFT_CHANNEL], data[0]);
#endif

#if (WAV_STEREO_RIGHT == 1)
                /* set On-Duty of right channel PWM */
                (void)PWM_SetOnDuty(s_UsePwmChannel[RIGHT_CHANNEL], data[1]);
#endif
            }


  /* if MONO */
    if( s_WavFmtInfo.Channels == 1) LRch0[3]=LRch0[2];

    /* data is 1 bit shift for I2S output */
    bit_shift1= ((LRch0[2] & 0x0001) << 15);
    LRch0[2] = bit_shift0 | ((LRch0[2] >> 1) & 0x7fff);
    bit_shift0= ((LRch0[3] & 0x0001) << 15);
    LRch0[3] = bit_shift1 | ((LRch0[3] >> 1) & 0x7fff);


            /* set return value to successfully complete */
            ret = WAV_RET_OK;
        }
        else
        {
            /* set return value to buffer empty */

    debug_printf("-error: ring buffer underflow !\n");
            ret = WAV_RET_BUF_EMPTY;
        }
    }
}
else  /* end of if( FM3_GPIO->PDIR5_f.P3 == 0)  Low , Lch Output */
{  /* Rch Output */
 
}
    return (ret);
}

(3)timer.c
static uint8_t s_CallbackRegCnt[TIMER_CH_MAX];

/* add */
/* global in wav.c */
extern int16_t LRch0[5];


    /* add */
    /* Change fs to 2*fs because to make LRCK Low and High pattern */
    value=value/2;

    /* get higher 16 bit of reload value */
    hi_value = HIHWORD(value);
 


void TIMER_RldIRQHandler(void)
{
    uint16_t  i;                                   /* loop counter */

    /* underflow interrupt request of ch.0 reload timer is generated */
    if (bFM3_BT0_RT_STC_UDIR == BIT_SET)
    {
        /* clear underflow interrupt flag */
        bFM3_BT0_RT_STC_UDIR = BIT_CLR;

        /* check each element of callback table  */
        for (i = 0; i < s_CallbackRegCnt[TIMER_CH0]; i++)
        {
            /* interrupt generation counter increment */
            s_CallBackTable[TIMER_CH0][i].Cnt++;

            /* if reached callback interval then to do below */
            if (s_CallBackTable[TIMER_CH0][i].Interval == s_CallBackTable[TIMER_CH0][i].Cnt)
            {
                /* call callback function */
                s_CallBackTable[TIMER_CH0][i].Function(s_CallBackTable[TIMER_CH0][i].Context);
                /* clear interrupt generation counter */
                s_CallBackTable[TIMER_CH0][i].Cnt = BIT_CLR;
            }
        }
    }
    /* underflow interrupt request of ch.1 reload timer is generated */
    else if (bFM3_BT1_RT_STC_UDIR == BIT_SET)
    {
        /* clear underflow interrupt flag */
        bFM3_BT1_RT_STC_UDIR = BIT_CLR;

   /* add */
   if( FM3_GPIO->PDIR5_f.P3 == 0)  /* Low , Lch Output */
   {
    FM3_MFS1_CSIO->TDR = (LRch0[0] >> 8); // L ch high byte
    LRch0[4]=LRch0[0];  /* dummy operation, jikan kazegi */
    FM3_MFS1_CSIO->TDR =  LRch0[0];       // L ch low  byte
   }
   else
   { /* Rch Output */
      FM3_MFS1_CSIO->TDR = (LRch0[1] >> 8); // R ch high byte
      LRch0[4]=LRch0[1];  /* dummy operation, jikan kazegi */
      FM3_MFS1_CSIO->TDR =  LRch0[1];       // R ch low  byte
   }

        /* check each element of callback table  */
        for (i = 0; i < s_CallbackRegCnt[TIMER_CH1]; i++)
        {
            /* interrupt generation counter increment */
            s_CallBackTable[TIMER_CH1][i].Cnt++;

            /* if reached callback interval then to do below */
            if (s_CallBackTable[TIMER_CH1][i].Interval == s_CallBackTable[TIMER_CH1][i].Cnt)
            {
                /* call callback function */
                s_CallBackTable[TIMER_CH1][i].Function(s_CallBackTable[TIMER_CH1][i].Context);
                /* clear interrupt generation counter */
                s_CallBackTable[TIMER_CH1][i].Cnt = BIT_CLR;
            }
        }

   /* add */
   if( FM3_GPIO->PDIR5_f.P3 == 0)  /* Low , Lch Output */
   {
   }
   else
   { /* Rch Output */
       /* for next */
       LRch0[0]=LRch0[2];
       LRch0[1]=LRch0[3];
   }

    }
    else
    {
        ; /* do nothing */
    }
}

44100HzのWAVファイル再生で、どこかでデータが異常になって、出力される音がノイズだらけになるので、
試しに、以下のバッファ容量を増加(アップ)してみる。
=================================================================================
☆リングバッファの容量アップ

(1)wav_config.h

/* data buffer size setting */
/* #define WAV_BUFFER_SIZE         (512U)  */      /* data buffer size */
                                              /* 1~65535 */
/******************************/
/* Ring Buffer Size 1152*2(channels)*2(btyes) =  4608 */
#define WAV_BUFFER_SIZE (4608U)


 つでに、USBメモリーからの読み出しブロック容量もアップ。 
但し、 DATA_BLOCK_SIZE は WAV_BUFFER_SIZEより 小さいこと。
(2)usbhost_demoapp.c
/* data block size using for fill WAV data buffer */
/*#define DATA_BLOCK_SIZE          (256U) */ /* 256 Byte (process time:32ms) */
                                         /* note: 256 * (1 / BytePerSec) */

/**********************************/
/* F_read data block size         */
#define DATA_BLOCK_SIZE  (1024U)     


=================================================================================
☆Libmadのリンクの概要 
多くの変更をしたため どこを直したか分からなくなってしまった。そこで、変更内容の概要だけを
メモ書きとして残しておく。

インターフェイス2012年7月号の記事(FM3マイコン基板を使ったMP3プレーやの製作)のソフトがもとになっている。

①Makefileに libmadの必要なファイルを追加する。
CSRC += libmad-0.15.1b/bit.c
CSRC += libmad-0.15.1b/decoder.c
CSRC += libmad-0.15.1b/fixed.c
CSRC += libmad-0.15.1b/frame.c
CSRC += libmad-0.15.1b/huffman.c
CSRC += libmad-0.15.1b/layer12.c
CSRC += libmad-0.15.1b/layer3.c
CSRC += libmad-0.15.1b/minimad.c
CSRC += libmad-0.15.1b/stream.c
CSRC += libmad-0.15.1b/synth.c
CSRC += libmad-0.15.1b/timer.c

②mallocをどうするか? 同じような機能のプログラムが2個存在してしまう。
叉、確保できるメモリー容量を再設定する。メモリー容量が大きすぎるとプログラム開始後に暴走する。
*容量を必要最小限に抑えても、decode を呼ぶと 暴走してしまう時がある。メモリー破壊が起きているようだ。
CSRC += libmad-0.15.1b/sbrk.c   libmadの中のもの
#CSRC += example/source/malloc.c fm3_sample_usbhostの中のもの
③型名などコンパイル時にエラーになったときは 該当するヘッダーファイルを追記するなど調整する。
④その他 必要なこと。


(1)usbhost_demoapp.c
/* for libmad ****************************/
extern int decode(unsigned char const *start, unsigned long length);
int play_mp3(char *filename);
FIL fobj;
#define MP3_WORK_SIZE (1152*2*2)   
static unsigned char mp3_work[MP3_WORK_SIZE]; 
static unsigned char *next_header;
int32_t MP3_flag[5];    //[0] 3: MP3, 0: WAV, MP3's [1]sampling frequecny,[2] bits, [3] channels
extern int output_counter0;
/* for libmad ****************************/
int play_mp3(char *filename)
{
    int i;

    /* buffer for read wav file */
    static uint8_t s_wav_read_buffer[2];  // this is dummy declare, only use declare
    /* header size of wav file:from start of file to offset of data of data chunk */
    static uint8_t  wav_header_length = 0;

    FRESULT res;
    int  version_mp3;
    int  layer_mp3;
    int  channel_mp3;
    int  dwBitRate_mp3;
    int  dwSampleRate_mp3;
    int  dwSampleTable[][3] = {
        {44100, 48000, 32000}, // MPEG1
        {22050, 24000, 16000} // MPEG2
    };    
    DWORD dwBitTableLayer3[][16] = {
        {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}, // MPEG1
        {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0} // MPEG2
    };

    next_header = 0;
    res = f_open( &fobj, filename, FA_READ);

    if(res != FR_OK) goto play_return;
        else  debug_printf(" f_open mp3 file \n");

    res = get_header();
    if(res != FR_OK) goto play_return;
        else debug_printf(" skip header \n");

        /* check header start */
    if(mp3_work[0] != 0xff) goto play_return;


    if((mp3_work[1] & 0xf0) != 0xf0)
        {
           debug_printf("-mpeg v2.5 not suppor, return \n");
           goto play_return;
        }
        else
        {
          if((mp3_work[1] & 0x08) != 0x00)  version_mp3=1;
          else version_mp3=2;
          debug_printf(" mpeg version %d\n", version_mp3);

         
           layer_mp3=-999;
           if((mp3_work[1] & 0x06) == 0x02) layer_mp3=3;
           else if((mp3_work[1] & 0x06) == 0x04) layer_mp3=2;
           else if((mp3_work[1] & 0x06) == 0x06) layer_mp3=1;
           debug_printf(" mpeg layer %d\n", layer_mp3);
        }


        dwBitRate_mp3= (int) ((mp3_work[2] >> 4) & 0x0f);
        dwBitRate_mp3= dwBitTableLayer3[ version_mp3 -1 ][dwBitRate_mp3];
        debug_printf(" bit rate  %d\n",dwBitRate_mp3 );

        dwSampleRate_mp3= (int) ((mp3_work[2] >> 2) & 0x03);
        dwSampleRate_mp3= dwSampleTable[ version_mp3 -1 ][dwSampleRate_mp3];
        debug_printf(" sample rate  %d\n",dwSampleRate_mp3 );

        channel_mp3 = (int) (mp3_work[3] >> 6);
        switch( channel_mp3 )
        {
            case 0:
                    channel_mp3=2;
                    debug_printf(" stereo \n");
                    break;
            case 1:
                    channel_mp3=2;
                    debug_printf(" joint sterro \n");
                    break;
            case 2:
                    channel_mp3=2;
                    debug_printf(" dual channel (stereo) \n");
                    break;
            case 3:
                    channel_mp3=1;
                    debug_printf(" mono \n");
                    break;
            default:
                debug_printf(" error, in play_mp3 \n");   
        }

        MP3_flag[0]=3;
        MP3_flag[1]=dwSampleRate_mp3;
        MP3_flag[2]=dwBitRate_mp3;
        MP3_flag[3]=channel_mp3;

        next_header = mp3_work;


            /* analyze WAV file header */
            if (WAV_Analyze(s_wav_read_buffer, &wav_header_length, &s_WavHeaderInfo) == WAV_RET_OK)
            {
               debug_printf("+call WAV_Analyze()\n");
              /* set wav play stage to playing stage */
              s_WavPlayStage = WAVPLAY_STAGE_PLAYING;
            }

           /* start individual timer of specified channel */
           (void)TIMER_Start(TIMER_CH1);
          /* start WAV output operation */
          (void)WAV_Start();    
    
        debug_printf("+call decode in mp3_play\n");
        decode((unsigned char const *)mp3_work, (unsigned long)MP3_WORK_SIZE);
        usbhost_demoapp_stop_wav();
        res = f_close(&fobj);

    if(res != FR_OK) goto play_return;

play_return:
    return (int)res;
}

get_header
read_frame
copy_next_header
get_next_frame
の各functionの内容もusbhost_demoapp.cに書き足しておく。


(2)minimad.c 

extern  unsigned char get_char(void);
extern unsigned char  WAV_FillBuffer(const unsigned char *pWaveData, unsigned short  WaveDataSize);
extern unsigned char  WAV_GetBufferEmptySize(unsigned short  *pBufferEmptySize);
int output_counter0=0;
static
enum mad_flow output(void *data,
             struct mad_header const *header,
             struct mad_pcm *pcm)
{
  unsigned int nchannels, nsamples;
  mad_fixed_t const *left_ch, *right_ch;
  unsigned short  wav_empty_buf_size, wav_size0x;          /* buffer empty size */
  int i,l0, sample0;
  unsigned char c;
 
  short *ps0; 
  char  *cp0;
 
  /* pcm->samplerate contains the sampling frequency */

  nchannels = pcm->channels;
  nsamples  = pcm->length;    // number of sample
  left_ch   = pcm->samples[0];
  right_ch  = pcm->samples[1];

  ps0=(short *) pcm->samples[0];
  cp0=(char *) pcm->samples[0];

  output_counter0 += nsamples;
  l0= nsamples;
 

 データを16ビットのLとRの順に並べ替えをしている。
  for(i=0;i<l0;++i)
  {
      *ps0++ = scale( *left_ch++);
      if (nchannels == 2)
      {
        *ps0++ = scale( *right_ch++);      
      }
  }

    wav_size0x = (short)l0 * sizeof(short);
    if(nchannels==2) wav_size0x = 2 * wav_size0x;
   do
   {
      /* get buffer empty size */
      WAV_GetBufferEmptySize(&wav_empty_buf_size);
      if (wav_empty_buf_size >=  wav_size0x )
      {
       /* fill data buffer with specified WAV data from offset of data chunk */
         WAV_FillBuffer(cp0, wav_size0x  );
          break;
      }
  } while (wav_empty_buf_size <  wav_size0x  );

MP3デコード出力データがそろったときに、入力を確認すると云う 美しくないプログラムになっている。
     c = get_char();
     switch (c)
     {
       case '0':
             debug_printf("+call MAD_FLOW_STOP in  mad_flow output, nsample= %d nch= %d \n",nsamples,nchannels);
             return MAD_FLOW_STOP; break;
      case  '9':
             debug_printf(" output_counter0= %d \n", output_counter0);

wav_empty_buf_sizeがリングバッファの容量に近いときは、デコードが間に合っていないことを示すと考えられる。
wav_empty_buf_size,がwav_size0xと(だいたい)同じときは、処理は間に合っていている(余裕がある。)と考えられる。
             debug_printf(" wav_empty_buf_size =%d wav_size0x= %d \n", wav_empty_buf_size, wav_size0x);
             break;
      default:
             break;
     }
  return MAD_FLOW_CONTINUE;
}


(3)wav.c

extern int32_t MP3_flag[5];

WAV_Analyze


   int i0;
 
if( MP3_flag[0] == 3)
{
                        pWavHeader->FmtChunk.Channels =MP3_flag[3];
                        pWavHeader->FmtChunk.BitsWidth=MP3_flag[2];
                        pWavHeader->FmtChunk.SampleRate=MP3_flag[1];


                        /* set WAV format information */
                        s_WavFmtInfo.Channels = pWavHeader->FmtChunk.Channels;
                        s_WavFmtInfo.BitsWidth = pWavHeader->FmtChunk.BitsWidth;
                        s_WavFmtInfo.SampleRate = pWavHeader->FmtChunk.SampleRate;


    debug_printf(" Channels %d, Bits %d, SampleRate %d\n",s_WavFmtInfo.Channels , s_WavFmtInfo.BitsWidth, s_WavFmtInfo.SampleRate);



                                 /* set timer cycle */
                                /****************************************************/
                                timer_cycle /= s_WavFmtInfo.SampleRate;
                                if (pWavHeader->FmtChunk.SampleRate == SAMPLE_RATE_192000) timer_cycle=4;
                                TIMER_SetCh1Cycle((uint16_t)timer_cycle);

                               
                                 /*                             */
                                 /* Regist as one call back function of Timer Ch1, here ! */
                                 /*                                                       */
                                 /* register callback function with update the OnDuty of data from data buffer to timer module */
                                (void)TIMER_Callback_Reg(TIMER_CH1, (TIMER_CallbackIrq*)&WAV_UpdateWavOnDuty, 1, NULL);

                                /* set size of WAV header data */
                                /////*pWavHeadDataSize = WAV_HEADER_LENGTH + delta;

                                /* set WAV output status to analyzed status */
                                s_WavStatus = WAV_STATUS_ANALYZE;

                                /* set return value to successfully complete */
                                ret = WAV_RET_OK;

                                /*************************************************************/
                                /*                                                           */
                                /* Only For MP3, at first, fill WavDataBuf zero data         */
                                /*                                                           */
                                /* s_WavDataBuf[WAV_BUFFER_SIZE]; data buffer                */
                                for(i0=0;i0<WAV_BUFFER_SIZE;++i0) s_WavDataBuf[i0]=0;
                                /* empty size of data buffer initialize */
                                s_BufEmptySize = 0;   //WAV_BUFFER_SIZE;
                                /* write index initialize */
                                s_BufWriteIndex = WAV_BUFFER_SIZE;  //0;
}
else
{
    /* check parameter */
    if ( (pWavHeadData != NULL) && (pWavHeader != NULL) && (pWavHeadDataSize != NULL)    )
    {


(4)wav_config.h
リングバッファの容量をアップしてみたが、音が抜ける問題には効果がないみたい。
/******************************/
/* Ring Buffer Size 1152*2(channels)*2(btyes) =  4608 */
#define WAV_BUFFER_SIZE (10240U)   // 10k


=================================================================================

☆PHY IC DP83848C の使用

(1)PHY.h
/* add for DP83848C*/
#define PHY_REG_MICR        17    //MICR 0x11
#define PHY_REG_MISR        18    //MISR 0x12
#define DP83848C_ADDR   0x01    // add

//#define LAN8187_ID
//#define ICS1894_ID

#ifdef DP83848C                                        // add
#define PHY_ADDR        DP83848C_ADDR
#endif


(2)fm3_ether.c

void PHY_Init(void)

        debug_printf("PHY: IntOut initialize NG\n");
    }
#endif


#ifdef DP83848C   // add 
        // LED mode1 
        // LINK LED GOOD ON, NG OFF

        //Write 0003h to MICR to set INTEN and INT_OE PHY ICの割り込みの設定をしている
     if (PHY_Write(PHY_ADDR, PHY_REG_MICR, 0x0003, MII_WR_TOUT) == TRUE) {
        debug_printf("PHY: MICR initialize OK\n");
    } else {
        debug_printf("PHY: MICR initialize NG\n");
    }      

        //Write  to MISR to set LINK_INT_EN  割り込みの要因の設定
     if (PHY_Write(PHY_ADDR, PHY_REG_MISR, 0x0020, MII_WR_TOUT) == TRUE) {
        debug_printf("PHY: MISR initialize OK\n");
    } else {
        debug_printf("PHY: MISR initialize NG\n");
    }   
#endif

(3)fm3_exti.c

void EXTI_Init(void)



#ifdef DP83848C 
       debug_printf("EXTI_Init()\n");
    FM3_GPIO->PFRA |= 0x00000010;    // PA4周辺ピン設定 ok
    FM3_GPIO->EPFR06 = 0x00000000;    // INT03_0を選択 default is OK
    FM3_EXTI->ENIR = 0x00000000;    // 外部割込み許可レジスタをクリア

PHYモジュールからの割り込みの論理が逆になっている。
    FM3_EXTI->ELVR = 0x000000C0;    // 外部割込み要求レベルレジスタでINT3の 立下がりエッジを検出 chg ok
    FM3_EXTI->EICL = 0x00000000;    // 外部割込み要因クリアレジスタをクリア
    FM3_EXTI->ENIR = 0x00000008;    // 外部割込み許可レジスタでINT03を許可 ok
    NVIC_EnableIRQ(EXINT0_7_IRQn);
    NVIC_SetPriority(EXINT0_7_IRQn, FM3_EXTI_PRIORITY);
    //NVIC_EnableIRQ(EXINT8_31_IRQn);
    //NVIC_SetPriority(EXINT8_31_IRQn, FM3_EXTI_PRIORITY);
#else
    //debug_printf("EXTI_Init()\n");
    FM3_GPIO->PFRA |= 0x00000030;    // PA4, PA5を周辺ピン設定
   (中略)
#endif

(4)void PHY_Interrupt(void) FM3側の割り込み処理。 動作がまだおかしい。

#ifdef DP83848C
        PHY_Read(PHY_ADDR, PHY_REG_MISR,&reg23, MII_RD_TOUT);    // Clear INt state
        if( reg23 & 0x2000) debug_printf("PHY: LINK INT HAPPEN \n");
        PHY_Read(PHY_ADDR, PHY_REG_STS, &reg23, MII_RD_TOUT);    // get stauts info
#else
    PHY_Read(PHY_ADDR, PHY_REG_23, &reg23, MII_RD_TOUT);    // LINK状態の取得
#endif

  以下はまだ未完全である。
    debug_printf("PHY_REG_STS= %08x\n", reg23);
    if (reg23 & 1) {
        debug_printf("PHY: Link Up\n");
    } else if (reg23 & 4) {
        debug_printf("PHY: Link Down\n");
    } else {
        debug_printf("External Interrupt\n");
    }

#ifdef DP83848C
         PHY_Write(PHY_ADDR, PHY_REG_MISR, 0x0020, MII_RD_TOUT);    // set INT again
#else
    PHY_Write(PHY_ADDR, PHY_REG_23, reg23, MII_WR_TOUT);    // LINK状態のクリア
    //PHY_Read(PHY_ADDR, PHY_REG_23, &reg23, MII_RD_TOUT);
    //debug_printf("PHY23 %08x\n", reg23);
#endif

=========================================================================================

☆uIP WebClientを動かす

WebClient を動かすためには まず resolvが動いていること。
resolvを動かすために、UDPを使うので
uip.h uip.c main.cの中の
#if UIP_UDP

#endif
のプログラム文を生かすように変更する。

宣言が喧嘩するものがあるので、WebServerは止める。

コンパイルすると 色々なエラーがでるので コンパイラgccが通過するように変更する。

例えば、webclient.c で 左辺 lvalue がない というエラーがでるので
parse_statusline(u16_t len)
  char *p0;
    p0=(char *)uip_appdata; p0++;  uip_appdata=p0;
    /*  ++((char *)uip_appdata); */
正しくないかもしれないが、gccが通過するように変更してみた。


(1)Makefile
#CSRC += ../../uip/apps/webserver/httpd.c
#CSRC += ../../uip/apps/webserver/httpd-cgi.c
#CSRC += ../../uip/apps/webserver/httpd-fs.c
#CSRC += ../../uip/apps/webserver/http-strings.c

CSRC += ../../uip/apps/webclient/webclient.c
CSRC += ../../uip/apps/webclient/webclient-strings.c
CSRC += ../../uip/apps/resolv/resolv.c

CINCS += ../../uip/apps/webclient
CINCS += ../../uip/apps/resolv

(2)uip-conf.h
/* #include "webserver.h" */
/*#include "dhcpc.h"*/
#include "resolv.h"
#include "webclient.h"

(3)main.c
  /* httpd_init(); */  ←WebServerはお休み。

    webclient_init();
    resolv_init();
    uip_ipaddr(ipaddr, 192,168,1,???); ← DNSのためのアドレスを設定
    resolv_conf(ipaddr);
   resolv_query("www.yahoo.com"); ← 接続したいホスト名を記入
   

resolv_found()
 webclient_get("www.yahoo.com", 80, "/"); ← データを受信GETするための 接続したいホスト名とポート番号とディレクトリー名を記入


webclient_getの起動が成功した場合、受信したデータ量を表示するプログラム

static int disp_c0=0;

webclient_datahandler(char *data, u16_t len)

  char test1[31];

  if(  disp_c0 == 0)
  {
     printf("Webclient: got %d bytes of data. of nth %d\n", len, disp_c0);
     for(i=0;i<30;++i)
     {
       test1[i]=data[i];
     }
     test1[30]=0x00;
     printf("%s\n", test1); ← はじめの30文字だけ表示
   }
   else
   {
     printf("Webclient: got %d bytes of data. of nth %d\n", len, disp_c0);
  }
  disp_c0++;

(4)tapdev.c

tapdev_init()

/////#elif defined(ICS1894) || defined(LAN8187)
#else    ← LAN8700以外は MY_MAC_ADDRを有効にする。

(5) uipopt.h
/**
 * The size of the uIP packet buffer.
 *
 * The uIP packet buffer should not be smaller than 60 bytes, and does
 * not need to be larger than 1500 bytes. Lower size results in lower
 * TCP throughput, larger size results in higher TCP throughput.
 *
 * \hideinitializer
 */

////#ifndef UIP_CONF_BUFFER_SIZE
////#define UIP_BUFSIZE     400
////#else /* UIP_CONF_BUFFER_SIZE */
////#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
////#endif /* UIP_CONF_BUFFER_SIZE */

#define UIP_BUFSIZE     1024  ←バッファ容量をここで設定するようにした

(6)webclient.c
WEBサーバーからのヘッダ部分を含む全データが欲しかったので、webclient.cのヘッダー解析部分はパスすることにした。また、もともと このヘッダー解析部分は上手く動いていないし。

parse_statusline(u16_t len)
{
  char *cptr;

    /* change  to skip parse_statusline */ 
      s.httpflag = HTTPFLAG_NONE;
      s.httpheaderlineptr = 0;
      s.state = WEBCLIENT_STATE_HEADERS;
      return len;;


parse_headers(u16_t len)
{
  char *cptr;
  static unsigned char i;
 
 /* change  to skip parse_headers */ 
 s.state = WEBCLIENT_STATE_DATA;
 s.httpheaderlineptr = 0;
 return len;

=========================================================================================