1111#include " Driver/es8374/es8374.h"
1212#include " Driver/es8388/es8388.h"
1313#include " Driver/tas5805m/tas5805m.h"
14+ #include " Driver/wm8960/mtb_wm8960.h"
1415#include " Driver/wm8994/wm8994.h"
1516
1617#include " DriverPins.h"
@@ -205,7 +206,7 @@ class AudioDriver {
205206 // / make sure that value is in range
206207 // / @param volume
207208 // / @return
208- int limitVolume (int volume, int min = 0 , int max = 100 ) {
209+ int limitValue (int volume, int min = 0 , int max = 100 ) {
209210 if (volume > max)
210211 volume = max;
211212 if (volume < min)
@@ -223,7 +224,7 @@ class AudioDriverAC101Class : public AudioDriver {
223224public:
224225 bool setMute (bool mute) { return ac101_set_voice_mute (mute); }
225226 bool setVolume (int volume) {
226- return ac101_set_voice_volume (limitVolume (volume));
227+ return ac101_set_voice_volume (limitValue (volume));
227228 };
228229 int getVolume () {
229230 int vol;
@@ -345,7 +346,7 @@ class AudioDriverES7210Class : public AudioDriver {
345346 bool setMute (bool mute) { return es7210_set_mute (mute) == RESULT_OK; }
346347 bool setVolume (int volume) {
347348 this ->volume = volume;
348- return es7210_adc_set_volume (limitVolume (volume)) == RESULT_OK;
349+ return es7210_adc_set_volume (limitValue (volume)) == RESULT_OK;
349350 }
350351 int getVolume () { return volume; }
351352
@@ -380,7 +381,7 @@ class AudioDriverES7243Class : public AudioDriver {
380381 return es7243_adc_set_voice_mute (mute) == RESULT_OK;
381382 }
382383 bool setVolume (int volume) {
383- return es7243_adc_set_voice_volume (limitVolume (volume)) == RESULT_OK;
384+ return es7243_adc_set_voice_volume (limitValue (volume)) == RESULT_OK;
384385 }
385386 int getVolume () {
386387 int vol;
@@ -420,7 +421,7 @@ class AudioDriverES7243eClass : public AudioDriver {
420421 }
421422 bool setVolume (int volume) {
422423 this ->volume = volume;
423- return es7243e_adc_set_voice_volume (limitVolume (volume)) == RESULT_OK;
424+ return es7243e_adc_set_voice_volume (limitValue (volume)) == RESULT_OK;
424425 }
425426 int getVolume () {
426427 int vol;
@@ -460,7 +461,7 @@ class AudioDriverES8156Class : public AudioDriver {
460461 }
461462 bool setVolume (int volume) {
462463 AD_LOGD (" volume %d" , volume);
463- return es8156_codec_set_voice_volume (limitVolume (volume)) == RESULT_OK;
464+ return es8156_codec_set_voice_volume (limitValue (volume)) == RESULT_OK;
464465 }
465466 int getVolume () {
466467 int vol;
@@ -496,7 +497,7 @@ class AudioDriverES8311Class : public AudioDriver {
496497public:
497498 bool setMute (bool mute) { return es8311_set_voice_mute (mute) == RESULT_OK; }
498499 bool setVolume (int volume) {
499- return es8311_codec_set_voice_volume (limitVolume (volume)) == RESULT_OK;
500+ return es8311_codec_set_voice_volume (limitValue (volume)) == RESULT_OK;
500501 }
501502 int getVolume () {
502503 int vol;
@@ -536,7 +537,7 @@ class AudioDriverES8374Class : public AudioDriver {
536537 bool setMute (bool mute) { return es8374_set_voice_mute (mute) == RESULT_OK; }
537538 bool setVolume (int volume) {
538539 AD_LOGD (" volume %d" , volume);
539- return es8374_codec_set_voice_volume (limitVolume (volume)) == RESULT_OK;
540+ return es8374_codec_set_voice_volume (limitValue (volume)) == RESULT_OK;
540541 }
541542 int getVolume () {
542543 int vol;
@@ -574,7 +575,7 @@ class AudioDriverES8388Class : public AudioDriver {
574575 bool setMute (bool mute) { return es8388_set_voice_mute (mute) == RESULT_OK; }
575576 bool setVolume (int volume) {
576577 AD_LOGD (" volume %d" , volume);
577- return es8388_set_voice_volume (limitVolume (volume)) == RESULT_OK;
578+ return es8388_set_voice_volume (limitValue (volume)) == RESULT_OK;
578579 }
579580 int getVolume () {
580581 int vol;
@@ -584,7 +585,7 @@ class AudioDriverES8388Class : public AudioDriver {
584585
585586 bool setInputVolume (int volume) {
586587 // map values from 0 - 100 to 0 to 10
587- es_mic_gain_t gain = (es_mic_gain_t )(limitVolume (volume) / 10 );
588+ es_mic_gain_t gain = (es_mic_gain_t )(limitValue (volume) / 10 );
588589 AD_LOGD (" input volume: %d -> gain %d" , volume, gain);
589590 return setMicrophoneGain (gain);
590591 }
@@ -618,7 +619,7 @@ class AudioDriverTAS5805MClass : public AudioDriver {
618619 bool setMute (bool mute) { return tas5805m_set_mute (mute) == RESULT_OK; }
619620 bool setVolume (int volume) {
620621 AD_LOGD (" volume %d" , volume);
621- return tas5805m_set_volume (limitVolume (volume)) == RESULT_OK;
622+ return tas5805m_set_volume (limitValue (volume)) == RESULT_OK;
622623 }
623624 int getVolume () {
624625 int vol;
@@ -638,6 +639,179 @@ class AudioDriverTAS5805MClass : public AudioDriver {
638639 bool deinit () { return tas5805m_deinit () == RESULT_OK; }
639640};
640641
642+ /* *
643+ * @brief Driver API for WM8990 codec chip
644+ * @author Phil Schatzmann
645+ * @copyright GPLv3
646+ */
647+ class AudioDriverWM8960Class : public AudioDriver {
648+ public:
649+ bool begin (CodecConfig codecCfg, DriverPins &pins) {
650+ codec_cfg = codecCfg;
651+
652+ auto i2c = pins.getI2CPins (CODEC);
653+ if (!i2c) {
654+ AD_LOGE (" i2c pins not defined" );
655+ return false ;
656+ }
657+ // define wire object
658+ mtb_wm8960_set_wire (i2c.value ().p_wire );
659+
660+ // setup wm8960
661+ if (!init (codecCfg)) {
662+ AD_LOGE (" init" );
663+ return false ;
664+ }
665+ setVolume (DRIVER_DEFAULT_VOLUME);
666+ if (!mtb_wm8960_activate ()) {
667+ AD_LOGE (" mtb_wm8960_activate" );
668+ return false ;
669+ }
670+ if (!configure_clocking ()) {
671+ AD_LOGE (" configure_clocking" );
672+ return false ;
673+ }
674+ return true ;
675+ }
676+ bool end (void ) {
677+ mtb_wm8960_deactivate ();
678+ mtb_wm8960_free ();
679+ return true ;
680+ }
681+ bool setMute (bool enable) { return setVolume (enable ? 0 : volume_out); }
682+ // / Defines the Volume (in %) if volume is 0, mute is enabled,range is 0-100.
683+ bool setVolume (int volume) {
684+ setOutputVolume (volume);
685+ return true ;
686+ };
687+ int getVolume () { return volume_out; }
688+ bool setInputVolume (int volume) {
689+ adjustInputVolume (volume);
690+ return true ;
691+ }
692+ bool isVolumeSupported () { return true ; }
693+ bool isInputVolumeSupported () { return true ; }
694+
695+ protected:
696+ int volume_in;
697+ int volume_out;
698+ int i2c_retry_count = 5 ;
699+ int vs1053_mclk_hz = 0 ;
700+ bool vs1053_enable_pll = true ;
701+
702+ void adjustInputVolume (int vol) {
703+ volume_in = limitValue (vol, 0 , 100 );
704+ int vol_int = map (volume_in, 0 , 100 , 0 , 30 );
705+ mtb_wm8960_adjust_input_volume (vol_int);
706+ }
707+
708+ void setOutputVolume (int vol) {
709+ volume_out = limitValue (vol, 0 , 100 );
710+ int vol_int = volume_out == 0.0 ? 0 : map (volume_out, 0 , 100 , 30 , 0x7F );
711+ mtb_wm8960_set_output_volume (vol_int);
712+ }
713+
714+ bool init (CodecConfig cfg) {
715+ mtb_wm8960_set_write_retry_count (i2c_retry_count);
716+ int features = 0 ;
717+ switch (cfg.dac_output ) {
718+ case DAC_OUTPUT_LINE1:
719+ features = features | WM8960_FEATURE_SPEAKER;
720+ break ;
721+ case DAC_OUTPUT_LINE2:
722+ features = features | WM8960_FEATURE_HEADPHONE;
723+ break ;
724+ case DAC_OUTPUT_ALL:
725+ features = features | WM8960_FEATURE_SPEAKER | WM8960_FEATURE_HEADPHONE;
726+ break ;
727+ default :
728+ break ;
729+ }
730+ switch (cfg.adc_input ) {
731+ case ADC_INPUT_LINE1:
732+ features = features | WM8960_FEATURE_MICROPHONE1;
733+ break ;
734+ case ADC_INPUT_LINE2:
735+ features = features | WM8960_FEATURE_MICROPHONE2;
736+ break ;
737+ case ADC_INPUT_ALL:
738+ features = features | WM8960_FEATURE_MICROPHONE1 |
739+ WM8960_FEATURE_MICROPHONE2 | WM8960_FEATURE_MICROPHONE3;
740+ break ;
741+ default :
742+ break ;
743+ }
744+ AD_LOGW (" Setup features: %d" , features);
745+ return mtb_wm8960_init (features);
746+ }
747+
748+ bool configure_clocking () {
749+ if (vs1053_mclk_hz == 0 ) {
750+ // just pick a multiple of the sample rate
751+ vs1053_mclk_hz = 512 * codec_cfg.getRateNumeric ();
752+ }
753+ if (!mtb_wm8960_configure_clocking (
754+ vs1053_mclk_hz, vs1053_enable_pll, sampleRate (codec_cfg.getRateNumeric ()),
755+ wordLength (codec_cfg.getBitsNumeric ()),
756+ modeMasterSlave (codec_cfg.i2s .mode == MODE_MASTER))) {
757+ AD_LOGE (" mtb_wm8960_configure_clocking" );
758+ return false ;
759+ }
760+ return true ;
761+ }
762+
763+ mtb_wm8960_adc_dac_sample_rate_t sampleRate (int rate) {
764+ switch (rate) {
765+ case 48000 :
766+ return WM8960_ADC_DAC_SAMPLE_RATE_48_KHZ;
767+ case 44100 :
768+ return WM8960_ADC_DAC_SAMPLE_RATE_44_1_KHZ;
769+ case 32000 :
770+ return WM8960_ADC_DAC_SAMPLE_RATE_32_KHZ;
771+ case 24000 :
772+ return WM8960_ADC_DAC_SAMPLE_RATE_24_KHZ;
773+ case 22050 :
774+ return WM8960_ADC_DAC_SAMPLE_RATE_22_05_KHZ;
775+ case 16000 :
776+ return WM8960_ADC_DAC_SAMPLE_RATE_16_KHZ;
777+ case 12000 :
778+ return WM8960_ADC_DAC_SAMPLE_RATE_12_KHZ;
779+ case 11025 :
780+ return WM8960_ADC_DAC_SAMPLE_RATE_11_025_KHZ;
781+ case 8018 :
782+ return WM8960_ADC_DAC_SAMPLE_RATE_8_018_KHZ;
783+ case 8000 :
784+ return WM8960_ADC_DAC_SAMPLE_RATE_8_KHZ;
785+ default :
786+ AD_LOGE (" Unsupported rate: %d" , rate);
787+ return WM8960_ADC_DAC_SAMPLE_RATE_44_1_KHZ;
788+ }
789+ }
790+
791+ mtb_wm8960_word_length_t wordLength (int bits) {
792+ switch (bits) {
793+ case 16 :
794+ return WM8960_WL_16BITS;
795+ case 20 :
796+ return WM8960_WL_20BITS;
797+ case 24 :
798+ return WM8960_WL_24BITS;
799+ case 32 :
800+ return WM8960_WL_32BITS;
801+ default :
802+ AD_LOGE (" Unsupported bits: %d" , bits);
803+ return WM8960_WL_16BITS;
804+ }
805+ }
806+
807+ // / if microcontroller is master then module is slave
808+ mtb_wm8960_mode_t modeMasterSlave (bool microcontroller_is_master) {
809+ return microcontroller_is_master ? WM8960_MODE_SLAVE : WM8960_MODE_MASTER;
810+ }
811+
812+ void volumeError (float vol) { AD_LOGE (" Invalid volume %f" , vol); }
813+ };
814+
641815/* *
642816 * @brief Driver API for the wm8994 codec chip
643817 * @author Phil Schatzmann
@@ -658,7 +832,7 @@ class AudioDriverWM8994Class : public AudioDriver {
658832 delay (10 );
659833 p_pins = &pins;
660834 int vol = map (volume, 0 , 100 , DEFAULT_VOLMIN, DEFAULT_VOLMAX);
661- uint32_t freq = codecCfg.getRateNumeric ();
835+ uint32_t freq = codecCfg.getRateNumeric ();
662836 uint16_t outputDevice = getOutput (codec_cfg.dac_output );
663837
664838 auto i2c = pins.getI2CPins (CODEC);
@@ -694,7 +868,6 @@ class AudioDriverWM8994Class : public AudioDriver {
694868 return cnt == 0 ;
695869 }
696870
697-
698871 uint16_t getOutput (dac_output_t dac_output) {
699872 switch (dac_output) {
700873 case DAC_OUTPUT_NONE:
0 commit comments