ADC using MODDMA and then sending the sampled value encapsulated in an OSC message
Dependencies: EthernetNetIf mbed
main.cpp
- Committer:
- Wahaj
- Date:
- 2012-06-25
- Revision:
- 1:887b266205f3
- Parent:
- 0:c6ffbdc6661d
File content as of revision 1:887b266205f3:
#include "mbed.h" #include "MODDMA.h" #include "mbedOSC.h" // How long between grabbing samples on all channels. // Value is in microseconds. #define SAMPLE_PERIOD 10000//////10ms sampling of all adc pins #define NUM_OF_SAMPLES 6 //// ETHERNET // Ethernet can be created with *either* an address assigned by DHCP or a static IP address. Uncomment the define line for DHCP //#define DHCP #ifdef DHCP EthernetNetIf eth; #else EthernetNetIf eth( IpAddr(192,168,1,1), //IP Address IpAddr(255,255,255,0), //Network Mask IpAddr(), //Gateway IpAddr() //DNS ); #endif DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); DigitalOut led4(LED4); //// OSC // The object to do the work of sending and receiving OSCClass osc; // The message objects to send and receive with OSCMessage recMes; OSCMessage sendMes; // Setting - The port we're listening to on the mbed for OSC messages int mbedListenPort = 9000; // Setting - The address and port we're going to send to, from the mbed uint8_t destIp[] = { 192, 168, 1, 2}; int destPort = 8000; //// Our messageReceivedCallback function void processOSC() { // If this function has been called, the OSC message just received will have been parsed into our recMes OSCMessage object // Note we can access recMes here, outside of the main loop, as we created it as a global variable. // TASK: If this message one we want, do something about it. // In this example we're listening for messages with a top address of "mbed". // Note the strcmp function returns 0 if identical, so !strcmp is true if the two strings are the same if ( !strcmp( recMes.getAddress(0) , "mbed" ) ) { printf("OSC Message received addressed to mbed \r\n"); if ( !strcmp( recMes.getAddress(1) , "test1" ) ) printf("Received subAddress= test1 \r\n"); // Send some osc message: sendMes.setTopAddress("/working..."); osc.sendOsc(&sendMes); } led1=!led1; } uint32_t adBuffer[NUM_OF_SAMPLES]; bool dmaTransferComplete; MODDMA dma; MODDMA_Config *conf; void TC0_callback(void); /////DMA Transmission void ERR0_callback(void); void Sensor_Tap(int chan, uint32_t value1); //////Sending OSC extern "C" void TIMER1_handler(void) __irq ////// Aka Wahaj bhai!!! yeah im talking to myself ...this function is called { ///when i want to sample the analgue pins using burst mode and reseting the DMA and timer Configuration for the next sample led2 = !led2; // Show life //uint32_t dummyADC = LPC_ADC->ADGDR; dma.Setup( conf ); // Pre-prep a transfer dma.Enable( conf ); LPC_ADC->ADCR |= (1UL << 16); // ADC burst mode LPC_ADC->ADINTEN = 0x100; // Do all channels. LPC_TIM1->IR = 1; // Clr timer1 irq. } int main() { //// TASK: Set up the Ethernet port printf("Setting up ethernet...\r\n"); EthernetErr ethErr = eth.setup(); if (ethErr) { printf("Ethernet Failed to setup. Error: %d\r\n", ethErr); return -1; } printf("Ethernet OK\r\n"); //// TASK: Set up OSC message sending // In the OSC message container we've made for send messages, set where we want it to go: sendMes.setIp( destIp ); sendMes.setPort( destPort ); //// TASK: Set up OSC message receiving // In the OSC send/receive object... // Set the OSC message container for it to parse received messages into osc.setReceiveMessage(&recMes); // Tell it to begin listening for OSC messages at the port specified (the IP address we know already, it's the mbed's!). osc.begin(mbedListenPort); // 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. // This line does that, attaching a callback function we've written before getting to this point, in this case it's called processOSC // For more info how this works, see http://mbed.org/cookbook/FunctionPointer osc.messageReceivedCallback.attach(&processOSC); ///////////////DMA AND ADC////////// memset(adBuffer, 0, sizeof(adBuffer)); // Power up the ADC and set PCLK-----Configuraion LPC_SC->PCONP |= (1UL << 12); LPC_SC->PCLKSEL0 |= (3UL << 24); // PCLK = CCLK/8 96M/8 = 12MHz NVIC_DisableIRQ(ADC_IRQn); ///For burst mode disable NVIc for adc // Set the pin functions to ADC LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14); LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14; LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14); LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14; //p16://=p0.24 of LPC1768 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16); LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16; LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16); LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16; // p17://=p0.25 of LPC1768 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18); LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18; LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18); LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18; //p18://=p0.26 of LPC1768: LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20); LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20; LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20); LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20; //=p1.30 of LPC1768 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28); LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28; LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28); LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28; //=p1.31 of LPC1768 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30); LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30; LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30); LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30; LPC_ADC->ADINTEN = 0x100; ////////////////Enable ADC////1Mhz clock////6 ADC pins LPC_ADC->ADCR = (1UL << 21) | (11UL << 8) | (63UL << 0); //////TIMER 1 Configuraion LPC_SC->PCONP |= (1UL << 2); // TIM1 On LPC_SC->PCLKSEL0 |= (3UL << 4); // CCLK/8 = 12MHz LPC_TIM1->PR = 11; // TC clocks at 1MHz. LPC_TIM1->MR0 = SAMPLE_PERIOD-1; LPC_TIM1->MCR = 3; // Reset TCR to zero on match and irq. NVIC_SetVector(TIMER1_IRQn, (uint32_t)TIMER1_handler); NVIC_EnableIRQ(TIMER1_IRQn); // Prepare the GPDMA system. conf = new MODDMA_Config; conf ->channelNum ( MODDMA::Channel_0 ) ->dstMemAddr ( (uint32_t)adBuffer ) ->transferSize ( NUM_OF_SAMPLES ) ->transferType ( MODDMA::p2m ) ->transferWidth ( MODDMA::word ) ->srcConn ( MODDMA::ADC ) ->attach_tc ( &TC0_callback ) ->attach_err ( &ERR0_callback ) ; // end conf. // Prepare configuration. if (!dma.Setup( conf )) { error("Doh!"); } // Begin. LPC_TIM1->TCR = 1; while (1) { // This polls the network connection for new activity, without keeping on calling this you won't receive any OSC! Net::poll(); if (dmaTransferComplete) { int i, value, channel; for (i = 0; i <NUM_OF_SAMPLES ; i++) { value = (adBuffer[i] >> 4) & 0xFFF; channel = (adBuffer[i] >> 24) & 0x3; channel--; adBuffer[i]=0; if (channel == -1) channel = 5; // Workaround ch num problem. double fVal = 5 * (double)((double)value) / ((double)0x1000); // scale to 0v to 3.3v Sensor_Tap(i,(uint32_t)fVal); //pc.printf("ADC input (channel=%d) = 0x%03x %01.3f volts\n", channel, value, fVal); } dmaTransferComplete = false; wait(0.05); ////wait for 50 ms for the next finger to pe pressed } } } // Configuration callback on TC void TC0_callback(void) { led4=!led4; MODDMA_Config *config = dma.getConfig(); // Disbale burst mode and switch off the IRQ flag. LPC_ADC->ADCR &= ~(1UL << 16); LPC_ADC->ADINTEN = 0; // Finish the DMA cycle by shutting down the channel. dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); // Tell main() while(1) loop to print the results. dmaTransferComplete = true; // Clear DMA IRQ flags. if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); } // Configuration callback on Error void ERR0_callback(void) { // Switch off burst conversions. LPC_ADC->ADCR |= ~(1UL << 16); LPC_ADC->ADINTEN = 0; error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); } void Sensor_Tap(int chan, uint32_t value1) { led3 = !led3; // if((value>>4)&0xFFFF >= Adc_Threshold) { //SendOsc sendMes.setTopAddress("/MidiGlove"); switch (chan) { case 0: default: sendMes.setSubAddress("/Thumb"); break; case 1: sendMes.setSubAddress("/Finger1"); break; case 2: sendMes.setSubAddress("/Finger2"); break; case 3: sendMes.setSubAddress("/Finger3"); break; case 4: sendMes.setSubAddress("/Finger4"); break; case 5: sendMes.setSubAddress("/Finger5"); break; } // uint32_t v=123; 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). osc.sendOsc(&sendMes); } }