DSP program for the Surfboard hardware (PCB to be open sourced) http://www.avbotz.com/ourauv/electrical/signal-processing/

Dependencies:   MODDMA SimpleIOMacros mbed-dsp mbed

Committer:
avbotz
Date:
Fri Aug 02 02:25:12 2013 +0000
Revision:
1:f69ec4c889ff
Parent:
0:2381a319fc35
Initial commit. Not working. MODDMA makes DMA setup slow, and the mbed SPI peripheral corrupts data sometimes. I will write my own SPI and DMA classes and see how it goes.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
avbotz 0:2381a319fc35 1 #include "dma.h"
avbotz 0:2381a319fc35 2
avbotz 0:2381a319fc35 3 DigitalOut test5(p5);
avbotz 0:2381a319fc35 4 DigitalOut test6(p6);
avbotz 0:2381a319fc35 5 DigitalOut test(p7);
avbotz 0:2381a319fc35 6
avbotz 0:2381a319fc35 7 char buf[NUM_CHANNELS * 3]; // 3 bytes per sample
avbotz 0:2381a319fc35 8 char dummy_buf[sizeof(buf) / sizeof(char)];
avbotz 0:2381a319fc35 9
avbotz 0:2381a319fc35 10 SPI ads1274(/*mosi, unconnected*/ p11, /*miso, dout*/ p12, /*sclk*/ p13);
avbotz 0:2381a319fc35 11
avbotz 0:2381a319fc35 12 MODDMA_Cache dma;
avbotz 0:2381a319fc35 13 MODDMA_Config* dma_conf = new MODDMA_Config;
avbotz 0:2381a319fc35 14 MODDMA_Config* sclk_dummy_conf = new MODDMA_Config;
avbotz 0:2381a319fc35 15
avbotz 0:2381a319fc35 16 //q15_t parsed[2][NUM_CHANNELS][BLOCK_SIZE];
avbotz 0:2381a319fc35 17 char parsed[2][NUM_CHANNELS][BLOCK_SIZE][3];
avbotz 0:2381a319fc35 18
avbotz 0:2381a319fc35 19
avbotz 0:2381a319fc35 20 char write_block = 0;
avbotz 0:2381a319fc35 21 int buf_index = 0;
avbotz 0:2381a319fc35 22 unsigned int read_blocks = 0;
avbotz 0:2381a319fc35 23
avbotz 0:2381a319fc35 24 extern bool fresh_data;
avbotz 0:2381a319fc35 25
avbotz 0:2381a319fc35 26 int setup_dma()
avbotz 0:2381a319fc35 27 {
avbotz 0:2381a319fc35 28 ads1274.frequency(12 * 1000000); // Theoretical minimum 9.6MHz
avbotz 0:2381a319fc35 29 ads1274.format(8, 3); // clock polarity cpol = 1; clock phase cpha = 1
avbotz 0:2381a319fc35 30
avbotz 0:2381a319fc35 31 memset(buf, 0, sizeof(buf));
avbotz 0:2381a319fc35 32 // stolen from moddma example 2
avbotz 0:2381a319fc35 33 dma_conf
avbotz 0:2381a319fc35 34 ->channelNum ( MODDMA::Channel_1 )
avbotz 0:2381a319fc35 35 ->srcMemAddr ( 0 )
avbotz 0:2381a319fc35 36 ->dstMemAddr ( (uint32_t)buf )
avbotz 0:2381a319fc35 37 ->transferSize ( sizeof(buf) )
avbotz 0:2381a319fc35 38 ->transferType ( MODDMA::p2m )
avbotz 0:2381a319fc35 39 ->transferWidth ( MODDMA::word ) // 4 bytes at a time
avbotz 0:2381a319fc35 40 ->srcConn ( MODDMA::SSP0_Rx ) // SSP0: pins 11-13. SSP1: pins 5-7.
avbotz 0:2381a319fc35 41 ->dstConn ( 0 )
avbotz 0:2381a319fc35 42 ->dmaLLI ( 0 )
avbotz 0:2381a319fc35 43 ->attach_tc ( &parse_data ) // called when transferSize is reached
avbotz 0:2381a319fc35 44 ->attach_err ( &dma_error_cb )
avbotz 0:2381a319fc35 45 ;
avbotz 0:2381a319fc35 46 dma.Setup(dma_conf);
avbotz 0:2381a319fc35 47
avbotz 0:2381a319fc35 48 memset(dummy_buf, 0x55, sizeof(dummy_buf));
avbotz 0:2381a319fc35 49 dummy_buf[sizeof(dummy_buf) - 1] = '\0';
avbotz 0:2381a319fc35 50 sclk_dummy_conf
avbotz 0:2381a319fc35 51 ->channelNum ( MODDMA::Channel_0 ) // make this one the highest priority DMA
avbotz 0:2381a319fc35 52 ->srcMemAddr ( (uint32_t)dummy_buf )
avbotz 0:2381a319fc35 53 ->dstMemAddr ( 0 )
avbotz 0:2381a319fc35 54 ->transferSize ( sizeof(dummy_buf) )
avbotz 0:2381a319fc35 55 ->transferType ( MODDMA::m2p )
avbotz 0:2381a319fc35 56 ->transferWidth ( MODDMA::word ) // 4 bytes at a time
avbotz 0:2381a319fc35 57 ->srcConn ( 0 )
avbotz 0:2381a319fc35 58 ->dstConn ( MODDMA::SSP0_Tx ) // SSP0: pins 11-13. SSP1: pins 5-7.
avbotz 0:2381a319fc35 59 ->dmaLLI ( 0 )
avbotz 0:2381a319fc35 60 ->attach_tc ( 0 ) // called when transferSize is reached
avbotz 0:2381a319fc35 61 ->attach_err ( &dma_error_cb )
avbotz 0:2381a319fc35 62 ;
avbotz 0:2381a319fc35 63 dma.Setup(sclk_dummy_conf);
avbotz 0:2381a319fc35 64
avbotz 0:2381a319fc35 65 return 0; // success
avbotz 0:2381a319fc35 66 }
avbotz 0:2381a319fc35 67
avbotz 0:2381a319fc35 68 void teardown_dma()
avbotz 0:2381a319fc35 69 {
avbotz 0:2381a319fc35 70
avbotz 0:2381a319fc35 71 }
avbotz 0:2381a319fc35 72
avbotz 0:2381a319fc35 73 // Stolen from Andy Kirkham http://mbed.org/forum/mbed/topic/2326/
avbotz 0:2381a319fc35 74
avbotz 0:2381a319fc35 75 // "One last piece of advice...You have to be careful when you start doing 'neat things' directly with the peripherals to ensure you don't break other things that previously worked fine."
avbotz 0:2381a319fc35 76 // -- ANdy Kirkham, aka Daniel Naito in 20 years
avbotz 0:2381a319fc35 77 /** EINT3_IRQHandler
avbotz 0:2381a319fc35 78 */
avbotz 0:2381a319fc35 79 extern "C" void EINT3_IRQHandler()
avbotz 0:2381a319fc35 80 {
avbotz 0:2381a319fc35 81
avbotz 0:2381a319fc35 82 // The "event" is connected to pin p8 which is LPC1768 P0_6 so lets trap
avbotz 0:2381a319fc35 83 // that and ignore all other GPIO interrupts.
avbotz 0:2381a319fc35 84 // Test for IRQ on Port0.
avbotz 0:2381a319fc35 85 if (LPC_GPIOINT->IntStatus & 0x1)
avbotz 0:2381a319fc35 86 {
avbotz 0:2381a319fc35 87 // If P0_6/p8 rises, call get_data()
avbotz 0:2381a319fc35 88 // The "R" means we're looking for the rising edge
avbotz 0:2381a319fc35 89 if (LPC_GPIOINT->IO0IntStatR & (1 << 6))
avbotz 0:2381a319fc35 90 {
avbotz 0:2381a319fc35 91 // We found what we're looking for
avbotz 0:2381a319fc35 92 get_data();
avbotz 0:2381a319fc35 93 }
avbotz 0:2381a319fc35 94 }
avbotz 0:2381a319fc35 95
avbotz 0:2381a319fc35 96 // Clear all possible GPIO-generated interrupts as they don't concern us.
avbotz 0:2381a319fc35 97 // Once we process the interrupt, we wipe out this interrupt and all the others
avbotz 0:2381a319fc35 98 //LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
avbotz 0:2381a319fc35 99 //LPC_GPIOINT->IO0IntClr = (LPC_GPIOINT->IO0IntStatR | LPC_GPIOINT->IO0IntStatF);
avbotz 0:2381a319fc35 100
avbotz 0:2381a319fc35 101 // Clear only this interrupt
avbotz 0:2381a319fc35 102 LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO0IntStatR & (1 << 6);
avbotz 0:2381a319fc35 103 }
avbotz 0:2381a319fc35 104
avbotz 0:2381a319fc35 105 void event_irq_init()
avbotz 0:2381a319fc35 106 {
avbotz 0:2381a319fc35 107 // Use macro to set p8 as an input.
avbotz 0:2381a319fc35 108 p8_AS_INPUT;
avbotz 0:2381a319fc35 109 // Enable P0_6/p8 for rising edge interrupt generation.
avbotz 0:2381a319fc35 110 LPC_GPIOINT->IO0IntEnR |= (1UL << 6); //hope this works
avbotz 0:2381a319fc35 111 // Enable the interrupt.
avbotz 0:2381a319fc35 112 NVIC_SetVector(EINT3_IRQn, (uint32_t)EINT3_IRQHandler);
avbotz 0:2381a319fc35 113 NVIC_EnableIRQ(EINT3_IRQn);
avbotz 0:2381a319fc35 114 }
avbotz 0:2381a319fc35 115
avbotz 0:2381a319fc35 116 void dma_error_cb()
avbotz 0:2381a319fc35 117 {
avbotz 0:2381a319fc35 118
avbotz 0:2381a319fc35 119 }
avbotz 0:2381a319fc35 120
avbotz 0:2381a319fc35 121 // 6.80 us
avbotz 0:2381a319fc35 122 inline void get_data()
avbotz 0:2381a319fc35 123 {
avbotz 0:2381a319fc35 124 // Need to wait 4 mbed clock cycles here. Callback overhead (about 1.2 us) is more than enough.
avbotz 0:2381a319fc35 125
avbotz 0:2381a319fc35 126 p7_TOGGLE;
avbotz 0:2381a319fc35 127 #define USE_RESET
avbotz 0:2381a319fc35 128
avbotz 0:2381a319fc35 129 #ifndef USE_RESET
avbotz 0:2381a319fc35 130 dma.Setup(dma_conf);
avbotz 0:2381a319fc35 131 dma.Setup(sclk_dummy_conf);
avbotz 0:2381a319fc35 132 #else
avbotz 0:2381a319fc35 133 dma.Reset(dma_conf);
avbotz 0:2381a319fc35 134 dma.Reset(sclk_dummy_conf);
avbotz 0:2381a319fc35 135 #endif
avbotz 0:2381a319fc35 136
avbotz 0:2381a319fc35 137 dma.Enable(sclk_dummy_conf);
avbotz 0:2381a319fc35 138 dma.Enable(dma_conf);
avbotz 0:2381a319fc35 139
avbotz 0:2381a319fc35 140 // enable ssp0 fifo. Seems to be required for DMA to work.
avbotz 0:2381a319fc35 141 LPC_SSP0->DMACR = 0x3;
avbotz 0:2381a319fc35 142 //wait_ms(10);
avbotz 0:2381a319fc35 143 //fresh_data = true;
avbotz 0:2381a319fc35 144
avbotz 0:2381a319fc35 145 /*
avbotz 0:2381a319fc35 146 for (int i = 0; i < sizeof(buf)/sizeof(char); i++)
avbotz 0:2381a319fc35 147 {
avbotz 0:2381a319fc35 148 buf[i] = ads1274.write(0);
avbotz 0:2381a319fc35 149 }
avbotz 0:2381a319fc35 150 parse_data();
avbotz 0:2381a319fc35 151 */
avbotz 0:2381a319fc35 152
avbotz 0:2381a319fc35 153 if (led2num > TARGET_SPS)
avbotz 0:2381a319fc35 154 {
avbotz 0:2381a319fc35 155 LED2_TOGGLE;
avbotz 0:2381a319fc35 156 led2num = 0;
avbotz 0:2381a319fc35 157 }
avbotz 0:2381a319fc35 158 else
avbotz 0:2381a319fc35 159 {
avbotz 0:2381a319fc35 160 led2num++;
avbotz 0:2381a319fc35 161 }
avbotz 0:2381a319fc35 162
avbotz 0:2381a319fc35 163 p7_TOGGLE;
avbotz 0:2381a319fc35 164 }
avbotz 0:2381a319fc35 165
avbotz 0:2381a319fc35 166 // 310 ns
avbotz 0:2381a319fc35 167 inline void parse_data()
avbotz 0:2381a319fc35 168 {
avbotz 0:2381a319fc35 169 p5_TOGGLE;
avbotz 0:2381a319fc35 170 // Assumes a little-endian CPU. Intel is always little-endian. ARM is
avbotz 0:2381a319fc35 171 // configurable, but the LPC1768 is little-endian.
avbotz 0:2381a319fc35 172 // We flip the byte order because the ADS1274 is big-endian. Also throw out
avbotz 0:2381a319fc35 173 // the least significant byte for speed.
avbotz 0:2381a319fc35 174 /*
avbotz 0:2381a319fc35 175 parsed[write_block][0][buf_index] = buf[ 5] | (((uint16_t)buf[4]) << 8);
avbotz 0:2381a319fc35 176 parsed[write_block][1][buf_index] = buf[ 9] | (((uint16_t)buf[8]) << 8);
avbotz 0:2381a319fc35 177 parsed[write_block][2][buf_index] = buf[ 12] | (((uint16_t)buf[11]) << 8);
avbotz 0:2381a319fc35 178 parsed[write_block][3][buf_index] = buf[ 15] | (((uint16_t)buf[14]) << 8);
avbotz 0:2381a319fc35 179 */
avbotz 0:2381a319fc35 180 for (int i = 0; i < NUM_CHANNELS; i++)
avbotz 0:2381a319fc35 181 {
avbotz 0:2381a319fc35 182 for (int j = 0; j < 3; j++)
avbotz 0:2381a319fc35 183 {
avbotz 0:2381a319fc35 184 parsed[write_block][i][buf_index][j] = buf[3*i+j];
avbotz 0:2381a319fc35 185 }
avbotz 0:2381a319fc35 186 }
avbotz 0:2381a319fc35 187
avbotz 0:2381a319fc35 188
avbotz 0:2381a319fc35 189 /*
avbotz 0:2381a319fc35 190 if (buf_index > 100)
avbotz 0:2381a319fc35 191 {
avbotz 0:2381a319fc35 192 for (int i = 0; i < NUM_CHANNELS*3; i++)
avbotz 0:2381a319fc35 193 {
avbotz 0:2381a319fc35 194 submarine.printf("%02x ", buf[i]);
avbotz 0:2381a319fc35 195 }
avbotz 0:2381a319fc35 196 while (true);
avbotz 0:2381a319fc35 197 }
avbotz 0:2381a319fc35 198 */
avbotz 0:2381a319fc35 199 bool valid = (parsed[write_block][0][buf_index] != 0);
avbotz 0:2381a319fc35 200
avbotz 0:2381a319fc35 201 buf_index++;
avbotz 0:2381a319fc35 202
avbotz 0:2381a319fc35 203 if (buf_index == BLOCK_SIZE)
avbotz 0:2381a319fc35 204 {
avbotz 0:2381a319fc35 205 fresh_data = true;
avbotz 0:2381a319fc35 206 // Switch to the other half of this buffer.
avbotz 0:2381a319fc35 207 write_block ^= 0x1; //toggle the last bit
avbotz 0:2381a319fc35 208 read_blocks++;
avbotz 0:2381a319fc35 209 buf_index = 0;
avbotz 0:2381a319fc35 210 }
avbotz 0:2381a319fc35 211 if (valid){
avbotz 0:2381a319fc35 212 if (led3num > TARGET_SPS)
avbotz 0:2381a319fc35 213 {
avbotz 0:2381a319fc35 214 LED3_TOGGLE;
avbotz 0:2381a319fc35 215 led3num = 0;
avbotz 0:2381a319fc35 216 }
avbotz 0:2381a319fc35 217 else
avbotz 0:2381a319fc35 218 {
avbotz 0:2381a319fc35 219 led3num++;
avbotz 0:2381a319fc35 220 }}
avbotz 0:2381a319fc35 221 p5_TOGGLE;
avbotz 0:2381a319fc35 222 }