USBD_Audio_DrvCtrlFU_VolManage

Description

Get or set volume for one or all logical channels inside a cluster.

Files

usbd_audio_drv_<codec-name>.h / usbd_audio_drv_<codec-name>.c

Prototype

static  CPU_BOOLEAN  USBD_Audio_DrvCtrlFU_VolManage (USBD_AUDIO_DRV  *p_audio_drv,
                                                     CPU_INT08U       req,
                                                     CPU_INT08U       unit_id,
                                                     CPU_INT08U       log_ch_nbr,
                                                     CPU_INT16U      *p_vol);


Arguments

p_audio_drv

Pointer to audio driver structure.

req

Volume request:

USBD_AUDIO_REQ_GET_CUR
USBD_AUDIO_REQ_GET_RES
USBD_AUDIO_REQ_GET_MIN
USBD_AUDIO_REQ_GET_MAX
USBD_AUDIO_REQ_SET_CUR

unit_id

Feature Unit ID.

log_ch_nbr

Logical channel number.

p_vol

Pointer to the volume value to set or get.

Endianness

p_vol uses a little endian memory organization. Hence, you should use µC/LIB macros MEM_VAL_GET_INT16U_LITTLE() and MEM_VAL_SET_INT16U_LITTLE() when reading or writing the volume from/to it. This will ensure data is accessed correctly regarding your CPU endianness.

Returned Value

DEF_OK, if NO error(s) occurred and request is supported.

DEF_FAIL, otherwise.

Callers

Audio Class.

Implementation guidelines

  1. log_ch_nbr allows you to get or set the volume for a specific channel. When log_ch_nbr is 0, you get or set the volume for all channels. Indeed, the logical channel #0 represents the master channel and encompasses all channels.

This listing shows an example usage of this function.

Listing - USBD_Audio_DrvCtrlFU_VolManage() Example Usage
#define  FU_SPEAKER_ID      							 6u
#define  FU_MIC_ID          							 7u

#define  CODEC_MASTER_VOL_CTRL_MIN_dB               0xC200u
#define  CODEC_MASTER_VOL_CTRL_MAX_dB               0x0000u
#define  CODEC_MASTER_VOL_CTRL_RES_dB               0x0040u
#define  CODEC_MASTER_VOL_CTRL_SILENCE                 252u
#define  CODEC_DECIMATOR_VOL_CTRL_MIN_dB            0xBF80u
#define  CODEC_DECIMATOR_VOL_CTRL_MAX_dB            0x1800u
#define  CODEC_DECIMATOR_VOL_CTRL_RES_dB            0x0080u
#define  CODEC_DECIMATOR_VOL_CTRL_SILENCE              128u


static  CPU_BOOLEAN  USBD_Audio_DrvCtrlFU_VolManage (CPU_INT08U   req,
                                                     CPU_INT08U   unit_id,
                                                     CPU_INT08U   log_ch_nbr,
                                                     CPU_INT16U  *p_vol)
{
    CPU_INT16S  temp;
    CPU_INT08U  vol_to_set;


    (void)&log_ch_nbr;											              

    switch (req) {												              (1)
        case USBD_AUDIO_REQ_GET_CUR:							              (2)
             if (unit_id == FU_SPEAKER_ID) {
                 *p_vol = FU_VolSpeaker;
             } else {
                 *p_vol = FU_VolMic;
             }
             break;


        case USBD_AUDIO_REQ_GET_MIN:							              (3)
             if (unit_id == FU_SPEAKER_ID) {
                 *p_vol = CODEC_MASTER_VOL_CTRL_MIN_dB;       /* -78 dB.                               				  */
             } else {
                 *p_vol = CODEC_DECIMATOR_VOL_CTRL_MIN_dB;    /* -63.5 dB.                             			      */
             }
             break;


        case USBD_AUDIO_REQ_GET_MAX:							              (4)
             if (unit_id == FU_SPEAKER_ID) {
                 *p_vol = CODEC_MASTER_VOL_CTRL_MAX_dB;       /* 0 dB.                                                */
             } else {
                 *p_vol = CODEC_DECIMATOR_VOL_CTRL_MAX_dB;    /* +24 dB.                                              */
             }
             break;


        case USBD_AUDIO_REQ_GET_RES:							              (5)
             if (unit_id == FU_SPEAKER_ID) {
                 *p_vol = CODEC_MASTER_VOL_CTRL_RES_dB;       /* Resolution of 0.25 dB.                               */
             } else {
                 *p_vol = CODEC_DECIMATOR_VOL_CTRL_RES_dB;    /* Resolution of 0.5 dB.                                */
             }
             break;


        case USBD_AUDIO_REQ_SET_CUR:							
             if (unit_id == FU_SPEAKER_ID) {
                 FU_VolSpeaker = *p_vol;						              (6)
                 if (*p_vol == USBD_AUDIO_FU_CTRL_VOL_SILENCE) {
                     vol_to_set = CODEC_MASTER_VOL_CTRL_SILENCE;
                 }
                                                              /* Negative dB.                                         */
                                                                              (7)
                 temp       = (CPU_INT16S)*p_vol;
                 vol_to_set = (CPU_INT08U)(-temp / CODEC_MASTER_VOL_CTRL_RES_dB);
                                                                              (8)
                 /* $$$$ Set volume level for record stream in audio chip. */


             } else
                 FU_VolMic = *p_vol;
                 if (*p_vol == USBD_AUDIO_FU_CTRL_VOL_SILENCE) {
                     vol_to_set = CODEC_DECIMATOR_VOL_CTRL_SILENCE;
                 }
                                                               /* Negative dB.                                         */
                 if (*p_vol > CODEC_DECIMATOR_VOL_CTRL_MIN_dB) {              (7)
                     temp       = (CPU_INT16S)*p_vol;
                     vol_to_set = (CPU_INT08U)(-temp / CODEC_DECIMATOR_VOL_CTRL_RES_dB);
                 } else {                                      /* Positive dB.                                         */
                     vol_to_set = (CPU_INT08U)(*p_vol / CODEC_DECIMATOR_VOL_CTRL_RES_dB);
                 }
                                                                              (8)
                 /* $$$$ Set volume level for record stream in audio chip. */
             }
             break;

        default:
             return (DEF_FAIL);
    }

    return (DEF_OK);
}

(1) The request type may be processed in a switch statement. Volume control supports all GET_XXX requests and SET_CUR.

(2) By using the Feature Unit ID, unique within the audio function, you can return the current volume level stored for example in a local global variable updated by the SET_CUR request case.

(3) By using the Feature Unit ID, you can return the minimum volume level possible. This value will be a constant. In this example, the volume attenuation for the speaker ranges from 0 to -78 dB and corresponds to the range supported by the audio codec. Thus, the minimum value is -78 dB. Refer to the warning below about volume levels range translated from audio codec range to Audio 1.0 specification range and vice versa.

(4) By using the Feature Unit ID, you can return the maximum volume level possible. This value will be a constant. In this example, the volume attenuation for the speaker ranges from 0 to -78 dB and corresponds to the range supported by the audio codec. Thus, the minimum value is 0 dB. Refer to the warning below about volume levels range translated from audio codec range to Audio 1.0 specification range and vice versa.

(5) By using the Feature Unit ID, you can return the resolution supported by the audio codec to change the volume level. This value will be a constant. In this example, the codec uses steps of 0.25 dB. Refer to the warning below about volume levels range translated from audio codec range to Audio 1.0 specification range and vice versa.

(6) For the request SET_CUR, you can update the volume level stored for instance locally in a global variable. This global variable will be read by GET_CUR request case.

(7) The volume value pointed by p_vol is translated into a value understood by the audio codec. Indeed, the volume value sent by the host corresponds to the volume range defined by Audio 1.0 specification. This range does not necessarily match the volume range supported by the audio codec. Refer to the warning below about volume levels range translated from Audio 1.0 specification range to audio codec range to and vice versa.

(8) You should use the proper functions to set the volume level in the audio codec. It could be for instance sending some I2C commands to write in some audio codec registers. Return DEF_FAIL if any error occurs during the volume setting.

Volume Values Range Conversion (Audio Chip <-> Audio 1.0 spec)

When manipulating volume levels, be aware that you must handle the conversion from the audio codec range to the Audio 1.0 specification range and vice versa. Audio 1.0 indicates that the volume can range from +127.9961 dB (0x7FFF) down to -127.9961 dB (0x8001) in steps of 1/256 dB (0x0001) with an extended value of 0x8000 for -∞dB.

For GET_MIN, GET_MAX, and GET_RES request, respectively, the minimum, maximum and step volume must be translated from the audio codec range to the Audio 1.0 range.

For SET_CUR request, the volume level must be translated from the Audio 1.0 range to the audio codec range.