Jonne Valola / PokittoLib Featured

Dependents:   YATTT sd_map_test cPong SnowDemo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HWSound.cpp Source File

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 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