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);
    }

 }