/// @param _min_freq is the minimum frequency in Hz /// @param _max_freq is the maximum frequency in Hz /// @param in is a 16384 element array that will be loaded with the recorded data /// @prereq I2S interrupts are disabled /// @return 0 for success, nonzero for failure (TODO: error checking) void recordSweep(Uint32 _min_freq, Uint32 _max_freq, Uint32 fs, Int16 *in, Int32 *avg) { Uint32 FTV, FTV_min, FTV_max, step, i, counter; Int16 out, left, right; Uint32 min_freq = _min_freq; Uint32 max_freq = _max_freq; // float duration = 0.2; // 48450 // num cycles for loop takes static const Int32 DIV_FACTOR = 9690; // 0.2 * 48450 //FTV sweep range calculations FTV_min = (Uint32)((min_freq*65536UL)/fs)<<16; // calculate initial FTV value FTV_max = (Uint32)((max_freq*65536UL)/fs)<<16; // calculate max FTV value step = ((FTV_max-FTV))/(DIV_FACTOR); //Init FTV variables counter = 0; FTV = FTV_min; // Pre-tone for(i=0; i<16384; ++i) { counter = counter + FTV; out = (sinetable[counter>>23]); AIC_write2(out>>1,out>>1); // scale so that output is similar in scale to EQ AIC_read2(&left, &right); } //Generate Sweep for(i=0; i<16384; ++i) { FTV = FTV + step; //if(FTV > FTV_max) { // //FTV = (Uint32)(min_freq/fs*65536)<<16; //} counter = counter + FTV; out = (sinetable[counter>>23]); AIC_write2(out>>1,out>>1); // scale so that output is similar in scale to EQ AIC_read2(&left, &right); in[i]= left; } // Post-tone for(i=0; i<16384; ++i) { counter = counter + FTV; out = (sinetable[counter>>23]); AIC_write2(out>>1,out>>1); // scale so that output is similar in scale to EQ AIC_read2(&left, &right); } #ifdef PLAYBACK // Playback for(i=0; i<16384; ++i) { AIC_write2(in[i] ,in[i]); } #endif XVGAinit(0); processFFT(in, mypOUT, avg); }
FFTWidget::FFTWidget(QWidget *parent) : QWidget(parent) { int err; snd_pcm_hw_params_t *hw_params; const char *dev_name = "hw:SDR"; if ((err = snd_pcm_open(&capture_handle, dev_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", dev_name, snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_rate(capture_handle, hw_params, 96000, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); exit (1); } snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_prepare (capture_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); } setRectWindow(); timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(processFFT())); timer->start(); // Zero-delay if((err = snd_pcm_start(capture_handle)) < 0) { fprintf (stderr, "cannot start audio interface (%s)\n", snd_strerror (err)); exit(1); } }
/***************************************************************************//** * @brief * Main function. Setup ADC, FFT, clocks, PRS, DMA, Timer, * and process FFT forever. *******************************************************************************/ int main(void) { arm_status status; char buf[20]; bool redraw = false; int glibStatus; DMA_Init_TypeDef dmaInit; TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT; /* Initialize DVK board register access */ BSP_Init(BSP_INIT_DEFAULT); /* If first word of user data page is non-zero, enable eA Profiler trace */ BSP_TraceEtmSetup(); /* Connect audio in to ADC */ BSP_PeripheralAccess(BSP_AUDIO_IN, true); /* Wait a while in order to let signal from audio-in stabilize after */ /* enabling audio-in peripheral. */ RTCDRV_Trigger(1000, NULL); EMU_EnterEM2(true); /* Initialize the CFFT/CIFFT module */ status = arm_rfft_init_f32(&rfft_instance, &cfft_instance, GUITAR_AUDIO_BUFFER_SAMPLES, 0, /* forward transform */ 1); /* normal, not bitreversed, order */ if (status != ARM_MATH_SUCCESS) { /* Error initializing RFFT module. */ while (1) ; } dataReadyForFFT = false; processingFFT = false; /* Use the HFXO. We still only manage to process about * a third the buffers through FFT */ CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); /* Setup SysTick Timer for 1 msec interrupts */ if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) { while (1) ; } /* Enable clocks required */ CMU_ClockEnable(cmuClock_HFPER, true); CMU_ClockEnable(cmuClock_ADC0, true); CMU_ClockEnable(cmuClock_PRS, true); CMU_ClockEnable(cmuClock_DMA, true); CMU_ClockEnable(cmuClock_TIMER0, true); NVIC_SetPriority(DMA_IRQn, 0); /* Highest priority */ /* Configure peripheral reflex system used by TIMER to trigger ADC/DAC */ guitarPRSConfig(GUITAR_PRS_CHANNEL); /* Configure general DMA issues */ dmaInit.hprot = 0; dmaInit.controlBlock = dmaControlBlock; DMA_Init(&dmaInit); /* Configure ADC used for audio-in */ guitarADCConfig(); /* Trigger sampling according to configured sample rate */ TIMER_TopSet(TIMER0, CMU_ClockFreqGet(cmuClock_HFPER) / GUITAR_AUDIO_SAMPLE_RATE); TIMER_Init(TIMER0, &timerInit); /* Wait until we have control over display */ while(!redraw) { redraw = TFT_AddressMappedInit(); } /* Init graphics context - abort on failure */ glibStatus = GLIB_contextInit(&gc); if (glibStatus != GLIB_OK) while (1) ; /* Clear the screen */ gc.backgroundColor = GLIB_rgbColor(0, 0, 0); GLIB_clear(&gc); while (1) { while (dataReadyForFFT) { float32_t freq; processingFFT = true; processFFT(); dataReadyForFFT = false; processingFFT = false; /* Get frequency and make string with one decimal accuracy */ freq = getFreq(); sprintf(buf, "%6.1f", freq); /* Check if we should control TFT display instead of AEM/board controller */ redraw = TFT_AddressMappedInit(); if (redraw) { gc.foregroundColor = GLIB_rgbColor(220, 220, 220); gc.backgroundColor = GLIB_rgbColor(0, 0, 0); /* Print the frequency somewhere in the middle of the screen */ GLIB_drawString(&gc, buf, strlen(buf), 100, 120, 1); } } EMU_EnterEM1(); } }