ADC using MODDMA and then sending the sampled value encapsulated in an OSC message

Dependencies:   EthernetNetIf mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "MODDMA.h"
00003 #include "mbedOSC.h"
00004 
00005 
00006 // How long between grabbing samples on all channels.
00007 // Value is in microseconds. 
00008 #define SAMPLE_PERIOD   10000//////10ms sampling of all adc pins
00009 #define NUM_OF_SAMPLES  6
00010 
00011 
00012 //// ETHERNET
00013 // Ethernet can be created with *either* an address assigned by DHCP or a static IP address. Uncomment the define line for DHCP
00014 //#define DHCP
00015 #ifdef DHCP
00016 EthernetNetIf eth;
00017 #else
00018 EthernetNetIf eth(
00019     IpAddr(192,168,1,1), //IP Address
00020     IpAddr(255,255,255,0), //Network Mask
00021     IpAddr(), //Gateway
00022     IpAddr()  //DNS
00023 );
00024 #endif
00025 
00026 
00027 
00028 DigitalOut led1(LED1);
00029 DigitalOut led2(LED2);
00030 DigitalOut led3(LED3);
00031 DigitalOut led4(LED4);
00032 
00033 //// OSC
00034 // The object to do the work of sending and receiving
00035 OSCClass osc;
00036 // The message objects to send and receive with
00037 OSCMessage recMes;
00038 OSCMessage sendMes;
00039 // Setting - The port we're listening to on the mbed for OSC messages
00040 int  mbedListenPort  = 9000;
00041 // Setting - The address and port we're going to send to, from the mbed
00042 uint8_t destIp[]  = { 192, 168, 1, 2};
00043 int  destPort = 8000;
00044 //// Our messageReceivedCallback function
00045 void processOSC()
00046  {
00047     // If this function has been called, the OSC message just received will have been parsed into our recMes OSCMessage object
00048     // Note we can access recMes here, outside of the main loop, as we created it as a global variable.
00049     // TASK: If this message one we want, do something about it.
00050     // In this example we're listening for messages with a top address of "mbed".
00051     // Note the strcmp function returns 0 if identical, so !strcmp is true if the two strings are the same
00052     if ( !strcmp( recMes.getAddress(0) , "mbed" ) ) {
00053         printf("OSC Message received addressed to mbed \r\n");
00054         if ( !strcmp( recMes.getAddress(1) , "test1" ) )
00055             printf("Received subAddress= test1 \r\n");
00056         // Send some osc message:
00057         sendMes.setTopAddress("/working...");
00058         osc.sendOsc(&sendMes);
00059     }
00060     led1=!led1;
00061 }
00062 
00063 
00064 uint32_t adBuffer[NUM_OF_SAMPLES];
00065 bool dmaTransferComplete;
00066 
00067 MODDMA dma;
00068 MODDMA_Config *conf;
00069 
00070 
00071 void TC0_callback(void);                 /////DMA Transmission
00072 void ERR0_callback(void);
00073 void Sensor_Tap(int chan, uint32_t value1); //////Sending OSC
00074 
00075 extern "C" void TIMER1_handler(void) __irq          ////// Aka Wahaj bhai!!! yeah im talking to myself ...this function is called 
00076 {                                                   ///when i want to sample the analgue pins using burst mode and reseting the DMA and timer Configuration for the next sample
00077     led2 = !led2; // Show life
00078     //uint32_t dummyADC = LPC_ADC->ADGDR;           
00079     dma.Setup( conf ); // Pre-prep a transfer
00080     dma.Enable( conf );
00081     LPC_ADC->ADCR |= (1UL << 16); // ADC burst mode
00082     LPC_ADC->ADINTEN = 0x100;     // Do all channels.
00083     LPC_TIM1->IR = 1; // Clr timer1 irq.
00084 }
00085 
00086 int main()
00087  {
00088  
00089   //// TASK: Set up the Ethernet port
00090     printf("Setting up ethernet...\r\n");
00091     EthernetErr ethErr = eth.setup();
00092     if (ethErr) {
00093         printf("Ethernet Failed to setup. Error: %d\r\n", ethErr);
00094         return -1;
00095     }
00096     printf("Ethernet OK\r\n");
00097     //// TASK: Set up OSC message sending
00098     // In the OSC message container we've made for send messages, set where we want it to go:
00099     sendMes.setIp( destIp );
00100     sendMes.setPort( destPort );
00101     //// TASK: Set up OSC message receiving
00102     // In the OSC send/receive object...
00103     // Set the OSC message container for it to parse received messages into
00104     osc.setReceiveMessage(&recMes);
00105     // Tell it to begin listening for OSC messages at the port specified (the IP address we know already, it's the mbed's!).
00106     osc.begin(mbedListenPort);
00107     // Rather than constantly checking to see whether there are new messages waiting, the object can call some code of ours to run when a message is received.
00108     // This line does that, attaching a callback function we've written before getting to this point, in this case it's called processOSC
00109     // For more info how this works, see http://mbed.org/cookbook/FunctionPointer
00110     osc.messageReceivedCallback.attach(&processOSC);
00111  
00112  
00113  
00114  
00115  
00116 ///////////////DMA AND ADC//////////
00117     
00118     memset(adBuffer, 0, sizeof(adBuffer));
00119     
00120     
00121     // Power up the ADC and set PCLK-----Configuraion
00122     LPC_SC->PCONP    |=  (1UL << 12);
00123     LPC_SC->PCLKSEL0 |= (3UL << 24);    // PCLK = CCLK/8 96M/8 = 12MHz
00124     NVIC_DisableIRQ(ADC_IRQn); ///For burst mode disable NVIc for adc  
00125     
00126     // Set the pin functions to ADC
00127    
00128                 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
00129                 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14;
00130                 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
00131                 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14;
00132                
00133                 //p16://=p0.24 of LPC1768
00134                 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
00135                 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16;
00136                 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
00137                 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16;
00138              
00139                 // p17://=p0.25 of LPC1768
00140                 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
00141                 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18;
00142                 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
00143                 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18;
00144               
00145                 //p18://=p0.26 of LPC1768:
00146                 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
00147                 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20;
00148                 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
00149                 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20;
00150 
00151                 //=p1.30 of LPC1768
00152                 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
00153                 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28;
00154                 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
00155                 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28;
00156                 
00157                 //=p1.31 of LPC1768
00158                 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
00159                 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30;
00160                 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
00161                 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30;
00162     
00163     LPC_ADC->ADINTEN = 0x100;
00164     ////////////////Enable ADC////1Mhz clock////6 ADC pins 
00165     LPC_ADC->ADCR = (1UL << 21) | (11UL << 8) | (63UL << 0);
00166     
00167     
00168    //////TIMER 1 Configuraion 
00169     LPC_SC->PCONP    |= (1UL << 2); // TIM1 On
00170     LPC_SC->PCLKSEL0 |= (3UL << 4); // CCLK/8 = 12MHz
00171     LPC_TIM1->PR      = 11;          // TC clocks at 1MHz.
00172     LPC_TIM1->MR0     = SAMPLE_PERIOD-1;
00173     LPC_TIM1->MCR     = 3;          // Reset TCR to zero on match and irq.
00174     NVIC_SetVector(TIMER1_IRQn, (uint32_t)TIMER1_handler);
00175     NVIC_EnableIRQ(TIMER1_IRQn);
00176     
00177     // Prepare the GPDMA system.
00178     conf = new MODDMA_Config;
00179     conf
00180      ->channelNum    ( MODDMA::Channel_0 )
00181      ->dstMemAddr    ( (uint32_t)adBuffer )
00182      ->transferSize  ( NUM_OF_SAMPLES )
00183      ->transferType  ( MODDMA::p2m )
00184      ->transferWidth ( MODDMA::word )
00185      ->srcConn       ( MODDMA::ADC )
00186      ->attach_tc     ( &TC0_callback )
00187      ->attach_err    ( &ERR0_callback )
00188     ; // end conf.
00189     
00190     // Prepare configuration.
00191     if (!dma.Setup( conf )) 
00192     {
00193         error("Doh!");
00194     }
00195     
00196     // Begin.
00197     LPC_TIM1->TCR = 1;
00198       while (1)
00199      {  
00200         
00201           // This polls the network connection for new activity, without keeping on calling this you won't receive any OSC!
00202         Net::poll();
00203         if (dmaTransferComplete) 
00204         {
00205             int i, value, channel;
00206             
00207             for (i = 0; i <NUM_OF_SAMPLES ; i++) 
00208             {
00209                 value = (adBuffer[i] >> 4) & 0xFFF;
00210                 channel = (adBuffer[i] >> 24) & 0x3;
00211                 channel--;
00212                 adBuffer[i]=0;
00213                 if (channel == -1)
00214                  channel = 5; // Workaround ch num problem.
00215                 double fVal = 5 * (double)((double)value) / ((double)0x1000); // scale to 0v to 3.3v 
00216                 Sensor_Tap(i,(uint32_t)fVal);
00217            
00218                 
00219                  //pc.printf("ADC input (channel=%d) = 0x%03x %01.3f volts\n", channel, value, fVal);                
00220             }
00221             dmaTransferComplete = false;
00222             wait(0.05);       ////wait for 50 ms for the next finger to pe pressed    
00223  
00224         }
00225     }       
00226 }
00227 
00228 // Configuration callback on TC
00229 void TC0_callback(void) 
00230 {
00231     led4=!led4;
00232     MODDMA_Config *config = dma.getConfig();
00233     
00234     // Disbale burst mode and switch off the IRQ flag.
00235     LPC_ADC->ADCR &= ~(1UL << 16);
00236     LPC_ADC->ADINTEN = 0;    
00237     
00238     // Finish the DMA cycle by shutting down the channel.
00239     dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum());
00240     dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
00241     
00242     // Tell main() while(1) loop to print the results.
00243         dmaTransferComplete = true;            
00244     
00245     // Clear DMA IRQ flags.
00246     if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();    
00247     if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();
00248 }
00249 
00250 // Configuration callback on Error
00251 void ERR0_callback(void) {
00252     // Switch off burst conversions.
00253     LPC_ADC->ADCR |= ~(1UL << 16);
00254     LPC_ADC->ADINTEN = 0;
00255     error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
00256 }
00257 
00258 
00259 void Sensor_Tap(int chan, uint32_t value1)
00260  {
00261         led3 = !led3;
00262         
00263       //  if((value>>4)&0xFFFF >= Adc_Threshold)
00264         {        
00265         //SendOsc
00266         
00267          sendMes.setTopAddress("/MidiGlove");
00268         switch (chan)
00269             {
00270         case 0:
00271             default:
00272             sendMes.setSubAddress("/Thumb");
00273             break;
00274         case 1:
00275             sendMes.setSubAddress("/Finger1");
00276             break;
00277         case 2:
00278             sendMes.setSubAddress("/Finger2");
00279             break;
00280         case 3:
00281             sendMes.setSubAddress("/Finger3");
00282             break;
00283         case 4:
00284             sendMes.setSubAddress("/Finger4");
00285             break;
00286         case 5:
00287             sendMes.setSubAddress("/Finger5");
00288             break;
00289     }
00290        // uint32_t v=123;
00291             sendMes.setArgs("i",&value1); // The payload will be the button state as an integer, ie. 0 or 1. We need to cast to 'long' for ints (and 'double' for floats).
00292             osc.sendOsc(&sendMes);
00293     }
00294 
00295  }