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+ }
0 commit comments