Mbed firmware to capture 4 mic inputs and provide data over ethernet.
Dependencies: EthernetInterface MODDMA mbed-rtos mbed
main.cpp@0:7eb08d1a4037, 2014-07-30 (annotated)
- Committer:
- Andrew Pullin
- Date:
- Wed Jul 30 14:58:05 2014 -0700
- Revision:
- 0:7eb08d1a4037
Initial commit of files
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Andrew Pullin |
0:7eb08d1a4037 | 1 | /*This code is based off of Andy Kirkham's |
Andrew Pullin |
0:7eb08d1a4037 | 2 | *work making MODDMA. |
Andrew Pullin |
0:7eb08d1a4037 | 3 | *http://mbed.org/users/AjK/code/MODDMA/ |
Andrew Pullin |
0:7eb08d1a4037 | 4 | */ |
Andrew Pullin |
0:7eb08d1a4037 | 5 | #include "mbed.h" |
Andrew Pullin |
0:7eb08d1a4037 | 6 | #include "MODDMA.h" |
Andrew Pullin |
0:7eb08d1a4037 | 7 | #include "string.h" |
Andrew Pullin |
0:7eb08d1a4037 | 8 | #include "EthernetInterface.h" |
Andrew Pullin |
0:7eb08d1a4037 | 9 | |
Andrew Pullin |
0:7eb08d1a4037 | 10 | #define SAMPLE_BUFFER_LENGTH 32 |
Andrew Pullin |
0:7eb08d1a4037 | 11 | |
Andrew Pullin |
0:7eb08d1a4037 | 12 | DigitalOut led1(LED1); |
Andrew Pullin |
0:7eb08d1a4037 | 13 | DigitalOut led2(LED2); |
Andrew Pullin |
0:7eb08d1a4037 | 14 | |
Andrew Pullin |
0:7eb08d1a4037 | 15 | MODDMA dma; |
Andrew Pullin |
0:7eb08d1a4037 | 16 | const int BROADCAST_PORT = 58083; |
Andrew Pullin |
0:7eb08d1a4037 | 17 | |
Andrew Pullin |
0:7eb08d1a4037 | 18 | // ISR set's this when transfer complete. |
Andrew Pullin |
0:7eb08d1a4037 | 19 | bool dmaTransferComplete = false; |
Andrew Pullin |
0:7eb08d1a4037 | 20 | |
Andrew Pullin |
0:7eb08d1a4037 | 21 | // Function prototypes for IRQ callbacks. |
Andrew Pullin |
0:7eb08d1a4037 | 22 | // See definitions following main() below. |
Andrew Pullin |
0:7eb08d1a4037 | 23 | void TC0_callback(void); |
Andrew Pullin |
0:7eb08d1a4037 | 24 | void ERR0_callback(void); |
Andrew Pullin |
0:7eb08d1a4037 | 25 | |
Andrew Pullin |
0:7eb08d1a4037 | 26 | int main() { |
Andrew Pullin |
0:7eb08d1a4037 | 27 | //Set up the ethernet to broadcast |
Andrew Pullin |
0:7eb08d1a4037 | 28 | EthernetInterface eth; |
Andrew Pullin |
0:7eb08d1a4037 | 29 | eth.init(); //Use DHCP |
Andrew Pullin |
0:7eb08d1a4037 | 30 | eth.connect(); |
Andrew Pullin |
0:7eb08d1a4037 | 31 | |
Andrew Pullin |
0:7eb08d1a4037 | 32 | UDPSocket sock; |
Andrew Pullin |
0:7eb08d1a4037 | 33 | sock.init(); |
Andrew Pullin |
0:7eb08d1a4037 | 34 | sock.set_broadcasting(); |
Andrew Pullin |
0:7eb08d1a4037 | 35 | |
Andrew Pullin |
0:7eb08d1a4037 | 36 | Endpoint broadcast; |
Andrew Pullin |
0:7eb08d1a4037 | 37 | broadcast.set_address("255.255.255.255", BROADCAST_PORT); |
Andrew Pullin |
0:7eb08d1a4037 | 38 | |
Andrew Pullin |
0:7eb08d1a4037 | 39 | // Create a buffer to hold the ADC samples and clear it. |
Andrew Pullin |
0:7eb08d1a4037 | 40 | // Note, we are going to sample two ADC inputs so they |
Andrew Pullin |
0:7eb08d1a4037 | 41 | // end up in this buffer "interleaved". So you will want |
Andrew Pullin |
0:7eb08d1a4037 | 42 | // a buffer twice this size to a real life given sample |
Andrew Pullin |
0:7eb08d1a4037 | 43 | // frequency. See the printf() output for details. |
Andrew Pullin |
0:7eb08d1a4037 | 44 | uint32_t adcInputBuffer[SAMPLE_BUFFER_LENGTH]; |
Andrew Pullin |
0:7eb08d1a4037 | 45 | memset(adcInputBuffer, 0, sizeof(adcInputBuffer)); |
Andrew Pullin |
0:7eb08d1a4037 | 46 | |
Andrew Pullin |
0:7eb08d1a4037 | 47 | // We use the ADC irq to trigger DMA and the manual says |
Andrew Pullin |
0:7eb08d1a4037 | 48 | // that in this case the NVIC for ADC must be disabled. |
Andrew Pullin |
0:7eb08d1a4037 | 49 | NVIC_DisableIRQ(ADC_IRQn); |
Andrew Pullin |
0:7eb08d1a4037 | 50 | |
Andrew Pullin |
0:7eb08d1a4037 | 51 | // Power up the ADC and set PCLK |
Andrew Pullin |
0:7eb08d1a4037 | 52 | LPC_SC->PCONP |= (1UL << 12); |
Andrew Pullin |
0:7eb08d1a4037 | 53 | LPC_SC->PCLKSEL0 &= ~(3UL << 24); // PCLK = CCLK/4 96M/4 = 24MHz |
Andrew Pullin |
0:7eb08d1a4037 | 54 | |
Andrew Pullin |
0:7eb08d1a4037 | 55 | // Enable the ADC, 12MHz, ADC0.0 & .1 |
Andrew Pullin |
0:7eb08d1a4037 | 56 | LPC_ADC->ADCR = (1UL << 21) | (1UL << 8) | (3UL << 0); |
Andrew Pullin |
0:7eb08d1a4037 | 57 | |
Andrew Pullin |
0:7eb08d1a4037 | 58 | // Set the pin functions to ADC |
Andrew Pullin |
0:7eb08d1a4037 | 59 | LPC_PINCON->PINSEL1 &= ~(3UL << 14); /* P0.23, Mbed p15. */ |
Andrew Pullin |
0:7eb08d1a4037 | 60 | LPC_PINCON->PINSEL1 |= (1UL << 14); |
Andrew Pullin |
0:7eb08d1a4037 | 61 | LPC_PINCON->PINSEL1 &= ~(3UL << 16); /* P0.24, Mbed p16. */ |
Andrew Pullin |
0:7eb08d1a4037 | 62 | LPC_PINCON->PINSEL1 |= (1UL << 16); |
Andrew Pullin |
0:7eb08d1a4037 | 63 | |
Andrew Pullin |
0:7eb08d1a4037 | 64 | // Prepare an ADC configuration. |
Andrew Pullin |
0:7eb08d1a4037 | 65 | MODDMA_Config *conf = new MODDMA_Config; |
Andrew Pullin |
0:7eb08d1a4037 | 66 | conf |
Andrew Pullin |
0:7eb08d1a4037 | 67 | ->channelNum ( MODDMA::Channel_0 ) |
Andrew Pullin |
0:7eb08d1a4037 | 68 | ->srcMemAddr ( 0 ) |
Andrew Pullin |
0:7eb08d1a4037 | 69 | ->dstMemAddr ( (uint32_t)adcInputBuffer ) |
Andrew Pullin |
0:7eb08d1a4037 | 70 | ->transferSize ( SAMPLE_BUFFER_LENGTH ) |
Andrew Pullin |
0:7eb08d1a4037 | 71 | ->transferType ( MODDMA::p2m ) |
Andrew Pullin |
0:7eb08d1a4037 | 72 | ->transferWidth ( MODDMA::word ) |
Andrew Pullin |
0:7eb08d1a4037 | 73 | ->srcConn ( MODDMA::ADC ) |
Andrew Pullin |
0:7eb08d1a4037 | 74 | ->dstConn ( 0 ) |
Andrew Pullin |
0:7eb08d1a4037 | 75 | ->dmaLLI ( 0 ) |
Andrew Pullin |
0:7eb08d1a4037 | 76 | ->attach_tc ( &TC0_callback ) |
Andrew Pullin |
0:7eb08d1a4037 | 77 | ->attach_err ( &ERR0_callback ) |
Andrew Pullin |
0:7eb08d1a4037 | 78 | ; // end conf. |
Andrew Pullin |
0:7eb08d1a4037 | 79 | |
Andrew Pullin |
0:7eb08d1a4037 | 80 | // Prepare configuration. |
Andrew Pullin |
0:7eb08d1a4037 | 81 | dma.Setup( conf ); |
Andrew Pullin |
0:7eb08d1a4037 | 82 | |
Andrew Pullin |
0:7eb08d1a4037 | 83 | // Enable configuration. |
Andrew Pullin |
0:7eb08d1a4037 | 84 | dma.Enable( conf ); |
Andrew Pullin |
0:7eb08d1a4037 | 85 | |
Andrew Pullin |
0:7eb08d1a4037 | 86 | // Enable ADC irq flag (to DMA). |
Andrew Pullin |
0:7eb08d1a4037 | 87 | // Note, don't set the individual flags, |
Andrew Pullin |
0:7eb08d1a4037 | 88 | // just set the global flag. |
Andrew Pullin |
0:7eb08d1a4037 | 89 | LPC_ADC->ADINTEN = 0x100; |
Andrew Pullin |
0:7eb08d1a4037 | 90 | |
Andrew Pullin |
0:7eb08d1a4037 | 91 | // Enable burst mode on inputs 0 and 1. |
Andrew Pullin |
0:7eb08d1a4037 | 92 | LPC_ADC->ADCR |= (1UL << 16); |
Andrew Pullin |
0:7eb08d1a4037 | 93 | |
Andrew Pullin |
0:7eb08d1a4037 | 94 | char out_buffer[SAMPLE_BUFFER_LENGTH]; |
Andrew Pullin |
0:7eb08d1a4037 | 95 | |
Andrew Pullin |
0:7eb08d1a4037 | 96 | while (1) { |
Andrew Pullin |
0:7eb08d1a4037 | 97 | // When transfer complete do this block. |
Andrew Pullin |
0:7eb08d1a4037 | 98 | if (dmaTransferComplete) { |
Andrew Pullin |
0:7eb08d1a4037 | 99 | delete conf; // No memory leaks, delete the configuration. |
Andrew Pullin |
0:7eb08d1a4037 | 100 | dmaTransferComplete = false; |
Andrew Pullin |
0:7eb08d1a4037 | 101 | for (int i = 0; i < SAMPLE_BUFFER_LENGTH; i++) { |
Andrew Pullin |
0:7eb08d1a4037 | 102 | //int channel = (adcInputBuffer[i] >> 24) & 0x7; |
Andrew Pullin |
0:7eb08d1a4037 | 103 | int iVal = (adcInputBuffer[i] >> 4) & 0xFFF; |
Andrew Pullin |
0:7eb08d1a4037 | 104 | double fVal = 3.3 * (double)((double)iVal) / ((double)0x1000); // scale to 0v to 3.3v |
Andrew Pullin |
0:7eb08d1a4037 | 105 | memcpy(&out_buffer,&fVal,sizeof(fVal)); |
Andrew Pullin |
0:7eb08d1a4037 | 106 | } |
Andrew Pullin |
0:7eb08d1a4037 | 107 | } |
Andrew Pullin |
0:7eb08d1a4037 | 108 | sock.sendTo(broadcast, out_buffer, sizeof(out_buffer)); |
Andrew Pullin |
0:7eb08d1a4037 | 109 | wait(0.25); |
Andrew Pullin |
0:7eb08d1a4037 | 110 | } |
Andrew Pullin |
0:7eb08d1a4037 | 111 | } |
Andrew Pullin |
0:7eb08d1a4037 | 112 | |
Andrew Pullin |
0:7eb08d1a4037 | 113 | // Configuration callback on TC |
Andrew Pullin |
0:7eb08d1a4037 | 114 | void TC0_callback(void) { |
Andrew Pullin |
0:7eb08d1a4037 | 115 | |
Andrew Pullin |
0:7eb08d1a4037 | 116 | MODDMA_Config *config = dma.getConfig(); |
Andrew Pullin |
0:7eb08d1a4037 | 117 | |
Andrew Pullin |
0:7eb08d1a4037 | 118 | // Disbale burst mode and switch off the IRQ flag. |
Andrew Pullin |
0:7eb08d1a4037 | 119 | LPC_ADC->ADCR &= ~(1UL << 16); |
Andrew Pullin |
0:7eb08d1a4037 | 120 | LPC_ADC->ADINTEN = 0; |
Andrew Pullin |
0:7eb08d1a4037 | 121 | |
Andrew Pullin |
0:7eb08d1a4037 | 122 | // Finish the DMA cycle by shutting down the channel. |
Andrew Pullin |
0:7eb08d1a4037 | 123 | dma.haltAndWaitChannelComplete( (MODDMA::CHANNELS)config->channelNum()); |
Andrew Pullin |
0:7eb08d1a4037 | 124 | dma.Disable( (MODDMA::CHANNELS)config->channelNum() ); |
Andrew Pullin |
0:7eb08d1a4037 | 125 | |
Andrew Pullin |
0:7eb08d1a4037 | 126 | // Tell main() while(1) loop to print the results. |
Andrew Pullin |
0:7eb08d1a4037 | 127 | dmaTransferComplete = true; |
Andrew Pullin |
0:7eb08d1a4037 | 128 | |
Andrew Pullin |
0:7eb08d1a4037 | 129 | // Switch on LED2 to show transfer complete. |
Andrew Pullin |
0:7eb08d1a4037 | 130 | led2 = 1; |
Andrew Pullin |
0:7eb08d1a4037 | 131 | |
Andrew Pullin |
0:7eb08d1a4037 | 132 | // Clear DMA IRQ flags. |
Andrew Pullin |
0:7eb08d1a4037 | 133 | if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); |
Andrew Pullin |
0:7eb08d1a4037 | 134 | if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq(); |
Andrew Pullin |
0:7eb08d1a4037 | 135 | } |
Andrew Pullin |
0:7eb08d1a4037 | 136 | |
Andrew Pullin |
0:7eb08d1a4037 | 137 | // Configuration callback on Error |
Andrew Pullin |
0:7eb08d1a4037 | 138 | void ERR0_callback(void) { |
Andrew Pullin |
0:7eb08d1a4037 | 139 | // Switch off burst conversions. |
Andrew Pullin |
0:7eb08d1a4037 | 140 | LPC_ADC->ADCR |= ~(1UL << 16); |
Andrew Pullin |
0:7eb08d1a4037 | 141 | LPC_ADC->ADINTEN = 0; |
Andrew Pullin |
0:7eb08d1a4037 | 142 | error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem"); |
Andrew Pullin |
0:7eb08d1a4037 | 143 | } |