PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Fork of PokittoLib by
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 00046 00047 00048 using namespace Pokitto; 00049 00050 /** Sound Variables **/ 00051 #if (POK_STREAMING_MUSIC > 0) 00052 unsigned char buffers[4][BUFFER_SIZE]; 00053 volatile int currentBuffer = 0, oldBuffer = 0; 00054 volatile int bufindex = 0, vol=1; 00055 volatile unsigned char * currentPtr; 00056 volatile unsigned char * endPtr; 00057 int8_t streamvol=3; 00058 uint32_t streamcounter=0; 00059 uint8_t streamstep=0; 00060 #endif 00061 00062 #if POK_ENABLE_SOUND > 0 00063 pwmout_t Pokitto::audiopwm; // this way (instead of PwmOut class) pwm doesn't start screaming until it is initialized ! 00064 Ticker Pokitto::audio; 00065 00066 using namespace Pokitto; 00067 00068 /** stream output and status */ 00069 uint8_t Pokitto::streambyte,Pokitto::streamon; 00070 00071 uint8_t soundbuf[256], soundbufindex=0, Pokitto::HWvolume=0; 00072 bool volpotError=false; //test for broken MCP4018 00073 00074 uint16_t soundbyte; 00075 00076 00077 #if POK_USE_DAC > 0 00078 #if POK_BOARDREV == 1 00079 /** 2-layer board rev 1.3 **/ 00080 DigitalOut dac0(P1_6); 00081 DigitalOut dac1(P1_0); 00082 DigitalOut dac2(P1_16); 00083 DigitalOut dac3(P0_19); 00084 DigitalOut dac4(P0_17); 00085 DigitalOut dac5(P1_12); 00086 DigitalOut dac6(P1_15); 00087 DigitalOut dac7(P1_8); 00088 #else 00089 /** 4-layer board rev 2.1 **/ 00090 DigitalOut dac0(P1_28); 00091 DigitalOut dac1(P1_29); 00092 DigitalOut dac2(P1_30); 00093 DigitalOut dac3(P1_31); 00094 /* has daniel made a mistake ?*/ 00095 DigitalOut dac4(P2_20); 00096 DigitalOut dac5(P2_21); 00097 DigitalOut dac6(P2_22); 00098 DigitalOut dac7(P2_23); 00099 00100 DigitalOut amp(P1_17); 00101 00102 #endif // POK_BOARDREV 00103 #endif // POK_USE_DAC 00104 00105 #if POK_BOARDREV == 2 00106 //MCP4018 volpot(P0_5,P0_4); 00107 00108 void initHWvolumecontrol() { 00109 HWvolume=0; 00110 volpotError=true; 00111 //if (volpot.put(HWvolume)) volpotError=true; //try if MCP4018 answers 00112 setHWvolume(VOLUME_STARTUP); 00113 } 00114 00115 int Pokitto::setHWvolume(uint8_t v) { 00116 HWvolume = 0x7F&v; 00117 //if (!volpotError) return volpot.put(HWvolume); //use normal I2C 00118 /* fallback method for broken MCP4018 */ 00119 SoftwareI2C swvolpot(P0_4, P0_5); //swapped SDA,SCL 00120 swvolpot.write(0x5e,HWvolume); 00121 return HWvolume; 00122 } 00123 00124 uint8_t Pokitto::getHWvolume() { 00125 return HWvolume; 00126 } 00127 00128 void Pokitto::changeHWvolume(int8_t v) { 00129 int temp = HWvolume + v; 00130 if (temp < 0) temp = 0; //prevent volume "looparound" than can make a massive crack 00131 if (temp > 127) temp = 127; 00132 setHWvolume(temp); 00133 } 00134 00135 uint8_t Pokitto::ampIsOn() { 00136 return amp; 00137 } 00138 00139 void Pokitto::ampEnable(uint8_t v) { 00140 if (v>1) v=1; // limit against funny values 00141 amp=v; 00142 } 00143 #endif // POK_BOARDREV == 2 00144 00145 void Pokitto::dac_write(uint8_t value) { 00146 #if POK_USE_DAC > 0 00147 #if POK_BOARDREV == 1 // was 1 00148 if (value & 1) SET_DAC0 else CLR_DAC0; 00149 value >>= 1; 00150 if (value & 1) SET_DAC1 else CLR_DAC1; 00151 value >>= 1; 00152 if (value & 1) SET_DAC2 else CLR_DAC2; 00153 value >>= 1; 00154 if (value & 1) SET_DAC3 else CLR_DAC3; 00155 value >>= 1; 00156 if (value & 1) SET_DAC4 else CLR_DAC4; 00157 value >>= 1; 00158 if (value & 1) SET_DAC5 else CLR_DAC5; 00159 value >>= 1; 00160 if (value & 1) SET_DAC6 else CLR_DAC6; 00161 value >>= 1; 00162 if (value & 1) SET_DAC7 else CLR_DAC7; 00163 #else 00164 //uint32_t val; 00165 //val = value<<28; //lower 4 bits go higher - because port mask is used, no AND is needed to clear bits 00166 //val += value<<(15-4); //higher 4 bits go lower. No need to shift by 15 because bits are in the higher nibble 00167 /* daniel has made a mistake with ports */ 00168 //val = ((value&0x70)<<(28-4)); //higher 4 bits go higher - because port mask is used, no AND is needed to clear bits 00169 //val += value<<(15); //lower 4 bits go lower. No need to shift by 15 because bits are in the higher nibble 00170 //SET_MASK_DAC; 00171 //LPC_GPIO_PORT->MPIN[1] = val; // write bits to port 00172 //CLR_MASK_DAC; 00173 /* fixed here */ 00174 /*val=value; 00175 SET_MASK_DAC_LO; 00176 LPC_GPIO_PORT->MPIN[1] = val<<28; // write lower 4 bits to port 00177 CLR_MASK_DAC_LO; 00178 SET_MASK_DAC_HI; 00179 LPC_GPIO_PORT->MPIN[2] = val<<(20-4); // write bits to port 00180 CLR_MASK_DAC_HI; */ 00181 if (value & 1) SET_DAC0 else CLR_DAC0; 00182 value >>= 1; 00183 if (value & 1) SET_DAC1 else CLR_DAC1; 00184 value >>= 1; 00185 if (value & 1) SET_DAC2 else CLR_DAC2; 00186 value >>= 1; 00187 if (value & 1) SET_DAC3 else CLR_DAC3; 00188 value >>= 1; 00189 if (value & 1) SET_DAC4 else CLR_DAC4; 00190 value >>= 1; 00191 if (value & 1) SET_DAC5 else CLR_DAC5; 00192 value >>= 1; 00193 if (value & 1) SET_DAC6 else CLR_DAC6; 00194 value >>= 1; 00195 if (value & 1) SET_DAC7 else CLR_DAC7; 00196 //CLR_MASK_DAC; 00197 #endif // BOARDREV 00198 #endif 00199 } 00200 00201 /** SOUND INIT **/ 00202 void Pokitto::soundInit() { 00203 00204 pwmout_init(&audiopwm,POK_AUD_PIN); 00205 pwmout_period_us(&audiopwm,POK_AUD_PWM_US); //was 31us 00206 pwmout_write(&audiopwm,0.1f); 00207 00208 #if POK_GBSOUND > 0 00209 /** GAMEBUINO SOUND **/ 00210 audio.attach_us(&audio_IRQ, 1000000/(POK_AUD_FREQ>>0)); 00211 #else 00212 /** NOT GAMEBUINO SOUND **/ 00213 audio.attach_us(&pokSoundIRQ , 1000000/(POK_AUD_FREQ>>0)); 00214 #endif // POK_GAMEBUINO_SUPPORT 00215 00216 //emptySong(); 00217 //emptyOscillators(); 00218 //emptyBlocks(); 00219 //emptyPatches(); 00220 #ifdef TEST_SOUND 00221 testOsc(); 00222 #endif // TEST_SOUND 00223 #if POK_BOARDREV == 2 00224 initHWvolumecontrol(); 00225 #endif 00226 00227 } 00228 00229 00230 uint8_t Pokitto::streamPaused() { 00231 return !streamon; 00232 } 00233 00234 void Pokitto::pauseStream() { 00235 streamon=0; 00236 } 00237 00238 void Pokitto::playStream() { 00239 streamon=1; 00240 } 00241 00242 00243 void pokPauseStream() { 00244 streamon=0; 00245 } 00246 00247 void pokPlayStream() { 00248 streamon=1; 00249 } 00250 00251 void pokSoundIRQ () { 00252 uint8_t output=0; 00253 #ifndef POK_SIM 00254 //pwmout_t* obj = &audiopwm; 00255 #endif 00256 #if POK_STREAMING_MUSIC > 0 00257 #if POK_STREAMFREQ_HALVE 00258 streamstep = 1-streamstep; 00259 #else 00260 streamstep = 1; 00261 #endif // POK_STREAMFREQ_HALVE 00262 streamstep &= streamon; // streamon is used to toggle SD music streaming on and off 00263 if (streamstep) { 00264 output = (*currentPtr++); 00265 if(streamvol && streamon) { 00266 output >>= 3-streamvol; 00267 streambyte = output; 00268 } else { 00269 streambyte = 0; // duty cycle 00270 output = 0; 00271 } 00272 if (currentPtr >= endPtr) 00273 { 00274 currentBuffer++; 00275 if (currentBuffer==4) currentBuffer=0; 00276 currentPtr = buffers[currentBuffer]; 00277 endPtr = currentPtr + BUFFER_SIZE; 00278 } 00279 } 00280 #endif // POK_STREAMING_MUSIC 00281 00282 /** DO ADDITIONAL SOUND PROCESSING (NOT STREAM) OF SOUND HERE **/ 00283 00284 #if POK_ENABLE_SYNTH 00285 /** if song is being played from sd **/ 00286 if (playing) { 00287 notetick++; 00288 updatePlaybackSD(playerpos&7); 00289 } 00290 /** oscillators update **/ 00291 osc1.count += osc1.cinc + (osc1.pitchbend >> 4); // counts to 65535 and overflows to zero WAS 8 ! 00292 osc2.count += osc2.cinc + (osc2.pitchbend >> 4); // counts to 65535 and overflows to zero 00293 osc3.count += osc3.cinc + (osc3.pitchbend >> 4); // counts to 65535 and overflows to zero 00294 Marr[tick](); // call mixing function 00295 --tick; 00296 00297 /** mixing oscillator output **/ 00298 00299 uint16_t op = (uint16_t) ((osc1.output)*(osc1.vol>>8))>>9;// >> 2 osc1.vol Marr; 00300 op += (uint16_t) ((osc2.output)*(osc2.vol>>8))>>9;// >> 2 osc1.vol Marr; 00301 op += (uint16_t) ((osc3.output)*(osc3.vol>>8))>>9;// >> 2 osc1.vol Marr; 00302 output = (uint8_t) op; 00303 00304 #endif // POK_ENABLE_SYNTH 00305 00306 #ifndef POK_SIM 00307 /** HARDWARE **/ 00308 #if POK_ENABLE_SOUND > 0 00309 #if POK_STREAMING_MUSIC > 0 00310 /** sound is enabled, streaming is enabled */ 00311 #if POK_STREAM_TO_DAC > 0 00312 /** stream goes to DAC */ 00313 #if POK_USE_DAC > 0 00314 if (streamstep) dac_write((uint8_t)streambyte); // duty cycle 00315 #endif // POK_USE_DAC 00316 #else 00317 /** stream goes to PWM */ 00318 if (streamstep) { 00319 pwmout_write(&audiopwm,(float)streambyte/(float)255); 00320 //uint32_t t_on = (uint32_t)(((obj->pwm->MATCHREL0)*streambyte)>>8); //cut out float 00321 //obj->pwm->MATCHREL1 = t_on; 00322 //dac_write((uint8_t)streambyte); // duty cycle 00323 } 00324 #endif // POK_STREAM_TO_DAC 00325 #endif // POK_STREAMING_MUSIC 00326 #if POK_STREAM_TO_DAC > 0 00327 /** synth goes to PWM */ 00328 pwmout_write(&audiopwm,(float)output/(float)255); 00329 //uint32_t t_on = (uint32_t)(((obj->pwm->MATCHREL0)*output)>>8); //cut out float 00330 //obj->pwm->MATCHREL1 = t_on; 00331 #else 00332 dac_write((uint8_t)output); 00333 #endif // decide where synth is output 00334 soundbyte = (output+streambyte)>>1; 00335 soundbuf[soundbufindex++]=soundbyte; 00336 #endif //POK_ENABLE_SOUND 00337 #endif // HARDWARE 00338 } 00339 00340 00341 void Pokitto::updateSDAudioStream() { 00342 if (streamPaused()) return; 00343 00344 #if POK_STREAMING_MUSIC > 0 00345 if (oldBuffer != currentBuffer) { 00346 if (currentBuffer==0) fileReadBytes(&buffers[3][0],BUFFER_SIZE); 00347 else if (currentBuffer==1) fileReadBytes(&buffers[0][0],BUFFER_SIZE); 00348 else if (currentBuffer==2) fileReadBytes(&buffers[1][0],BUFFER_SIZE); 00349 else fileReadBytes(&buffers[2][0],BUFFER_SIZE); 00350 oldBuffer = currentBuffer; 00351 streamcounter += BUFFER_SIZE; 00352 } else return; 00353 00354 #ifndef POK_SIM 00355 if ( streamcounter > fs.fsize - (BUFFER_SIZE*6)) { 00356 #else 00357 if ( streamcounter > getFileLength() - (BUFFER_SIZE*6)) { 00358 #endif 00359 streamcounter=0; 00360 #if POK_STREAM_LOOP 00361 fileRewind(); 00362 #else 00363 pokPauseStream(); 00364 #endif 00365 } 00366 #endif 00367 } 00368 00369 00370 #endif // POK_ENABLE_SOUND 00371 00372
Generated on Tue Jul 12 2022 18:08:12 by 1.7.2