Skip to content

Commit a7fa3bb

Browse files
add xenon_tone, xenon_post_beep, some documentation to sound.h (#69)
* add xenon_tone and xenon_post_beep * add some documentation to sound.h * Update sound.c
1 parent 1502f56 commit a7fa3bb

2 files changed

Lines changed: 86 additions & 3 deletions

File tree

libxenon/drivers/xenon_sound/sound.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <pci/io.h>
2+
#include <stdint.h>
23
#include <string.h>
34
#include <xenon_smc/xenon_smc.h>
45
#include <xenon_smc/xenon_gpio.h>
@@ -122,4 +123,49 @@ int xenon_sound_get_unplayed(void)
122123
l += cur_len;
123124

124125
return l;
125-
}
126+
}
127+
128+
void xenon_tone(uint32_t frequency, uint32_t duration, int16_t amplitude)
129+
{
130+
uint8_t pcm_data[1024];
131+
132+
// xenon assumes a 48kHz sample rate for submitted audio data
133+
const uint32_t sample_rate = 48000;
134+
135+
uint32_t phase = 0;
136+
uint32_t phase_step = (uint32_t)(((uint64_t)frequency << 32) / sample_rate);
137+
138+
const uint32_t bytes_per_frame = sizeof(int16_t) * 2;
139+
const uint32_t total_frames = (sample_rate * duration) / 1000;
140+
uint32_t frames_remaining = total_frames;
141+
142+
while (frames_remaining)
143+
{
144+
uint32_t i;
145+
uint32_t chunk_frames = sizeof(pcm_data) / bytes_per_frame;
146+
147+
if (chunk_frames > frames_remaining)
148+
chunk_frames = frames_remaining;
149+
150+
for (i = 0; i < chunk_frames; ++i)
151+
{
152+
// 50% duty square wave
153+
int16_t v = (phase & 0x80000000U) ? -amplitude : amplitude;
154+
uint16_t le = (uint16_t)v;
155+
uint32_t o = i * bytes_per_frame;
156+
157+
// Write little-endian 16-bit stereo PCM
158+
pcm_data[o + 0] = le & 0xFF;
159+
pcm_data[o + 1] = (le >> 8) & 0xFF;
160+
pcm_data[o + 2] = le & 0xFF;
161+
pcm_data[o + 3] = (le >> 8) & 0xFF;
162+
163+
phase += phase_step;
164+
}
165+
166+
while (xenon_sound_get_unplayed() >= 32768);
167+
168+
xenon_sound_submit(pcm_data, sizeof(pcm_data));
169+
frames_remaining -= chunk_frames;
170+
}
171+
}

libxenon/drivers/xenon_sound/sound.h

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,50 @@
55
extern "C" {
66
#endif
77

8-
/* you init, you get the nr. of LE, 16bit x 2 channels, signed audio bytes to write, and submit that as max. */
9-
8+
/**
9+
* Initialize DAC, de-assert AUD_CLAMP, initialize HDMI audio
10+
*/
1011
void xenon_sound_init(void);
12+
13+
/**
14+
* Submit PCM audio data to be played on the conencted TV, monitor, audio device
15+
*
16+
* 48kHz sample rate
17+
* Signed 16-bit stereo PCM, little endian
18+
*
19+
* @param data Pointer to buffer of audio data
20+
* @param len Number of bytes from the buffer to submit
21+
*/
1122
void xenon_sound_submit(void *data, int len);
23+
24+
/**
25+
* @return Available free buffer space in bytes.
26+
*/
1227
int xenon_sound_get_free(void);
28+
29+
/**
30+
* @return Unplayed queued data size in bytes.
31+
*/
1332
int xenon_sound_get_unplayed(void);
1433

34+
/**
35+
* Generare a square wave tone
36+
*
37+
* @param frequency Tone frequency
38+
* @param duration Tone length in milliseconds.
39+
* @param amplitude Peak sample amplitude (signed 16-bit).
40+
*/
41+
void xenon_tone(uint32_t frequency, uint32_t duration, int16_t amplitude);
42+
43+
#define XENON_TONE_AMPLITUDE_100 12000
44+
#define XENON_TONE_AMPLITUDE_50 6000
45+
#define XENON_TONE_AMPLITUDE_25 3000
46+
47+
/**
48+
* Does the classic POST beep that old computers do (950hz tone, 250ms)
49+
*/
50+
#define xenon_post_beep() xenon_tone(950, 250, XENON_TONE_AMPLITUDE_50)
51+
1552
#ifdef __cplusplus
1653
};
1754
#endif

0 commit comments

Comments
 (0)