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

📄 buffer.c

📁 这项工程将让您把自己的MP3播放器平台
💻 C
字号:
//++
//buffer.c - Disk Buffer Management Functions
//
// Copyright (C) 2005 by Spare Time Gizmos.  All rights reserved.
//
// This file is part of the Spare Time Gizmos' MP3 Player firmware.
//
// This firmware is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 59 Temple
// Place, Suite 330, Boston, MA  02111-1307  USA.
//
//DESCRIPTION:
//   Rather than fixed, statically allocated buffers for reading FATs, direct-
// ory data, and MP3 file data from the CF card, this code uses a somewhat more
// elaborate scheme.  A number (usually 4 or 8, depending on the MCU RAM size)
// of 512 byte buffers are allocated at system initialization time, and each one
// of these buffers has a buffer control block (aka BCB) associated with it.
// The BCBs themselves are stored in IDATA and each BCB keeps track of
//
//	* the address (in XDATA) of the associated 512 byte buffer
//	* a count of the bytes used in this buffer
//	* and a link to another BCB, for chaining BCBs together
//
//   All BCBs are initially put on a free list, and the code can pull buffers
// off of the free list as they are needed.  When the code is done with a
// buffer, it simply returns it to the free list.  Simple, no?  For playing
// MP3 data, the MP3DRQ code actually keeps another queue of buffers which
// contain MP3 data; the background process reads data from the file and
// places filled buffers on this queue, and the MP3DRQ code removes filled
// buffers, sends them to the STA013, and then puts them back on the free
// list.
//
//  Although it sounds complex, it's actually not that hard and this system
// does have a few advantages:
//
//  * Since the actual buffers in XDATA are always aligned on 512 byte boundaries,
//  the address arithmetic to calculate buffer indicies is greatly simplified.
//
//  * Since the BCBs themselves are stored in IDATA, entire buffers can be moved
//  from one list to another by manipulating single byte pointers.
//
//  * There are no special case conditions in the playing code for wrap around as
//  there would be with a circular buffer.
//
//  * It's easy for functions that need a temporary disk buffer (e.g. the ID3 tag
//  reader) to pull disk sector buffers "out of the rotation", use them for a
//  few moments, and then return them to the free pool.
//
//REVISION HISTORY:
// dd-mmm-yy    who     description
// 28-May-05	RLA	New file.
// 12-OCT-05	RLA	Implement cbReserved parameter for InitializeBuffers().
//			 Create as many buffers as we can, starting from the top
//			 of external RAM and working downwards...
// 19-Oct-05	RLA	Add STACKSLOCS hack to InitializeBuffers() for SDCC.
//--

// Include files...
#include <stdio.h>		// needed so DBGOUT(()) can find printf!
#include "standard.h"		// standard types - BYTE, WORD, BOOL, etc
#include "player.h"		// project wide (hardware configuration) declarations
#include "post.h"		// RAMSize(), et al...
#include "cfcard.h"		// needed for IDE_SECTOR_SIZE
#include "buffer.h"		// declarations for this module

// This is the free buffer queue...
PUBLIC PIBCB g_pFreeBufferList;

//   And this allocates idata space for the actual buffer control blocks.
// Note that this doesn't need to be public - all the rest of the modules
// interact with the BCBs by means of pointers which they obtain (or _should_
// obtain!) from the free buffer pool.
PRIVATE BUFFER_CONTROL_BLOCK IDATA m_aBufferControlBlocks[MAX_NUMBER_OF_BUFFERS];


//++
//   This routine will allocate XDATA RAM for the disk buffer pool.  The exact
// number of buffers that can be created is limited both by the size of XRAM
// and the number of buffer control blocks.  Although the buffers themselves
// are allocated in XDATA, the buffer control blocks (BCBs) themselves are stored
// in IDATA and there are a limited number of BCBs (currently 4) available.  Thus
// on a P89C664 processor with 1792 bytes of XDATA RAM, we can allocate only three
// buffers maximum, 1536 bytes, and the remaining BCBs go unused.  However, on the
// P89C668 MCU (7936 bytes of XDATA RAM) we can allocate only as many buffers as
// we have BCBs, and the remaining XRAM goes unused.
//
//   [BTW, the Philips marketing literature says the '664 has 2K of RAM and that
// the P89C668 has 8K.  Don't believe them - turns out they're counting the 256
// bytes of 8051 internal IDATA/DATA RAM in that total!  The actual amount of real
// XDATA memory is only 1792 or 7936 bytes!]
//
//   This routine uses the RAMSize() function to determine the amount of XDATA RAM
// and then allocates the buffers downward, starting from the highest RAM address,
// until we run out of RAM or BCBs, which ever comes first.  The cbReserved
// parameter specifies the number of bytes of XDATA that are to be reserved for
// static XDATA variables.  Remember that static variables are allocated by the
// linker from the bottom (lowest address) UP, which is why buffers are allocated
// top down.  For example, on a P89C664 MCU, with RAMSize() == 1536, and cbReserved
// == 512, we can fit two disk buffers.
//
//  Lastly, don't agonize too much over fine tuning the value of cbReserved.  For
// example, in the previous case, unless you can reduce cbReserved below 256 bytes
// (pretty much not possible in the current code), nothing will change.  Since disk
// buffers are always 512 bytes, whether cbReserved == 512, 600, 400 or even 300,
// there's still only room for two buffers.
//--
PUBLIC void InitializeBuffers (WORD cbReserved) STACKSLOCS
{
  BYTE i;  PXBYTE pbFree;
  pbFree = (PXBYTE) RAMSize();
  g_pFreeBufferList = NULL;
  DBGOUT(("Buffers allocated at"));
  for (i = 0;  i < MAX_NUMBER_OF_BUFFERS;  ++i) {
    pbFree -= IDE_SECTOR_SIZE;
    if ((WORD) pbFree < cbReserved) break;
    m_aBufferControlBlocks[i].pNext = g_pFreeBufferList;
    m_aBufferControlBlocks[i].pbBuffer = pbFree;
    m_aBufferControlBlocks[i].cbBuffer = 0;
    DBGOUT((" %04X", (WORD) pbFree));
    //DBGOUT(("InitializeBuffers: Buffer# %bd, pNext=0x%02bX, pbBuffer=0x%04X\n", 
    //  i, (BYTE) m_aBufferControlBlocks[i].pNext, (WORD) m_aBufferControlBlocks[i].pbBuffer));
    g_pFreeBufferList = &(m_aBufferControlBlocks[i]);
  }
  DBGOUT((" (%bd buffers) ...\n", (BYTE) i));
  //DBGOUT(("InitializeBuffers: m_pFreeBufferList=0x%02bX\n", (BYTE) m_pFreeBufferList));
}

//++
//   This routine is used for debugging memory leak problems.  It will show a
// list of the currently free buffers and, as a side effect, return a count
// of them...
//--
#ifdef DEBUG
PUBLIC BYTE ShowBufferPool (void)
{
  PIBCB piBCB;  BYTE bFree = 0;
  //DBGOUT(("Free buffers: "));
  for (piBCB = g_pFreeBufferList;  piBCB != NULL;  piBCB = piBCB->pNext) {
    //DBGOUT((" %04X", (WORD) (piBCB->pbBuffer)));
    ++bFree;
  }
  //DBGOUT(("\n"));
  return bFree;
}
#endif


⌨️ 快捷键说明

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