Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
PwmOutSpeaker.cpp
00001 /* mbed PwmOutSpeaker Library 00002 * Copyright (C) 2016 dkato 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "PwmOutSpeaker.h" 00018 #if defined(TARGET_RZ_A1H) || defined(TARGET_VK_RZ_A1H) || defined(TARGET_GR_LYCHEE) 00019 #include "vfp_neon_push_pop.h" 00020 #else 00021 static void dummy_func(void) {} 00022 #define __vfp_neon_push dummy_func 00023 #define __vfp_neon_pop dummy_func 00024 #endif 00025 00026 PwmOutSpeaker::PwmOutSpeaker(PinName pwm_l, PinName pwm_r) : _speaker_l(pwm_l), _speaker_r(pwm_r) { 00027 _bottom = 0; 00028 _top = 0; 00029 _playing = false; 00030 outputVolume(1.0f, 1.0f); 00031 format(16); 00032 frequency(44100); 00033 } 00034 00035 bool PwmOutSpeaker::format(char length) { 00036 switch (length) { 00037 case 8: 00038 case 16: 00039 break; 00040 default: 00041 return false; 00042 } 00043 _length = length; 00044 _data_cnt = 0; 00045 return true; 00046 } 00047 00048 bool PwmOutSpeaker::frequency(int hz) { 00049 int wk_us; 00050 00051 switch (hz) { 00052 case 48000: 00053 _hz_multi = 6; 00054 break; 00055 case 44100: 00056 _hz_multi = 5; 00057 break; 00058 case 32000: 00059 _hz_multi = 4; 00060 break; 00061 case 8021: 00062 case 8000: 00063 _hz_multi = 1; 00064 break; 00065 default: 00066 return false; 00067 } 00068 _speaker_l.write(0.5f); 00069 _speaker_r.write(0.5f); 00070 _playing = false; 00071 _speaker_l.period_us(10); // 100kHz 00072 _speaker_r.period_us(10); // 100kHz 00073 wk_us = (int)(1000000.0f / hz * _hz_multi + 0.5f); 00074 _timer.attach_us(Callback<void()>(this, &PwmOutSpeaker::sound_out), wk_us); 00075 _data_cnt = 0; 00076 00077 return true; 00078 } 00079 00080 int PwmOutSpeaker::write(void * const p_data, uint32_t data_size, const rbsp_data_conf_t * const p_data_conf) { 00081 int data_num; 00082 int i = 0; 00083 float wk_vol_l; 00084 float wk_ofs_l; 00085 float wk_vol_r; 00086 float wk_ofs_r; 00087 00088 if (_length == 8) { 00089 data_num = data_size; 00090 } else { 00091 data_num = data_size / 2; 00092 } 00093 while (i < data_num) { 00094 if (_data_cnt < (_hz_multi - 1)) { 00095 _data_cnt++; 00096 i += 2; 00097 } else { 00098 _data_cnt = 0; 00099 while (((_bottom + 2) & MSK_RING_BUFF) == _top) { 00100 Thread::wait(1); 00101 } 00102 wk_vol_l = _speaker_vol_l; 00103 wk_ofs_l = (1.0f - wk_vol_l) / 2; 00104 wk_vol_r = _speaker_vol_r; 00105 wk_ofs_r = (1.0f - wk_vol_r) / 2; 00106 if (_length == 8) { 00107 _pwm_duty_buf[_bottom] = ((float)((uint8_t *)p_data)[i++] / (float)0xff) * wk_vol_l + wk_ofs_l; 00108 _pwm_duty_buf[_bottom + 1] = ((float)((uint8_t *)p_data)[i++] / (float)0xff) * wk_vol_r + wk_ofs_r; 00109 } else { 00110 _pwm_duty_buf[_bottom] = ((float)(((int16_t *)p_data)[i++] + 0x8000) / (float)0xffff) * wk_vol_l + wk_ofs_l; 00111 _pwm_duty_buf[_bottom + 1] = ((float)(((int16_t *)p_data)[i++] + 0x8000) / (float)0xffff) * wk_vol_r + wk_ofs_r; 00112 } 00113 _bottom = (_bottom + 2) & MSK_RING_BUFF; 00114 } 00115 } 00116 00117 if (p_data_conf != NULL) { 00118 return data_size; 00119 } 00120 00121 if (p_data_conf->p_notify_func != NULL) { 00122 p_data_conf->p_notify_func(p_data, data_size, p_data_conf->p_app_data); 00123 } 00124 00125 return 0; 00126 } 00127 00128 bool PwmOutSpeaker::outputVolume(float leftVolumeOut, float rightVolumeOut) { 00129 if ((leftVolumeOut < 0.0) || (leftVolumeOut > 1.0)) { 00130 return false; 00131 } 00132 if ((rightVolumeOut < 0.0) || (rightVolumeOut > 1.0)) { 00133 return false; 00134 } 00135 _speaker_vol_l = leftVolumeOut; 00136 _speaker_vol_r = rightVolumeOut; 00137 return true; 00138 } 00139 00140 void PwmOutSpeaker::sound_out(void) { 00141 if (_top != _bottom) { 00142 __vfp_neon_push(); 00143 _speaker_l.write(_pwm_duty_buf[_top + 0]); 00144 _speaker_r.write(_pwm_duty_buf[_top + 1]); 00145 __vfp_neon_pop(); 00146 _top = (_top + 2) & MSK_RING_BUFF; 00147 _playing = true; 00148 } else if (_playing) { 00149 __vfp_neon_push(); 00150 _speaker_l.write(0.5f); 00151 _speaker_r.write(0.5f); 00152 __vfp_neon_pop(); 00153 _playing = false; 00154 } else { 00155 // do nothing 00156 } 00157 }
Generated on Tue Jul 12 2022 20:33:39 by
1.7.2