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.
Dependents: YATTT sd_map_test cPong SnowDemo ... more
HWSound.cpp
00001 /**************************************************************************/ 00002 /*! 00003 @file HWSound.cpp 00004 @author Jonne Valola 00005 00006 @section LICENSE 00007 00008 Software License Agreement (BSD License) 00009 00010 Copyright (c) 2016, Jonne Valola 00011 All rights reserved. 00012 00013 Redistribution and use in source and binary forms, with or without 00014 modification, are permitted provided that the following conditions are met: 00015 1. Redistributions of source code must retain the above copyright 00016 notice, this list of conditions and the following disclaimer. 00017 2. Redistributions in binary form must reproduce the above copyright 00018 notice, this list of conditions and the following disclaimer in the 00019 documentation and/or other materials provided with the distribution. 00020 3. Neither the name of the copyright holders nor the 00021 names of its contributors may be used to endorse or promote products 00022 derived from this software without specific prior written permission. 00023 00024 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 00025 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00026 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 00028 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00029 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00031 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00033 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 */ 00035 /**************************************************************************/ 00036 00037 #include "mbed.h" 00038 #include "HWSound.h" 00039 //#include "MCP4018.h" 00040 #include "SoftwareI2C.h" 00041 #include "Pokitto_settings.h " 00042 #include "PokittoDisk.h " 00043 #include "PokittoGlobs.h " 00044 #include "Synth.h " 00045 #include "timer_11u6x.h" 00046 #include "clock_11u6x.h" 00047 #include "HWLCD.h " 00048 //#include "beat_11025.h" 00049 00050 00051 Pokitto::Sound __shw; 00052 00053 using namespace Pokitto; 00054 00055 #ifndef POK_SIM 00056 #if POK_ENABLE_SOUND 00057 pwmout_t* obj = &audiopwm; 00058 #endif 00059 #endif 00060 00061 /** Sound Variables **/ 00062 #if (POK_STREAMING_MUSIC > 0) 00063 00064 #if POK_HIGH_RAM == HIGH_RAM_MUSIC 00065 unsigned char *buffers[4] = { 00066 (unsigned char *) 0x20000000, 00067 (unsigned char *) 0x20000400, 00068 (unsigned char *) 0x20004000, 00069 (unsigned char *) 0x20004400 00070 }; 00071 #else 00072 unsigned char buffers[4][BUFFER_SIZE]; 00073 #endif 00074 00075 volatile int currentBuffer = 0, oldBuffer = 0; 00076 volatile int bufindex = 0, vol=1; 00077 volatile unsigned char * currentPtr; 00078 volatile unsigned char * endPtr; 00079 int8_t streamvol=3; 00080 uint32_t streamcounter=0; 00081 uint8_t streamstep=0; 00082 #endif 00083 00084 #if POK_ENABLE_SOUND > 0 00085 pwmout_t Pokitto::audiopwm; // this way (instead of PwmOut class) pwm doesn't start screaming until it is initialized ! 00086 //Ticker Pokitto::audio; 00087 00088 using namespace Pokitto; 00089 00090 00091 /** stream output and status */ 00092 uint8_t Pokitto::streambyte,Pokitto::streamon; 00093 00094 uint8_t soundbuf[SBUFSIZE]; 00095 uint8_t Pokitto::HWvolume=0; 00096 uint16_t soundbufindex; 00097 uint8_t* soundbufptr; 00098 00099 bool volpotError=false; //test for broken MCP4018 00100 00101 uint16_t soundbyte; 00102 00103 00104 #if POK_USE_DAC > 0 00105 #if POK_BOARDREV == 1 00106 /** 2-layer board rev 1.3 **/ 00107 DigitalOut dac0(P1_6); 00108 DigitalOut dac1(P1_0); 00109 DigitalOut dac2(P1_16); 00110 DigitalOut dac3(P0_19); 00111 DigitalOut dac4(P0_17); 00112 DigitalOut dac5(P1_12); 00113 DigitalOut dac6(P1_15); 00114 DigitalOut dac7(P1_8); 00115 #else 00116 /** 4-layer board rev 2.1 **/ 00117 DigitalOut dac0(P1_28); 00118 DigitalOut dac1(P1_29); 00119 DigitalOut dac2(P1_30); 00120 DigitalOut dac3(P1_31); 00121 /* has daniel made a mistake ?*/ 00122 DigitalOut dac4(P2_20); 00123 DigitalOut dac5(P2_21); 00124 DigitalOut dac6(P2_22); 00125 DigitalOut dac7(P2_23); 00126 00127 DigitalOut amp(P1_17); 00128 00129 #endif // POK_BOARDREV 00130 #endif // POK_USE_DAC 00131 00132 #if POK_BOARDREV == 2 00133 //MCP4018 volpot(P0_5,P0_4); 00134 00135 /** 00136 * @brief Handle interrupt from 32-bit timer 0 00137 * @return Nothing 00138 */ 00139 00140 uint32_t p=0; 00141 uint8_t pixx=0, pixy=0; 00142 00143 extern "C" void TIMER32_0_IRQHandler (void) 00144 { 00145 if (Chip_TIMER_MatchPending(LPC_TIMER32_0, 1)) { 00146 Chip_TIMER_ClearMatch(LPC_TIMER32_0, 1); 00147 //pokSoundBufferedIRQ(); 00148 #if POK_GBSOUND > 0 00149 /** GAMEBUINO SOUND **/ 00150 Pokitto::audio_IRQ(); 00151 #else 00152 /** NOT GAMEBUINO SOUND **/ 00153 #if POK_SOUND_BUFFERED 00154 pokSoundBufferedIRQ(); 00155 #else 00156 pokSoundIRQ (); 00157 #endif 00158 #endif 00159 } 00160 } 00161 00162 00163 void initHWvolumecontrol() { 00164 HWvolume=0; 00165 volpotError=true; 00166 //if (volpot.put(HWvolume)) volpotError=true; //try if MCP4018 answers 00167 setHWvolume(discrete_vol_hw_levels[VOLUME_STARTUP>>5]); 00168 } 00169 00170 int Pokitto::setHWvolume(uint8_t v) { 00171 HWvolume=v; 00172 if (HWvolume>127) HWvolume=127; 00173 //HWvolume = 0x7F&v; 00174 //if (!volpotError) return volpot.put(HWvolume); //use normal I2C 00175 /* fallback method for broken MCP4018 */ 00176 SoftwareI2C swvolpot(P0_4, P0_5); //swapped SDA,SCL 00177 swvolpot.write(0x5e,HWvolume); 00178 return HWvolume; 00179 } 00180 00181 uint8_t Pokitto::getHWvolume() { 00182 return HWvolume; 00183 } 00184 00185 void Pokitto::changeHWvolume(int8_t v) { 00186 int temp = HWvolume + v; 00187 if (temp < 0) temp = 0; //prevent volume "looparound" than can make a massive crack 00188 if (temp > 127) temp = 127; 00189 setHWvolume(temp); 00190 } 00191 00192 uint8_t Pokitto::ampIsOn() { 00193 return amp; 00194 } 00195 00196 void Pokitto::ampEnable(uint8_t v) { 00197 if (v>1) v=1; // limit against funny values 00198 amp=v; 00199 } 00200 #endif // POK_BOARDREV == 2 00201 00202 void Pokitto::dac_write(uint8_t value) { 00203 #if POK_USE_DAC > 0 00204 #if POK_BOARDREV == 1 // was 1 00205 if (value & 1) SET_DAC0 else CLR_DAC0; 00206 value >>= 1; 00207 if (value & 1) SET_DAC1 else CLR_DAC1; 00208 value >>= 1; 00209 if (value & 1) SET_DAC2 else CLR_DAC2; 00210 value >>= 1; 00211 if (value & 1) SET_DAC3 else CLR_DAC3; 00212 value >>= 1; 00213 if (value & 1) SET_DAC4 else CLR_DAC4; 00214 value >>= 1; 00215 if (value & 1) SET_DAC5 else CLR_DAC5; 00216 value >>= 1; 00217 if (value & 1) SET_DAC6 else CLR_DAC6; 00218 value >>= 1; 00219 if (value & 1) SET_DAC7 else CLR_DAC7; 00220 #else 00221 00222 //val = value<<28; //lower 4 bits go higher - because port mask is used, no AND is needed to clear bits 00223 //val += value<<(15-4); //higher 4 bits go lower. No need to shift by 15 because bits are in the higher nibble 00224 /* daniel has made a mistake with ports */ 00225 //val = ((value&0x70)<<(28-4)); //higher 4 bits go higher - because port mask is used, no AND is needed to clear bits 00226 //val += value<<(15); //lower 4 bits go lower. No need to shift by 15 because bits are in the higher nibble 00227 //SET_MASK_DAC; 00228 //LPC_GPIO_PORT->MPIN[1] = val; // write bits to port 00229 //CLR_MASK_DAC; 00230 /* fixed here */ 00231 #define MASKED_DAC 0 00232 #if MASKED_DAC 00233 uint32_t val; 00234 val=value; 00235 SET_MASK_DAC_LO; 00236 LPC_GPIO_PORT->MPIN[1] = val<<28; // write lower 4 bits to port 00237 CLR_MASK_DAC_LO; 00238 SET_MASK_DAC_HI; 00239 LPC_GPIO_PORT->MPIN[2] = val<<(20-4); // write bits to port 00240 CLR_MASK_DAC_HI; 00241 #else 00242 if (value & 1) SET_DAC0 else CLR_DAC0; 00243 value >>= 1; 00244 if (value & 1) SET_DAC1 else CLR_DAC1; 00245 value >>= 1; 00246 if (value & 1) SET_DAC2 else CLR_DAC2; 00247 value >>= 1; 00248 if (value & 1) SET_DAC3 else CLR_DAC3; 00249 value >>= 1; 00250 if (value & 1) SET_DAC4 else CLR_DAC4; 00251 value >>= 1; 00252 if (value & 1) SET_DAC5 else CLR_DAC5; 00253 value >>= 1; 00254 if (value & 1) SET_DAC6 else CLR_DAC6; 00255 value >>= 1; 00256 if (value & 1) SET_DAC7 else CLR_DAC7; 00257 #endif //MASKED_DAC 00258 //CLR_MASK_DAC; 00259 #endif // BOARDREV 00260 #endif 00261 } 00262 00263 void Pokitto::soundInit() { 00264 soundInit(false); 00265 } 00266 00267 /** SOUND INIT **/ 00268 void Pokitto::soundInit(uint8_t reinit) { 00269 #ifdef XPERIMENTAL 00270 mbed::DigitalOut expr4(EXT4); 00271 expr4=0; 00272 #endif 00273 #if POK_ENABLE_SOUND > 0 00274 uint32_t timerFreq; 00275 #if POK_USE_PWM 00276 if (!reinit) { 00277 pwmout_init(&audiopwm,POK_AUD_PIN); 00278 pwmout_period_us(&audiopwm,POK_AUD_PWM_US); //was 31us 00279 pwmout_write(&audiopwm,0.1f); 00280 } 00281 #endif 00282 00283 //#if POK_GBSOUND > 0 00284 /** GAMEBUINO SOUND **/ 00285 //audio.attach_us(&audio_IRQ, 1000000/(POK_AUD_FREQ>>0)); 00286 //#else 00287 /** NOT GAMEBUINO SOUND **/ 00288 //audio.attach_us(&pokSoundBufferedIRQ, 1000000/(POK_AUD_FREQ>>0)); 00289 /* Initialize 32-bit timer 0 clock */ 00290 Chip_TIMER_Init(LPC_TIMER32_0); 00291 00292 /* Timer rate is system clock rate */ 00293 timerFreq = Chip_Clock_GetSystemClockRate(); 00294 00295 /* Timer setup for match and interrupt at TICKRATE_HZ */ 00296 Chip_TIMER_Reset(LPC_TIMER32_0); 00297 00298 /* Enable both timers to generate interrupts when time matches */ 00299 Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 1); 00300 00301 /* Setup 32-bit timer's duration (32-bit match time) */ 00302 Chip_TIMER_SetMatch(LPC_TIMER32_0, 1, (timerFreq / POK_AUD_FREQ)); 00303 00304 /* Setup both timers to restart when match occurs */ 00305 Chip_TIMER_ResetOnMatchEnable(LPC_TIMER32_0, 1); 00306 00307 /* Start both timers */ 00308 Chip_TIMER_Enable(LPC_TIMER32_0); 00309 00310 /* Clear both timers of any pending interrupts */ 00311 #define TIMER_32_0_IRQn 18 00312 NVIC_ClearPendingIRQ((IRQn_Type)TIMER_32_0_IRQn); 00313 00314 /* Redirect IRQ vector - Jonne*/ 00315 NVIC_SetVector((IRQn_Type)TIMER_32_0_IRQn, (uint32_t)&TIMER32_0_IRQHandler ); 00316 00317 /* Enable both timer interrupts */ 00318 NVIC_EnableIRQ((IRQn_Type)TIMER_32_0_IRQn); 00319 //#endif // POK_GAMEBUINO_SUPPORT 00320 00321 //emptySong(); 00322 //emptyOscillators(); 00323 //emptyBlocks(); 00324 //emptyPatches(); 00325 #ifdef TEST_SOUND 00326 testOsc(); 00327 #endif // TEST_SOUND 00328 #if POK_BOARDREV == 2 00329 //initHWvolumecontrol(); 00330 #endif 00331 00332 #if POK_ENABLE_SYNTH 00333 emptyOscillators(); 00334 #endif 00335 00336 00337 #endif // POK_ENABLE_SOUND 00338 00339 } 00340 00341 00342 uint8_t Pokitto::streamPaused() { 00343 return !streamon; 00344 } 00345 00346 void Pokitto::pauseStream() { 00347 streamon=0; 00348 } 00349 00350 void Pokitto::playStream() { 00351 streamon=1; 00352 } 00353 00354 00355 void pokPauseStream() { 00356 streamon=0; 00357 } 00358 00359 void pokPlayStream() { 00360 streamon=1; 00361 } 00362 00363 00364 00365 inline void pokSoundBufferedIRQ() { 00366 uint32_t output = soundbuf[soundbufindex+=Pokitto::streamon]; 00367 if (soundbufindex==SBUFSIZE) soundbufindex=0; 00368 //if (p==sizeof(beat_11025_raw)) p=0; 00369 //soundbuf[soundbufindex++] = output; 00370 //uint32_t t_on = (uint32_t)(((obj->pwm->MATCHREL0)*output)>>8); //cut out float 00371 //obj->pwm->MATCHREL1 = t_on; 00372 output *= discrete_vol_multipliers[discrete_vol]; 00373 output >>= 8; 00374 dac_write(output); 00375 00376 //setDRAMpoint(pixx, pixy); 00377 } 00378 00379 inline void pokSoundIRQ () { 00380 #if POK_ENABLE_SOUND > 0 00381 //#define TICKY 0xFFFF //160 00382 //#define INCY 409 00383 uint32_t output=0;uint32_t op; 00384 //streamon=1; 00385 //if (test==TICKY) test=0; 00386 //if (test<(TICKY/2)) { tpin=1; pwmout_write(&audiopwm,(float)0/(float)255);}//dac_write(0);} 00387 //else {tpin=0; pwmout_write(&audiopwm,(float)255/(float)255);}//dac_write(64);} 00388 //test+=INCY; 00389 //return; 00390 #ifndef POK_SIM 00391 #if POK_USE_PWM 00392 pwmout_t* obj = &audiopwm; 00393 #endif 00394 #endif 00395 #if POK_STREAMING_MUSIC > 0 00396 #if POK_STREAMFREQ_HALVE 00397 streamstep = 1-streamstep; 00398 #else 00399 streamstep = 1; 00400 #endif // POK_STREAMFREQ_HALVE 00401 #ifndef PROJ_SDFS_STREAMING 00402 streamon=1; // force enable stream 00403 #endif 00404 streamstep &= streamon; // streamon is used to toggle SD music streaming on and off 00405 if (streamstep) { 00406 output = (*currentPtr++); 00407 if( Pokitto::Sound::sfxDataPtr != Pokitto::Sound::sfxEndPtr ){ 00408 #ifdef PROJ_SDFS_STREAMING 00409 int32_t s = (int32_t(output) + int32_t(*Pokitto::Sound::sfxDataPtr++)) - 128; 00410 #else 00411 int32_t s = (127 + int32_t(*Pokitto::Sound::sfxDataPtr++)) - 128; 00412 #endif 00413 if( s < 0 ) s = 0; 00414 else if( s > 255 ) s = 255; 00415 output = s; 00416 } 00417 if(streamvol && streamon) { 00418 output >>= 3-streamvol; 00419 streambyte = output; 00420 } else { 00421 streambyte = 0; // duty cycle 00422 output = 0; 00423 } 00424 if (currentPtr >= endPtr) 00425 { 00426 currentBuffer++; 00427 if (currentBuffer==4) currentBuffer=0; 00428 currentPtr = buffers[currentBuffer]; 00429 endPtr = currentPtr + BUFFER_SIZE; 00430 } 00431 } 00432 #endif // POK_STREAMING_MUSIC 00433 00434 /** DO ADDITIONAL SOUND PROCESSING (NOT STREAM) OF SOUND HERE **/ 00435 00436 #if POK_ENABLE_SYNTH 00437 /** if song is being played from sd **/ 00438 if (playing) { 00439 notetick++; 00440 updatePlayback(); 00441 } 00442 /** oscillators update **/ 00443 osc1.count += osc1.cinc + (osc1.pitchbend); // counts to 65535 and overflows to zero WAS 8 ! 00444 osc2.count += osc2.cinc + (osc2.pitchbend); // counts to 65535 and overflows to zero 00445 osc3.count += osc3.cinc + (osc3.pitchbend); // counts to 65535 and overflows to zero 00446 #if POK_ALT_MIXING > 0 // heaviest cpu load, recalculate envelopes on each cycle 00447 uint32_t o = 0; 00448 Marr[3](); 00449 Marr[2](); 00450 Marr[1](); 00451 if (tick==0) Marr[0](); 00452 #else 00453 Marr[tick](); // call mixing function 00454 #endif // ALT_MIXING 00455 --tick; 00456 00457 /** mixing oscillator output **/ 00458 00459 op = (uint32_t) ((osc1.output)*(osc1.vol>>8))>>9;// >> 2 osc1.vol Marr; 00460 op += (uint32_t) ((osc2.output)*(osc2.vol>>8))>>9;// >> 2 osc1.vol Marr; 00461 op += (uint32_t) ((osc3.output)*(osc3.vol>>8))>>9;// >> 2 osc1.vol Marr; 00462 op *= discrete_vol_multipliers[discrete_vol]; 00463 op >>= 8; 00464 output = op & 0xFF; 00465 00466 #endif // POK_ENABLE_SYNTH 00467 00468 #ifndef POK_SIM 00469 /** HARDWARE **/ 00470 #if POK_ENABLE_SOUND > 0 00471 #if POK_STREAMING_MUSIC > 0 00472 /** sound is enabled, streaming is enabled */ 00473 #if POK_STREAM_TO_DAC > 0 00474 /** stream goes to DAC */ 00475 #if POK_USE_DAC > 0 00476 uint32_t sbyte = streambyte; 00477 sbyte *= discrete_vol_multipliers[discrete_vol]; 00478 sbyte >>= 8; 00479 dac_write((uint8_t)sbyte); // duty cycle 00480 #endif // POK_USE_DAC 00481 #else 00482 /** stream goes to PWM */ 00483 if (streamstep) { 00484 //pwmout_write(&audiopwm,(float)streambyte/(float)255); 00485 #if POK_USE_PWM 00486 uint32_t sbyte = streambyte; 00487 sbyte *= discrete_vol_multipliers[discrete_vol]; 00488 sbyte >>= 8; 00489 uint32_t t_on = (uint32_t)((((obj->pwm->MATCHREL0)*sbyte)>>8)); //cut out float 00490 obj->pwm->MATCHREL1 = t_on; 00491 #endif 00492 //dac_write((uint8_t)streambyte); // duty cycle 00493 } 00494 #endif // POK_STREAM_TO_DAC 00495 #endif // POK_STREAMING_MUSIC 00496 #if POK_STREAM_TO_DAC > 0 00497 /** synth goes to PWM */ 00498 //pwmout_write(&audiopwm,(float)output/(float)255); 00499 #if POK_USE_PWM 00500 op = output; 00501 op *= discrete_vol_multipliers[discrete_vol]; 00502 op >>= 8; 00503 uint32_t t_on = (uint32_t)((((obj->pwm->MATCHREL0)*op)>>8)); //cut out float 00504 obj->pwm->MATCHREL1 = t_on; 00505 #endif 00506 #else // POK_STREAMING_MUSIC 00507 op = output; 00508 op *= discrete_vol_multipliers[discrete_vol]; 00509 op >>= 8; 00510 dac_write((uint8_t)op); // SYNTH to DAC 00511 #endif 00512 soundbyte = (output+streambyte)>>1; 00513 soundbuf[soundbufindex++]=soundbyte; 00514 if (soundbufindex==256) soundbufindex=0; 00515 #endif //POK_ENABLE_SOUND 00516 #endif // HARDWARE 00517 #endif //POK_ENABLE_SOUND 00518 } 00519 00520 00521 void Pokitto::updateSDAudioStream() { 00522 if (streamPaused()) return; 00523 00524 #if POK_STREAMING_MUSIC > 0 00525 if (oldBuffer != currentBuffer) { 00526 if (currentBuffer==0) fileReadBytes(&buffers[3][0],BUFFER_SIZE); 00527 else if (currentBuffer==1) fileReadBytes(&buffers[0][0],BUFFER_SIZE); 00528 else if (currentBuffer==2) fileReadBytes(&buffers[1][0],BUFFER_SIZE); 00529 else fileReadBytes(&buffers[2][0],BUFFER_SIZE); 00530 oldBuffer = currentBuffer; 00531 streamcounter += BUFFER_SIZE; 00532 } else return; 00533 00534 #ifndef POK_SIM 00535 if ( streamcounter > fs.fsize - (BUFFER_SIZE*6)) { 00536 #else 00537 if ( streamcounter > getFileLength() - (BUFFER_SIZE*6)) { 00538 #endif 00539 streamcounter=0; 00540 #if POK_STREAM_LOOP 00541 fileRewind(); 00542 #else 00543 pokPauseStream(); 00544 #endif 00545 } 00546 #endif 00547 } 00548 00549 00550 #endif // POK_ENABLE_SOUND 00551 00552 00553
Generated on Tue Jul 12 2022 11:20:32 by
1.7.2