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)
http://mpu.up.seesaa.net/image/16bit-wave-player-output-schema.png
USER_BUTTON: PC_13(default button)
Next song: One click in Play mode.
Pause : Push long time .
Play : One click from Pause.

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