test public

Dependencies:   HttpServer_snapshot_mbed-os

Committer:
anhtran
Date:
Fri Oct 18 03:09:43 2019 +0000
Revision:
0:e9fd5575b10e
abc

Who changed what in which revision?

UserRevisionLine numberNew contents of line
anhtran 0:e9fd5575b10e 1 /* mbed PwmOutSpeaker Library
anhtran 0:e9fd5575b10e 2 * Copyright (C) 2016 dkato
anhtran 0:e9fd5575b10e 3 *
anhtran 0:e9fd5575b10e 4 * Licensed under the Apache License, Version 2.0 (the "License");
anhtran 0:e9fd5575b10e 5 * you may not use this file except in compliance with the License.
anhtran 0:e9fd5575b10e 6 * You may obtain a copy of the License at
anhtran 0:e9fd5575b10e 7 *
anhtran 0:e9fd5575b10e 8 * http://www.apache.org/licenses/LICENSE-2.0
anhtran 0:e9fd5575b10e 9 *
anhtran 0:e9fd5575b10e 10 * Unless required by applicable law or agreed to in writing, software
anhtran 0:e9fd5575b10e 11 * distributed under the License is distributed on an "AS IS" BASIS,
anhtran 0:e9fd5575b10e 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
anhtran 0:e9fd5575b10e 13 * See the License for the specific language governing permissions and
anhtran 0:e9fd5575b10e 14 * limitations under the License.
anhtran 0:e9fd5575b10e 15 */
anhtran 0:e9fd5575b10e 16
anhtran 0:e9fd5575b10e 17 #include "PwmOutSpeaker.h"
anhtran 0:e9fd5575b10e 18
anhtran 0:e9fd5575b10e 19 PwmOutSpeaker::PwmOutSpeaker(PinName pwm_l, PinName pwm_r) :
anhtran 0:e9fd5575b10e 20 _speaker_l(NULL), _speaker_r(NULL), _audioThread(osPriorityHigh), _sound_out_req(0) {
anhtran 0:e9fd5575b10e 21 _bottom = 0;
anhtran 0:e9fd5575b10e 22 _top = 0;
anhtran 0:e9fd5575b10e 23 _playing = false;
anhtran 0:e9fd5575b10e 24 if (pwm_l != NC) {
anhtran 0:e9fd5575b10e 25 _speaker_l = new PwmOut(pwm_l);
anhtran 0:e9fd5575b10e 26 }
anhtran 0:e9fd5575b10e 27 if (pwm_r != NC) {
anhtran 0:e9fd5575b10e 28 _speaker_r = new PwmOut(pwm_r);
anhtran 0:e9fd5575b10e 29 }
anhtran 0:e9fd5575b10e 30 _audioThread.start(callback(this, &PwmOutSpeaker::audio_process));
anhtran 0:e9fd5575b10e 31 outputVolume(1.0f, 1.0f);
anhtran 0:e9fd5575b10e 32 format(16);
anhtran 0:e9fd5575b10e 33 frequency(44100);
anhtran 0:e9fd5575b10e 34 }
anhtran 0:e9fd5575b10e 35
anhtran 0:e9fd5575b10e 36 PwmOutSpeaker::~PwmOutSpeaker() {
anhtran 0:e9fd5575b10e 37 if (_speaker_l != NULL) {
anhtran 0:e9fd5575b10e 38 delete _speaker_l;
anhtran 0:e9fd5575b10e 39 }
anhtran 0:e9fd5575b10e 40 if (_speaker_r != NULL) {
anhtran 0:e9fd5575b10e 41 delete _speaker_r;
anhtran 0:e9fd5575b10e 42 }
anhtran 0:e9fd5575b10e 43 }
anhtran 0:e9fd5575b10e 44
anhtran 0:e9fd5575b10e 45 bool PwmOutSpeaker::format(char length) {
anhtran 0:e9fd5575b10e 46 switch (length) {
anhtran 0:e9fd5575b10e 47 case 8:
anhtran 0:e9fd5575b10e 48 case 16:
anhtran 0:e9fd5575b10e 49 break;
anhtran 0:e9fd5575b10e 50 default:
anhtran 0:e9fd5575b10e 51 return false;
anhtran 0:e9fd5575b10e 52 }
anhtran 0:e9fd5575b10e 53 _length = length;
anhtran 0:e9fd5575b10e 54 _data_cnt = 0;
anhtran 0:e9fd5575b10e 55 return true;
anhtran 0:e9fd5575b10e 56 }
anhtran 0:e9fd5575b10e 57
anhtran 0:e9fd5575b10e 58 bool PwmOutSpeaker::frequency(int hz) {
anhtran 0:e9fd5575b10e 59 int wk_us;
anhtran 0:e9fd5575b10e 60
anhtran 0:e9fd5575b10e 61 switch (hz) {
anhtran 0:e9fd5575b10e 62 case 48000:
anhtran 0:e9fd5575b10e 63 _hz_multi = 6;
anhtran 0:e9fd5575b10e 64 break;
anhtran 0:e9fd5575b10e 65 case 44100:
anhtran 0:e9fd5575b10e 66 _hz_multi = 5;
anhtran 0:e9fd5575b10e 67 break;
anhtran 0:e9fd5575b10e 68 case 32000:
anhtran 0:e9fd5575b10e 69 _hz_multi = 4;
anhtran 0:e9fd5575b10e 70 break;
anhtran 0:e9fd5575b10e 71 case 8021:
anhtran 0:e9fd5575b10e 72 case 8000:
anhtran 0:e9fd5575b10e 73 _hz_multi = 1;
anhtran 0:e9fd5575b10e 74 break;
anhtran 0:e9fd5575b10e 75 default:
anhtran 0:e9fd5575b10e 76 return false;
anhtran 0:e9fd5575b10e 77 }
anhtran 0:e9fd5575b10e 78 _playing = false;
anhtran 0:e9fd5575b10e 79 if (_speaker_l != NULL) {
anhtran 0:e9fd5575b10e 80 _speaker_l->write(0.5f);
anhtran 0:e9fd5575b10e 81 _speaker_l->period_us(10); // 100kHz
anhtran 0:e9fd5575b10e 82 }
anhtran 0:e9fd5575b10e 83 if (_speaker_r != NULL) {
anhtran 0:e9fd5575b10e 84 _speaker_r->write(0.5f);
anhtran 0:e9fd5575b10e 85 _speaker_r->period_us(10); // 100kHz
anhtran 0:e9fd5575b10e 86 }
anhtran 0:e9fd5575b10e 87 wk_us = (int)(1000000.0f / hz * _hz_multi + 0.5f);
anhtran 0:e9fd5575b10e 88 _timer.attach_us(Callback<void()>(this, &PwmOutSpeaker::sound_out), wk_us);
anhtran 0:e9fd5575b10e 89 _data_cnt = 0;
anhtran 0:e9fd5575b10e 90
anhtran 0:e9fd5575b10e 91 return true;
anhtran 0:e9fd5575b10e 92 }
anhtran 0:e9fd5575b10e 93
anhtran 0:e9fd5575b10e 94 int PwmOutSpeaker::write(void * const p_data, uint32_t data_size, const rbsp_data_conf_t * const p_data_conf) {
anhtran 0:e9fd5575b10e 95 int data_num;
anhtran 0:e9fd5575b10e 96 int i = 0;
anhtran 0:e9fd5575b10e 97 float wk_vol_l;
anhtran 0:e9fd5575b10e 98 float wk_ofs_l;
anhtran 0:e9fd5575b10e 99 float wk_vol_r;
anhtran 0:e9fd5575b10e 100 float wk_ofs_r;
anhtran 0:e9fd5575b10e 101
anhtran 0:e9fd5575b10e 102 if (_length == 8) {
anhtran 0:e9fd5575b10e 103 data_num = data_size;
anhtran 0:e9fd5575b10e 104 } else {
anhtran 0:e9fd5575b10e 105 data_num = data_size / 2;
anhtran 0:e9fd5575b10e 106 }
anhtran 0:e9fd5575b10e 107 while (i < data_num) {
anhtran 0:e9fd5575b10e 108 if (_data_cnt < (_hz_multi - 1)) {
anhtran 0:e9fd5575b10e 109 _data_cnt++;
anhtran 0:e9fd5575b10e 110 i += 2;
anhtran 0:e9fd5575b10e 111 } else {
anhtran 0:e9fd5575b10e 112 _data_cnt = 0;
anhtran 0:e9fd5575b10e 113 while (((_bottom + 2) & MSK_RING_BUFF) == _top) {
anhtran 0:e9fd5575b10e 114 ThisThread::sleep_for(1);
anhtran 0:e9fd5575b10e 115 }
anhtran 0:e9fd5575b10e 116
anhtran 0:e9fd5575b10e 117 wk_vol_l = _speaker_vol_l;
anhtran 0:e9fd5575b10e 118 wk_ofs_l = (1.0f - wk_vol_l) / 2;
anhtran 0:e9fd5575b10e 119 wk_vol_r = _speaker_vol_r;
anhtran 0:e9fd5575b10e 120 wk_ofs_r = (1.0f - wk_vol_r) / 2;
anhtran 0:e9fd5575b10e 121 if (_length == 8) {
anhtran 0:e9fd5575b10e 122 _pwm_duty_buf[_bottom] = ((float)((uint8_t *)p_data)[i++] / (float)0xff) * wk_vol_l + wk_ofs_l;
anhtran 0:e9fd5575b10e 123 _pwm_duty_buf[_bottom + 1] = ((float)((uint8_t *)p_data)[i++] / (float)0xff) * wk_vol_r + wk_ofs_r;
anhtran 0:e9fd5575b10e 124 } else {
anhtran 0:e9fd5575b10e 125 _pwm_duty_buf[_bottom] = ((float)(((int16_t *)p_data)[i++] + 0x8000) / (float)0xffff) * wk_vol_l + wk_ofs_l;
anhtran 0:e9fd5575b10e 126 _pwm_duty_buf[_bottom + 1] = ((float)(((int16_t *)p_data)[i++] + 0x8000) / (float)0xffff) * wk_vol_r + wk_ofs_r;
anhtran 0:e9fd5575b10e 127 }
anhtran 0:e9fd5575b10e 128 _bottom = (_bottom + 2) & MSK_RING_BUFF;
anhtran 0:e9fd5575b10e 129 }
anhtran 0:e9fd5575b10e 130 }
anhtran 0:e9fd5575b10e 131
anhtran 0:e9fd5575b10e 132 if (p_data_conf != NULL) {
anhtran 0:e9fd5575b10e 133 return data_size;
anhtran 0:e9fd5575b10e 134 }
anhtran 0:e9fd5575b10e 135
anhtran 0:e9fd5575b10e 136 if (p_data_conf->p_notify_func != NULL) {
anhtran 0:e9fd5575b10e 137 p_data_conf->p_notify_func(p_data, data_size, p_data_conf->p_app_data);
anhtran 0:e9fd5575b10e 138 }
anhtran 0:e9fd5575b10e 139
anhtran 0:e9fd5575b10e 140 return 0;
anhtran 0:e9fd5575b10e 141 }
anhtran 0:e9fd5575b10e 142
anhtran 0:e9fd5575b10e 143 bool PwmOutSpeaker::outputVolume(float leftVolumeOut, float rightVolumeOut) {
anhtran 0:e9fd5575b10e 144 if ((leftVolumeOut < 0.0) || (leftVolumeOut > 1.0)) {
anhtran 0:e9fd5575b10e 145 return false;
anhtran 0:e9fd5575b10e 146 }
anhtran 0:e9fd5575b10e 147 if ((rightVolumeOut < 0.0) || (rightVolumeOut > 1.0)) {
anhtran 0:e9fd5575b10e 148 return false;
anhtran 0:e9fd5575b10e 149 }
anhtran 0:e9fd5575b10e 150 _speaker_vol_l = leftVolumeOut;
anhtran 0:e9fd5575b10e 151 _speaker_vol_r = rightVolumeOut;
anhtran 0:e9fd5575b10e 152 return true;
anhtran 0:e9fd5575b10e 153 }
anhtran 0:e9fd5575b10e 154
anhtran 0:e9fd5575b10e 155 void PwmOutSpeaker::sound_out(void) {
anhtran 0:e9fd5575b10e 156 _sound_out_req.release();
anhtran 0:e9fd5575b10e 157 }
anhtran 0:e9fd5575b10e 158
anhtran 0:e9fd5575b10e 159 void PwmOutSpeaker::audio_process() {
anhtran 0:e9fd5575b10e 160 while (true) {
anhtran 0:e9fd5575b10e 161 _sound_out_req.wait();
anhtran 0:e9fd5575b10e 162 if (_top != _bottom) {
anhtran 0:e9fd5575b10e 163 if (_speaker_l != NULL) {
anhtran 0:e9fd5575b10e 164 _speaker_l->write(_pwm_duty_buf[_top + 0]);
anhtran 0:e9fd5575b10e 165 }
anhtran 0:e9fd5575b10e 166 if (_speaker_r != NULL) {
anhtran 0:e9fd5575b10e 167 _speaker_r->write(_pwm_duty_buf[_top + 1]);
anhtran 0:e9fd5575b10e 168 }
anhtran 0:e9fd5575b10e 169 _top = (_top + 2) & MSK_RING_BUFF;
anhtran 0:e9fd5575b10e 170 _playing = true;
anhtran 0:e9fd5575b10e 171 } else if (_playing) {
anhtran 0:e9fd5575b10e 172 if (_speaker_l != NULL) {
anhtran 0:e9fd5575b10e 173 _speaker_l->write(0.5f);
anhtran 0:e9fd5575b10e 174 }
anhtran 0:e9fd5575b10e 175 if (_speaker_r != NULL) {
anhtran 0:e9fd5575b10e 176 _speaker_r->write(0.5f);
anhtran 0:e9fd5575b10e 177 }
anhtran 0:e9fd5575b10e 178 _playing = false;
anhtran 0:e9fd5575b10e 179 } else {
anhtran 0:e9fd5575b10e 180 // do nothing
anhtran 0:e9fd5575b10e 181 }
anhtran 0:e9fd5575b10e 182 }
anhtran 0:e9fd5575b10e 183 }
anhtran 0:e9fd5575b10e 184