Microchip® Advanced Software Framework

sound.c File Reference

Sound sample and sinewave playback driver definitions.

Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.

#include <board.h>
#include <compiler.h>
#include <dac.h>
#include <string.h>
#include <nvm.h>
#include <tc.h>
#include "sound.h"
#include "snd_samples.h"
#include "get_far.h"

Macros

#define SOUND_DDS_RES   (0xFFFFFFFFUL / SOUND_SAMPLE_RATE)
 Direct Digital Synthesization residue. More...
 
#define SOUND_SINEWAVE_VOICES   8
 Number of concurrent sinewaves that can be output. More...
 

Functions

void sample_callback (void)
 Callback function for updating DAC sample value. More...
 
static uint16_t sound_get_16_bit_sample (uint32_t snd_ptr, uint16_t smpl_cnt)
 Get 16-bit sample from soundtable. More...
 
static uint8_t sound_get_8_bit_sample (uint32_t snd_ptr, uint16_t smpl_cnt)
 Get 8-bit sample from soundtable. More...
 
static uint16_t sound_get_frequency_from_note (uint8_t note)
 Get the frequency of specified note. More...
 
static uint16_t sound_get_next_sinewave_sample (uint32_t *dds_acc, uint16_t freq)
 Get next sinewave sample by means of DDS (Direct Digital Synth). More...
 
void sound_init (void)
 Initialize the DAC, timer/counter and event system. More...
 
bool sound_is_playing (void)
 Convenience function to check if a sound is currently playing. More...
 
void sound_play_note (uint8_t buttons)
 Set sinewave frequencies to generate. More...
 
void sound_play_sample (uint8_t buttons)
 Starts playing samples when button status is sent. More...
 

Variables

uint16_t notes [20]
 Table of frequencies for 20 notes, starting at an A (at 441Hz). More...
 
static volatile flash_addr_t prog_snd_ptr = 0
 Progmem far flash "pointer". More...
 
static volatile uint16_t sinefreqs [SOUND_SINEWAVE_VOICES] = {0}
 Table to contain sinewave frequencies – this is polytonal. More...
 
static volatile uint16_t snd_cnt = 0
 Current frame in sound. More...
 
static volatile uint16_t snd_len = 0
 Number of frames in a sound. More...
 
static uint8_t snd_samplewidth = 0
 1 or 2 bytes sample width More...
 

#define SOUND_DDS_RES   (0xFFFFFFFFUL / SOUND_SAMPLE_RATE)

Direct Digital Synthesization residue.

This value represents the value that must be added to the DDS accumulators for every DAC conversion if we wanted to convert one period of the signal every second. Usually, one wants to play at a higher rate than 1 Hertz, so this value is multiplied by the desired frequency, before adding to the accumulator.

Referenced by sound_get_next_sinewave_sample().

#define SOUND_SINEWAVE_VOICES   8

Number of concurrent sinewaves that can be output.

Note
There is no point in making this higher than the number of available buttons or notes.

Referenced by sample_callback().

void sample_callback ( void  )

Callback function for updating DAC sample value.

This handles loading of the next sample into the DAC channel data register. Depending on the global variables associated with the currently playing sounds, this will load either a sound sample or the next value for the sinewaves.

The actual DAC conversion is initiated by the overflow event, not this ISR.

The volume is controlled by bit-shifting the sample values. However, if the values are shifted too much, the signal will be severely distorted since the MSBs are lost first.

References acc, dac_set_channel_value(), prog_snd_ptr, sinefreqs, snd_cnt, snd_len, snd_samplewidth, sound_get_16_bit_sample(), sound_get_8_bit_sample(), sound_get_next_sinewave_sample(), SOUND_SINEWAVE_VOICES, and sound_stop_timer().

Referenced by sound_init().

static uint16_t sound_get_16_bit_sample ( uint32_t  snd_ptr,
uint16_t  smpl_cnt 
)
inlinestatic

Get 16-bit sample from soundtable.

Parameters
snd_ptrPointer to start of soundtable.
smpl_cntSample in table to get.
Returns
16-bit sample value.

References nvm_flash_read_word().

Referenced by sample_callback().

static uint8_t sound_get_8_bit_sample ( uint32_t  snd_ptr,
uint16_t  smpl_cnt 
)
inlinestatic

Get 8-bit sample from soundtable.

Parameters
snd_ptrPointer to start of soundtable.
smpl_cntSample in table to get.
Returns
8-bit sample value.

References nvm_flash_read_byte().

Referenced by sample_callback().

static uint16_t sound_get_frequency_from_note ( uint8_t  note)
inlinestatic

Get the frequency of specified note.

Parameters
noteNote number, must be in range of notes.
Returns
Frequency, in Hertz, for specified note.

References Assert, and notes.

Referenced by sound_play_note().

static uint16_t sound_get_next_sinewave_sample ( uint32_t *  dds_acc,
uint16_t  freq 
)
inlinestatic

Get next sinewave sample by means of DDS (Direct Digital Synth).

Parameters
dds_accAccumulator to be used for calculation and lookup.
freqThe frequency in Hz that is desired.

References nvm_flash_read_word(), and SOUND_DDS_RES.

Referenced by sample_callback().

bool sound_is_playing ( void  )

Convenience function to check if a sound is currently playing.

Return values
trueSound is currently being played back.
falseSound is not being played back.

References snd_cnt, and snd_len.

Referenced by play_game(), and sound_play_sample().

void sound_play_note ( uint8_t  buttons)

Set sinewave frequencies to generate.

Sets the frequencies of notes to generate based on currently pressed buttons (each button corresponds to a unique note).

Note
This updates the global variable sinefreqs, and will start or stop the sound timer if some or no buttons are pressed, respectively.
Parameters
buttonsMask of buttons which are pressed.

References sinefreqs, sound_get_frequency_from_note(), sound_start_timer(), and sound_stop_timer().

Referenced by play_game(), and record_buttons().

void sound_play_sample ( uint8_t  buttons)

Starts playing samples when button status is sent.

Loads information about the sound to play starts the sound timer which triggers conversions and updates of sample value in DAC, at a rate of SOUND_SAMPLE_RATE times per second.

Note
This modifies the global variables snd_cnt, snd_len snd_samplewidth, and starts the sound timer.

See get_far.h for usage of GET_FAR_ADDRESS(symbol).

Parameters
buttonsMask of buttons which are pressed.

References GET_FAR_ADDRESS, prog_snd_ptr, snd_cnt, snd_len, snd_samplewidth, sound_is_playing(), and sound_start_timer().

Referenced by play_game(), and record_buttons().

uint16_t notes[20]
Initial value:
= {
441, 467, 495, 524, 555, 588, 623, 660, 700, 741, 785,
832, 882, 934, 990, 1048, 1111, 1177, 1247, 1321,
}

Table of frequencies for 20 notes, starting at an A (at 441Hz).

Referenced by sound_get_frequency_from_note().

volatile flash_addr_t prog_snd_ptr = 0
static

Progmem far flash "pointer".

Pointer to current sample in flash memory. A uint32_t is used for this because avr-gcc is limited to 16 bit pointers – this does not cover memory addresses above 2^16.

Referenced by sample_callback(), and sound_play_sample().

volatile uint16_t sinefreqs[SOUND_SINEWAVE_VOICES] = {0}
static

Table to contain sinewave frequencies – this is polytonal.

Referenced by sample_callback(), and sound_play_note().

volatile uint16_t snd_cnt = 0
static

Current frame in sound.

Referenced by sample_callback(), sound_is_playing(), and sound_play_sample().

volatile uint16_t snd_len = 0
static

Number of frames in a sound.

Referenced by sample_callback(), sound_is_playing(), and sound_play_sample().

uint8_t snd_samplewidth = 0
static

1 or 2 bytes sample width

Referenced by sample_callback(), and sound_play_sample().