Skip to content

Commit

Permalink
Interrupt driven PCM sound added
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Robson committed Aug 6, 2024
1 parent df2f964 commit 791173c
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 37 deletions.
23 changes: 7 additions & 16 deletions basic/test.bsc
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
f$ = "test.xxx"
f$ = "testdir2"
fName = $D000
poke fName,len(f$)
for i = 1 to len(f$):poke fname+i,asc(mid$(f$,i)):next

while peek($FF00):wend
doke $FF04,$D000
poke $FF01,16
poke $FF00,3
while peek($FF00):wend

result = peek($FF02)
size = deek($FF04)
attrib = peek($FF08)
print result,size,attrib
cls
repeat
for x = 0 to 319
y = x * 2 \ 3
rect frame 0,0 ink rand(16) to x,y
next
until false
63 changes: 42 additions & 21 deletions firmware/sources/hardware/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,35 @@
#include "dvi.h"
#include "system/dvi_video.h"

#define SOUND_PIN (20) // Beeper pin.
#define AUDIO_PIN (20) // Beeper pin.

static uint sliceNumber,channel;
// static uint sliceNumber,channel;

// ***************************************************************************************
//
// Set up code, borrowed from Harry Fairhead
//
// ***************************************************************************************

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;
}
// 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;
// }

static int wav_position;

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);
}

// ***************************************************************************************
//
Expand All @@ -48,10 +54,25 @@ static int32_t SNDSetPWMFrequencyDuty(uint slice_num,uint chan,uint32_t f, int d
// ***************************************************************************************

void SNDInitialise(void) {
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);
gpio_set_function(AUDIO_PIN, GPIO_FUNC_PWM);
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_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);
}

// ***************************************************************************************
Expand All @@ -61,10 +82,10 @@ void SNDInitialise(void) {
// ***************************************************************************************

void SNDUpdateSoundChannel(uint8_t channel,SOUND_CHANNEL *c) {
if (channel < SOUND_CHANNELS) {
SNDSetPWMFrequencyDuty(sliceNumber,channel, c->currentFrequency, 50);
pwm_set_enabled(sliceNumber,c->isPlayingNote);
}
// if (channel < SOUND_CHANNELS) {
// SNDSetPWMFrequencyDuty(sliceNumber,channel, c->currentFrequency, 50);
// pwm_set_enabled(sliceNumber,c->isPlayingNote);
// }
}

// ***************************************************************************************
Expand Down
76 changes: 76 additions & 0 deletions firmware/sources/hardware/sound_beeper.cpp.disabled
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// ***************************************************************************************
// ***************************************************************************************
//
// Name : sound.cpp
// Authors : Paul Robson ([email protected])
// Harry Fairhead
// Date : 21st November 2023
// Reviewed : No
// Purpose : Audio support for Neo6502
//
// ***************************************************************************************
// ***************************************************************************************

#include "common.h"
#include "stdlib.h"
#include "hardware/pwm.h"
#include "dvi.h"
#include "system/dvi_video.h"

#define SOUND_PIN (20) // Beeper pin.

static uint sliceNumber,channel;

// ***************************************************************************************
//
// Set up code, borrowed from Harry Fairhead
//
// ***************************************************************************************

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;
}



// ***************************************************************************************
//
// Initialise sound channel, return # of supported channels
//
// ***************************************************************************************

void SNDInitialise(void) {
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);
}

// ***************************************************************************************
//
// 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
//
// ***************************************************************************************

0 comments on commit 791173c

Please sign in to comment.