2020-11-15 21:29:25 +01:00
/*! @file audio.c
@ brief play sound
@ author Lukas Fürderer
@ version V1 .0
@ date 15.11 .2020
This file contains the main app function and init .
*/
2020-11-15 20:14:26 +01:00
# include "audio.h"
# include "Board_DAC.h"
2020-11-30 18:49:36 +01:00
# include "Board_GLCD.h"
2020-11-15 20:14:26 +01:00
# include "LPC17xx.h"
# include "melody.h"
2020-12-05 23:50:47 +01:00
# include "Welcome.h"
2020-11-15 20:14:26 +01:00
# define FREQ(x) ((x & 0xffff0000) >> 16)
# define WAVES(x) (x & 0xffff)
struct AudioState
{
2020-11-15 21:29:25 +01:00
bool highState ;
uint16_t u16RemainingWaves ;
uint32_t u32EndBreak ;
const uint32_t * cpu32NextAction ;
uint32_t u32StackPointer ;
const uint32_t * cpu32Stack [ 10 ] ;
2020-11-30 18:49:36 +01:00
const char * cpcExpectedText ;
2020-11-15 20:14:26 +01:00
} ;
2020-11-30 18:49:36 +01:00
volatile static struct AudioState sAudioState ;
2020-11-15 20:14:26 +01:00
bool bPerformAudioStep ( )
{
2020-11-15 21:29:25 +01:00
bool bSuccess = true ;
2020-11-15 20:14:26 +01:00
2020-11-15 21:29:25 +01:00
sAudioState . highState = ! sAudioState . highState ;
if ( sAudioState . highState )
{
if ( sAudioState . u16RemainingWaves > 0 )
{
2020-12-05 23:50:47 +01:00
DAC_SetValue ( ( u32Volume < < 6 ) ) ;
2020-11-15 21:29:25 +01:00
}
else
{
if ( FREQ ( * sAudioState . cpu32NextAction ) = = 0 )
{
2020-11-29 23:49:58 +01:00
// GOTO
sAudioState . highState = false ;
2020-11-15 21:29:25 +01:00
sAudioState . cpu32NextAction = cppu32JumpLabels [ * sAudioState . cpu32NextAction ] ;
bSuccess = false ;
}
else if ( FREQ ( * sAudioState . cpu32NextAction ) = = 1 )
{
2020-11-29 23:49:58 +01:00
// CALL
sAudioState . highState = false ;
2020-11-15 21:29:25 +01:00
sAudioState . cpu32Stack [ sAudioState . u32StackPointer ] = sAudioState . cpu32NextAction + 1 ;
sAudioState . cpu32NextAction = cppu32JumpLabels [ WAVES ( * sAudioState . cpu32NextAction ) ] ;
sAudioState . u32StackPointer + + ;
bSuccess = false ;
}
else if ( FREQ ( * sAudioState . cpu32NextAction ) = = 2 )
{
2020-11-29 23:49:58 +01:00
// RETURN
sAudioState . highState = false ;
2020-11-15 21:29:25 +01:00
sAudioState . u32StackPointer - - ;
sAudioState . cpu32NextAction = sAudioState . cpu32Stack [ sAudioState . u32StackPointer ] ;
bSuccess = false ;
}
2020-11-29 23:49:58 +01:00
else if ( FREQ ( * sAudioState . cpu32NextAction ) = = 3 )
{
// PAUSE
sAudioState . highState = false ;
LPC_TIM0 - > MR0 = WAVES ( * sAudioState . cpu32NextAction ) < < 12 ;
sAudioState . cpu32NextAction + + ;
}
2020-11-30 18:49:36 +01:00
else if ( FREQ ( * sAudioState . cpu32NextAction ) = = 4 )
{
// TEXT
sAudioState . highState = false ;
sAudioState . cpcExpectedText = cpcTexts [ WAVES ( * sAudioState . cpu32NextAction ) ] ;
sAudioState . cpu32NextAction + + ;
bSuccess = false ;
}
2020-11-15 21:29:25 +01:00
else
{
2020-11-29 23:49:58 +01:00
DAC_SetValue ( 512 ) ;
2020-11-15 21:29:25 +01:00
uint32_t u32Frequency = FREQ ( * sAudioState . cpu32NextAction ) ;
LPC_TIM0 - > MR0 = u32Frequency * 2 ;
uint32_t u32Waves = WAVES ( * sAudioState . cpu32NextAction ) ;
sAudioState . u16RemainingWaves = u32Waves * 9 / 10 - 1 ;
sAudioState . u32EndBreak = u32Waves * u32Frequency * 2 / 5 ;
sAudioState . cpu32NextAction + + ;
}
}
}
2020-11-29 23:49:58 +01:00
else
{
DAC_SetValue ( 0 ) ;
sAudioState . u16RemainingWaves - - ;
if ( sAudioState . u16RemainingWaves = = 0 )
{
LPC_TIM0 - > MR0 = sAudioState . u32EndBreak ;
}
}
2020-11-15 20:14:26 +01:00
2020-11-15 21:29:25 +01:00
return bSuccess ;
2020-11-15 20:14:26 +01:00
}
2020-11-30 18:49:36 +01:00
void vUpdateLyrics ( )
{
static const char * cpcCurrentText = 0 ;
if ( cpcCurrentText = = 0 )
{
cpcCurrentText = cpcTexts [ 0 ] ;
}
const char * cpcExpectedText = sAudioState . cpcExpectedText ;
if ( cpcCurrentText ! = cpcExpectedText )
{
GLCD_DrawString ( 0 , 213 , cpcExpectedText ) ;
cpcCurrentText = cpcExpectedText ;
}
}
2020-11-15 20:14:26 +01:00
void TIMER0_IRQHandler ( )
{
2020-11-15 21:29:25 +01:00
LPC_TIM0 - > IR = 0x1 ; // acknowledge interrupt
2020-11-15 20:14:26 +01:00
2020-11-15 21:29:25 +01:00
while ( ! bPerformAudioStep ( ) )
{
}
2020-11-15 20:14:26 +01:00
}
// Initializes the interrupt-driven audio output
void vStartAudio ( )
{
2020-11-29 23:49:58 +01:00
sAudioState . highState = false ;
2020-11-15 21:29:25 +01:00
sAudioState . u16RemainingWaves = 0 ;
sAudioState . cpu32NextAction = cpu32EntryPoint ;
sAudioState . u32StackPointer = 0 ;
2020-11-30 18:49:36 +01:00
sAudioState . cpcExpectedText = cpcTexts [ 0 ] ;
2020-11-15 20:14:26 +01:00
2020-11-15 21:29:25 +01:00
// Init timerinterrupt 0 (20 ms)
LPC_SC - > PCONP | = ( 1 < < 2 ) ; // turn on
LPC_SC - > PCLKSEL0 | = ( 1 < < 2 ) ; // select clock
LPC_TIM0 - > MR0 = 100000 * 2 - 1 ;
LPC_TIM0 - > MCR = 0x3 ;
NVIC_SetPriority ( TIMER0_IRQn , 1U ) ; // priority
NVIC_EnableIRQ ( TIMER0_IRQn ) ;
2020-12-05 23:52:24 +01:00
LPC_TIM0 - > TCR = 1 ; // start music
2020-11-15 20:14:26 +01:00
}