PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Embed:
(wiki syntax)
Show/hide line numbers
HWSound.cpp
Go to the documentation of this file.
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 #ifdef XPERIMENTAL 00054 DigitalOut e4(EXT4); 00055 e4=0; 00056 #endif 00057 00058 using namespace Pokitto; 00059 00060 00061 00062 #ifndef POK_SIM 00063 #if POK_ENABLE_SOUND 00064 pwmout_t* obj = &audiopwm; 00065 #endif 00066 #endif 00067 00068 /** Sound Variables **/ 00069 #if (POK_STREAMING_MUSIC > 0) 00070 unsigned char buffers[4][BUFFER_SIZE]; 00071 volatile int currentBuffer = 0, oldBuffer = 0; 00072 volatile int bufindex = 0, vol=1; 00073 volatile unsigned char * currentPtr; 00074 volatile unsigned char * endPtr; 00075 int8_t streamvol=3; 00076 uint32_t streamcounter=0; 00077 uint8_t streamstep=0; 00078 #endif 00079 00080 #if POK_ENABLE_SOUND > 0 00081 pwmout_t Pokitto::audiopwm; // this way (instead of PwmOut class) pwm doesn't start screaming until it is initialized ! 00082 //Ticker Pokitto::audio; 00083 00084 using namespace Pokitto; 00085 00086 00087 /** stream output and status */ 00088 uint8_t Pokitto::streambyte,Pokitto::streamon; 00089 00090 uint8_t soundbuf[SBUFSIZE]; 00091 uint8_t Pokitto::HWvolume=0; 00092 uint16_t soundbufindex; 00093 uint8_t* soundbufptr; 00094 00095 bool volpotError=false; //test for broken MCP4018 00096 00097 uint16_t soundbyte; 00098 00099 00100 #if POK_USE_DAC > 0 00101 #if POK_BOARDREV == 1 00102 /** 2-layer board rev 1.3 **/ 00103 DigitalOut dac0(P1_6); 00104 DigitalOut dac1(P1_0); 00105 DigitalOut dac2(P1_16); 00106 DigitalOut dac3(P0_19); 00107 DigitalOut dac4(P0_17); 00108 DigitalOut dac5(P1_12); 00109 DigitalOut dac6(P1_15); 00110 DigitalOut dac7(P1_8); 00111 #else 00112 /** 4-layer board rev 2.1 **/ 00113 DigitalOut dac0(P1_28); 00114 DigitalOut dac1(P1_29); 00115 DigitalOut dac2(P1_30); 00116 DigitalOut dac3(P1_31); 00117 /* has daniel made a mistake ?*/ 00118 DigitalOut dac4(P2_20); 00119 DigitalOut dac5(P2_21); 00120 DigitalOut dac6(P2_22); 00121 DigitalOut dac7(P2_23); 00122 00123 DigitalOut amp(P1_17); 00124 00125 #endif // POK_BOARDREV 00126 #endif // POK_USE_DAC 00127 00128 #if POK_BOARDREV == 2 00129 //MCP4018 volpot(P0_5,P0_4); 00130 00131 /** 00132 * @brief Handle interrupt from 32-bit timer 0 00133 * @return Nothing 00134 */ 00135 00136 uint32_t p=0; 00137 uint8_t pixx=0, pixy=0; 00138 00139 extern "C" void TIMER32_0_IRQHandler (void) 00140 { 00141 if (Chip_TIMER_MatchPending(LPC_TIMER32_0, 1)) { 00142 Chip_TIMER_ClearMatch(LPC_TIMER32_0, 1); 00143 //pokSoundBufferedIRQ(); 00144 #if POK_GBSOUND > 0 00145 /** GAMEBUINO SOUND **/ 00146 Pokitto::audio_IRQ(); 00147 #else 00148 /** NOT GAMEBUINO SOUND **/ 00149 #if POK_SOUND_BUFFERED 00150 pokSoundBufferedIRQ(); 00151 #else 00152 pokSoundIRQ (); 00153 #endif 00154 #endif 00155 } 00156 } 00157 00158 00159 void initHWvolumecontrol() { 00160 HWvolume=0; 00161 volpotError=true; 00162 //if (volpot.put(HWvolume)) volpotError=true; //try if MCP4018 answers 00163 setHWvolume(discrete_vol_hw_levels[VOLUME_STARTUP>>5]); 00164 } 00165 00166 int Pokitto::setHWvolume(uint8_t v) { 00167 HWvolume=v; 00168 if (HWvolume>127) HWvolume=127; 00169 //HWvolume = 0x7F&v; 00170 //if (!volpotError) return volpot.put(HWvolume); //use normal I2C 00171 /* fallback method for broken MCP4018 */ 00172 SoftwareI2C swvolpot(P0_4, P0_5); //swapped SDA,SCL 00173 swvolpot.write(0x5e,HWvolume); 00174 return HWvolume; 00175 } 00176 00177 uint8_t Pokitto::getHWvolume() { 00178 return HWvolume; 00179 } 00180 00181 void Pokitto::changeHWvolume(int8_t v) { 00182 int temp = HWvolume + v; 00183 if (temp < 0) temp = 0; //prevent volume "looparound" than can make a massive crack 00184 if (temp > 127) temp = 127; 00185 setHWvolume(temp); 00186 } 00187 00188 uint8_t Pokitto::ampIsOn() { 00189 return amp; 00190 } 00191 00192 void Pokitto::ampEnable(uint8_t v) { 00193 if (v>1) v=1; // limit against funny values 00194 amp=v; 00195 } 00196 #endif // POK_BOARDREV == 2 00197 00198 void Pokitto::dac_write(uint8_t value) { 00199 #if POK_USE_DAC > 0 00200 #if POK_BOARDREV == 1 // was 1 00201 if (value & 1) SET_DAC0 else CLR_DAC0; 00202 value >>= 1; 00203 if (value & 1) SET_DAC1 else CLR_DAC1; 00204 value >>= 1; 00205 if (value & 1) SET_DAC2 else CLR_DAC2; 00206 value >>= 1; 00207 if (value & 1) SET_DAC3 else CLR_DAC3; 00208 value >>= 1; 00209 if (value & 1) SET_DAC4 else CLR_DAC4; 00210 value >>= 1; 00211 if (value & 1) SET_DAC5 else CLR_DAC5; 00212 value >>= 1; 00213 if (value & 1) SET_DAC6 else CLR_DAC6; 00214 value >>= 1; 00215 if (value & 1) SET_DAC7 else CLR_DAC7; 00216 #else 00217 00218 //val = value<<28; //lower 4 bits go higher - because port mask is used, no AND is needed to clear bits 00219 //val += value<<(15-4); //higher 4 bits go lower. No need to shift by 15 because bits are in the higher nibble 00220 /* daniel has made a mistake with ports */ 00221 //val = ((value&0x70)<<(28-4)); //higher 4 bits go higher - because port mask is used, no AND is needed to clear bits 00222 //val += value<<(15); //lower 4 bits go lower. No need to shift by 15 because bits are in the higher nibble 00223 //SET_MASK_DAC; 00224 //LPC_GPIO_PORT->MPIN[1] = val; // write bits to port 00225 //CLR_MASK_DAC; 00226 /* fixed here */ 00227 #define MASKED_DAC 0 00228 #if MASKED_DAC 00229 uint32_t val; 00230 val=value; 00231 SET_MASK_DAC_LO; 00232 LPC_GPIO_PORT->MPIN[1] = val<<28; // write lower 4 bits to port 00233 CLR_MASK_DAC_LO; 00234 SET_MASK_DAC_HI; 00235 LPC_GPIO_PORT->MPIN[2] = val<<(20-4); // write bits to port 00236 CLR_MASK_DAC_HI; 00237 #else 00238 if (value & 1) SET_DAC0 else CLR_DAC0; 00239 value >>= 1; 00240 if (value & 1) SET_DAC1 else CLR_DAC1; 00241 value >>= 1; 00242 if (value & 1) SET_DAC2 else CLR_DAC2; 00243 value >>= 1; 00244 if (value & 1) SET_DAC3 else CLR_DAC3; 00245 value >>= 1; 00246 if (value & 1) SET_DAC4 else CLR_DAC4; 00247 value >>= 1; 00248 if (value & 1) SET_DAC5 else CLR_DAC5; 00249 value >>= 1; 00250 if (value & 1) SET_DAC6 else CLR_DAC6; 00251 value >>= 1; 00252 if (value & 1) SET_DAC7 else CLR_DAC7; 00253 #endif //MASKED_DAC 00254 //CLR_MASK_DAC; 00255 #endif // BOARDREV 00256 #endif 00257 } 00258 00259 /** SOUND INIT **/ 00260 void Pokitto::soundInit() { 00261 #if POK_ENABLE_SOUND > 0 00262 uint32_t timerFreq; 00263 #if POK_USE_PWM 00264 00265 pwmout_init(&audiopwm,POK_AUD_PIN); 00266 pwmout_period_us(&audiopwm,POK_AUD_PWM_US); //was 31us 00267 pwmout_write(&audiopwm,0.1f); 00268 #endif 00269 00270 //#if POK_GBSOUND > 0 00271 /** GAMEBUINO SOUND **/ 00272 //audio.attach_us(&audio_IRQ, 1000000/(POK_AUD_FREQ>>0)); 00273 //#else 00274 /** NOT GAMEBUINO SOUND **/ 00275 //audio.attach_us(&pokSoundBufferedIRQ, 1000000/(POK_AUD_FREQ>>0)); 00276 /* Initialize 32-bit timer 0 clock */ 00277 Chip_TIMER_Init(LPC_TIMER32_0); 00278 00279 /* Timer rate is system clock rate */ 00280 timerFreq = Chip_Clock_GetSystemClockRate(); 00281 00282 /* Timer setup for match and interrupt at TICKRATE_HZ */ 00283 Chip_TIMER_Reset(LPC_TIMER32_0); 00284 00285 /* Enable both timers to generate interrupts when time matches */ 00286 Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 1); 00287 00288 /* Setup 32-bit timer's duration (32-bit match time) */ 00289 Chip_TIMER_SetMatch(LPC_TIMER32_0, 1, (timerFreq / POK_AUD_FREQ)); 00290 00291 /* Setup both timers to restart when match occurs */ 00292 Chip_TIMER_ResetOnMatchEnable(LPC_TIMER32_0, 1); 00293 00294 /* Start both timers */ 00295 Chip_TIMER_Enable(LPC_TIMER32_0); 00296 00297 /* Clear both timers of any pending interrupts */ 00298 #define TIMER_32_0_IRQn 18 00299 NVIC_ClearPendingIRQ((IRQn_Type)TIMER_32_0_IRQn); 00300 00301 /* Redirect IRQ vector - Jonne*/ 00302 NVIC_SetVector((IRQn_Type)TIMER_32_0_IRQn, (uint32_t)&TIMER32_0_IRQHandler ); 00303 00304 /* Enable both timer interrupts */ 00305 NVIC_EnableIRQ((IRQn_Type)TIMER_32_0_IRQn); 00306 //#endif // POK_GAMEBUINO_SUPPORT 00307 00308 //emptySong(); 00309 //emptyOscillators(); 00310 //emptyBlocks(); 00311 //emptyPatches(); 00312 #ifdef TEST_SOUND 00313 testOsc(); 00314 #endif // TEST_SOUND 00315 #if POK_BOARDREV == 2 00316 //initHWvolumecontrol(); 00317 #endif 00318 00319 #if POK_ENABLE_SYNTH 00320 emptyOscillators(); 00321 #endif 00322 00323 00324 #endif // POK_ENABLE_SOUND 00325 00326 } 00327 00328 00329 uint8_t Pokitto::streamPaused() { 00330 return !streamon; 00331 } 00332 00333 void Pokitto::pauseStream() { 00334 streamon=0; 00335 } 00336 00337 void Pokitto::playStream() { 00338 streamon=1; 00339 } 00340 00341 00342 void pokPauseStream() { 00343 streamon=0; 00344 } 00345 00346 void pokPlayStream() { 00347 streamon=1; 00348 } 00349 00350 00351 00352 inline void pokSoundBufferedIRQ() { 00353 uint32_t output = soundbuf[soundbufindex+=Pokitto::streamon]; 00354 if (soundbufindex==SBUFSIZE) soundbufindex=0; 00355 //if (p==sizeof(beat_11025_raw)) p=0; 00356 //soundbuf[soundbufindex++] = output; 00357 //uint32_t t_on = (uint32_t)(((obj->pwm->MATCHREL0)*output)>>8); //cut out float 00358 //obj->pwm->MATCHREL1 = t_on; 00359 output *= discrete_vol_multipliers[discrete_vol]; 00360 output >>= 8; 00361 dac_write(output); 00362 00363 //setDRAMpoint(pixx, pixy); 00364 } 00365 00366 inline void pokSoundIRQ () { 00367 #if POK_ENABLE_SOUND > 0 00368 //#define TICKY 0xFFFF //160 00369 //#define INCY 409 00370 uint32_t output=0;uint32_t op; 00371 //streamon=1; 00372 //if (test==TICKY) test=0; 00373 //if (test<(TICKY/2)) { tpin=1; pwmout_write(&audiopwm,(float)0/(float)255);}//dac_write(0);} 00374 //else {tpin=0; pwmout_write(&audiopwm,(float)255/(float)255);}//dac_write(64);} 00375 //test+=INCY; 00376 //return; 00377 #ifndef POK_SIM 00378 #if POK_USE_PWM 00379 pwmout_t* obj = &audiopwm; 00380 #endif 00381 #endif 00382 #if POK_STREAMING_MUSIC > 0 00383 #if POK_STREAMFREQ_HALVE 00384 streamstep = 1-streamstep; 00385 #else 00386 streamstep = 1; 00387 #endif // POK_STREAMFREQ_HALVE 00388 streamstep &= streamon; // streamon is used to toggle SD music streaming on and off 00389 if (streamstep) { 00390 output = (*currentPtr++); 00391 if(streamvol && streamon) { 00392 output >>= 3-streamvol; 00393 streambyte = output; 00394 } else { 00395 streambyte = 0; // duty cycle 00396 output = 0; 00397 } 00398 if (currentPtr >= endPtr) 00399 { 00400 currentBuffer++; 00401 if (currentBuffer==4) currentBuffer=0; 00402 currentPtr = buffers[currentBuffer]; 00403 endPtr = currentPtr + BUFFER_SIZE; 00404 } 00405 } 00406 #endif // POK_STREAMING_MUSIC 00407 00408 /** DO ADDITIONAL SOUND PROCESSING (NOT STREAM) OF SOUND HERE **/ 00409 00410 #if POK_ENABLE_SYNTH 00411 /** if song is being played from sd **/ 00412 if (playing) { 00413 notetick++; 00414 updatePlayback(); 00415 } 00416 /** oscillators update **/ 00417 osc1.count += osc1.cinc + (osc1.pitchbend >> 4); // counts to 65535 and overflows to zero WAS 8 ! 00418 osc2.count += osc2.cinc + (osc2.pitchbend >> 4); // counts to 65535 and overflows to zero 00419 osc3.count += osc3.cinc + (osc3.pitchbend >> 4); // counts to 65535 and overflows to zero 00420 Marr[tick](); // call mixing function 00421 --tick; 00422 00423 /** mixing oscillator output **/ 00424 00425 op = (uint32_t) ((osc1.output)*(osc1.vol>>8))>>9;// >> 2 osc1.vol Marr; 00426 op += (uint32_t) ((osc2.output)*(osc2.vol>>8))>>9;// >> 2 osc1.vol Marr; 00427 op += (uint32_t) ((osc3.output)*(osc3.vol>>8))>>9;// >> 2 osc1.vol Marr; 00428 op *= discrete_vol_multipliers[discrete_vol]; 00429 op >>= 8; 00430 output = op & 0xFF; 00431 00432 #endif // POK_ENABLE_SYNTH 00433 00434 #ifndef POK_SIM 00435 /** HARDWARE **/ 00436 #if POK_ENABLE_SOUND > 0 00437 #if POK_STREAMING_MUSIC > 0 00438 /** sound is enabled, streaming is enabled */ 00439 #if POK_STREAM_TO_DAC > 0 00440 /** stream goes to DAC */ 00441 #if POK_USE_DAC > 0 00442 uint32_t sbyte = streambyte; 00443 sbyte *= discrete_vol_multipliers[discrete_vol]; 00444 sbyte >>= 8; 00445 dac_write((uint8_t)sbyte); // duty cycle 00446 #endif // POK_USE_DAC 00447 #else 00448 /** stream goes to PWM */ 00449 if (streamstep) { 00450 //pwmout_write(&audiopwm,(float)streambyte/(float)255); 00451 #if POK_USE_PWM 00452 uint32_t sbyte = streambyte; 00453 sbyte *= discrete_vol_multipliers[discrete_vol]; 00454 sbyte >>= 8; 00455 uint32_t t_on = (uint32_t)((((obj->pwm->MATCHREL0)*sbyte)>>8)); //cut out float 00456 obj->pwm->MATCHREL1 = t_on; 00457 #endif 00458 //dac_write((uint8_t)streambyte); // duty cycle 00459 } 00460 #endif // POK_STREAM_TO_DAC 00461 #endif // POK_STREAMING_MUSIC 00462 #if POK_STREAM_TO_DAC > 0 00463 /** synth goes to PWM */ 00464 //pwmout_write(&audiopwm,(float)output/(float)255); 00465 #if POK_USE_PWM 00466 op = output; 00467 op *= discrete_vol_multipliers[discrete_vol]; 00468 op >>= 8; 00469 uint32_t t_on = (uint32_t)((((obj->pwm->MATCHREL0)*op)>>8)); //cut out float 00470 obj->pwm->MATCHREL1 = t_on; 00471 #endif 00472 #else // POK_STREAMING_MUSIC 00473 op = output; 00474 op *= discrete_vol_multipliers[discrete_vol]; 00475 op >>= 8; 00476 dac_write((uint8_t)op); // SYNTH to DAC 00477 #endif 00478 soundbyte = (output+streambyte)>>1; 00479 soundbuf[soundbufindex++]=soundbyte; 00480 if (soundbufindex==256) soundbufindex=0; 00481 #endif //POK_ENABLE_SOUND 00482 #endif // HARDWARE 00483 #endif //POK_ENABLE_SOUND 00484 } 00485 00486 00487 void Pokitto::updateSDAudioStream() { 00488 if (streamPaused()) return; 00489 00490 #if POK_STREAMING_MUSIC > 0 00491 if (oldBuffer != currentBuffer) { 00492 if (currentBuffer==0) fileReadBytes(&buffers[3][0],BUFFER_SIZE); 00493 else if (currentBuffer==1) fileReadBytes(&buffers[0][0],BUFFER_SIZE); 00494 else if (currentBuffer==2) fileReadBytes(&buffers[1][0],BUFFER_SIZE); 00495 else fileReadBytes(&buffers[2][0],BUFFER_SIZE); 00496 oldBuffer = currentBuffer; 00497 streamcounter += BUFFER_SIZE; 00498 } else return; 00499 00500 #ifndef POK_SIM 00501 if ( streamcounter > fs.fsize - (BUFFER_SIZE*6)) { 00502 #else 00503 if ( streamcounter > getFileLength() - (BUFFER_SIZE*6)) { 00504 #endif 00505 streamcounter=0; 00506 #if POK_STREAM_LOOP 00507 fileRewind(); 00508 #else 00509 pokPauseStream(); 00510 #endif 00511 } 00512 #endif 00513 } 00514 00515 00516 #endif // POK_ENABLE_SOUND 00517 00518 00519
Generated on Tue Jul 12 2022 21:03:50 by 1.7.2