gonya707 2 Posted December 26, 2013 Share Posted December 26, 2013 This is a FM synthesizer made for the Stellarpad using the AD9850 function generator. The FM synthesis is teorethicaly the same as the all-known frequency modoulation used for radio communications, but in this case the frequencies are suited to stay at the audio range, i.e. from 20Hz to 20kHz. Basically The AD9850 is used as a sine wave generator, and the microcontroller create each cycle a sample of ANOTHER sine wave, this one goes from 5Hz to 100Hz more or less. We can modulate this two sinewaves, the AD signal being the carrier and the stellaris signal the baseband. The outcoming spectrum can be represented by the Bessel functions for each harmonic, making some interesting sounds for electronic music. Attaching two potentiometers we can control the baseband sine frequency and its amplitude, thus controlling the modulation index.This is a recording I made with this project (is there any way to display souncloud embed on the forum?):https://soundcloud.com/gonya707/fm-synthesizer-grsynth-comThe first seconds were non-modulated waves and then I pressed a note (C3 if I recall correctly) and played with the potentiometers.. This is a simplfied schematic of the project. The complete schematic of each module can be found respectively here: AD9850 module: http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf MIDI boosterpack by RobG: http://forum.43oh.com/topic/1773-midi-booster-pack/page-3#entry23763 And finally, this is the main code for this project: // // FM Synthesizer for Stellaris Launchpad and AD9850 // Coded by Gonzalo Recio // #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "inc/hw_gpio.h" #include "inc/hw_sysctl.h" #include "driverlib/pin_map.h" #include "driverlib/uart.h" #include "inc/hw_ints.h" #include "driverlib/interrupt.h" #include "driverlib/adc.h" #include "math.h" #include "midi.h" #include "STELLARIS_AD9850.h" #define PI 3.141592 #define GPIO_PB0_U1RX 0x00010001 #define GPIO_PB1_U1TX 0x00010401 // Global variables unsigned long message; unsigned long note, velocity; int on=0, off=0; int flagON = 0, flagOFF = 0; unsigned short i = 0, z,y; float t = 0; float freq = 0; unsigned long ulADC0_Value[4]; int main(void){ //50MHz clock SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN); //enable UART for MIDI T/R SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); GPIOPinConfigure(GPIO_PB0_U1RX); //B0 receptor GPIOPinConfigure(GPIO_PB1_U1TX); //B1 transmitter GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 31250, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE) ); //enable AD9850 SysCtlPeripheralEnable(PORT_ENABLE); GPIOPinTypeGPIOOutput(PORT, W_CLK|FQ_UD|DATA|RESET); AD9850_Init(); AD9850_Reset(); //ADC0 config SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS); ADCHardwareOversampleConfigure(ADC0_BASE, 4); ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_4|GPIO_PIN_5); ADCSequenceStepConfigure(ADC0_BASE, 1 , 0 , ADC_CTL_CH8 ); ADCSequenceStepConfigure(ADC0_BASE, 1 , 1 , ADC_CTL_CH9 | ADC_CTL_IE | ADC_CTL_END); ADCSequenceEnable(ADC0_BASE, 1); ADCIntClear(ADC0_BASE, 1); //Begin the interrupt detection IntMasterEnable(); IntEnable(INT_UART1); UARTIntEnable(UART1_BASE, UART_INT_RX | UART_INT_RT); while(1){ if (on == off){ AD9850_PowerDown(); } else{ ADCProcessorTrigger(ADC0_BASE, 1 ); while(!ADCIntStatus(ADC0_BASE, 1 , false)){ } ADCIntClear(ADC0_BASE, 1 ); ADCSequenceDataGet(ADC0_BASE, 1 , ulADC0_Value); AD9850_Osc(freq + y*sin(t), 0); } z=(ulADC0_Value[0] / 4 ) + 1; y=(ulADC0_Value[1]); i=(i + 1) % z; //timescale between 0 and 2*pi t=((float)i / (float)z ) * 2 * PI; } } //uart1handler void UARTIntHandler(void){ IntDisable(INT_UART1); unsigned long ulStatus = UARTIntStatus(UART1_BASE, true); //get interrupt status. RX or RT? UARTIntClear(UART1_BASE, ulStatus); //clear the asserted interrupts while(UARTCharsAvail(UART1_BASE)){ //loop while there are chars message = UARTCharGetNonBlocking(UART1_BASE); if(flagON){ // if the last message was a note ON, then this message is on++; // the note code. if (note != message){ note = message; freq = code2Freq(note); } } else if(flagOFF){ off++; } flagON = isNoteOn(message); flagOFF = isNoteOff(message); } IntEnable(INT_UART1); } The codes for the AD9850 library were also made by me, you can find them in this other thread.The MIDI library used in this project is here midi.c, midi.h. I was also the author for this one.If you don't have a MIDI boosterpack I've made also a no-MIDI version, the on-board switches trigger two different notes. You still need to attach a potentiometer to E4 and E5 though. You can find this version HERE. bluehash 1 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.