1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (c) 2011 Michael Sevakis
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #include "pcm_mixer.h"
29 static int32_t beep_phase
; /* Phase of square wave generator */
30 static uint32_t beep_step
; /* Step of square wave generator on each sample */
31 static uint32_t beep_amplitude
; /* Amplitude of square wave generator */
32 static int beep_count
; /* Number of samples remaining to generate */
34 /* Reserve enough static space for keyclick to fit */
35 #define BEEP_BUF_COUNT (NATIVE_FREQUENCY / 1000 * KEYCLICK_DURATION)
36 static uint32_t beep_buf
[BEEP_BUF_COUNT
] IBSS_ATTR
;
38 /* Actually output samples into beep_buf */
40 static FORCE_INLINE
void beep_generate(int count
)
42 uint32_t *out
= beep_buf
;
47 "eor %3, %5, %1, asr #31 \n"
52 : "+r"(out
), "+r"(beep_phase
), "+r"(count
),
54 : "r"(beep_step
), "r"(beep_amplitude
));
56 #elif defined (CPU_COLDFIRE)
57 static FORCE_INLINE
void beep_generate(int count
)
59 uint32_t *out
= beep_buf
;
72 : "+a"(out
), "+d"(beep_phase
), "+d"(count
),
74 : "r"(beep_step
), "d"(beep_amplitude
));
77 static FORCE_INLINE
void beep_generate(int count
)
79 uint32_t *out
= beep_buf
;
80 uint32_t amplitude
= beep_amplitude
;
81 uint32_t step
= beep_step
;
82 int32_t phase
= beep_phase
;
86 *out
++ = (phase
>> 31) ^ amplitude
;
95 /* Callback to generate the beep frames - also don't want inlining of
96 call below in beep_play */
97 static void __attribute__((noinline
))
98 beep_get_more(unsigned char **start
, size_t *size
)
100 int count
= beep_count
;
104 count
= MIN(count
, BEEP_BUF_COUNT
);
106 *start
= (unsigned char *)beep_buf
;
107 *size
= count
* sizeof(uint32_t);
108 beep_generate(count
);
112 /* Generates a constant square wave sound with a given frequency in Hertz for
113 a duration in milliseconds */
114 void beep_play(unsigned int frequency
, unsigned int duration
,
115 unsigned int amplitude
)
117 mixer_channel_stop(PCM_MIXER_CHAN_BEEP
);
119 if (frequency
== 0 || duration
== 0 || amplitude
== 0)
122 if (amplitude
> INT16_MAX
)
123 amplitude
= INT16_MAX
;
125 /* Setup the parameters for the square wave generator */
127 beep_step
= 0xffffffffu
/ NATIVE_FREQUENCY
* frequency
;
128 beep_count
= NATIVE_FREQUENCY
/ 1000 * duration
;
129 beep_amplitude
= amplitude
| (amplitude
<< 16); /* Word:|AMP16|AMP16| */
131 /* If it fits - avoid cb overhead */
132 unsigned char *start
;
135 /* Generate first frame here */
136 beep_get_more(&start
, &size
);
138 mixer_channel_set_amplitude(PCM_MIXER_CHAN_BEEP
, MIX_AMP_UNITY
);
139 mixer_channel_play_data(PCM_MIXER_CHAN_BEEP
,
140 beep_count
? beep_get_more
: NULL
,