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
dma.cpp
00001 #include "dma.h" 00002 00003 DigitalOut test5(p5); 00004 DigitalOut test6(p6); 00005 DigitalOut test(p7); 00006 00007 char buf[NUM_CHANNELS * 3]; // 3 bytes per sample 00008 char dummy_buf[sizeof(buf) / sizeof(char)]; 00009 00010 SPI ads1274(/*mosi, unconnected*/ p11, /*miso, dout*/ p12, /*sclk*/ p13); 00011 00012 MODDMA_Cache dma; 00013 MODDMA_Config* dma_conf = new MODDMA_Config; 00014 MODDMA_Config* sclk_dummy_conf = new MODDMA_Config; 00015 00016 //q15_t parsed[2][NUM_CHANNELS][BLOCK_SIZE]; 00017 char parsed[2][NUM_CHANNELS][BLOCK_SIZE][3]; 00018 00019 00020 char write_block = 0; 00021 int buf_index = 0; 00022 unsigned int read_blocks = 0; 00023 00024 extern bool fresh_data; 00025 00026 int setup_dma() 00027 { 00028 ads1274.frequency(12 * 1000000); // Theoretical minimum 9.6MHz 00029 ads1274.format(8, 3); // clock polarity cpol = 1; clock phase cpha = 1 00030 00031 memset(buf, 0, sizeof(buf)); 00032 // stolen from moddma example 2 00033 dma_conf 00034 ->channelNum ( MODDMA::Channel_1 ) 00035 ->srcMemAddr ( 0 ) 00036 ->dstMemAddr ( (uint32_t)buf ) 00037 ->transferSize ( sizeof(buf) ) 00038 ->transferType ( MODDMA::p2m ) 00039 ->transferWidth ( MODDMA::word ) // 4 bytes at a time 00040 ->srcConn ( MODDMA::SSP0_Rx ) // SSP0: pins 11-13. SSP1: pins 5-7. 00041 ->dstConn ( 0 ) 00042 ->dmaLLI ( 0 ) 00043 ->attach_tc ( &parse_data ) // called when transferSize is reached 00044 ->attach_err ( &dma_error_cb ) 00045 ; 00046 dma.Setup(dma_conf); 00047 00048 memset(dummy_buf, 0x55, sizeof(dummy_buf)); 00049 dummy_buf[sizeof(dummy_buf) - 1] = '\0'; 00050 sclk_dummy_conf 00051 ->channelNum ( MODDMA::Channel_0 ) // make this one the highest priority DMA 00052 ->srcMemAddr ( (uint32_t)dummy_buf ) 00053 ->dstMemAddr ( 0 ) 00054 ->transferSize ( sizeof(dummy_buf) ) 00055 ->transferType ( MODDMA::m2p ) 00056 ->transferWidth ( MODDMA::word ) // 4 bytes at a time 00057 ->srcConn ( 0 ) 00058 ->dstConn ( MODDMA::SSP0_Tx ) // SSP0: pins 11-13. SSP1: pins 5-7. 00059 ->dmaLLI ( 0 ) 00060 ->attach_tc ( 0 ) // called when transferSize is reached 00061 ->attach_err ( &dma_error_cb ) 00062 ; 00063 dma.Setup(sclk_dummy_conf); 00064 00065 return 0; // success 00066 } 00067 00068 void teardown_dma() 00069 { 00070 00071 } 00072 00073 // Stolen from Andy Kirkham http://mbed.org/forum/mbed/topic/2326/ 00074 00075 // "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." 00076 // -- ANdy Kirkham, aka Daniel Naito in 20 years 00077 /** EINT3_IRQHandler 00078 */ 00079 extern "C" void EINT3_IRQHandler() 00080 { 00081 00082 // The "event" is connected to pin p8 which is LPC1768 P0_6 so lets trap 00083 // that and ignore all other GPIO interrupts. 00084 // Test for IRQ on Port0. 00085 if (LPC_GPIOINT->IntStatus & 0x1) 00086 { 00087 // If P0_6/p8 rises, call get_data() 00088 // The "R" means we're looking for the rising edge 00089 if (LPC_GPIOINT->IO0IntStatR & (1 << 6)) 00090 { 00091 // We found what we're looking for 00092 get_data(); 00093 } 00094 } 00095 00096 // Clear all possible GPIO-generated interrupts as they don't concern us. 00097 // Once we process the interrupt, we wipe out this interrupt and all the others 00098 //LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF); 00099 //LPC_GPIOINT->IO0IntClr = (LPC_GPIOINT->IO0IntStatR | LPC_GPIOINT->IO0IntStatF); 00100 00101 // Clear only this interrupt 00102 LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO0IntStatR & (1 << 6); 00103 } 00104 00105 void event_irq_init() 00106 { 00107 // Use macro to set p8 as an input. 00108 p8_AS_INPUT; 00109 // Enable P0_6/p8 for rising edge interrupt generation. 00110 LPC_GPIOINT->IO0IntEnR |= (1UL << 6); //hope this works 00111 // Enable the interrupt. 00112 NVIC_SetVector(EINT3_IRQn, (uint32_t)EINT3_IRQHandler); 00113 NVIC_EnableIRQ(EINT3_IRQn); 00114 } 00115 00116 void dma_error_cb() 00117 { 00118 00119 } 00120 00121 // 6.80 us 00122 inline void get_data() 00123 { 00124 // Need to wait 4 mbed clock cycles here. Callback overhead (about 1.2 us) is more than enough. 00125 00126 p7_TOGGLE; 00127 #define USE_RESET 00128 00129 #ifndef USE_RESET 00130 dma.Setup(dma_conf); 00131 dma.Setup(sclk_dummy_conf); 00132 #else 00133 dma.Reset(dma_conf); 00134 dma.Reset(sclk_dummy_conf); 00135 #endif 00136 00137 dma.Enable(sclk_dummy_conf); 00138 dma.Enable(dma_conf); 00139 00140 // enable ssp0 fifo. Seems to be required for DMA to work. 00141 LPC_SSP0->DMACR = 0x3; 00142 //wait_ms(10); 00143 //fresh_data = true; 00144 00145 /* 00146 for (int i = 0; i < sizeof(buf)/sizeof(char); i++) 00147 { 00148 buf[i] = ads1274.write(0); 00149 } 00150 parse_data(); 00151 */ 00152 00153 if (led2num > TARGET_SPS) 00154 { 00155 LED2_TOGGLE; 00156 led2num = 0; 00157 } 00158 else 00159 { 00160 led2num++; 00161 } 00162 00163 p7_TOGGLE; 00164 } 00165 00166 // 310 ns 00167 inline void parse_data() 00168 { 00169 p5_TOGGLE; 00170 // Assumes a little-endian CPU. Intel is always little-endian. ARM is 00171 // configurable, but the LPC1768 is little-endian. 00172 // We flip the byte order because the ADS1274 is big-endian. Also throw out 00173 // the least significant byte for speed. 00174 /* 00175 parsed[write_block][0][buf_index] = buf[ 5] | (((uint16_t)buf[4]) << 8); 00176 parsed[write_block][1][buf_index] = buf[ 9] | (((uint16_t)buf[8]) << 8); 00177 parsed[write_block][2][buf_index] = buf[ 12] | (((uint16_t)buf[11]) << 8); 00178 parsed[write_block][3][buf_index] = buf[ 15] | (((uint16_t)buf[14]) << 8); 00179 */ 00180 for (int i = 0; i < NUM_CHANNELS; i++) 00181 { 00182 for (int j = 0; j < 3; j++) 00183 { 00184 parsed[write_block][i][buf_index][j] = buf[3*i+j]; 00185 } 00186 } 00187 00188 00189 /* 00190 if (buf_index > 100) 00191 { 00192 for (int i = 0; i < NUM_CHANNELS*3; i++) 00193 { 00194 submarine.printf("%02x ", buf[i]); 00195 } 00196 while (true); 00197 } 00198 */ 00199 bool valid = (parsed[write_block][0][buf_index] != 0); 00200 00201 buf_index++; 00202 00203 if (buf_index == BLOCK_SIZE) 00204 { 00205 fresh_data = true; 00206 // Switch to the other half of this buffer. 00207 write_block ^= 0x1; //toggle the last bit 00208 read_blocks++; 00209 buf_index = 0; 00210 } 00211 if (valid){ 00212 if (led3num > TARGET_SPS) 00213 { 00214 LED3_TOGGLE; 00215 led3num = 0; 00216 } 00217 else 00218 { 00219 led3num++; 00220 }} 00221 p5_TOGGLE; 00222 }
Generated on Tue Jul 12 2022 21:48:58 by 1.7.2