📄 patest.c
字号:
/*
* Copyright (c) 1995-1999 by TriMedia Technologies.
*
* +------------------------------------------------------------------+
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such |
* | a license and with the inclusion of this copyright notice. This |
* | software or any other copies of this software may not be provided|
* | or otherwise made available to any other person. The ownership |
* | and title of this software is not transferred. |
* | |
* | The information in this software is subject to change without |
* | any prior notice and should not be construed as a commitment by |
* | TriMedia Technologies. |
* | |
* | this code and information is provided "as is" without any |
* | warranty of any kind, either expressed or implied, including but |
* | not limited to the implied warranties of merchantability and/or |
* | fitness for any particular purpose. |
* +------------------------------------------------------------------+
*
* Module name : patest.c 1.36
*
* Last update : 17:31:45 - 00/11/09
*
* Description :
*
* pSOS stub for audio testing: This is an example of a simple pSOS program
* which reads in a file of audio data and plays it.
*
*
*/
/*----------------------------- includes ------------------------------------*/
#include <stdio.h>
#include <psos.h>
#include <ops/custom_defs.h>
#include <tmlib/tmlibc.h>
#include <tmlib/AppModel.h>
#include <tm1/mmio.h>
#include <tm1/tmInterrupts.h>
#include <tm1/tmAO.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <tmlib/dprintf.h>
#include "sys_conf.h"
#include <string.h>
#include <tm1/tmHelp.h>
/*------------------------- local definitions -------------------------------*/
#define BUFSIZE 1536
#define NUM_BUFS 3
#define PRIORITY_BASE 100
#define TM1_CACHE_BLOCK_SIZE 64
#define ENDIAN_SWAP(a) \
( (a<<24) + ((a&0xFF00)<<8) + ((a>>8)&0xFF00) + ((a>>24) & 0xFF) )
/*
* The following defines two queues of packets circulating between the audio
* decoder and the audio renderer; full buffers stream from decoder to
* renderer, and empty ones back to the decoder to be filled again. The
* packets streaming through the queues are allocated from the packet_pool.
*/
typedef struct {
Pointer pointer;
UInt size;
} MixPacket_t;
static UInt32 full_q, empty_q;
static MixPacket_t *packet1, *packet2;
static MixPacket_t packet_pool[NUM_BUFS];
/*
* The following contain the buffer of fixed audio data which will be read
* from file at startup, to be passed repeatedly from decoder to renderer:
*/
static Int *waveData;
static Int waveLength;
/*------------------------- utility functions -------------------------------*/
/*
* Attempt to load a file from the host's disk into an allocated buffer, and
* return this buffer, with size.
*
* Return True upon success, False upon failure
*/
#define MAX_READ_SIZE 6000000 /* 6 meg */
static Bool
LoadFile(String FileName, Int ** FileData, Int * FileSize)
{
FILE *f;
Pointer data;
int mallocSize;
f = fopen(FileName, "rb");
if (f == Null) {
return False;
}
else {
/* get as much memory is available (less than 6M) */
data = NULL;
for (mallocSize = 0x600000; !(data = (Pointer) malloc(mallocSize)); mallocSize -= 32768);
mallocSize -= 32768; /* leave extra space for OS */
*FileData = data;
if (data != Null)
*FileSize = fread(data, 1, mallocSize, f);
fclose(f);
return (data != Null);
}
}
/*
* Attempt to load a wave file into an allocated buffer; either use the file
* name provided by the user, or use the default "g.bin"
*
* Return True upon success, False upon failure Upon success, the buffer plus
* wave length are placed into the global variables waveData resp waveLength
*/
static Bool
LoadWaveFile()
{
Char input_line[80];
Char *cp;
String used_soundfile;
#ifdef __BIG_ENDIAN__
int i;
#endif /* __BIG_ENDIAN__ */
/*
* Get the data, or return failure:
*/
printf("Enter the name of a sound file to be played. (g.bin is default)\n");
fgets(input_line, 80, stdin);
if (cp = strchr(input_line, '\n'))
*cp = 0; /* zap null byte */
used_soundfile = input_line;
if (!LoadFile(used_soundfile, &waveData, &waveLength)) {
printf(" failed opening sound file %s. Checking for default, g.bin\n", input_line);
used_soundfile = "g.bin";
if (!LoadFile(used_soundfile, &waveData, &waveLength)) {
printf("\n\t!!Failed to open g.bin.\n");
return False;
}
}
/* we need the size in words */
waveLength /= sizeof(Int);
/*
* assuming wave files are little endian, we can swap them for big
* endian playback
*/
#ifdef __BIG_ENDIAN__
for (i = 0; i < waveLength; i++)
waveData[i] = ENDIAN_SWAP(waveData[i]);
#endif
printf("Read %d words from file %s in 0x%08x\n", waveLength, used_soundfile, waveData);
DP(("Read %d words from file %s in 0x%08x\n", waveLength, used_soundfile, waveData));
return True;
}
/*
* Print processor information
*
*/
static void
print_banner()
{
UInt id;
paoCapabilities_t ao_caps;
boardGetID(&id);
aoGetCapabilities(&ao_caps);
/* --- . --- */
DP_START(32768, Null);
DP(("\npatest: TM-1 audio example program using pSOS.\n"));
tmHelpReportSystem(Null);
printf("\npatest: TM-1 audio example program using pSOS.\n\n");
tmHelpReportSystem(stdout);
/* --- . --- */
printf("* Audio Interface v%d.%d (%d)\n",
ao_caps->version.majorVersion,
ao_caps->version.minorVersion,
ao_caps->version.buildVersion);
}
/*--------------------------- Audio Renderer --------------------------------*/
static void
_arendISR(void)
{
UInt32 message[4];
MixPacket_t *tempak;
UInt stat;
stat = MMIO(AO_STATUS);
if (q_receive(full_q, Q_NOWAIT, 0, message)) {
DP(("underrun in arendISR\n"));
if (aoBUF1_EMPTY(stat))
aoAckACK1();
if (aoBUF2_EMPTY(stat))
aoAckACK2();
}
else {
tempak = (MixPacket_t *) message[0];
if (aoBUF1_EMPTY(stat)) {
message[0] = (unsigned int) packet1;
packet1 = tempak;
aoSetBASE1((unsigned long) packet1->pointer);
aoAckACK1();
}
if (aoBUF2_EMPTY(stat)) {
message[0] = (unsigned int) packet2;
packet2 = tempak;
aoSetBASE2((unsigned long) packet2->pointer);
aoAckACK2();
}
q_send(empty_q, message);
}
}
static void
arendISR(void)
{
#pragma TCS_handler
AppModel_suspend_scheduling();
AppModel_run_on_sstack((AppModel_Fun)_arendISR, Null);
AppModel_resume_scheduling();
}
/*
* The following is the psos task function of the audio rendererer. This task
* sets up the audio out interrupt stream which keeps itself going receiving
* buffers from the full queue, and giving these to the audio out device.
*/
static void
a_rend()
{
aoInstanceSetup_t ao;
UInt32 message[4];
Int instance;
printf("\n\n\tAudio Renderer is running:\n");
/* need two buffers before we can start the hardware */
q_receive(full_q, Q_WAIT, 0, message);
packet1 = (MixPacket_t *) message[0];
q_receive(full_q, Q_WAIT, 0, message);
packet2 = (MixPacket_t *) message[0];
/* setup control structure */
ao.audioTypeFormat = atfLinearPCM;
ao.audioSubtypeFormat = apfStereo16;
ao.isr = arendISR;
ao.interruptPriority = intPRIO_3;
ao.sRate = 48000.0;
ao.size = packet1->size;
ao.output = aaaNone;
ao.base1 = packet1->pointer;
ao.base2 = packet2->pointer;
ao.underrunEnable = False;
ao.hbeEnable = False;
ao.buf1emptyEnable = True;
ao.buf2emptyEnable = True;
if (aoOpen(&instance) != TMLIBDEV_OK) {
printf("aoOpen failed. Audio Renderer suspending.\n");
t_suspend(0L);
}
if (aoInstanceSetup(instance, &ao) != TMLIBDEV_OK) {
printf("aoInstanceSetup failed. Audio Renderer suspending.\n");
t_suspend(0L);
}
/* start audio hardware */
if (aoStart(instance) != TMLIBDEV_OK) {
printf("aoStart failed\n");
}
/* sets output volume to default (no attenuation) */
aoSetVolume(instance, 0, 0);
printf("\tPlease press return to exit.\n");
getchar();
aoStop(instance);
aoClose(instance);
_psos_exit(0);
}
/*--------------------------- Audio Decoder (Stub) --------------------------*/
/*
* The following is the psos task function of the audio decoder; the decoder
* continuously reads a buffer from the empty_q, puts decoded audio data in
* it, and places it into the full_q to be picked up by the audio renderer.
*
* In this example, the data is simply obtained from the fixed waveData buffer,
* which has been read in by the root task.
*/
static void
dec_stub()
{
Int *curData = waveData;
printf("\n\n\tAudio Decoder is running:\n");
while (True) {
UInt32 message[4];
MixPacket_t *mixpak;
Int32 *dPtr;
Int i;
/*
* Get an empty buffer; if not yet available, then wait until
* one can be obtained:
*/
q_receive(empty_q, Q_WAIT, 0, message);
mixpak = (MixPacket_t *) message[0];
/*
* Fill the buffer, and copy it back to SDRAM (the Audio Out
* does not read its data via the cache):
*/
dPtr = (Int32 *) mixpak->pointer;
for (i = 0; i < mixpak->size; i++) {
dPtr[i] = *curData++;
if (curData >= &waveData[waveLength])
curData = waveData;
}
_cache_copyback(mixpak->pointer, mixpak->size * sizeof(Int));
/*
* Send it to the renderer:
*/
q_send(full_q, message);
}
}
/*------------------------------ pSOS root task -----------------------------*/
extern void
root(void)
{
UInt32 audio_decoder, audio_render;
Int *bufPtr, i;
UInt32 message[4];
/*-------------------------------
* Print header including processor info:
*/
print_banner();
/*-------------------------------
* Load the wave file from disk;
* the data is returned in global
* variables waveData resp waveLength:
*/
if (!LoadWaveFile()) {
_psos_exit(0x47);
}
/*-------------------------------
* Create the buffer queues.
* Initialise the 'empty' buffer queue
* with cache aligned packet buffers;
* the assumption here is that
* BUFSIZE * sizeof(Int) is a multiple
* of the data cache page size (64):
*/
q_create("frat", NUM_BUFS, Q_LOCAL | Q_FIFO | Q_NOLIMIT, &full_q);
q_create("erat", NUM_BUFS, Q_LOCAL | Q_FIFO | Q_NOLIMIT, &empty_q);
bufPtr = (Pointer) _cache_malloc(NUM_BUFS * BUFSIZE * sizeof(Int), -1);
if (bufPtr == Null) {
printf("!!dec_stub: Failed to allocate buffer memory.\n");
t_suspend(0L);
}
for (i = 0; i < NUM_BUFS; i++) {
packet_pool[i].pointer = bufPtr;
packet_pool[i].size = BUFSIZE;
message[0] = (UInt) & packet_pool[i];
q_send(empty_q, message);
bufPtr += BUFSIZE;
}
/*-------------------------------
* Create and start psos tasks,
* and get things going:
*/
t_create("adec", PRIORITY_BASE + 6, 40000, 40000, T_LOCAL, &audio_decoder);
t_start(audio_decoder, T_PREEMPT | T_TSLICE | T_NOASR | T_ISR, dec_stub, Null);
t_create("arnd", PRIORITY_BASE + 8, 10000, 10000, T_LOCAL, &audio_render);
t_start(audio_render, T_PREEMPT | T_TSLICE | T_NOASR | T_ISR, a_rend, Null);
printf("Thank you! Now deleting root...\n");
t_delete(0L);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -