Skip to content

Commit

Permalink
Fix Sounder pitch issue
Browse files Browse the repository at this point in the history
- Sounder pitch becomes Float
  • Loading branch information
yswallow committed Nov 22, 2022
1 parent bc0257a commit e16c23a
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 63 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ target_link_libraries(${PROJECT}
hardware_adc
hardware_dma
hardware_sync
hardware_irq
)

include_directories(${PROJECT} PRIVATE
Expand Down
10 changes: 5 additions & 5 deletions src/ruby/app/models/mml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def compile(str)
i += 1
end
# @type var note: Integer
(6.875 * (2<<(@octave + octave_fix)) * 2 ** (note / 12.0)).to_i
6.875 * (2<<(@octave + octave_fix)) * 2 ** (note / 12.0)
end
fraction_str, i = MML.number_str(str, i)
punti, i = MML.count_punto(str, i)
Expand All @@ -125,15 +125,15 @@ def compile(str)
sustain = (pitch == 0 || @q == 8) ? duration : (duration / 8.0 * @q).to_i
release = duration - sustain
if pitch == 0
yield(0, lazy_sustain + sustain)
yield(0.0, lazy_sustain + sustain)
lazy_sustain = 0
else
yield(0, lazy_sustain) if 0 < lazy_sustain
yield(pitch, sustain)
yield(0.0, lazy_sustain) if 0 < lazy_sustain
yield(pitch.to_f, sustain)
end
lazy_sustain = release
end
yield(0, lazy_sustain) if 0 < lazy_sustain
yield(0.0, lazy_sustain) if 0 < lazy_sustain
return total_duration
end
end
2 changes: 1 addition & 1 deletion src/ruby/sig/mml.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ class MML
def self.count_punto: (String, Integer) -> [Integer, Integer]
def self.coef: (Integer) -> Float

def compile: (String) { (Integer, Integer) -> bool } -> Integer
def compile: (String) { (Float, Integer) -> bool } -> Integer
end
2 changes: 1 addition & 1 deletion src/ruby/sig/sounder.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Sounder
def compile: (*String | Symbol) -> void
def add_song: (Symbol name, *String measures) -> void
def initialize: (Integer) -> void
def add_note: (Integer frequency, Integer duration) -> bool
def add_note: (Float frequency, Integer duration) -> bool
def clear_song: () -> void
def replay_if_key_pressed: () -> void
end
4 changes: 2 additions & 2 deletions src/ruby/test/mml_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ def basic_case

description "A flat"
def a_flat_case
duration = MML.new.compile("AA-") { |p, d| @data << [p, d] }
duration = MML.new.compile("AA-") { |p, d| @data << [p.to_i, d] }
assert_equal [[440, 500],[415,500]], @data
assert_equal 1000, duration
end

description "C flat"
def c_flat_case
duration = MML.new.compile("CC-") { |p, d| @data << [p, d] }
duration = MML.new.compile("CC-") { |p, d| @data << [p.to_i, d] }
assert_equal [[261, 500],[246,500]], @data
assert_equal 1000, duration
end
Expand Down
75 changes: 41 additions & 34 deletions src/sounder.c
Original file line number Diff line number Diff line change
@@ -1,44 +1,46 @@
#include <mrubyc.h>

#include "hardware/pio.h"
#include "hardware/dma.h"
#include "hardware/clocks.h"
#include "hardware/irq.h"
#include "ws2812.pio.h"
#include "uart_tx.pio.h"
#include "sounder.pio.h"

#define PIO_SOUNDER_INST_HEAD ( uart_tx_program.length + ws2812_program.length )
#define SOUNDER_PIO_FINISH_IRQ_ID PIO1_IRQ_1
#define SOUNDER_DEFAULT_HZ 2000
#define SOUNDER_SM_CYCLES 128
#define SONG_MAX_LEN 128
#define SOUNDER_BASE_HZ (100000UL)

static PIO pio = pio1;
static uint sm = 2;

static uint32_t song_data[SONG_MAX_LEN] = {0};
static float song_data[SONG_MAX_LEN] = {0};
static uint16_t song_len[SONG_MAX_LEN] = {0};
static uint8_t song_data_index = 0;
static int sounder_dma_channel = -1;
static uint8_t song_data_len = 0;

static void
init_dma_sounder(void)
{
if(sounder_dma_channel < 0) {
sounder_dma_channel = dma_claim_unused_channel(true);
}
sounder_resume_handler(void) {
pio_interrupt_clear(pio, 1);
irq_clear(SOUNDER_PIO_FINISH_IRQ_ID);

if( song_data_index==song_data_len ) { return; }

float hz = song_data[song_data_index];
uint16_t len = song_len[song_data_index];

dma_channel_config c = dma_channel_get_default_config(sounder_dma_channel);
channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, false);
channel_config_set_dreq(&c, ( pio==pio0 ? DREQ_PIO0_TX0 : DREQ_PIO1_TX0 ) + sm);
channel_config_set_irq_quiet(&c, true);
if( len==0 ) { return; }

dma_channel_configure(
sounder_dma_channel, // Channel to be configured
&c, // The configuration we just created
pio->txf+sm, // The initial write address
song_data, // The initial read address
SONG_MAX_LEN, // Number of transfers; in this case each is 4 byte.
false // Start immediately.
);
if(hz==0) {
pio_sm_set_clkdiv(pio, sm, (float)clock_get_hz(clk_sys) / (SOUNDER_DEFAULT_HZ*SOUNDER_SM_CYCLES));
pio_sm_put_blocking(pio, sm, len);
} else {
pio_sm_set_clkdiv(pio, sm, (float)clock_get_hz(clk_sys) / hz);
pio_sm_put_blocking(pio, sm, (1<<31) | len);
}
song_data_index++;
}

void
Expand All @@ -49,42 +51,47 @@ c_sounder_init(mrb_vm *vm, mrb_value *v, int argc)
}

sounder_program_init(pio, sm, PIO_SOUNDER_INST_HEAD, GET_INT_ARG(1));

init_dma_sounder();
pio_set_irq1_source_enabled(pio, pis_interrupt1, true);
irq_set_exclusive_handler(SOUNDER_PIO_FINISH_IRQ_ID, sounder_resume_handler);
irq_set_priority(SOUNDER_PIO_FINISH_IRQ_ID, PICO_DEFAULT_IRQ_PRIORITY);
irq_set_enabled(SOUNDER_PIO_FINISH_IRQ_ID, true);
}

void
c_sounder_clear_song(mrb_vm *vm, mrb_value *v, int argc)
{
song_data_index = 0;
memset(song_data, 0, sizeof(song_data));
song_data_len = 0;
memset(song_len, 0, sizeof(song_len));
}

void
c_sounder_add_note(mrb_vm *vm, mrb_value *v, int argc)
{
uint16_t pitch = GET_INT_ARG(1);
float pitch = GET_FLOAT_ARG(1);
uint16_t duration = GET_INT_ARG(2);

if (SONG_MAX_LEN == song_data_index+1) {
if (SONG_MAX_LEN == song_data_len+1) {
console_printf("SONG_MAX_LEN overflowed\n");
SET_FALSE_RETURN();
return;
}

if (0 < pitch) {
song_data[song_data_index] = ( (SOUNDER_BASE_HZ/pitch) & 0x0FFF ) | ( (duration*pitch<<2) & 0xFFFFF000UL );
song_data[song_data_len] = pitch*SOUNDER_SM_CYCLES;
song_len[song_data_len] = pitch*duration/1000;
} else {
song_data[song_data_index] = (duration<<12);
song_data[song_data_len] = 0;
song_len[song_data_len] = SOUNDER_DEFAULT_HZ*duration/1000;
}
song_data_index++;

song_data_len++;
SET_TRUE_RETURN();
}

void
c_sounder_replay(mrb_vm *vm, mrb_value *v, int argc)
{
dma_channel_abort(sounder_dma_channel);
pio_sm_drain_tx_fifo(pio, sm);
dma_channel_set_read_addr(sounder_dma_channel, song_data, true);
song_data_index = 0;
sounder_resume_handler();
}
32 changes: 12 additions & 20 deletions src/sounder.pio
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,19 @@

.wrap_target
pull; blocks
out ISR, 12;
out Y, 20;
loopOUTER:
mov X, ISR;
jmp !X, noTone;
set pins, 1;
loopHI:
jmp X--, loopHI [5];
mov X, ISR;
set pins, 0;
loopLO:
jmp X--, loopLO [5];
jmp loopOuterEND;
noTone:
set X, 0x1F; set 0b00011111
loopZERO:
jmp X--, loopZERO [31]; wait for 900 clocks
loopOuterEND:
jmp Y--, loopOUTER;
out X, 31;
out Y, 1;
loop:
set pins, 0 [31];
jmp !Y, noSound [31];
set pins, 1 [ 0];
noSound:
nop [30];
jmp X--, loop [31];
irq 1;
.wrap


% c-sdk {
#include "hardware/clocks.h"

Expand All @@ -41,7 +33,7 @@ static inline void sounder_program_init(PIO pio, uint sm, uint offset, uint pin)

// all the FIFOs is TX
//sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / (1000000UL));
sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / (2000UL));

// start state machine
pio_sm_init(pio, sm, offset, &c);
Expand Down

0 comments on commit e16c23a

Please sign in to comment.