Troy Davis Caitlin Smart Step Counter Music DJ Troy Davis Caitlin Smart
Responsibilities Most of the development will be shared Troy will responsible for interfacing the SD card as well as MP3 player system integration Caitlin will be in charge of the accelerometer and updating song selection based on the runner’s pace
Motivation and Functionality Have a song automatically selected for you that matches your jogging pace Accelerometer to measure steps MP3s from SD card Provide all regular MP3 player functionality
Design Decode MP3s from SD card and choose a song with similar BPM as joggers pace Will have two tasks: one that polls accelerometer and one that plays MP3s Audio codec & accelerometer interface via I²C
Reusable Design Elements FPGA cores I²C interface (via opencores.org) WM8731 controller (via Altera) C code Drivers from I²C and WM8731 via their respective sources Libraries LIBMAD MPEG audio decoder library
Design Challenges Getting the audio codec to send input from audio source to a speaker output Decoding MP3s in real time
Code // audio_ctrl.c #include "audio_ctrl.h" #include "io.h" #include <unistd.h> void i2c_write(unsigned char i2c_address, unsigned short data ); int audio_codec_write_ctrl( unsigned char reg_addr, unsigned short data ) { unsigned char first_byte, second_byte; unsigned short i2c_complete_data_word; // First byte contains the reg address and bit 8 of the data // This is a weird requirement of the audio codec chip first_byte = ( reg_addr << 1 ) | (( data >> 8 ) & 0x1 ); // Second byte contains bits 7:0 of the data second_byte = data & 0xFF; i2c_complete_data_// The address of the audio codec is always 0x1A // TODO: Make this a define. word = ( first_byte << 8 | second_byte ); i2c_write( AUDIO_CODEC_I2C_ADDRESS, i2c_complete_data_word ); return( 0 ); }
int audio_codec_init_i2c( alt_audio_codec* audio_codec ) { disable_audio_codec_controller( audio_codec ); reset_audio_codec_controller( audio_codec ); // audio_codec_set_headphone_volume( audio_codec, 0 ); // Initialize the audio codec chip. audio_codec_write_ctrl(AUDIO_CTRL_REG_RESET,0x000); //RESET audio_codec_write_ctrl( AUDIO_CTRL_REG_DIG_PATH_CTRL, 0x008 ); // Digital audio path: DAC soft mute on, De-emphasis off audio_codec_write_ctrl( AUDIO_CTRL_REG_POWER_DOWN, 0x0E7 ); // power down control: CLKOUT-down, OSC-down, Mic-down, adc-down, line-in down audio_codec_write_ctrl( AUDIO_CTRL_REG_IF_FORMAT, 0x003 );//slave mode and DSP mode audio_codec_write_ctrl( AUDIO_CTRL_REG_ANG_PATH_CTRL, 0x0cb ); // sound select: sidetone ATT -15dB, sidetone off, DAC off, LineIn to ADC, by-pass on 11010000 audio_codec_write_ctrl( AUDIO_CTRL_REG_SAMPLING_CTRL, 0x023 ); // mclk: 44 kHz sampling audio_codec_write_ctrl( AUDIO_CTRL_REG_LINE_IN_L, 0x117 ); // L/R input audio_codec_write_ctrl( AUDIO_CTRL_REG_ACTIVE_CTRL, 0x001 ); // activate digital interface audio_codec_write_ctrl( AUDIO_CTRL_REG_POWER_DOWN, 0x067 ); // turn on power audio_codec_write_ctrl( AUDIO_CTRL_REG_DIG_PATH_CTRL, 0x000 ); // unmute audio_codec_set_headphone_volume( audio_codec, audio_codec->headphone_volume ); enable_audio_codec_controller( audio_codec ); return( 0 ); }
int audio_codec_set_headphone_volume( alt_audio_codec int audio_codec_set_headphone_volume( alt_audio_codec* audio_codec, int volume ) { //char min = 0x2F; // 00101111 47 unused //char max = 0x7F; // 01111111 127 unused // default = 0x79 // 01111001 unsigned char r_volume_code, l_volume_code, l_pct, r_pct; audio_codec->headphone_volume = volume; // Calculate balance if( audio_codec->headphone_balance <= 50 ){ l_pct = 100; } else { l_pct = ( 50 - ( audio_codec->headphone_balance - 50 ) * 2); } if( audio_codec->headphone_balance >= 50 ){ r_pct = 100; } else { r_pct = ( audio_codec->headphone_balance * 2 ); } l_volume_code = (((((( audio_codec->headphone_volume * l_pct ) / 100 ) * 80 ) / 100 ) + 48 ) - 1 ); r_volume_code = (((((( audio_codec->headphone_volume * r_pct ) / 100 ) * 80 ) / 100 ) + 48 ) - 1 ); audio_codec_write_ctrl( AUDIO_CTRL_REG_HEADPHONE_L, l_volume_code ); audio_codec_write_ctrl( AUDIO_CTRL_REG_HEADPHONE_R, r_volume_code ); return( 0 );
Test Plan Test units independently: Get sample BPM from jogging Audio Codec through speaker output(Done!) Accelerometer and measuring BPM SD card Get sample BPM from jogging Shake accelerometer to see if music syncs
Optional Features Display track information on LCD Volume control Move onto the small portable Altera board
Questions?