16bit resolution PWM wave player with SD card, super lite version.
Dependencies: mbed DirectSPI FastPWM
Supported boards (confirmed):
Nucleo-F030R8
Nucleo-L152RE
Nucleo-F401RE
Nucleo-F411RE
Only compilation is OK (unchecked, but may work):
Nucleo-L073RZ
Nucleo-F334R8
Nucleo-F303RE
Nucleo-F429ZI
Nucleo-F446RE
Nucleo-F446ZE
Nucleo-L476RG
Supported SD card:
SDSC/SDHC card,
FAT16 and FAT32.
(1) At first, format SD card using SD Card Formatter
https://www.sdcard.org/downloads/formatter_4/index.html
(2) Copy PCM wav files to the SD card.
Supported file:
PCM wave file that have file extension ".wav" on root directory.
16bit/8bit, fs(sampling rate)=32kHz,44.1kHz,48kHz.
Stereo/Mono.
Hardware setting:
Refer to the file port_setting.txt
PWM output port:
Left upper(Hi) PWM 8bit out: PB_5 (TM3_CH2)
Right upper(Hi) PWM 8bit out: PB4 (TM3_CH1)
Left lower(Low) PWM 8bit out: PC_9 (TM3_CH4)
Right lower(Low) PWM 8bit out: PC_8 (TM3_CH3)
USER_BUTTON: PC_13(default button)
Next song: One click in Play mode.
Pause : Push long time .
Play : One click from Pause.
Diff: wave_player_main.cpp
- Revision:
- 11:8dc9fa1e1bdc
- Parent:
- 8:e35c1f3add8c
- Child:
- 13:544349ffb861
diff -r 1108261dabe8 -r 8dc9fa1e1bdc wave_player_main.cpp --- a/wave_player_main.cpp Mon Jan 21 22:17:25 2019 +0900 +++ b/wave_player_main.cpp Sun Feb 03 10:28:22 2019 +0900 @@ -10,9 +10,14 @@ #define send_ff() spi_read() #define send_ff16() spi_read16() #define CUT_LAST_TAG_NOISE (30*1000) -#if (HAVE_LED_INDICATOR==1) || (HAVE_LED_INDICATOR_2==1) +#if (HAVE_LED_IND_PWM==1) || (HAVE_LED_IND_BLINK==1) DigitalOut led(IND_LED); #endif +#define ind_on() (led = 1) +#define ind_off() (led = 0) + +#define pwm_period_timer_music_start() ( pwm_period_timer_start(),fPlaying = true) +#define pwm_period_timer_music_stop() ( pwm_period_timer_stop(), fPlaying = false) /****************** varialble definitions @@ -25,8 +30,7 @@ byte lbSample_bits = 16; byte lbCh_mode = CH_STEREO; byte bVolumeUpFactor; -sbit fPlaying; -sbit lfEndOneSong = true ; //to start music automatically +bool fPlaying = false; DigitalIn btn_bit_now(USER_BUTTON,PullUp); @@ -43,7 +47,6 @@ #if TEST_PORT_ENABLE test_port =1; #endif - fPlaying = true; #if PWM16BIT word wL_low,wL_hi,wR_low,wR_hi; dword dw; @@ -126,7 +129,7 @@ void wave_player_main(){ bVolumeUpFactor = calcPcmValidBits() - 8; word wBtnLowCount = 0; - #if HAVE_LED_INDICATOR_2 + #if HAVE_LED_IND_BLINK byte bTimeout_led = 0; #endif sbit btn_bit_prev = true, btn_short_on = false; @@ -134,20 +137,20 @@ #if HAVE_POWER_OFF_MODE btn_long_on2 = false; #endif + sbit btn_pause_prev = false; - #define btn_next_song_on btn_short_on + #define fbtn_next_song_on btn_short_on #define btn_pause_on btn_long_on #define btn_power_off_on btn_long_on2 - #if HAVE_LED_INDICATOR // pseudo PWM setting - const byte LED_OFF_DELAY_PAUSE = 5; - const byte LED_OFF_DELAY_PLAY = 50; - const sbyte PRD_COUNT = 0x6f ; //max 0x7f - const sbyte PAUSE_DUTY_MAX = PRD_COUNT/4; - sbyte sbDuty=0, sbCurrent_pos=0, sbDir=1; - sbyte sbMode_duty = PRD_COUNT ; //set duty playing - sbyte sbPseudo_period = PRD_COUNT ; //period for pseudo PWM - byte bOff_delay = LED_OFF_DELAY_PAUSE; + #if HAVE_LED_IND_PWM // pseudo PWM setting + const int8_t IND_PERIOD = 125; + const int8_t IND_DUTY_LOW_SPEED = 1; + const int8_t IND_DUTY_HI_SPEED = 3; + int8_t sbIndDuty = 0; + int8_t sbIndCurrPos = 0; + int8_t sbIndSpeed = IND_DUTY_LOW_SPEED; + int8_t sbIndDelta = sbIndSpeed; #endif init_tickTimer(); @@ -158,26 +161,14 @@ if( ldwSongFileSectors == 0 ){ //; found end of file break; //promptly exit and prepare next song } - - #if HAVE_LED_INDICATOR - /*--------------------- - pseudo PWM for LED - ---------------------*/ - if( sbCurrent_pos < sbDuty ){ - if( sbDir == 0 ){ - led = 0; - }else{ - led = 1; - } - } else { - led = 0; - } - sbCurrent_pos = sbCurrent_pos + 1; - sbPseudo_period = sbPseudo_period - 1; - if( sbPseudo_period == 0 ){ - sbPseudo_period = PRD_COUNT; - sbCurrent_pos = 0; - } + #if HAVE_LED_IND_PWM + /*# --------------------- + # pseudo PWM for LED + # ---------------------*/ + if(sbIndCurrPos < sbIndDuty) { ind_on();} + else{ ind_off();} + sbIndCurrPos++; + if(sbIndCurrPos == IND_PERIOD){ sbIndCurrPos = 0; } #endif } //; end. wait 10msec Ticker flag @@ -185,123 +176,64 @@ tickTimer_IF_clear(); //------------------- - #if HAVE_BUTTON_SW - /*------------------- - Pause release - -------------------*/ - if( btn_next_song_on){ - if( !fPlaying){ // ; if during pause - fPlaying = true ; //release pause - btn_next_song_on = false; - btn_pause_on = false; - #if HAVE_LED_INDICATOR - sbDuty = 0; - sbDir = 1; - #endif - pwm_period_timer_start(); - } - } - - /*------------------- - Pause enter - -------------------*/ - if( btn_pause_prev ^ btn_pause_on ){ - if( btn_pause_on ){ - fPlaying = false; - pwm_period_timer_stop(); - #if HAVE_LED_INDICATOR - sbDuty = PAUSE_DUTY_MAX/2; - sbDir = -1; - #endif - } - } - btn_pause_prev = btn_pause_on; - #endif - /*------------------- Next song and start -------------------*/ - if( lfEndOneSong){ - lfEndOneSong = false; + if ( ( ldwSongFileSectors == 0 ) | fbtn_next_song_on ){ + pwm_period_timer_music_stop(); + fbtn_next_song_on = false; + sd_stop_read(); + + /*# ------------------ + # Search next song + # ------------------*/ searchNextFile(); - //; delete about last 30Kbyte to cut tag data in *.wav file - ldwSongFileSectors = ( (gdwBPB_FileSize - CUT_LAST_TAG_NOISE) )>>9 ; //512 , change to sector //## Seek to Target file sector sd_start_read( gdwTargetFileSector ); - //### get wav header info ### - sd_read_pulse_byte(22);// ## Skip part of WAV header - lbCh_mode = sd_data_byte(); - sd_data_byte(); //# dummy read + //; delete about last 30Kbyte to cut tag data in *.wav file + ldwSongFileSectors = ( (gdwBPB_FileSize - CUT_LAST_TAG_NOISE) )>>9 ; //512 , change to sector + + /*# ------------------ + # Get wav header info + # ------------------*/ + sd_read_pulse_byte(22); // pos(22) ## Skip part of WAV header + lbCh_mode = sd_data_byte();// pos(23) + sd_data_byte(); // pos(24) # dummy read ldwSample_freq = sd_data_byte() + (sd_data_byte() << 8) + (sd_data_byte() << 16) + - (sd_data_byte() << 24); - setPwmPeriod(ldwSample_freq); - sd_read_pulse_byte(6);// ## Skip some headers - lbSample_bits = sd_data_byte(); - sd_read_pulse_byte(9) ;//## Skip to last position of header - //########################### - - lwReadCount = wREAD_COUNT - bHEADER_COUNT; - //; music start - pwm_period_timer_start(); + (sd_data_byte() << 24); // pos(28) + sd_read_pulse_byte(6); // pos(34) ## Skip some headers + lbSample_bits = sd_data_byte(); // pos(35) + sd_read_pulse_byte(9) ; // pos(44) ## Skip to last position of header - #if HAVE_LED_INDICATOR - sbDuty = 0; - sbDir = 1; - #endif - } + /*# ------------------ + # Set sampling frequency + # ------------------*/ + setPwmPeriod(ldwSample_freq); - /*------------------- - wait end of one song - -------------------*/ - if ( ( ldwSongFileSectors == 0 ) | btn_next_song_on ){ - pwm_period_timer_stop(); - fPlaying = false; - btn_next_song_on = false; - lfEndOneSong = true; - sd_stop_read(); + /*# ------------------ + # Music start + # ------------------*/ + lwReadCount = wREAD_COUNT - bHEADER_COUNT; + pwm_period_timer_music_start(); } /*------------------- LED indicator 1 --- pseudo PWM -------------------*/ - #if HAVE_LED_INDICATOR - if( fPlaying ){ - sbMode_duty = PRD_COUNT ; //during Playing - }else{ - #if HAVE_LED_PAUSE_INDICATOR - sbMode_duty = PAUSE_DUTY_MAX ;// during Pause - #else - sbMode_duty = 1; - #endif - } - //--- duty control - sbDuty = sbDuty + sbDir; - if(sbDuty == sbMode_duty ){ - sbDir = -1; - } - if( sbDuty == 0){ - sbDir = 0; - sbDuty = 1; - bOff_delay = LED_OFF_DELAY_PAUSE ;// during pause - if( fPlaying ){ - bOff_delay = LED_OFF_DELAY_PLAY ;// during play - } - } - if( sbDir == 0 ){ //; wait for a while at LED OFF - if( bOff_delay > 0 ){ - bOff_delay = bOff_delay - 1; - }else{ - sbDir = 1; - } - } + #if HAVE_LED_IND_PWM + sbIndDuty += sbIndDelta; + if(sbIndDuty > IND_PERIOD){ sbIndDelta = -1 * sbIndSpeed;} + if(sbIndDuty == 0){ sbIndDelta = sbIndSpeed;} + if(fPlaying){ sbIndSpeed = IND_DUTY_LOW_SPEED;} + else{ sbIndSpeed = IND_DUTY_HI_SPEED;} #endif /*------------------- LED indicator 2 --- simple ON/OFF -------------------*/ - #if HAVE_LED_INDICATOR_2 + #if HAVE_LED_IND_BLINK if (bTimeout_led == 0){ if( fPlaying ){ bTimeout_led = LED_PERIOD_PLAYNG ;// during Playing, on/off @@ -345,6 +277,29 @@ btn_long_on2 = true; } #endif + + /*------------------- + Pause release + -------------------*/ + if( fbtn_next_song_on){ + if( !fPlaying){ // ; if during pause + fPlaying = true ; //release pause + fbtn_next_song_on = false; + btn_pause_on = false; + pwm_period_timer_music_start(); + } + } + + /*------------------- + Pause enter + -------------------*/ + if( btn_pause_prev ^ btn_pause_on ){ + if( btn_pause_on ){ + fPlaying = false; + pwm_period_timer_music_stop(); + } + } + btn_pause_prev = btn_pause_on; #endif } //; [forever loop end] }