⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3_playback.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** *             __________               __   ___. *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  / *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  < *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \ *                     \/            \/     \/    \/            \/ * $Id: mp3_playback.c,v 1.6 2004/03/02 11:32:59 linusnielsen Exp $ * * Code that has been in mpeg.c before, now creating an encapsulated play * data module, to be used by other sources than file playback as well. * * Copyright (C) 2004 by Linus Nielsen Feltzing * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/#include <stdbool.h>#include "config.h"#include "debug.h"#include "panic.h"#include <kernel.h>#include "mpeg.h" /* ToDo: remove crosslinks */#include "mp3_playback.h"#ifndef SIMULATOR#include "i2c.h"#include "mas.h"#include "dac.h"#include "system.h"#include "hwcompat.h"#endif/* hacking into mpeg.c, recording is still there */#ifdef HAVE_MAS3587Fenum{    MPEG_DECODER,    MPEG_ENCODER} mpeg_mode;#endif /* #ifdef HAVE_MAS3587F *//**** globals ****//* own version, independent of mpeg.c */static bool paused; /* playback is paused */static bool playing; /* We are playing an MP3 stream */#ifndef SIMULATOR/* for measuring the play time */static long playstart_tick;static long cumulative_ticks;/* the registered callback function to ask for more mp3 data */static void (*callback_for_more)(unsigned char**, int*);#endif /* #ifndef SIMULATOR */static char *units[] ={    "%",    /* Volume */    "dB",   /* Bass */    "dB",   /* Treble */    "%",    /* Balance */    "dB",   /* Loudness */    "%",    /* Bass boost */    "",     /* AVC */    "",     /* Channels */    "dB",   /* Left gain */    "dB",   /* Right gain */    "dB",   /* Mic gain */};static int numdecimals[] ={    0,    /* Volume */    0,    /* Bass */    0,    /* Treble */    0,    /* Balance */    0,    /* Loudness */    0,    /* Bass boost */    0,    /* AVC */    0,    /* Channels */    1,    /* Left gain */    1,    /* Right gain */    1,    /* Mic gain */};static int minval[] ={    0,    /* Volume */    0,    /* Bass */    0,    /* Treble */    -50,  /* Balance */    0,    /* Loudness */    0,    /* Bass boost */    -1,   /* AVC */    0,    /* Channels */    0,    /* Left gain */    0,    /* Right gain */    0,    /* Mic gain */};static int maxval[] ={    100,  /* Volume */#ifdef HAVE_MAS3587F    24,   /* Bass */    24,   /* Treble */#else    30,   /* Bass */    30,   /* Treble */#endif    50,   /* Balance */    17,   /* Loudness */    10,   /* Bass boost */    3,    /* AVC */    6,    /* Channels */    15,   /* Left gain */    15,   /* Right gain */    15,   /* Mic gain */};static int defaultval[] ={    70,   /* Volume */#ifdef HAVE_MAS3587F    12+6, /* Bass */    12+6, /* Treble */#else    15+7, /* Bass */    15+7, /* Treble */#endif    0,    /* Balance */    0,    /* Loudness */    0,    /* Bass boost */    0,    /* AVC */    0,    /* Channels */    8,    /* Left gain */    8,    /* Right gain */    2,    /* Mic gain */};char *mpeg_sound_unit(int setting){    return units[setting];}int mpeg_sound_numdecimals(int setting){    return numdecimals[setting];}int mpeg_sound_min(int setting){    return minval[setting];}int mpeg_sound_max(int setting){    return maxval[setting];}int mpeg_sound_default(int setting){    return defaultval[setting];}/* list of tracks in memory */#define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */#define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1)#ifndef SIMULATORstatic bool mpeg_is_initialized = false;#endif#ifndef SIMULATORunsigned long mas_version_code;#ifdef HAVE_MAS3507Dstatic unsigned int bass_table[] ={    0x9e400, /* -15dB */    0xa2800, /* -14dB */    0xa7400, /* -13dB */    0xac400, /* -12dB */    0xb1800, /* -11dB */    0xb7400, /* -10dB */    0xbd400, /* -9dB */    0xc3c00, /* -8dB */    0xca400, /* -7dB */    0xd1800, /* -6dB */    0xd8c00, /* -5dB */    0xe0400, /* -4dB */    0xe8000, /* -3dB */    0xefc00, /* -2dB */    0xf7c00, /* -1dB */    0,    0x800,   /* 1dB */    0x10000, /* 2dB */    0x17c00, /* 3dB */    0x1f800, /* 4dB */    0x27000, /* 5dB */    0x2e400, /* 6dB */    0x35800, /* 7dB */    0x3c000, /* 8dB */    0x42800, /* 9dB */    0x48800, /* 10dB */    0x4e400, /* 11dB */    0x53800, /* 12dB */    0x58800, /* 13dB */    0x5d400, /* 14dB */    0x61800  /* 15dB */};static unsigned int treble_table[] ={    0xb2c00, /* -15dB */    0xbb400, /* -14dB */    0xc1800, /* -13dB */    0xc6c00, /* -12dB */    0xcbc00, /* -11dB */    0xd0400, /* -10dB */    0xd5000, /* -9dB */    0xd9800, /* -8dB */    0xde000, /* -7dB */    0xe2800, /* -6dB */    0xe7e00, /* -5dB */    0xec000, /* -4dB */    0xf0c00, /* -3dB */    0xf5c00, /* -2dB */    0xfac00, /* -1dB */    0,    0x5400,  /* 1dB */    0xac00,  /* 2dB */    0x10400, /* 3dB */    0x16000, /* 4dB */    0x1c000, /* 5dB */    0x22400, /* 6dB */    0x28400, /* 7dB */    0x2ec00, /* 8dB */    0x35400, /* 9dB */    0x3c000, /* 10dB */    0x42c00, /* 11dB */    0x49c00, /* 12dB */    0x51800, /* 13dB */    0x58400, /* 14dB */    0x5f800  /* 15dB */};static unsigned int prescale_table[] ={    0x80000,  /* 0db */    0x8e000,  /* 1dB */    0x9a400,  /* 2dB */    0xa5800, /* 3dB */    0xaf400, /* 4dB */    0xb8000, /* 5dB */    0xbfc00, /* 6dB */    0xc6c00, /* 7dB */    0xcd000, /* 8dB */    0xd25c0, /* 9dB */    0xd7800, /* 10dB */    0xdc000, /* 11dB */    0xdfc00, /* 12dB */    0xe3400, /* 13dB */    0xe6800, /* 14dB */    0xe9400  /* 15dB */};#endifbool dma_on;  /* The DMA is active */#ifdef HAVE_MAS3507Dstatic void mas_poll_start(int interval_in_ms){    unsigned int count;    count = (FREQ * interval_in_ms) / 1000 / 8;    if(count > 0xffff)    {        panicf("Error! The MAS poll interval is too long (%d ms)\n",               interval_in_ms);        return;    }        /* We are using timer 1 */        TSTR &= ~0x02; /* Stop the timer */    TSNC &= ~0x02; /* No synchronization */    TMDR &= ~0x02; /* Operate normally */    TCNT1 = 0;   /* Start counting at 0 */    GRA1 = count;    TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */    /* Enable interrupt on level 5 */    IPRC = (IPRC & ~0x000f) | 0x0005;        TSR1 &= ~0x02;    TIER1 = 0xf9; /* Enable GRA match interrupt */    TSTR |= 0x02; /* Start timer 1 */}#elsestatic void postpone_dma_tick(void){    unsigned int count;    count = FREQ / 1000 / 8;    /* We are using timer 1 */        TSTR &= ~0x02; /* Stop the timer */    TSNC &= ~0x02; /* No synchronization */    TMDR &= ~0x02; /* Operate normally */    TCNT1 = 0;   /* Start counting at 0 */    GRA1 = count;    TCR1 = 0x23; /* Clear at GRA match, sysclock/8 */    /* Enable interrupt on level 5 */    IPRC = (IPRC & ~0x000f) | 0x0005;        TSR1 &= ~0x02;    TIER1 = 0xf9; /* Enable GRA match interrupt */    TSTR |= 0x02; /* Start timer 1 */}#endif#ifdef HAVE_MAS3587Fvoid demand_irq_enable(bool on){    int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);        if(on)    {        IPRA = (IPRA & 0xfff0) | 0x000b;        ICR &= ~0x0010; /* IRQ3 level sensitive */    }    else        IPRA &= 0xfff0;    set_irq_level(oldlevel);}#endif /* #ifdef HAVE_MAS3587F */void play_tick(void){    if(playing && !paused)    {        /* Start DMA if it is disabled and the DEMAND pin is high */        if(!(SCR0 & 0x80) && (PBDR & 0x4000))        {            SCR0 |= 0x80;        }        playback_tick(); /* dirty call to mpeg.c */    }}#pragma interruptvoid DEI3(void){    unsigned char* start;    int size = 0;    if (callback_for_more != NULL)    {        callback_for_more(&start, &size);    }        if (size > 0)    {        DTCR3 = size & 0xffff;        SAR3 = (unsigned int) start;    }    else    {        CHCR3 &= ~0x0001; /* Disable the DMA interrupt */    }    CHCR3 &= ~0x0002; /* Clear DMA interrupt */}#pragma interruptvoid IMIA1(void) /* Timer 1 interrupt */{    if(playing)        play_tick();    TSR1 &= ~0x01;#ifdef HAVE_MAS3587F    /* Disable interrupt */    IPRC &= ~0x000f;#endif /* #ifdef HAVE_MAS3587F */}#pragma interruptvoid IRQ6(void) /* PB14: MAS stop demand IRQ */{    SCR0 &= ~0x80;}#ifdef HAVE_MAS3587F#pragma interruptvoid IRQ3(void) /* PA15: MAS demand IRQ */{    /* Begin with setting the IRQ to edge sensitive */    ICR |= 0x0010;        if(mpeg_mode == MPEG_ENCODER)        rec_tick();    else        postpone_dma_tick();}#endif /* #ifdef HAVE_MAS3587F */static void setup_sci0(void){    /* PB15 is I/O, PB14 is IRQ6, PB12 is SCK0, PB9 is TxD0 */    PBCR1 = (PBCR1 & 0x0cff) | 0x1208;        /* Set PB12 to output */    or_b(0x10, &PBIORH);    /* Disable serial port */    SCR0 = 0x00;    /* Synchronous, no prescale */    SMR0 = 0x80;    /* Set baudrate 1Mbit/s */    BRR0 = 0x03;    /* use SCK as serial clock output */    SCR0 = 0x01;    /* Clear FER and PER */    SSR0 &= 0xe7;    /* Set interrupt ITU2 and SCI0 priority to 0 */    IPRD &= 0x0ff0;    /* set PB15 and PB14 to inputs */     and_b(~0x80, &PBIORH);     and_b(~0x40, &PBIORH);    /* Enable End of DMA interrupt at prio 8 */    IPRC = (IPRC & 0xf0ff) | 0x0800;        /* Enable Tx (only!) */    SCR0 |= 0x20;}#endif /* SIMULATOR */#ifdef HAVE_MAS3587Fstatic void init_playback(void){    unsigned long val;    int rc;    mp3_play_pause(false);        mas_reset();        /* Enable the audio CODEC and the DSP core, max analog voltage range */    rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);    if(rc < 0)        panicf("mas_ctrl_w: %d", rc);    /* Stop the current application */    val = 0;    mas_writemem(MAS_BANK_D0,0x7f6,&val,1);        do    {        mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);    } while(val);        /* Enable the D/A Converter */    mas_codec_writereg(0x0, 0x0001);    /* ADC scale 0%, DSP scale 100% */    mas_codec_writereg(6, 0x0000);    mas_codec_writereg(7, 0x4000);    /* Disable SDO and SDI */    val = 0x0d;    mas_writemem(MAS_BANK_D0,0x7f2,&val,1);    /* Set Demand mode and validate all settings */    val = 0x25;    mas_writemem(MAS_BANK_D0,0x7f1,&val,1);    /* Start the Layer2/3 decoder applications */    val = 0x0c;    mas_writemem(MAS_BANK_D0,0x7f6,&val,1);    do    {        mas_readmem(MAS_BANK_D0, 0x7f7, &val, 1);    } while((val & 0x0c) != 0x0c);    mpeg_sound_channel_config(MPEG_SOUND_STEREO);    mpeg_mode = MPEG_DECODER;    /* set IRQ6 to edge detect */    ICR |= 0x02;    /* set IRQ6 prio 8 */    IPRB = ( IPRB & 0xff0f ) | 0x0080;    DEBUGF("MAS Decoding application started\n");}#endif /* #ifdef HAVE_MAS3587F */#ifndef SIMULATOR#ifdef HAVE_MAS3507Dint current_left_volume = 0;  /* all values in tenth of dB */int current_right_volume = 0;  /* all values in tenth of dB */int current_treble = 0;int current_bass = 0;int current_balance = 0;/* convert tenth of dB volume to register value */static int tenthdb2reg(int db) {    if (db < -540)        return (db + 780) / 30;    else        return (db + 660) / 15;}void set_prescaled_volume(void){    int prescale;    int l, r;    prescale = MAX(current_bass, current_treble);    if (prescale < 0)        prescale = 0;  /* no need to prescale if we don't boost                          bass or treble */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -