@@ -174,9 +174,11 @@ struct Hardware {
174174 /// The watchdog
175175 watchdog : hal:: Watchdog ,
176176 /// The audio CODEC
177- codec : tlv320aic23:: Codec ,
177+ audio_codec : tlv320aic23:: Codec ,
178178 /// PCM sample output queue
179179 audio_player : i2s:: Player ,
180+ /// How we are currently configured
181+ audio_config : common:: audio:: Config ,
180182}
181183
182184/// Flips between true and false so we always send a unique read request
@@ -1006,32 +1008,37 @@ impl Hardware {
10061008 i2s_lr_clock : hal_pins. gpio28 . into_mode ( ) ,
10071009 } ;
10081010
1009- let mut codec = tlv320aic23:: Codec :: new ( tlv320aic23:: BusAddress :: CsLow ) ;
1010- if let Err ( hal:: i2c:: Error :: Abort ( code) ) = codec . reset ( & mut i2c. acquire_i2c ( ) ) {
1011+ let mut audio_codec = tlv320aic23:: Codec :: new ( tlv320aic23:: BusAddress :: CsLow ) ;
1012+ if let Err ( hal:: i2c:: Error :: Abort ( code) ) = audio_codec . reset ( & mut i2c. acquire_i2c ( ) ) {
10111013 defmt:: error!( "CODEC did not respond: code {:?}" , code) ;
10121014 }
1013- codec. set_digital_interface_enabled ( true ) ;
1014- codec. set_dac_selected ( true ) ;
1015- codec. set_dac_mute ( false ) ;
1016- codec. set_bypass ( false ) ;
1017- codec. set_line_input_mute ( true , tlv320aic23:: Channel :: Both ) ;
1018- codec. set_powered_on ( tlv320aic23:: Subsystem :: AnalogDigitalConverter , true ) ;
1019- codec. set_powered_on ( tlv320aic23:: Subsystem :: MicrophoneInput , true ) ;
1020- codec. set_powered_on ( tlv320aic23:: Subsystem :: LineInput , true ) ;
1021- codec. set_headphone_output_volume ( 100 , tlv320aic23:: Channel :: Both ) ;
1022- codec. set_sample_rate (
1023- tlv320aic23:: CONFIG_USB_44K1 ,
1015+ audio_codec. set_digital_interface_enabled ( true ) ;
1016+ audio_codec. set_dac_selected ( true ) ;
1017+ audio_codec. set_dac_mute ( false ) ;
1018+ audio_codec. set_bypass ( false ) ;
1019+ audio_codec. set_line_input_mute ( true , tlv320aic23:: Channel :: Both ) ;
1020+ audio_codec. set_powered_on ( tlv320aic23:: Subsystem :: AnalogDigitalConverter , true ) ;
1021+ audio_codec. set_powered_on ( tlv320aic23:: Subsystem :: MicrophoneInput , true ) ;
1022+ audio_codec. set_powered_on ( tlv320aic23:: Subsystem :: LineInput , true ) ;
1023+ // Set volume to -6dB. 73 = 0 dB, and it's 1 dB per step.
1024+ audio_codec. set_headphone_output_volume ( 64 , tlv320aic23:: Channel :: Both ) ;
1025+ audio_codec. set_sample_rate (
1026+ tlv320aic23:: CONFIG_USB_48K ,
10241027 tlv320aic23:: LrSwap :: Disabled ,
10251028 tlv320aic23:: LrPhase :: RightOnHigh ,
10261029 tlv320aic23:: Mode :: Controller ,
10271030 tlv320aic23:: InputBitLength :: B16 ,
10281031 tlv320aic23:: DataFormat :: I2s ,
10291032 ) ;
1030- if let Err ( hal:: i2c:: Error :: Abort ( code) ) = codec. sync ( & mut i2c. acquire_i2c ( ) ) {
1033+ let audio_config = common:: audio:: Config {
1034+ sample_format : common:: audio:: SampleFormat :: SixteenBitStereo ,
1035+ sample_rate_hz : 48000 ,
1036+ } ;
1037+ if let Err ( hal:: i2c:: Error :: Abort ( code) ) = audio_codec. sync ( & mut i2c. acquire_i2c ( ) ) {
10311038 defmt:: error!( "CODEC did not respond: code {:?}" , code) ;
10321039 }
10331040
1034- let sample_queue = i2s:: init ( pio1, resets) ;
1041+ let audio_player = i2s:: init ( pio1, resets) ;
10351042
10361043 (
10371044 Hardware {
@@ -1062,8 +1069,9 @@ impl Hardware {
10621069 card_state : CardState :: Unplugged ,
10631070 clocks,
10641071 watchdog,
1065- codec,
1066- audio_player : sample_queue,
1072+ audio_codec,
1073+ audio_player,
1074+ audio_config,
10671075 } ,
10681076 hal_pins. gpio20 . into_pull_up_input ( ) ,
10691077 )
@@ -2092,43 +2100,43 @@ extern "C" fn audio_mixer_channel_get_info(
20922100 name : common:: FfiString :: new ( "LeftOut" ) ,
20932101 direction : common:: audio:: Direction :: Output ,
20942102 max_level : 79 ,
2095- current_level : hw. codec . get_headphone_output_volume ( ) . 0 ,
2103+ current_level : hw. audio_codec . get_headphone_output_volume ( ) . 0 ,
20962104 } ) ,
20972105 1 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
20982106 name : common:: FfiString :: new ( "RightOut" ) ,
20992107 direction : common:: audio:: Direction :: Output ,
21002108 max_level : 79 ,
2101- current_level : hw. codec . get_headphone_output_volume ( ) . 1 ,
2109+ current_level : hw. audio_codec . get_headphone_output_volume ( ) . 1 ,
21022110 } ) ,
21032111 2 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21042112 name : common:: FfiString :: new ( "LeftIn" ) ,
21052113 direction : common:: audio:: Direction :: Input ,
21062114 max_level : 31 ,
2107- current_level : hw. codec . get_line_input_volume_steps ( ) . 0 ,
2115+ current_level : hw. audio_codec . get_line_input_volume_steps ( ) . 0 ,
21082116 } ) ,
21092117 3 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21102118 name : common:: FfiString :: new ( "RightIn" ) ,
21112119 direction : common:: audio:: Direction :: Input ,
21122120 max_level : 31 ,
2113- current_level : hw. codec . get_line_input_volume_steps ( ) . 1 ,
2121+ current_level : hw. audio_codec . get_line_input_volume_steps ( ) . 1 ,
21142122 } ) ,
21152123 4 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21162124 name : common:: FfiString :: new ( "LeftInMute" ) ,
21172125 direction : common:: audio:: Direction :: Input ,
21182126 max_level : 1 ,
2119- current_level : hw. codec . get_line_input_mute ( ) . 0 as u8 ,
2127+ current_level : hw. audio_codec . get_line_input_mute ( ) . 0 as u8 ,
21202128 } ) ,
21212129 5 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21222130 name : common:: FfiString :: new ( "RightInMute" ) ,
21232131 direction : common:: audio:: Direction :: Input ,
21242132 max_level : 1 ,
2125- current_level : hw. codec . get_line_input_mute ( ) . 1 as u8 ,
2133+ current_level : hw. audio_codec . get_line_input_mute ( ) . 1 as u8 ,
21262134 } ) ,
21272135 6 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21282136 name : common:: FfiString :: new ( "Sidetone" ) ,
21292137 direction : common:: audio:: Direction :: Output ,
21302138 max_level : 5 ,
2131- current_level : match hw. codec . get_sidetone_level ( ) {
2139+ current_level : match hw. audio_codec . get_sidetone_level ( ) {
21322140 tlv320aic23:: Sidetone :: ZeroDb => 5 ,
21332141 tlv320aic23:: Sidetone :: Minus6 => 4 ,
21342142 tlv320aic23:: Sidetone :: Minus9 => 3 ,
@@ -2141,37 +2149,37 @@ extern "C" fn audio_mixer_channel_get_info(
21412149 name : common:: FfiString :: new ( "MicEnable" ) ,
21422150 direction : common:: audio:: Direction :: Input ,
21432151 max_level : 1 ,
2144- current_level : hw. codec . get_audio_input ( ) as u8 ,
2152+ current_level : hw. audio_codec . get_audio_input ( ) as u8 ,
21452153 } ) ,
21462154 8 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21472155 name : common:: FfiString :: new ( "MicBoost" ) ,
21482156 direction : common:: audio:: Direction :: Input ,
21492157 max_level : 1 ,
2150- current_level : hw. codec . get_microphone_boost ( ) as u8 ,
2158+ current_level : hw. audio_codec . get_microphone_boost ( ) as u8 ,
21512159 } ) ,
21522160 9 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21532161 name : common:: FfiString :: new ( "MicMute" ) ,
21542162 direction : common:: audio:: Direction :: Input ,
21552163 max_level : 1 ,
2156- current_level : hw. codec . get_microphone_mute ( ) as u8 ,
2164+ current_level : hw. audio_codec . get_microphone_mute ( ) as u8 ,
21572165 } ) ,
21582166 10 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21592167 name : common:: FfiString :: new ( "Bypass" ) ,
21602168 direction : common:: audio:: Direction :: Input ,
21612169 max_level : 1 ,
2162- current_level : hw. codec . get_bypass ( ) as u8 ,
2170+ current_level : hw. audio_codec . get_bypass ( ) as u8 ,
21632171 } ) ,
21642172 11 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21652173 name : common:: FfiString :: new ( "DacEnable" ) ,
21662174 direction : common:: audio:: Direction :: Output ,
21672175 max_level : 1 ,
2168- current_level : hw. codec . get_dac_selected ( ) as u8 ,
2176+ current_level : hw. audio_codec . get_dac_selected ( ) as u8 ,
21692177 } ) ,
21702178 12 => FfiOption :: Some ( common:: audio:: MixerChannelInfo {
21712179 name : common:: FfiString :: new ( "DacMute" ) ,
21722180 direction : common:: audio:: Direction :: Output ,
21732181 max_level : 1 ,
2174- current_level : hw. codec . get_dac_mute ( ) as u8 ,
2182+ current_level : hw. audio_codec . get_dac_mute ( ) as u8 ,
21752183 } ) ,
21762184 _ => FfiOption :: None ,
21772185 }
@@ -2192,60 +2200,120 @@ extern "C" fn audio_mixer_channel_set_level(audio_mixer_id: u8, level: u8) -> Ap
21922200 use tlv320aic23:: Channel ;
21932201
21942202 match audio_mixer_id {
2195- 0 => hw. codec . set_headphone_output_volume ( level, Channel :: Left ) ,
2196- 1 => hw. codec . set_headphone_output_volume ( level, Channel :: Right ) ,
2197- 2 => hw. codec . set_line_input_volume_steps ( level, Channel :: Left ) ,
2198- 3 => hw. codec . set_line_input_volume_steps ( level, Channel :: Right ) ,
2199- 4 => hw. codec . set_line_input_mute ( level == 1 , Channel :: Left ) ,
2200- 5 => hw. codec . set_line_input_mute ( level == 1 , Channel :: Right ) ,
2201- 6 => hw. codec . set_sidetone_level ( match level {
2203+ 0 => hw
2204+ . audio_codec
2205+ . set_headphone_output_volume ( level, Channel :: Left ) ,
2206+ 1 => hw
2207+ . audio_codec
2208+ . set_headphone_output_volume ( level, Channel :: Right ) ,
2209+ 2 => hw
2210+ . audio_codec
2211+ . set_line_input_volume_steps ( level, Channel :: Left ) ,
2212+ 3 => hw
2213+ . audio_codec
2214+ . set_line_input_volume_steps ( level, Channel :: Right ) ,
2215+ 4 => hw
2216+ . audio_codec
2217+ . set_line_input_mute ( level == 1 , Channel :: Left ) ,
2218+ 5 => hw
2219+ . audio_codec
2220+ . set_line_input_mute ( level == 1 , Channel :: Right ) ,
2221+ 6 => hw. audio_codec . set_sidetone_level ( match level {
22022222 5 => tlv320aic23:: Sidetone :: ZeroDb ,
22032223 4 => tlv320aic23:: Sidetone :: Minus6 ,
22042224 3 => tlv320aic23:: Sidetone :: Minus9 ,
22052225 2 => tlv320aic23:: Sidetone :: Minus12 ,
22062226 1 => tlv320aic23:: Sidetone :: Minus18 ,
22072227 _ => tlv320aic23:: Sidetone :: Disabled ,
22082228 } ) ,
2209- 7 => hw. codec . set_audio_input ( match level {
2229+ 7 => hw. audio_codec . set_audio_input ( match level {
22102230 0 => tlv320aic23:: AudioInput :: LineInput ,
22112231 _ => tlv320aic23:: AudioInput :: Microphone ,
22122232 } ) ,
2213- 8 => hw. codec . set_microphone_boost ( level == 1 ) ,
2214- 9 => hw. codec . set_microphone_mute ( level == 1 ) ,
2215- 10 => hw. codec . set_bypass ( level == 1 ) ,
2216- 11 => hw. codec . set_dac_selected ( level == 1 ) ,
2217- 12 => hw. codec . set_dac_mute ( level == 1 ) ,
2233+ 8 => hw. audio_codec . set_microphone_boost ( level == 1 ) ,
2234+ 9 => hw. audio_codec . set_microphone_mute ( level == 1 ) ,
2235+ 10 => hw. audio_codec . set_bypass ( level == 1 ) ,
2236+ 11 => hw. audio_codec . set_dac_selected ( level == 1 ) ,
2237+ 12 => hw. audio_codec . set_dac_mute ( level == 1 ) ,
22182238 _ => {
22192239 return ApiResult :: Err ( neotron_common_bios:: Error :: InvalidDevice ) ;
22202240 }
22212241 } ;
2222- if hw. codec . sync ( & mut hw. i2c . acquire_i2c ( ) ) . is_ok ( ) {
2242+ if hw. audio_codec . sync ( & mut hw. i2c . acquire_i2c ( ) ) . is_ok ( ) {
22232243 neotron_common_bios:: FfiResult :: Ok ( ( ) )
22242244 } else {
22252245 ApiResult :: Err ( neotron_common_bios:: Error :: DeviceError ( 0 ) )
22262246 }
22272247}
22282248
2229- extern "C" fn audio_output_set_config ( _config : common:: audio:: Config ) -> ApiResult < ( ) > {
2230- ApiResult :: Err ( CError :: Unimplemented )
2249+ extern "C" fn audio_output_set_config ( config : common:: audio:: Config ) -> ApiResult < ( ) > {
2250+ // We can't support 8-bit samples with this CODEC. See `audio_output_data`
2251+ // if you add any more supported sample formats, so the playback routine
2252+ // does the right thing.
2253+ match config. sample_format {
2254+ common:: audio:: SampleFormat :: SixteenBitStereo
2255+ | common:: audio:: SampleFormat :: SixteenBitMono => {
2256+ // Format Ok
2257+ }
2258+ _ => {
2259+ return ApiResult :: Err ( CError :: UnsupportedConfiguration ( 0 ) ) ;
2260+ }
2261+ }
2262+ let sample_rate = match config. sample_rate_hz {
2263+ 48000 => tlv320aic23:: CONFIG_USB_48K ,
2264+ 44100 => tlv320aic23:: CONFIG_USB_44K1 ,
2265+ 32000 => tlv320aic23:: CONFIG_USB_32K ,
2266+ 8000 => tlv320aic23:: CONFIG_USB_8K ,
2267+ _ => {
2268+ return ApiResult :: Err ( CError :: UnsupportedConfiguration ( 1 ) ) ;
2269+ }
2270+ } ;
2271+ let mut lock = HARDWARE . lock ( ) ;
2272+ let hw = lock. as_mut ( ) . unwrap ( ) ;
2273+ hw. audio_codec . set_sample_rate (
2274+ sample_rate,
2275+ tlv320aic23:: LrSwap :: Disabled ,
2276+ tlv320aic23:: LrPhase :: RightOnHigh ,
2277+ tlv320aic23:: Mode :: Controller ,
2278+ tlv320aic23:: InputBitLength :: B16 ,
2279+ tlv320aic23:: DataFormat :: I2s ,
2280+ ) ;
2281+ hw. audio_config = config;
2282+ ApiResult :: Ok ( ( ) )
22312283}
22322284
22332285extern "C" fn audio_output_get_config ( ) -> ApiResult < common:: audio:: Config > {
2234- ApiResult :: Err ( CError :: Unimplemented )
2286+ let mut lock = HARDWARE . lock ( ) ;
2287+ let hw = lock. as_mut ( ) . unwrap ( ) ;
2288+ let config = hw. audio_config . clone ( ) ;
2289+ ApiResult :: Ok ( config)
22352290}
22362291
22372292unsafe extern "C" fn audio_output_data ( samples : FfiByteSlice ) -> ApiResult < usize > {
22382293 let mut lock = HARDWARE . lock ( ) ;
22392294 let hw = lock. as_mut ( ) . unwrap ( ) ;
22402295 let samples = samples. as_slice ( ) ;
2241- let count = hw. audio_player . play_samples_16bit_stereo_48khz ( samples) ;
2296+ // We only support these two kinds.
2297+ let count = match hw. audio_config . sample_format {
2298+ common:: audio:: SampleFormat :: SixteenBitMono => {
2299+ hw. audio_player . play_samples_16bit_mono ( samples)
2300+ }
2301+ common:: audio:: SampleFormat :: SixteenBitStereo => {
2302+ hw. audio_player . play_samples_16bit_stereo ( samples)
2303+ }
2304+ _ => {
2305+ return ApiResult :: Err ( CError :: Unimplemented ) ;
2306+ }
2307+ } ;
22422308 ApiResult :: Ok ( count)
22432309}
22442310
22452311extern "C" fn audio_output_get_space ( ) -> ApiResult < usize > {
22462312 let mut lock = HARDWARE . lock ( ) ;
22472313 let hw = lock. as_mut ( ) . unwrap ( ) ;
2248- // The result is in samples, where each sample is 16-bit stereo (i.e. 32-bits)
2314+ // The result is in samples, where each sample is 16-bit stereo (i.e.
2315+ // 32-bits) or 16-bit mono (i.e. 16-bit) depending on the audio
2316+ // configuration.
22492317 ApiResult :: Ok ( hw. audio_player . available_space ( ) )
22502318}
22512319
0 commit comments