diff --git a/TODO b/TODO new file mode 100644 index 00000000..cabdf96a --- /dev/null +++ b/TODO @@ -0,0 +1,4 @@ +TODO List + +- extend the functionality, now emulator/hardware should be the same save for the sample rate. + \ No newline at end of file diff --git a/basic/test.bsc b/basic/test.bsc index 0ab42ff7..0b464fbf 100644 --- a/basic/test.bsc +++ b/basic/test.bsc @@ -1,7 +1,3 @@ -cls -repeat - for x = 0 to 319 - y = x * 2 \ 3 - rect frame 0,0 ink rand(16) to x,y - next -until false +sound 0,740,30 +sound 0,320,30 +sound 0,100,100,14 diff --git a/emulator/include/gfx.h b/emulator/include/gfx.h index e42496d7..5d748f61 100644 --- a/emulator/include/gfx.h +++ b/emulator/include/gfx.h @@ -78,47 +78,13 @@ int GFXReadJoystick0(void); int GFXControllerCount(void); unsigned int GFXReadController(int id); -class Beeper -{ -public: - static void open(); // Open the audio device - static void close(); // Close the audio device +void SOUNDOpen(); // Open the audio device +void SOUNDClose(); // Close the audio device - static void setFrequency(double frequency); // Units: Hz - static void setVolume(double volume); // Range: 0.0 .. 1.0 +void SOUNDSetFrequency(double frequency); // Units: Hz +void SOUNDSetVolume(double volume); // Range: 0.0 .. 1.0 - static void play(); - static void stop(); - - static SDL_AudioSpec m_obtainedSpec; - -private: - static SDL_AudioDeviceID m_audioDevice; - static double m_frequency; // Units: Hz - static double m_volume; // Range: 0.0 .. 1.0 - - // The current playback position, according to `getData()` and - // `audioCallback()`. Units: samples - static int m_pos; - - // Pointer to function for offset calculate. Differs between different - // audio formats. - static int (*m_calculateOffset)(int sample, int channel); - - // Pointer to function for writing data. Differs between different audio - // formats. - static void (*m_writeData)(uint8_t* ptr, double data); - - // Called by `audioCallback` to generate audio data. - static double getData(); - - // This is function is called repeatedly by SDL2 to send data to the audio - // device. - static void audioCallback( - void* userdata, - uint8_t* stream, - int len - ); -}; +void SOUNDPlay(); +void SOUNDStop(); #endif diff --git a/emulator/src/core/hardware.cpp b/emulator/src/core/hardware.cpp index e65ab0dd..6b7ee7a9 100644 --- a/emulator/src/core/hardware.cpp +++ b/emulator/src/core/hardware.cpp @@ -112,19 +112,23 @@ void KBDInitialise(void) { } void SNDInitialise(void) { } -// ******************************************************************************************************************************* -// -// Sound system set pitch -// -// ******************************************************************************************************************************* -void SNDUpdateSoundChannel(uint8_t channel,SOUND_CHANNEL *c) { - if (c->isPlayingNote != 0) { - GFXSetFrequency(c->currentFrequency,1); - } else { - GFXSilence(); - } -} + + + +// // ******************************************************************************************************************************* +// // +// // Sound system set pitch +// // +// // ******************************************************************************************************************************* + +// void SNDUpdateSoundChannel(uint8_t channel,SOUND_CHANNEL *c) { +// if (c->isPlayingNote != 0) { +// GFXSetFrequency(c->currentFrequency,1); +// } else { +// GFXSilence(); +// } +// } // ******************************************************************************************************************************* // diff --git a/emulator/src/framework/beeper.cpp b/emulator/src/framework/beeper.cpp index eaaffdfb..b70ac9b9 100644 --- a/emulator/src/framework/beeper.cpp +++ b/emulator/src/framework/beeper.cpp @@ -1,5 +1,5 @@ -// ******************************************************************************************************************************* -// ******************************************************************************************************************************* +// *************************************************************************************** +// *************************************************************************************** // // Name: beeper.cpp // Purpose: SoundSupport library for SDL. @@ -7,8 +7,8 @@ // Author: qxxxb (https://github.com/qxxxb/sdl2-beeper) // Paul Robson (paul@robsons.org.uk) // -// ******************************************************************************************************************************* -// ******************************************************************************************************************************* +// *************************************************************************************** +// *************************************************************************************** #include #include @@ -19,91 +19,64 @@ #include #include "sys_processor.h" #include - -#ifdef EMSCRIPTEN -#include "emscripten.h" -#endif - -// ******************************************************************************************************************************* -// -// Audio : 3 channel + noise. -// -// ******************************************************************************************************************************* +#include #include #include -#include -SDL_AudioDeviceID Beeper::m_audioDevice; -SDL_AudioSpec Beeper::m_obtainedSpec; -double Beeper::m_frequency; -double Beeper::m_volume; -int Beeper::m_pos; -void (*Beeper::m_writeData)(uint8_t* ptr, double data); -int (*Beeper::m_calculateOffset)(int sample, int channel); +static SDL_AudioDeviceID m_audioDevice; +static SDL_AudioSpec m_obtainedSpec; + +void (*m_writeData)(uint8_t* ptr, double data); +int (*m_calculateOffset)(int sample, int channel); -// --- -// Calculate the offset in bytes from the start of the audio stream to the -// memory address at `sample` and `channel`. +// *************************************************************************************** +// +// Calculate the offset in bytes from the start of the audio stream to the +// memory address at `sample` and `channel`. // -// Channels are interleaved. +// Channels are interleaved. +// +// *************************************************************************************** -int calculateOffset_s16(int sample, int channel) { +static int calculateOffset_s16(int sample, int channel) { return - (sample * sizeof(int16_t) * Beeper::m_obtainedSpec.channels) + + (sample * sizeof(int16_t) * m_obtainedSpec.channels) + (channel * sizeof(int16_t)); } -int calculateOffset_f32(int sample, int channel) { +static int calculateOffset_f32(int sample, int channel) { return - (sample * sizeof(float) * Beeper::m_obtainedSpec.channels) + + (sample * sizeof(float) * m_obtainedSpec.channels) + (channel * sizeof(float)); } -// --- -// Convert a normalized data value (range: 0.0 .. 1.0) to a data value matching -// the audio format. +// *************************************************************************************** +// +// Convert a normalized data value (range: 0.0 .. 1.0) to a data value matching +// the audio format. +// +// *************************************************************************************** -void writeData_s16(uint8_t* ptr, double data) { +static void writeData_s16(uint8_t* ptr, double data) { int16_t* ptrTyped = (int16_t*)ptr; double range = (double)INT16_MAX - (double)INT16_MIN; double dataScaled = data * range / 2.0; *ptrTyped = dataScaled; } -void writeData_f32(uint8_t* ptr, double data) { +static void writeData_f32(uint8_t* ptr, double data) { float* ptrTyped = (float*)ptr; *ptrTyped = data; } -// --- -// Generate audio data. This is how the waveform is generated. - -double Beeper::getData() { - double sampleRate = (double)(m_obtainedSpec.freq); - - // Units: samples - double period = sampleRate / m_frequency; - - // Reset m_pos when it reaches the start of a period so it doesn't run off - // to infinity (though this won't happen unless you are playing sound for a - // very long time) - if (m_pos % (int)period == 0) { - m_pos = 0; - } - - double pos = m_pos; - double angular_freq = (1.0 / period) * 2.0 * M_PI; - double amplitude = m_volume; - - return (sin(pos * angular_freq) > 0) ? -amplitude:amplitude; -} +// *************************************************************************************** +// +// Callback when requesting buffer be filled +// +// *************************************************************************************** -void Beeper::audioCallback( - void* userdata, - uint8_t* stream, - int len -) { +static void audioCallback(void* userdata,uint8_t* stream,int len) { // Unused parameters (void)userdata; (void)len; @@ -111,8 +84,8 @@ void Beeper::audioCallback( // Write data to the entire buffer by iterating through all samples and // channels. for (int sample = 0; sample < m_obtainedSpec.samples; ++sample) { - double data = getData(); - m_pos++; + uint16_t nextSample = SNDGetNextSample(); + double data = (nextSample-128)/128.0; // Write the same data to all channels for (int channel = 0; channel < m_obtainedSpec.channels; ++channel) { @@ -123,7 +96,13 @@ void Beeper::audioCallback( } } -void Beeper::open() { +// *************************************************************************************** +// +// Open a sound device +// +// *************************************************************************************** + +void SOUNDOpen() { // First define the specifications we want for the audio device SDL_AudioSpec desiredSpec; SDL_zero(desiredSpec); @@ -156,7 +135,7 @@ void Beeper::open() { // will be called by SDL2 in a separate thread when it needs to write data // to the audio buffer. In other words, we don't control when this function // is called; SDL2 manages it. - desiredSpec.callback = Beeper::audioCallback; + desiredSpec.callback = audioCallback; // When we open the audio device, we tell SDL2 what audio specifications we // desire. SDL2 will try to get these specifications when opening the audio @@ -194,40 +173,56 @@ void Beeper::open() { // TODO: throw exception } - std::cout << "[Beeper] frequency: " << m_obtainedSpec.freq << std::endl; - std::cout << "[Beeper] format: " << formatName << std::endl; + // std::cout << "[Beeper] frequency: " << m_obtainedSpec.freq << std::endl; + // std::cout << "[Beeper] format: " << formatName << std::endl; - std::cout - << "[Beeper] channels: " - << (int)(m_obtainedSpec.channels) - << std::endl; + // std::cout + // << "[Beeper] channels: " + // << (int)(m_obtainedSpec.channels) + // << std::endl; - std::cout << "[Beeper] samples: " << m_obtainedSpec.samples << std::endl; - std::cout << "[Beeper] padding: " << m_obtainedSpec.padding << std::endl; - std::cout << "[Beeper] size: " << m_obtainedSpec.size << std::endl; + // std::cout << "[Beeper] samples: " << m_obtainedSpec.samples << std::endl; + // std::cout << "[Beeper] padding: " << m_obtainedSpec.padding << std::endl; + // std::cout << "[Beeper] size: " << m_obtainedSpec.size << std::endl; } } -void Beeper::close() { +// *************************************************************************************** +// +// End the Sound system +// +// *************************************************************************************** + +void SOUNDClose() { SDL_CloseAudioDevice(m_audioDevice); } -// -- - -void Beeper::setFrequency(double frequency) { - m_frequency = frequency; -} +// *************************************************************************************** +// +// Start playing sound +// +// *************************************************************************************** -void Beeper::setVolume(double volume) { - m_volume = volume; +void SOUNDPlay() { + SDL_PauseAudioDevice(m_audioDevice, 0); } -// --- +// *************************************************************************************** +// +// Stop playing sound +// +// *************************************************************************************** -void Beeper::play() { - SDL_PauseAudioDevice(m_audioDevice, 0); +void SOUNDStop() { + SDL_PauseAudioDevice(m_audioDevice, 1); } -void Beeper::stop() { - SDL_PauseAudioDevice(m_audioDevice, 1); +// *************************************************************************************** +// +// Function that returns the sample rate in Hz of the implementeing hardware +// +// *************************************************************************************** + +int SNDGetSampleFrequency(void) { + return m_obtainedSpec.freq; } diff --git a/emulator/src/framework/debugger.cpp b/emulator/src/framework/debugger.cpp index 1b14a943..6ea8b0ba 100644 --- a/emulator/src/framework/debugger.cpp +++ b/emulator/src/framework/debugger.cpp @@ -14,7 +14,8 @@ #include "gfx.h" #include "sys_processor.h" #include "debugger.h" - +#include "common.h" + static int isInitialised = 0; // Flag to initialise first time static int addressSettings[] = { 0,0,0,0x20FFFF }; // Adjustable values : Code, Data, Other, Break. static int keyMapping[16]; // Mapping for control keys to key values @@ -24,11 +25,7 @@ static int stepBreakPoint; // Extra breakpoint used for step over. static Uint32 nextFrame = 0; // Time of next frame. static int frameCount = 0; -#ifdef EMSCRIPTEN -#define FRAMESKIP (1) -#else #define FRAMESKIP (0) -#endif // ******************************************************************************************************************************* // Handle one frame of rendering etc. for the debugger. @@ -83,11 +80,11 @@ int GFXXRender(SDL_Surface *surface) { if (CMDKEY(DBGKEY_RESET)) { // Reset processor (F1) DEBUG_RESET(); addressSettings[0] = DEBUG_HOMEPC(); - GFXSilence(); + SNDMuteAllChannels(); } if (inRunMode == 0) { - GFXSilence(); // Will drive us mental otherwise. + SNDMuteAllChannels(); if (isxdigit(currentKey)) { // Is it a hex digit 0-9 A-F. int digit = isdigit(currentKey)?currentKey:(currentKey-'A'+10); // Convert to a number. int setting = 0; // Which value is being changed ? diff --git a/emulator/src/framework/gfx.cpp b/emulator/src/framework/gfx.cpp index 25321499..7c3406f8 100644 --- a/emulator/src/framework/gfx.cpp +++ b/emulator/src/framework/gfx.cpp @@ -20,10 +20,6 @@ #include #include -#ifdef EMSCRIPTEN -#include "emscripten.h" -#endif - #define MAX_CONTROLLERS (4) static SDL_Window *mainWindow = NULL; @@ -66,9 +62,8 @@ void GFXOpenWindow(const char *title,int width,int height,int colour) { background = colour; // Remember required backgrounds. _GFXInitialiseKeyRecord(); // Set up key system. - Beeper::open(); - Beeper::setVolume(0.0); - Beeper::play(); + SOUNDOpen(); + SOUNDPlay(); SDL_ShowCursor(SDL_DISABLE); // Hide mouse cursor } @@ -84,14 +79,10 @@ static int isRunning = -1; // Is app running static void _GFXMainLoop(void *arg); void GFXStart(void) { - #ifdef EMSCRIPTEN - emscripten_set_main_loop_arg(_GFXMainLoop, NULL, -1, 1); - #else while(isRunning) { // While still running. _GFXMainLoop(NULL); } - #endif - Beeper::stop(); + SOUNDStop(); SDL_CloseAudio(); } @@ -402,25 +393,10 @@ int GFXToASCII(int ch,int applyModifiers) { // // ******************************************************************************************************************************* -int GFXTimer(void) { +int GFXTimer(void) { return SDL_GetTicks(); } -// ******************************************************************************************************************************* -// -// Beeper interface -// -// ******************************************************************************************************************************* - -void GFXSetFrequency(int freq,int channel) { - Beeper::setVolume(1.0); - Beeper::setFrequency(freq); -} - -void GFXSilence(void) { - Beeper::setVolume(0.0); -} - // ******************************************************************************************************************************* // // Get controller count diff --git a/firmware/common/config/miscellany/group8_sound.inc b/firmware/common/config/miscellany/group8_sound.inc index bcdd4f2a..20245440 100644 --- a/firmware/common/config/miscellany/group8_sound.inc +++ b/firmware/common/config/miscellany/group8_sound.inc @@ -37,6 +37,8 @@ GROUP 8 Sound su.frequency = DSPGetInt16(DCOMMAND,5); su.timeCS = DSPGetInt16(DCOMMAND,7); su.slide = DSPGetInt16(DCOMMAND,9); + su.type = 0; + su.volume = 100; *DERROR = SNDPlay(DPARAMS[0],&su); DOCUMENTATION Queue a sound. Refer to Section \#\ref{sound} "Sound" for details. @@ -55,3 +57,21 @@ GROUP 8 Sound DOCUMENTATION Deposit in Parameter:0 the number of notes outstanding before silence in the queue of the channel specified in Parameter:0, including the current playing sound, if any. + FUNCTION 7 Queue Sound Extended + su.frequency = DSPGetInt16(DCOMMAND,5); + su.timeCS = DSPGetInt16(DCOMMAND,7); + su.slide = DSPGetInt16(DCOMMAND,9); + su.type = DCOMMAND[11]; + su.volume = DCOMMAND[12]; + *DERROR = SNDPlay(DPARAMS[0],&su); + DOCUMENTATION + Queue a sound. Refer to Section \#\ref{sound} "Sound" for details. This is an extension of call 4 to support different waveform types and volumes. The source parameter is no longer used. + + The parameters are : Channel, Frequency Low, Frequency High, Duration Low, Duration High, Slide Low, Slide High, Sound Type and Sound Volume. All these + are 16 bit parameters except the sound type and volume, and the channel number. + + FUNCTION 8 Get Channel Count + DPARAMS[0] = SNDGetChannelCount(); + DOCUMENTATION + This returns the number of channels in Parameter #0 + diff --git a/firmware/common/include/interface/sound.h b/firmware/common/include/interface/sound.h index ced3d790..c864ef0a 100644 --- a/firmware/common/include/interface/sound.h +++ b/firmware/common/include/interface/sound.h @@ -13,20 +13,25 @@ #ifndef _XSOUND_H #define _XSOUND_H -#define SOUND_CHANNELS (1) - +#define SOUND_CHANNELS_MAX (4) #define SOUND_QUEUE_SIZE (32) +#define SOUNDTYPE_SQUARE (0) +#define SOUNDTYPE_NOISE (1) + typedef struct _sound_queue_item { uint16_t frequency; uint16_t timeCS; int16_t slide; - uint8_t soundType; + uint8_t type; + uint8_t volume; } SOUND_QUEUE_ELEMENT; typedef struct _sound_channel { + uint8_t currentType; int currentFrequency; int currentSlide; + int currentVolume; bool isPlayingNote; int tick50Remaining; int queueCount; @@ -37,12 +42,19 @@ typedef struct _sound_update { int frequency; int slide; int timeCS; + int type; + int volume; } SOUND_UPDATE; void SNDInitialise(void); +int SNDGetSampleFrequency(void); + +int SNDGetChannelCount(void); +uint16_t SNDGetNextSample(void); void SNDUpdateSoundChannel(uint8_t channel,SOUND_CHANNEL *c); -void SNDManager(void); +void SNDManager(void); +void SNDMuteAllChannels(void); void SNDResetAll(void); uint8_t SNDResetChannel(int channel); uint8_t SNDPlay(int channelID,SOUND_UPDATE *u); diff --git a/firmware/common/sources/interface/sfxmanager.cpp b/firmware/common/sources/interface/sfxmanager.cpp index 2f0c186d..0a531064 100644 --- a/firmware/common/sources/interface/sfxmanager.cpp +++ b/firmware/common/sources/interface/sfxmanager.cpp @@ -22,7 +22,7 @@ // *************************************************************************************** uint8_t SFXPlay(int channelID,int effect) { - if (channelID >= SOUND_CHANNELS) return 1; // Check legal channel/sfx + if (channelID >= SNDGetChannelCount()) return 1; // Check legal channel/sfx if (effect >= SFX_COUNT) return 2; const uint16_t *notes = sfxData[effect]; // List to queue while (*notes != 0xFFFF) { // Queue them diff --git a/firmware/common/sources/interface/sndcreator.cpp b/firmware/common/sources/interface/sndcreator.cpp new file mode 100644 index 00000000..18ebddf7 --- /dev/null +++ b/firmware/common/sources/interface/sndcreator.cpp @@ -0,0 +1,74 @@ +// *************************************************************************************** +// *************************************************************************************** +// +// Name : sndcreator.cpp +// Authors : Paul Robson (paul@robsons.org.uk) +// Date : 7th August 2024 +// Reviewed : No +// Purpose : Waveform generator, default sound system. +// +// *************************************************************************************** +// *************************************************************************************** + +#include "common.h" + +static int adder = 0; +static int wrapper = 0; +static int state = 0; +static int soundType = 0; +static int level = 0; + +// *************************************************************************************** +// +// Return number of channels supported by this implementation +// +// *************************************************************************************** + +int SNDGetChannelCount(void) { + return 1; +} + +void SNDMuteAllChannels(void) { +} + +// *************************************************************************************** +// +// Get the next sample for the driver provided hardware rate. +// +// *************************************************************************************** + +uint16_t SNDGetNextSample(void) { + + if (adder == 0) return 0; + + if (wrapper++ >= adder) { + wrapper = 0; + level = state = state ^ 0xFF; + if (soundType == SOUNDTYPE_NOISE) { + level = rand() & 0xFF; + } + } + return level; +} + +// *************************************************************************************** +// +// Play note on channel +// +// *************************************************************************************** + +void SNDUpdateSoundChannel(uint8_t channel,SOUND_CHANNEL *c) { + if (c->isPlayingNote) { + adder = SNDGetSampleFrequency() / c->currentFrequency / 2; + soundType = c->currentType; + } else { + adder = 0; + } +} + +// *************************************************************************************** +// +// Date Revision +// ==== ======== +// +// *************************************************************************************** diff --git a/firmware/common/sources/interface/sndmanager.cpp b/firmware/common/sources/interface/sndmanager.cpp index d3656bae..86e55e9e 100644 --- a/firmware/common/sources/interface/sndmanager.cpp +++ b/firmware/common/sources/interface/sndmanager.cpp @@ -13,7 +13,7 @@ #include "common.h" static bool isInitialised = false; -static SOUND_CHANNEL channel[SOUND_CHANNELS]; +static SOUND_CHANNEL channel[SOUND_CHANNELS_MAX]; // *************************************************************************************** // @@ -22,7 +22,7 @@ static SOUND_CHANNEL channel[SOUND_CHANNELS]; // *************************************************************************************** void SNDResetAll(void) { - for (int i = 0;i < SOUND_CHANNELS;i++) { + for (int i = 0;i < SNDGetChannelCount();i++) { SNDResetChannel(i); } } @@ -34,7 +34,7 @@ void SNDResetAll(void) { // *************************************************************************************** uint8_t SNDResetChannel(int channelID) { - if (channelID >= SOUND_CHANNELS) return 1; + if (channelID >= SNDGetChannelCount()) return 1; SOUND_CHANNEL *c = &channel[channelID]; // Initialise channel c->isPlayingNote = false; c->tick50Remaining = 0; @@ -66,7 +66,7 @@ void SNDStartup(void) { // *************************************************************************************** int SNDGetNoteCount(int channelID) { - if (channelID < 0 || channelID > SOUND_CHANNELS) return -1; + if (channelID < 0 || channelID > SNDGetChannelCount()) return -1; SOUND_CHANNEL *c = &channel[channelID]; return c->queueCount + (c->isPlayingNote ? 1 : 0); // # in queue + 1 if playing } @@ -83,7 +83,8 @@ void SNDPlayNextNote(int channelID) { SOUND_QUEUE_ELEMENT *qe = &(c->queue[0]); // Head of the queue. c->currentFrequency = qe->frequency; c->currentSlide = qe->slide; - + c->currentType = qe->type; + c->currentVolume = qe->volume; c->isPlayingNote = true; // Set up the channel data c->tick50Remaining = qe->timeCS / 2; SNDUpdateSoundChannel(channelID,c); // Update it @@ -100,7 +101,7 @@ void SNDPlayNextNote(int channelID) { // *************************************************************************************** uint8_t SNDPlay(int channelID,SOUND_UPDATE *u) { - if (channelID >= SOUND_CHANNELS) return 1; + if (channelID >= SNDGetChannelCount()) return 1; SOUND_CHANNEL *c = &channel[channelID]; if (c->queueCount != SOUND_QUEUE_SIZE) { // If queue not full SOUND_QUEUE_ELEMENT *qe = &(c->queue[c->queueCount]); // Add to queue. @@ -110,7 +111,8 @@ uint8_t SNDPlay(int channelID,SOUND_UPDATE *u) { qe->slide = (u->slide & 0x8000)?-1:1; } qe->timeCS = u->timeCS; - qe->soundType = 0; + qe->type = u->type; + qe->volume = u->volume; c->queueCount++; } if (!c->isPlayingNote) { // Not playing anything, try a new note. @@ -130,7 +132,7 @@ void SNDManager(void) { SNDResetAll(); isInitialised = true; } - for (int channelID = 0;channelID < SOUND_CHANNELS;channelID++) { // Process each. + for (int channelID = 0;channelID < SNDGetChannelCount();channelID++) { // Process each. SOUND_CHANNEL *c = &channel[channelID]; if (c->isPlayingNote) { // Playing a note. if (c->tick50Remaining == 0) { // End of note ? diff --git a/firmware/sources/hardware/sound.cpp b/firmware/sources/hardware/sound.cpp index 5de7f2cc..6b1c18d2 100644 --- a/firmware/sources/hardware/sound.cpp +++ b/firmware/sources/hardware/sound.cpp @@ -3,10 +3,9 @@ // // Name : sound.cpp // Authors : Paul Robson (paul@robsons.org.uk) -// Harry Fairhead -// Date : 21st November 2023 +// Date : 7th August 2024 // Reviewed : No -// Purpose : Audio support for Neo6502 +// Purpose : PWM Audio support for Neo6502 // // *************************************************************************************** // *************************************************************************************** @@ -18,33 +17,32 @@ #include "system/dvi_video.h" #define AUDIO_PIN (20) // Beeper pin. +#define SAMPLE_DIVIDER (32) // Divider, affects the interrupts / second of the PWM sample output -// static uint sliceNumber,channel; +static int sampleFrequency = -1; // *************************************************************************************** // -// Set up code, borrowed from Harry Fairhead +// Function that returns the sample rate in Hz of the implementeing hardware // // *************************************************************************************** -// static int32_t SNDSetPWMFrequencyDuty(uint slice_num,uint chan,uint32_t f, int d) -// { -// // uint32_t clock = DVI_TIMING.bit_clk_khz * 1024; -// // uint32_t divider16 = clock / f / 4096 + (clock % (f * 4096) != 0); -// // if (divider16 / 16 == 0) divider16 = 16; -// // uint32_t wrap = clock * 16 / divider16 / f - 1; -// // pwm_set_clkdiv_int_frac(slice_num, divider16/16,divider16 & 0xF); -// // pwm_set_wrap(slice_num, wrap); -// // pwm_set_chan_level(slice_num, chan, wrap * d / 100); -// // return wrap; -// } +int SNDGetSampleFrequency(void) { + if (sampleFrequency < 0) { + sampleFrequency = DVI_TIMING.bit_clk_khz * 1024 / SAMPLE_DIVIDER / 255; + } + return sampleFrequency; +} -static int wav_position; +// *************************************************************************************** +// +// Interrupt Handler +// +// *************************************************************************************** void pwm_interrupt_handler() { - wav_position++; pwm_clear_irq(pwm_gpio_to_slice_num(AUDIO_PIN)); - pwm_set_gpio_level(AUDIO_PIN,(wav_position & 0x100) ? 0x00:0xFF); + pwm_set_gpio_level(AUDIO_PIN,SNDGetNextSample()); } // *************************************************************************************** @@ -58,40 +56,23 @@ void SNDInitialise(void) { int audio_pin_slice = pwm_gpio_to_slice_num(AUDIO_PIN); // Setup PWM interrupt to fire when PWM cycle is complete pwm_clear_irq(audio_pin_slice); - pwm_set_irq_enabled(audio_pin_slice, true); // set the handle function above irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_interrupt_handler); irq_set_enabled(PWM_IRQ_WRAP, true); // Setup PWM for audio output pwm_config config = pwm_get_default_config(); - pwm_config_set_clkdiv(&config, 8.0f); - pwm_config_set_wrap(&config, 250); + pwm_config_set_clkdiv(&config, SAMPLE_DIVIDER); + pwm_config_set_wrap(&config, 255); pwm_init(audio_pin_slice, &config, true); // pwm_set_gpio_level(AUDIO_PIN, 0); - // gpio_set_function(SOUND_PIN, GPIO_FUNC_PWM); - // sliceNumber = pwm_gpio_to_slice_num(SOUND_PIN); - // channel = pwm_gpio_to_channel(SOUND_PIN); - // pwm_set_enabled(sliceNumber,false); + pwm_set_irq_enabled(audio_pin_slice, true); } -// *************************************************************************************** -// -// Play note on channel -// -// *************************************************************************************** - -void SNDUpdateSoundChannel(uint8_t channel,SOUND_CHANNEL *c) { - // if (channel < SOUND_CHANNELS) { - // SNDSetPWMFrequencyDuty(sliceNumber,channel, c->currentFrequency, 50); - // pwm_set_enabled(sliceNumber,c->isPlayingNote); - // } -} // *************************************************************************************** // // Date Revision // ==== ======== -// 16-01-24 Moved tick callback stuff to tick source for generalised usage // // *************************************************************************************** diff --git a/firmware/sources/hardware/sound_beeper.cpp.disabled b/firmware/sources/hardware/sound_beeper.cpp.disabled index ea017e9e..c9e871e6 100644 --- a/firmware/sources/hardware/sound_beeper.cpp.disabled +++ b/firmware/sources/hardware/sound_beeper.cpp.disabled @@ -61,7 +61,7 @@ void SNDInitialise(void) { // *************************************************************************************** void SNDUpdateSoundChannel(uint8_t channel,SOUND_CHANNEL *c) { - if (channel < SOUND_CHANNELS) { + if (channel < SNDGetChannelCount()) { SNDSetPWMFrequencyDuty(sliceNumber,channel, c->currentFrequency, 50); pwm_set_enabled(sliceNumber,c->isPlayingNote); }