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
log_ch_nbr
allows you to get or set the volume for a specific channel. Whenlog_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.
#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.