Dependencies:   mbed NetServicesMin

main.cpp

Committer:
fernya
Date:
2012-06-18
Revision:
0:aa9ebbd3715f

File content as of revision 0:aa9ebbd3715f:

/*
 * Demonstrates sending a buffer repeatedly to the DAC using DMA.
 * Connect an oscilloscope to Mbed pin 18. This example doesn't
 * output anything else (nothing on any serial ports).
 */
#include "mbed.h"

#include "MODDMA.h"

#include "EthernetNetIf.h"
#include "ipaddr.h"
#include "UDPSocket.h"

#include "fifo.h"
#include "rtp.h"

// Make the buffer size match the number of degrees
// in a circle since we are going to output a sinewave.
#define BUFFER_SIZE 300

// Set DAC output power mode.
#define DAC_POWER_MODE  (1 << 16)

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

volatile int life_counter = 0;

EthernetNetIf eth;
UDPSocket data_sock;

fifo circ_buf;
char packet_buf[512] = {0};
struct rtp_header head;
int play[2][40];

AnalogOut signal(p18);
Timer timeout;
MODDMA dma;
MODDMA_Config *conf0, *conf1;

void TC0_callback(void);
void ERR0_callback(void);

void TC1_callback(void);
void ERR1_callback(void);

int ethInit(void);
int udpInit(void);
void UDPReceive(UDPSocketEvent e);

int main() {
    
    //serial initialization
    Serial pc(USBTX, USBRX);
    pc.baud(115200);
    //serial init done
    
    ethInit();
    udpInit();

    // Prepare the GPDMA system for buffer0.
    conf0 = new MODDMA_Config;
    conf0
    ->channelNum    ( MODDMA::Channel_0 )
    ->srcMemAddr    ( (uint32_t) &play[0] )
    ->dstMemAddr    ( MODDMA::DAC )
    ->transferSize  ( 40 )
    ->transferType  ( MODDMA::m2p )
    ->dstConn       ( MODDMA::DAC )
    ->attach_tc     ( &TC0_callback )
    ->attach_err    ( &ERR0_callback )
    ; // config end

    // Prepare the GPDMA system for buffer1.
    conf1 = new MODDMA_Config;
    conf1
    ->channelNum    ( MODDMA::Channel_1 )
    ->srcMemAddr    ( (uint32_t) &play[1] )
    ->dstMemAddr    ( MODDMA::DAC )
    ->transferSize  ( 40 )
    ->transferType  ( MODDMA::m2p )
    ->dstConn       ( MODDMA::DAC )
    ->attach_tc     ( &TC1_callback )
    ->attach_err    ( &ERR1_callback )
    ; // config end


    // Calculating the transfer frequency:
    // By default, the Mbed library sets the PCLK_DAC clock value
    // to 24MHz. 

    LPC_DAC->DACCNTVAL = 3000; // 24e6/8000

    // Prepare first configuration.
    if (!dma.Prepare( conf0 )) {
        error("Doh!");
    }

    // Begin (enable DMA and counter). Note, don't enable
    // DBLBUF_ENA as we are using DMA double buffering.
    LPC_DAC->DACCTRL |= (3UL << 2);
    
    while (1) {
        // There's not a lot to do as DMA and interrupts are
        // now handling the buffer transfers. So we'll just
        // flash led1 to show the Mbed is alive and kicking.
        
        if (life_counter++ > 100000) {
            led1 = !led1; // Show some sort of life.
            life_counter = 0;
            Net::poll();
        }
    }
}

// Configuration callback on TC
void TC0_callback(void) {

    // Get configuration pointer.
    MODDMA_Config *config = dma.getConfig();

    // Finish the DMA cycle by shutting down the channel.
    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );

    // Swap to buffer1
    dma.Prepare( conf1 );

    // Clear DMA IRQ flags.
    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
    int i;

    for (i=0; i<40; i++) {
        circ_buf.get((uint32_t*)&play[0][i]);
    }
}

// Configuration callback on Error
void ERR0_callback(void) {
    error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
}

// Configuration callback on TC
void TC1_callback(void) {

    // Get configuration pointer.
    MODDMA_Config *config = dma.getConfig();

    // Finish the DMA cycle by shutting down the channel.
    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );

    // Swap to buffer0
    dma.Prepare( conf0 );

    // Clear DMA IRQ flags.
    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
    int i;

    for (i=0; i<40; i++) {
        circ_buf.get((uint32_t*)&play[1][i]);
    }
}

// Configuration callback on Error
void ERR1_callback(void) {
    error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
}

int ethInit(void) {
    //Ethernet konfiguracio (DHCP)
    printf("Setting up...\r\n");
    EthernetErr ethErr = eth.setup();
    IpAddr ownIP = eth.getIp();
    printf("My IP is: %d.%d.%d.%d\r\n",ownIP[0],ownIP[1],ownIP[2],ownIP[3]);
    if (ethErr) {
        printf("Error %d in Ethernet setup.\r\n", ethErr);
        return -1;
    }
    printf("Setup OK\r\n");
    return 0;
    //Ethernet konfiguracio vege
}

int udpInit(void) {
    //UDP konfiguracio
    Host rtp_addr;
    data_sock.setOnEvent(&UDPReceive);
    UDPSocketErr sockErr = data_sock.bind(Host(IpAddr(), 5004));
    printf("Ack\r\n");
    if (sockErr) {
        printf("Error %d in socket setup.\r\n", sockErr);
        return -1;
    }
    return 0;
    //UDP konfiguracio vege
}

/**UDP recv callback */
void UDPReceive(UDPSocketEvent e) {
    
    short * data_ptr;
    int i,length;
    int tmp;
    
    switch (e) {
        case UDPSOCKET_READABLE:
            Host host;
            while ( int len = data_sock.recvfrom(packet_buf, 512, &host ) ) {
                if ( len <= 0 )
                    break;
                rtp_decompose(packet_buf, len, &head, (char**)&data_ptr);
                length = head.data_len/2;
                for ( i = 0; i < length; i++ ) {
                    tmp = ntohs(data_ptr[i]); //network to host endianness
                    tmp = ((tmp + 0x7FFF) & 0xFFC0) | (DAC_POWER_MODE); //format DAC register input (signed->unsigned conversion and masking)
                    circ_buf.put( tmp ); //fill the circular buffer
                }
            }
            break;
    }
}