|
|
//
// MODULE : STAUDIO.C
// PURPOSE : Audio Routines
// AUTHOR : JBS Yadawa
// CREATED : 7/20/96
//
//
// Copyright (C) 1996 SGS-THOMSON Microelectronics
//
//
// REVISION HISTORY :
//
// DATE :
//
// COMMENTS :
//
#include "common.h"
#include "stdefs.h"
#include "staudio.h"
#include "debug.h"
#include "error.h"
#include "board.h"
#include "sti3520A.h"
#include <dos.h> ///////////
static PAUDIO pAudio; #define SLOW_MODE 0
#define PLAY_MODE 1
#define FAST_MODE 2
#define IT_A 0 // interrupt detected
void AudioOpen(PAUDIO pAud) { pAudio = pAud; pAudio->AudioState = AUDIO_POWER_UP; pAudio->IntAudio = NO_IT_A; pAudio->MaskItAudio = 0; pAudio->ErrorMsg = NO_ERROR; pAudio->FirstPTS = FALSE; // First PTS not reached yet
pAudio->mute = FALSE; pAudio->Stepped = FALSE; pAudio->FrameCount = 0; }
void AudioClose(void) { }
void AudioInitDecoder(WORD StreamType) { /*
#if 0
pAudio->StrType = StreamType; switch(pAudio->AudioState) { case AUDIO_POWER_UP: BoardWriteAudio(RESET, 1); // reset the decoder
//ALTERAClearPendingAudioIT(); // Clear pending audio interrupt generated by soft reset
BoardWriteAudio(INTR_EN, 0); // disable all interupts
BoardWriteAudio(INTR_EN + LSB, 0); BoardWriteAudio(PLAY, 0); // disable play output
BoardWriteAudio(MUTE, 0); // do not mute output. LRclk and Sclk Stopped here
BoardWriteAudio(INVERT_SCLK, 0); // standard
BoardWriteAudio(INVERT_LRCLK, 1);// standard
#ifndef VALID3520
//**************************************************************
// Philips TDA1311 is a 16 bit DAC (oversampling 1x, 2x, 4x, 8x)
// -> LRCLK = SCLK / 32
// -> SCLK = PCMCLK / 8 (8 times oversampling => PCM_DIV = 3)
// => PCMCLK = 256 * Sampling Frequency
//**************************************************************
BoardWriteAudio(PCM_DIV, 3); BoardWriteAudio(PCM_ORD, 0); // MSB first
BoardWriteAudio(PCM_18, 0); // 16 bits of PCM data
BoardWriteAudio(FORMAT, 0); // I2S output format
BoardWriteAudio(DIF, 0); // Optionnal in 16 bit output
#else
//**************************************************************
// Crystal CS4330 is an 18 bit DAC (oversampling 1x, 4x, 6x, 8x)
// -> LRCLK = SCLK / 64
// -> SCLK = PCMCLK / 4 (4 times oversampling => PCM_DIV = 1)
// => PCMCLK = 256 * Sampling Frequency
//**************************************************************
BoardWriteAudio(PCM_DIV, 1); BoardWriteAudio(PCM_ORD, 0); BoardWriteAudio(PCM_18, 1); // 18 bits of PCM data
BoardWriteAudio(FORMAT, 0); // I2S output format
BoardWriteAudio(DIF, 0); // Optionnal in 16 bit
#endif
BoardWriteAudio(STR_SEL, 0); // Default Stream Type is audio elem stream
BoardWriteAudio(CRC_ECM, 1); // mute on CRC error correction
BoardWriteAudio(SYNC_ECM, 1); // mute if Sync lost
BoardWriteAudio(SYNCHRO_CONFIRM, 1); // synchro confirmation mode
BoardWriteAudio(SYNC_REG, 0x3F); // layer, bitrate, fs fields not used
BoardWriteAudio(PACKET_SYNC_CHOICE, 0);// multiplexed stream
BoardWriteAudio(LATENCY, 0x0); // Low Lattency decoding
BoardWriteAudio(SYNC_LCK, 0x2); // locked after 2 good Sync
BoardWriteAudio(SIN_EN, 0x01); // Serial data input to enable bit buffer access
BoardWriteAudio(AUDIO_ID_EN, 0x0);// ignore audio stream ID
BoardWriteAudio(AUDIO_ID, 0x0); // audio stream ID ignored
BoardWriteAudio(FREE_FORM_H, 0x0);// not free format
BoardWriteAudio(FREE_FORM_L, 0x0); BoardWriteAudio(DUAL_REG, 0); // Select Stereo Mode
AudioSetSTCParameters(44100UL); BoardAudioSetSamplingFrequency(44100UL); pAudio->FrameCount = 0; // Reset Frame Count.
pAudio->AudioState = AUDIO_INIT; break; default: break; } #else
BoardWriteAudio(0xF0, 1); // reset the decoder
BoardWriteAudio(0xC6, 0); BoardWriteAudio(0xEF, 1); BoardWriteAudio(PCM_DIV, 2); BoardWriteAudio(0x9f, 0); BoardWriteAudio(0x99, 0); BoardWriteAudio(0xB6, 3); BoardWriteAudio(0x9e, 0); BoardWriteAudio(0xa0, 0); BoardWriteAudio(0x91, 0); BoardWriteAudio(0xb8, 0); BoardWriteAudio(0x96, 1); BoardWriteAudio(0xd3, 0); BoardWriteAudio(0xac, 0); BoardWriteAudio(0xc4, 0); BoardWriteAudio(0xc2, 1); BoardWriteAudio(0xAE, 1);
#endif
*/ }
WORD AudioTestReg(void) { #if 0
WORD ReadValue; BoardWriteAudio(ATTEN_L, 0x55); BoardWriteAudio(ATTEN_R, 0xAA); ReadValue = BoardReadAudio(ATTEN_L); if ((ReadValue & 0x3F) != 0x15) goto Error; ReadValue = BoardReadAudio(ATTEN_R); if ((ReadValue & 0x3F) != 0x2A) goto Error;
return NO_ERROR;
Error : SetErrorCode(ERR_AUDIO_REG_TEST_FAILED); return BAD_REG_A; #else
return NO_ERROR; #endif
}
WORD AudioTest(void) { #if 0
WORD TestResult; TestResult = AudioTestReg(); if (TestResult != NO_ERROR) return TestResult; else { #ifdef DOSAPP
if (AudioTestInt(pAudio) == NO_IT_A) return NO_IT_A; else #endif
return NO_ERROR; } #else
return NO_ERROR; #endif
}
WORD AudioTestInt(void) { WORD err = NO_ERROR; #if 0
U8 Threshold; WORD a = 0;
pAudio->MaskItAudio = FIFT; Threshold = BoardReadAudio(FIFO_IN_TRESHOLD); //---- Configure audio
BoardWriteAudio(PLAY, 0x00); BoardWriteAudio(FIFO_IN_TRESHOLD, 0x01); //---- Enable FIFO full interrupt
BoardWriteAudio(INTR_EN, 0x00); BoardWriteAudio(INTR_EN + LSB, 0x10); //---- Write a byte to force an interrupt
BoardWriteAudio(DATA_IN, 0x00); // wait for occurrence of first audio interrupt
while (pAudio->IntAudio == NO_IT_A) { Delay(1000); a++; /* incremented every 1 ms */ if (a >= 1000) { DPF((Trace, "AudioTestInt failed !!")); SetErrorCode(ERR_NO_AUDIO_INTR); err = NO_IT_A; /* No interrupt */ break; } } // Restore Interrupt mask
pAudio->MaskItAudio = 0; AudioMaskInt(); BoardWriteAudio(FIFO_IN_TRESHOLD, Threshold); BoardReadAudio(INTR); /* to clear audio interrupts flags */ #endif
return err; }
// Set the decoding mode and parameters
void AudioSetMode(WORD Mode, WORD param) { #if 0
pAudio->DecodeMode = Mode; switch (pAudio->DecodeMode) { case PLAY_MODE: BoardWriteAudio(MUTE, 0); pAudio->fastForward = 0; pAudio->decSlowDown = 0; break; case FAST_MODE: pAudio->fastForward = 1; pAudio->decSlowDown = 0; break; case SLOW_MODE: pAudio->fastForward = 0; pAudio->decSlowDown = param; break; } #endif
}
// Decode
void AudioDecode(void) { #if 0
switch (pAudio->AudioState) { case AUDIO_POWER_UP: break; case AUDIO_INIT: // Change in synchro + buffer over BALF +PTS
pAudio->MaskItAudio = SYNC|BOF|PCMU|CRC| PTS; BoardWriteAudio(INTR_EN, (BYTE)(pAudio->MaskItAudio & 0xFF)); BoardWriteAudio(INTR_EN + LSB, (BYTE)(pAudio->MaskItAudio >> 8 )); //yg BoardWriteAudio(MUTE, 1); // This Starts SClk and LRClk outputs
BoardWriteAudio(PLAY, 1); // Start decoding Output is Mute
pAudio->AudioState = AUDIO_STC_INIT; break; case AUDIO_STC_INIT: pAudio->AudioState = AUDIO_DECODE; BoardWriteAudio(PLAY, 1); // Restart decoding (decoding had been stopped when first audio PTS detected)
BoardWriteAudio(MUTE, 0); // Stop Muting output
break; case AUDIO_DECODE: break; case AUDIO_PAUSE: case AUDIO_STEP: BoardWriteAudio(PLAY, 1); BoardWriteAudio(MUTE, 0); pAudio->AudioState = AUDIO_DECODE; break; } #endif
}
void AudioStep(void) { #if 0
BoardWriteAudio(MUTE, 0); BoardWriteAudio(PLAY, 1); pAudio->AudioState = AUDIO_STEP; pAudio->Stepped = FALSE; #endif
}
void AudioStop(void) { #if 0
switch(pAudio->AudioState) { case AUDIO_POWER_UP: break; case AUDIO_INIT: break; case AUDIO_STC_INIT: case AUDIO_DECODE: pAudio->AudioState = AUDIO_POWER_UP; AudioInitDecoder(pAudio, pAudio->StrType); break; } #endif
}
void AudioPause(void) { #if 0
switch(pAudio->AudioState) { case AUDIO_POWER_UP: /* After reset */ case AUDIO_INIT: /* Initialisation + test of the decoders */ case AUDIO_STC_INIT: /* STC of audio decoder initialized */ case AUDIO_DECODE: /* Normal decode */ BoardWriteAudio(MUTE, 1); BoardWriteAudio(PLAY, 0); pAudio->AudioState = AUDIO_PAUSE; break; } #endif
}
WORD AudioGetState(void) { return ( pAudio->AudioState); }
void AudioSetSTCParameters(DWORD SampFreq) { #if 0
// Note :
// STCCLK = PCMCLK (fixed inside STi3520A)
// (PCMCLK * inc) / div = 90kHz
switch(SampFreq){ case 32000UL: // PCMCLK = 256 * 32 = 8192 kHz, inc = 45, div = 4096 -> 90kHz
BoardWriteAudio(STC_INC, 45); BoardWriteAudio(STC_DIVH, 0x10); BoardWriteAudio(STC_DIVL, 0x00); break;
case 44100UL: // PCMCLK = 256 * 44.1 = 11289.6 kHz, inc = 25, div = 3136 -> 90kHz
BoardWriteAudio(STC_INC, 25); BoardWriteAudio(STC_DIVH, 0x0C); BoardWriteAudio(STC_DIVL, 0x40); break;
case 48000UL: // PCMCLK = 256 * 48 = 12288 kHz, inc = 15, div = 2048 -> 90kHz
BoardWriteAudio(STC_INC, 15); BoardWriteAudio(STC_DIVH, 0x08); BoardWriteAudio(STC_DIVL, 0x00); break;
default : break; }
BoardWriteAudio(STC_CTL, 0x40); // Load STC_VID on rising edge of VSYNC
#endif
} DWORD AudioGetSTC(void) { #if 0
DWORD stc; WORD j;
BoardWriteAudio(STC_CTL, 0x44); // load current STC value to STC
for ( j = 0; j < 0xF; j++) ; stc = ( BoardReadAudio(STC_3 ) & 0xFFL ) << 24; stc = stc | ( ( BoardReadAudio(STC_2 ) & 0xFFL ) << 16); stc = stc | ( ( BoardReadAudio(STC_1 ) & 0xFFL ) << 8); stc = stc | ( BoardReadAudio(STC_0 ) & 0xFFL); return ( stc); #else
return 0; #endif
}
DWORD AudioGetVideoSTC(void) { #if 0
DWORD stc; WORD j;
BoardWriteAudio(STC_CTL, 0x48); // load STC_VID to STC, Mode 0 mapping
// BoardWriteAudio(STC_CTL, 0x44); accu
// BoardWriteAudio(STC_CTL, 0x50);
for ( j = 0; j < 0xF; j++) ; /*
stc = ( BoardReadAudio(STC_3 ) & 0xFFL ) << 24; stc = stc | ((BoardReadAudio(STC_2) & 0xFFL ) << 16); stc = stc | ((BoardReadAudio(STC_1) & 0xFFL ) << 8); stc = stc | ((BoardReadAudio(STC_0) & 0xFFL )); */ stc = ( BoardReadAudio(STC_0) & 0xFFL ) << 0; stc = stc | ((BoardReadAudio(STC_1) & 0xFFL ) << 8); stc = stc | ((BoardReadAudio(STC_2) & 0xFFL ) << 16); stc = stc | ((BoardReadAudio(STC_3) & 0xFFL ) << 24); return stc; #else
return 0; #endif
}
void AudioInitSTC(DWORD stc) { #if 0
BoardWriteAudio(STC_0, (U8)(stc & 0xFFL)); stc >>= 8; BoardWriteAudio(STC_1, (U8)(stc & 0xFFL)); stc >>= 8; BoardWriteAudio(STC_2, (U8)(stc & 0xFFL)); stc >>= 8; BoardWriteAudio(STC_3, (U8)(stc & 0xFFL)); BoardWriteAudio(STC_CTL, 0x41); // load STC to accumulator,
#endif
}
DWORD AudioGetPTS(void) { return pAudio->PtsAudio; }
WORD AudioGetErrorMsg(void) { return pAudio->ErrorMsg; }
void AudioSetRightVolume(WORD volume) { #if 0
BoardWriteAudio(ATTEN_R, (BYTE)volume); #endif
}
void AudioSetLeftVolume(WORD volume) { #if 0
BoardWriteAudio(ATTEN_L, (BYTE)volume); #endif
}
void AudioMute(void) { #if 0
if (pAudio->mute) { BoardWriteAudio(MUTE, 0); pAudio->mute = FALSE; } else { BoardWriteAudio(MUTE, 1); pAudio->mute = TRUE; } #endif
}
BOOL AudioIsFirstPTS(void) { return pAudio->FirstPTS; }
void AudioSetStreamType(WORD StrType) { #if 0
BoardWriteAudio(STR_SEL, (BYTE)StrType); #endif
} void AudioInitPesParser (WORD StreamType) { #if 0
switch(StreamType) { case SYSTEM_STREAM: case VIDEO_PACKET: case AUDIO_PACKET: case VIDEO_PES: case AUDIO_PES:
BoardWriteAudio( STR_SEL, 1); break; case DUAL_PES: BoardWriteAudio( STR_SEL, 4); break; case DUAL_ES: BoardWriteAudio( STR_SEL, 0); break; case VIDEO_STREAM: case AUDIO_STREAM: BoardWriteAudio( STR_SEL, 0); break;
} #endif
} void AudioMaskInt(void) { #if 0
BoardWriteAudio(INTR_EN, 0); BoardWriteAudio(INTR_EN + LSB, 0); #endif
}
void AudioRestoreInt(void) { #if 0
//HostDisplay(DISPLAY_FASTEST, "!%x!", pAudio->MaskItAudio);
BoardWriteAudio(INTR_EN, (BYTE)(pAudio->MaskItAudio & 0xFF)); BoardWriteAudio(INTR_EN + LSB, (BYTE)(pAudio->MaskItAudio >> 8)); #endif
}
BOOL AudioAudioInt(void) { #if 0
WORD int_stat_reg, i; BOOLEAN bAudioIntr = FALSE;
// Read the interrupt status register
int_stat_reg = BoardReadAudio(INTR); i = BoardReadAudio(INTR + LSB); i = i << 8; int_stat_reg = ( int_stat_reg & 0xFF ) | i; int_stat_reg = int_stat_reg & pAudio->MaskItAudio; /* Mask the IT not used */ if(int_stat_reg) bAudioIntr = TRUE;
/******************************************************/ /** FIFO FULL used to test audio interrupt generation**/ /******************************************************/ if (int_stat_reg & FIFT) { pAudio->IntAudio = IT_A; } /******************************************************/ /** CHANGE SYNCHRO **/ /******************************************************/ if (int_stat_reg & SYNC) { i = BoardReadAudio(SYNC_ST); // Synchronization status
if ((i & 0x3) == 3) { // Locked
// Disable Change in synchro
pAudio->MaskItAudio = pAudio->MaskItAudio & NSYNC; // Next Interrupt should be change in sampling freq
pAudio->MaskItAudio = pAudio->MaskItAudio | SAMP; } }
/******************************************************/ /** CHANGE IN SAMPLING FREQUENCY **/ /******************************************************/ if (int_stat_reg & SAMP) { i = BoardReadAudio(PCM_FS ) & 0x3; // Get Sampling frequency
switch(i) { case 0 : BoardAudioSetSamplingFrequency(44100UL); AudioSetSTCParameters(44100UL); break; case 1 : BoardAudioSetSamplingFrequency(48000UL); AudioSetSTCParameters(48000UL); break; case 2 : BoardAudioSetSamplingFrequency(32000UL); AudioSetSTCParameters(32000UL); break; default : break; } // Disable change in sampling frequency
pAudio->MaskItAudio = pAudio->MaskItAudio & NSAMP; }
/******************************************************/ /** CRC error **/ /******************************************************/ if (int_stat_reg & CRC) { }
/******************************************************/ /** PCM Underflow **/ /******************************************************/ if (int_stat_reg & PCMU) { }
/******************************************************/ /** Begining of Frame **/ /******************************************************/ if (int_stat_reg & BOF) { DWORD STC = AudioGetVideoSTC(); static DWORD STCOld;
// HostDisplay(DISPLAY_FASTEST, "STCBOF = %8lu D = %5ld\r\n", STC, STC - STCOld);
// STCOld = STC;
// Check if stepping
if ((pAudio->AudioState == AUDIO_STEP) && (pAudio->Stepped == FALSE)) { BoardWriteAudio(MUTE, 1); BoardWriteAudio(PLAY, 0); pAudio->Stepped = TRUE; } // If Slow motion or Fast forward, Mute Audio
if ( pAudio->DecodeMode != PLAY_MODE ) { BoardWriteAudio(MUTE, 1); pAudio->mute = TRUE; if ((pAudio->FrameCount % 4) && (pAudio->fastForward)) BoardWriteAudio(SKIP, 1); else if ((pAudio->DecodeMode == SLOW_MODE ) && ((pAudio->FrameCount % (pAudio->decSlowDown + 1)) != 0)) BoardWriteAudio(REPEAT, 1); }
pAudio->FrameCount++; // Increment Frame Count
}
/******************************************************/ /** PTS detected **/ /******************************************************/ if ( int_stat_reg & PTS ) { DWORD pts; //DBG1('p');
/*
BoardReadAudio(PTS_4); // To clear pts interrupt
pts = (BoardReadAudio(PTS_3) & 0xFFL) << 24; pts = pts | ((BoardReadAudio(PTS_2 ) & 0xFFL) << 16); pts = pts | ((BoardReadAudio(PTS_1 ) & 0xFFL) << 8); pts = pts | ( BoardReadAudio(PTS_0 ) & 0xFFL); */ pts = (BoardReadAudio(PTS_0) & 0xFFL) << 0; pts = pts | ((BoardReadAudio(PTS_1) & 0xFFL) << 8); pts = pts | ((BoardReadAudio(PTS_2) & 0xFFL) << 16); pts = pts | ((BoardReadAudio(PTS_3) & 0xFFL) << 24); BoardReadAudio(PTS_4); // To clear pts interrupt
pAudio->PtsAudio = pts; if (pAudio->AudioState == AUDIO_STC_INIT) { pAudio->FirstPTS = TRUE; //yg BoardWriteAudio(PLAY, 0);
} if (pAudio->AudioState == AUDIO_DECODE) { // HostDirectPutChar('P', BLACK, LIGHTBLUE);
AudioInitSTC ( pts); // DWORD STC = AudioGetVideoSTC();
// HostDisplay(DISPLAY_FASTEST, "STC = %8lu PTSA = %8lu D = %8ld\r\n", STC, pts, STC - pts);
} }
return bAudioIntr; #else
return FALSE; #endif
}
|