📄 buffer.h
字号:
//++
//buffer.h - buffer management declarations
//
// 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
//
//REVISION HISTORY:
// dd-mmm-yy who description
// 28-May-05 RLA New file.
// 19-Oct-05 RLA Add STACKSLOCS hack to InitializeBuffers() for SDCC.
//--
#ifndef _buffer_h_
#define _buffer_h_
#include "slocs.h" // STACKSLOCS hack for SDCC
// Our queues are single linked structures described by a head pointer
// (points to the first item in the queue) and a tail pointer (points to
// the last item in the queue). Generally, the head pointer is used for
// removing items from the front of the queue and the tail pointer is used
// to add items to the end of the queue. A queue with only one item has
// pHead == pTail, and an empty queue has pHead == NULL. In the case of an
// empty queue the pTail is undefined and could be anything.
//
// IMPORTANT!! None (NONE!) of these macros are interrupt safe. Any time
// you use one on a queue that's shared by both the background and interrupt
// level it needs to be bracketed with INT_OFF and INT_ON macros. That goes
// for the free buffer list (RELEASE_BUFFER and ALLOCATE_BUFFER macros) too!!
// If you change this data structure, you'll have to change MP3DRQ!!!
typedef struct _BUFFER_CONTROL_BLOCK BUFFER_CONTROL_BLOCK;
typedef BUFFER_CONTROL_BLOCK BCB;
typedef BUFFER_CONTROL_BLOCK IDATA *PIBCB;
// WARNING - the code in the MP3DRQ ISR (MP3DRQ.A51) makes some assumptions
// about the order and size of the fields in this structure. If you do anything
// other than add new fields to the end, you'll have to change that module!
struct _BUFFER_CONTROL_BLOCK {
BCB IDATA *pNext;
BYTE XDATA *pbBuffer;
WORD cbBuffer;
};
// This macro will add a buffer to the specified queue. Buffers are always
// added to the end of the queue in FIFO fashion and only pTail is changed.
// Unless, of course, the queue is empty in which case both pHead and pTail
// must be updated...
#define ADD_TO_QUEUE(pBCB,pHead,pTail) { \
pBCB->pNext = NULL; \
if (pHead == NULL) \
pHead = pTail = pBCB; \
else \
pTail->pNext = pBCB, pTail = pBCB; \
}
// And this macro will remove the first item from the head of the queue and
// return its BCB pointer. If the queue is empty, then NULL results. Note
// that the pTail pointer is unused - it's included as a parameter only for
// symmetry with ADD_TO_QUEUE()...
#define REMOVE_FROM_QUEUE(pBCB,pHead,pTail) { \
pBCB = pHead; \
if (pHead != NULL) pHead = pHead->pNext; \
}
// This macro will allocate a free buffer by removing it from the free
// buffer queue. If there are no free buffers left, then the resulting
// pointer will be NULL...
#define ALLOCATE_BUFFER(pBCB) { \
pBCB = g_pFreeBufferList; \
if (g_pFreeBufferList != NULL) \
g_pFreeBufferList = g_pFreeBufferList->pNext; \
}
// This macro will return a buffer to the free buffer pool. It's basically
// a special case of ADD_TO_QUEUE that adds the free buffer to the free buffer
// queue, but in this case we add it to the head of the queue. For free
// buffers the order is arbitrary and we save a byte or two of RAM by not
// keeping track of a pTail.
#define RELEASE_BUFFER(pBCB) { \
pBCB->pNext = g_pFreeBufferList; \
g_pFreeBufferList = pBCB; \
}
// Although the buffers are allocated dynamically in XDATA at startup, the
// buffer control blocks themselves must be stored in IDATA and are allocated
// statically. Since IDATA is a limited resource, there's a very finite limit
// on the number of BCBs, and therefore the number of buffers, we can have.
// For example, on the P89C668 MCU there's enough XDATA RAM for 14 or 15 buffers,
// but since we have IDATA space for only 4 or 5 BCBs, the remaining RAM goes
// unused. However on the P89C664, there's only enough XDATA RAM for two or
// three buffers, and the remaining BCBs are unused. Can't win :-)
#define MAX_NUMBER_OF_BUFFERS 4
// Note that the actual buffer control block array, m_aBufferControlBlocks,
// is not global. It doesn't need to be - all BCBs are accessed thru the free
// list, which contains their address.
//extern BUFFER_CONTROL_BLOCK idata m_aBufferControlBlocks[NUMBER_OF_BUFFERS];
// The list of free BCBs, however, is global!
extern PIBCB g_pFreeBufferList;
// Methods...
extern void InitializeBuffers (WORD cbReserved) STACKSLOCS;
#ifdef DEBUG
extern BYTE ShowBufferPool (void);
#endif
#endif // _buffer_h_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -