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.

pwm_lib.cpp

Committer:
mimi3
Date:
2020-10-09
Revision:
21:dc161a192ba7
Parent:
5:4aa4cc29d5ef

File content as of revision 21:dc161a192ba7:

/* */

#include "mbed.h"
#include "sys.h"
#include "pwm_lib.h"

/* Using FastPWM library from:
 * http://developer.mbed.org/users/Sissors/code/FastPWM/
 * Thank you this FastPWM library.
 */

static TIM_HandleTypeDef TimHandle_pwm;

/*
 * PWM definition
 * */
// Use PWM3-1(Right),PWM3-2(Left) with TIM3
TPWM pwmLeftHi( PWM_PORT_LEFT_HI ,PWM_TIMER_PRE_SCALE);
TPWM pwmRightHi(PWM_PORT_RIGHT_HI,PWM_TIMER_PRE_SCALE);
// Use PWM3-3,PWM3-4 with TIM3
TPWM pwmLeftLow( PWM_PORT_LEFT_LOW ,PWM_TIMER_PRE_SCALE);
TPWM pwmRightLow(PWM_PORT_RIGHT_LOW,PWM_TIMER_PRE_SCALE);

/*
 * PWM Timer constants value
 *
 *  TIMER_BASE_CLK is assumed that      bits
TARGET_NUCLEO_F411RE            96 MHz  11
TARGET_NUCLEO_F401RE            84 MHz  10
                                72 MHz  10
TARGET_NUCLEO_F103RB            64 MHz  10
TARGET_NUCLEO_F030R8            48 MHz  10
                                32 MHz   9
TARGET_NUCLEO_L152RE            24 MHz   9
                                16 MHz   8
                                12 MHz   8
*/
#define TIMER_BASE_CLK              ( SystemCoreClock )
#define PERIOD_TIMER_INPUT_CLK      ( TIMER_BASE_CLK / PWM_TIMER_PRE_SCALE )
#define PERIOD2TICS(period)         ( PERIOD_TIMER_INPUT_CLK / ( period ) )
#define INITIAL_PERIOD               44100  // fs=44.1kHz

/* WAVE signal effective bits
 * if fs==44.1kHz then:
 * PCM_SIGNIFICANT_BITS = int[ log_2[ (PERIOD_TIMER_INPUT_CLK / 44100 ) ] ]
 */
uint8_t gPcmShifNum;

uint8_t calcPcmValidBits( void )
{
    if( SystemCoreClock >= 96000000 ){
        return 11;
    } else if( SystemCoreClock >= 48000000  ){
        return 10;
    } else if( SystemCoreClock >= 24000000 ){
        return 9;
    }
    return 8;
}

/*
 * PWM Timer Interrupt routine
 * */
/**********************
  pwmPeriodIntr
 **********************/
void pwmPeriodIntr( void );

/**********************
  setPwmPeriod
 **********************/
void setPwmPeriod( int period )
{
    pwmLeftHi.period_ticks(  PERIOD2TICS(period) );
    pwmRightHi.period_ticks( PERIOD2TICS(period) );
    pwmLeftLow.period_ticks( PERIOD2TICS(period) );
    pwmRightLow.period_ticks(PERIOD2TICS(period) );
}

/**********************
  pwmTimerInit
 **********************/
void pwmTimerInit(void)
{
    TimHandle_pwm.Instance = TIM_PWM;
    HAL_NVIC_SetPriority(TIM_PWM_IRQ,    0, 0);
    NVIC_SetVector( TIM_PWM_IRQ, (uint32_t)&pwmPeriodIntr );
    pwmPeriodIntrEnable();
    periodTimerIntrStop();
    setPwmPeriod( INITIAL_PERIOD );
}

/******************
 pwm_start
*******************/
void pwm_period_timer_start() {
    periodTimerIntrStart();
}

/******************
 pwm_stop
*******************/
void pwm_period_timer_stop() {
    periodTimerIntrStop();
}

/******************
 pwm_init
*******************/
void pwm_init() {
    pwmTimerInit();
    gPcmShifNum = 16 - calcPcmValidBits();
}