Mercurial > hg > beaglert
comparison pru_rtaudio.p @ 67:472e892c6e41
Merge newapi into default
author | Andrew McPherson <a.mcpherson@qmul.ac.uk> |
---|---|
date | Fri, 17 Jul 2015 15:28:18 +0100 |
parents | 0d80ff9e2227 579c86316008 |
children | b697e82ebb25 |
comparison
equal
deleted
inserted
replaced
21:0d80ff9e2227 | 67:472e892c6e41 |
---|---|
29 #define GPIO0 0x44E07000 | 29 #define GPIO0 0x44E07000 |
30 #define GPIO1 0x4804C000 | 30 #define GPIO1 0x4804C000 |
31 #define GPIO_CLEARDATAOUT 0x190 | 31 #define GPIO_CLEARDATAOUT 0x190 |
32 #define GPIO_SETDATAOUT 0x194 | 32 #define GPIO_SETDATAOUT 0x194 |
33 | 33 |
34 #define PRU0_ARM_INTERRUPT 19 | 34 #define PRU0_ARM_INTERRUPT 19 // Interrupt signalling we're done |
35 #define PRU1_ARM_INTERRUPT 20 // Interrupt signalling a block is ready | |
35 | 36 |
36 #define C_ADC_DAC_MEM C24 // PRU0 mem | 37 #define C_ADC_DAC_MEM C24 // PRU0 mem |
37 #ifdef DBOX_CAPE | 38 #ifdef DBOX_CAPE |
38 #define DAC_GPIO GPIO0 | 39 #define DAC_GPIO GPIO0 |
39 #define DAC_CS_PIN (1<<5) // GPIO0:5 = P9 pin 17 | 40 #define DAC_CS_PIN (1<<5) // GPIO0:5 = P9 pin 17 |
79 #define COMM_LED_ADDRESS 24 // Which memory address to find the status LED on | 80 #define COMM_LED_ADDRESS 24 // Which memory address to find the status LED on |
80 #define COMM_LED_PIN_MASK 28 // Which pin to write to change LED | 81 #define COMM_LED_PIN_MASK 28 // Which pin to write to change LED |
81 #define COMM_FRAME_COUNT 32 // How many frames have elapse since beginning | 82 #define COMM_FRAME_COUNT 32 // How many frames have elapse since beginning |
82 #define COMM_USE_SPI 36 // Whether or not to use SPI ADC and DAC | 83 #define COMM_USE_SPI 36 // Whether or not to use SPI ADC and DAC |
83 #define COMM_NUM_CHANNELS 40 // Low 2 bits indicate 8 [0x3], 4 [0x1] or 2 [0x0] channels | 84 #define COMM_NUM_CHANNELS 40 // Low 2 bits indicate 8 [0x3], 4 [0x1] or 2 [0x0] channels |
84 | 85 #define COMM_USE_DIGITAL 44 // Whether or not to use DIGITAL |
86 | |
85 #define MCASP0_BASE 0x48038000 | 87 #define MCASP0_BASE 0x48038000 |
86 #define MCASP1_BASE 0x4803C000 | 88 #define MCASP1_BASE 0x4803C000 |
87 | 89 |
88 #define MCASP_PWRIDLESYSCONFIG 0x04 | 90 #define MCASP_PWRIDLESYSCONFIG 0x04 |
89 #define MCASP_PFUNC 0x10 | 91 #define MCASP_PFUNC 0x10 |
178 | 180 |
179 // Flags for the flags register | 181 // Flags for the flags register |
180 #define FLAG_BIT_BUFFER1 0 | 182 #define FLAG_BIT_BUFFER1 0 |
181 #define FLAG_BIT_USE_SPI 1 | 183 #define FLAG_BIT_USE_SPI 1 |
182 #define FLAG_BIT_MCASP_HWORD 2 // Whether we are on the high word for McASP transmission | 184 #define FLAG_BIT_MCASP_HWORD 2 // Whether we are on the high word for McASP transmission |
183 | 185 #define FLAG_BIT_USE_DIGITAL 3 |
184 // Registers used throughout | 186 // Registers used throughout |
185 | 187 |
186 // r1, r2, r3 are used for temporary storage | 188 // r1, r2, r3 are used for temporary storage |
189 #define MEM_DIGITAL_BASE 0x11000 //Base address for DIGITAL : Shared RAM + 0x400 | |
190 #define MEM_DIGITAL_BUFFER1_OFFSET 0x400 //Start pointer to DIGITAL_BUFFER1, which is 256 words after. | |
191 // 256 is the maximum number of frames allowed | |
192 | |
193 #define reg_digital_current r6 // Pointer to current storage location of DIGITAL | |
187 #define reg_num_channels r9 // Number of SPI ADC/DAC channels to use | 194 #define reg_num_channels r9 // Number of SPI ADC/DAC channels to use |
188 #define reg_frame_current r10 // Current frame count in SPI ADC/DAC transfer | 195 #define reg_frame_current r10 // Current frame count in SPI ADC/DAC transfer |
189 #define reg_frame_total r11 // Total frame count for SPI ADC/DAC | 196 #define reg_frame_total r11 // Total frame count for SPI ADC/DAC |
190 #define reg_dac_data r12 // Current dword for SPI DAC | 197 #define reg_dac_data r12 // Current dword for SPI DAC |
191 #define reg_adc_data r13 // Current dword for SPI ADC | 198 #define reg_adc_data r13 // Current dword for SPI ADC |
203 #define reg_comm_addr r25 // Memory address for communicating with ARM | 210 #define reg_comm_addr r25 // Memory address for communicating with ARM |
204 #define reg_spi_addr r26 // Base address for SPI | 211 #define reg_spi_addr r26 // Base address for SPI |
205 // r27, r28 used in macros | 212 // r27, r28 used in macros |
206 #define reg_mcasp_addr r29 // Base address for McASP | 213 #define reg_mcasp_addr r29 // Base address for McASP |
207 | 214 |
208 // Convert float to 16-bit int, multiplying by 32768 | 215 //0 P8_07 36 0x890/090 66 gpio2[2] |
209 // Converts -1.0 to 1.0 to a full 16-bit range | 216 //1 P8_08 37 0x894/094 67 gpio2[3] |
210 // input and output can safely be the same register | 217 //2 P8_09 39 0x89c/09c 69 gpio2[5] |
211 .macro FLOAT_TO_INT16 | 218 //3 P8_10 38 0x898/098 68 gpio2[4] |
212 .mparam input, output | 219 //4 P8_11 13 0x834/034 45 gpio1[13] |
213 // int exponent = ((input >> 23) & 0xFF) | 220 //5 P8_12 12 0x830/030 44 gpio1[12] |
214 LSR r27, input, 23 // exponent goes in r27 | 221 //6 P9_12 30 0x878/078 60 gpio1[28] |
215 AND r27, r27, 0xFF | 222 //7 P9_14 18 0x848/048 50 gpio1[18] |
216 | 223 //8 P8_15 15 0x83c/03c 47 gpio1[15] |
217 // Actual exponent is 127 less than the above; below -15 we | 224 //9 P8_16 14 0x838/038 46 gpio1[14] |
218 // should return 0. So check if it is less than 112. | 225 //10 P9_16 19 0x84c/04c 51 gpio1[19] |
219 QBLE EXPONENT_GREQ_MINUS15, r27, 112 | 226 //11 P8_18 35 0x88c/08c 65 gpio2[1] |
220 LDI output, 0 | 227 //12 P8_27 56 0x8e0/0e0 86 gpio2[22] |
221 QBA FLOAT_TO_INT16_DONE | 228 //13 P8_28 58 0x8e8/0e8 88 gpio2[24] |
222 EXPONENT_GREQ_MINUS15: | 229 //14 P8_29 57 0x8e4/0e4 87 gpio2[23] |
223 | 230 //15 P8_30 59 0x8ec/0ec 89 gpio2[25] |
224 // Next check if exponent is greater than or equal to 0 (i.e. | 231 |
225 // 127 in our adjusted version. If so we return the max. | 232 //generic GPIOs constants |
226 QBGT EXPONENT_LT_ZERO, r27, 127 | 233 //#define GPIO1 0x4804c000 |
227 QBBS NEGATIVE_MAX, input, 31 // Is sign negative? | 234 #define GPIO2 0x481ac000 |
228 LDI output, 32767 // Max positive value | 235 //#define GPIO_CLEARDATAOUT 0x190 //SETDATAOUT is CLEARDATAOUT+4 |
229 QBA FLOAT_TO_INT16_DONE | 236 #define GPIO_OE 0x134 |
230 NEGATIVE_MAX: | 237 #define GPIO_DATAIN 0x138 |
231 LDI output, 32768 // Actually will be -32768 in signed | 238 |
232 QBA FLOAT_TO_INT16_DONE | 239 .macro READ_GPIO_BITS |
233 EXPONENT_LT_ZERO: | 240 .mparam gpio_data, gpio_num_bit, digital_bit, digital |
234 | 241 QBBC DONE, digital, digital_bit //if the pin is set as an output, nothing to do here |
235 // Mask out the mantissa and shift | 242 QBBC CLEAR, gpio_data, gpio_num_bit |
236 // int mantissa = (input & 0x7FFFFF) | (1 << 23) | 243 SET digital, digital_bit+16 |
237 MOV r28, 0x007FFFFF | 244 QBA DONE |
238 AND r28, r28, input | 245 CLEAR: |
239 SET r28, 23 | 246 CLR digital, digital_bit+16 |
240 | 247 QBA DONE |
241 // Shift right by -(exponent - 127 - 8) to produce an int | 248 DONE: |
242 // after effectively multiplying by 2^15 | 249 .endm |
243 // ---> (135 - exponent) | 250 |
244 RSB r27, r27, 135 | 251 .macro SET_GPIO_BITS |
245 LSR r28, r28, r27 | 252 .mparam gpio_oe, gpio_setdataout, gpio_cleardataout, gpio_num_bit, digital_bit, digital //sets the bits in GPIO_OE, GPIO_SETDATAOUT and GPIO_CLEARDATAOUT |
246 | 253 //Remember that the GPIO_OE Output data enable register behaves as follows for each bit: |
247 // Finally, check the sign bit and invert if needed | 254 //0 = The corresponding GPIO pin is configured as an output. |
248 QBBS NEGATIVE_RESULT, input, 31 | 255 //1 = The corresponding GPIO pin is configured as an input. |
249 // Positive result: but might be 32768 so needs checking | 256 QBBS SETINPUT, digital, digital_bit |
250 LDI r27, 0x7FFF | 257 CLR gpio_oe, gpio_num_bit //if it is an output, configure pin as output |
251 MIN output, r27, r28 | 258 QBBC CLEARDATAOUT, digital, digital_bit+16 // check the output value. If it is 0, branch |
252 QBA FLOAT_TO_INT16_DONE | 259 SET gpio_setdataout, gpio_num_bit //if it is 1, set output to high |
253 NEGATIVE_RESULT: | 260 QBA DONE |
254 // Take negative: invert the bits and add 1 | 261 CLEARDATAOUT: |
255 LDI r27, 0xFFFF | 262 SET gpio_cleardataout, gpio_num_bit // set output to low |
256 XOR r28, r28, r27 | 263 QBA DONE |
257 ADD r28, r28, 1 | 264 SETINPUT: //if it is an input, set the relevant bit |
258 CLR output, r28, 16 // Clear carry bit if present | 265 SET gpio_oe, gpio_num_bit |
259 FLOAT_TO_INT16_DONE: | 266 QBA DONE |
260 .endm | 267 DONE: |
261 | 268 .endm |
262 | 269 |
263 // Convert float to 16-bit unsigned int, multiplying by 65536 | 270 QBA START // when first starting, go to START, skipping this section. |
264 // Converts 0.0 to 1.0 to a full 16-bit range | 271 |
265 // input and output can safely be the same register | 272 DIGITAL: |
266 .macro FLOAT_TO_UINT16 | 273 //IMPORTANT: do NOT use r28 in this macro, as it contains the return address for JAL |
267 .mparam input, output | 274 //r27 is now the input word passed in render(), one word per frame |
268 QBBC NONNEGATIVE, input, 31 // Is sign negative? | 275 //[31:16]: data(1=high, 0=low), [15:0]: direction (0=output, 1=input) ) |
269 LDI output, 0 // All < 0 inputs produce 0 output | 276 |
270 QBA FLOAT_TO_UINT16_DONE | 277 |
271 NONNEGATIVE: | 278 //Preparing the gpio_oe, gpio_cleardataout and gpio_setdataout for each module |
272 // int exponent = ((input >> 23) & 0xFF) | 279 //r2 will hold GPIO1_OE |
273 LSR r27, input, 23 // exponent goes in r27 | 280 //load current status of GPIO_OE in r2 |
274 AND r27, r27, 0xFF | 281 MOV r2, GPIO1 | GPIO_OE |
275 | 282 //it takes 190ns to go through the next instruction |
276 // Actual exponent is 127 less than the above; below -16 we | 283 LBBO r2, r2, 0, 4 |
277 // should return 0. So check if it is less than 111. | 284 //GPIO1-start |
278 QBLE EXPONENT_GREQ_MINUS16, r27, 111 | 285 //process oe and datain and prepare dataout for GPIO1 |
279 LDI output, 0 | 286 //r7 will contain GPIO1_CLEARDATAOUT |
280 QBA FLOAT_TO_UINT16_DONE | 287 //r8 will contain GPIO1_SETDATAOUT |
281 EXPONENT_GREQ_MINUS16: | 288 MOV r8, 0 |
282 | 289 MOV r7, 0 |
283 // Next check if exponent is greater than or equal to 0 (i.e. | 290 //map GPIO_ANALOG to gpio1 pins, |
284 // 127 in our adjusted version. If so we return the max. | 291 //r2 is gpio1_oe, r8 is gpio1_setdataout, r7 is gpio1_cleardataout, r27 is the input word |
285 QBGT EXPONENT_LT_ZERO, r27, 127 | 292 //the following operations will read from r27 and update r2,r7,r8 |
286 LDI output, 65535 // Max positive value | 293 SET_GPIO_BITS r2, r8, r7, 13, 4, r27 |
287 QBA FLOAT_TO_UINT16_DONE | 294 SET_GPIO_BITS r2, r8, r7, 12, 5, r27 |
288 EXPONENT_LT_ZERO: | 295 SET_GPIO_BITS r2, r8, r7, 28, 6, r27 |
289 | 296 SET_GPIO_BITS r2, r8, r7, 18, 7, r27 |
290 // Mask out the mantissa and shift | 297 SET_GPIO_BITS r2, r8, r7, 15, 8, r27 |
291 // int mantissa = (input & 0x7FFFFF) | (1 << 23) | 298 SET_GPIO_BITS r2, r8, r7, 14, 9, r27 |
292 MOV r28, 0x007FFFFF | 299 SET_GPIO_BITS r2, r8, r7, 19, 10, r27 |
293 AND r28, r28, input | 300 //set the output enable register for gpio1. |
294 SET r28, 23 | 301 MOV r3, GPIO1 | GPIO_OE //use r3 as a temp register |
295 | 302 SBBO r2, r3, 0, 4 //takes two cycles (10ns) |
296 // Shift right by -(exponent - 127 - 7) to produce an int | 303 //GPIO1-end |
297 // after effectively multiplying by 2^16 | 304 // r2 is now unused |
298 // ---> (134 - exponent) | 305 |
299 RSB r27, r27, 134 | 306 //GPIO2-start |
300 LSR r28, r28, r27 | 307 //r3 will hold GPIO1_OE |
301 | 308 //load current status of GPIO_OE in r3 |
302 // Check for 65536 and clip at 65535 | 309 MOV r3, GPIO2 | GPIO_OE |
303 LDI r27, 0xFFFF | 310 //it takes 200ns to go through the next instructions |
304 MIN output, r27, r28 | 311 LBBO r3, r3, 0, 4 |
305 FLOAT_TO_UINT16_DONE: | 312 //process oe and datain and prepare dataout for GPIO2 |
306 .endm | 313 //r4 will contain GPIO2_CLEARDATAOUT |
307 | 314 //r5 will contain GPIO2_SETDATAOUT |
308 | 315 MOV r5, 0 |
309 // Convert a 16-bit int to float. This macro assumes that the upper | 316 MOV r4, 0 |
310 // 16 bits of input are 0 and may behave strangely if this is not the case. | 317 //map GPIO_ANALOG to gpio2 pins |
311 // input and output must be different registers | 318 //r3 is gpio2_oe, r5 is gpio2_setdataout, r4 is gpio2_cleardataout, r27 is the input word |
312 .macro INT16_TO_FLOAT | 319 //the following operations will read from r27 and update r3,r4,r5 |
313 .mparam input, output | 320 SET_GPIO_BITS r3, r5, r4, 2, 0, r27 |
314 // Check edge cases first: 0 and -32768 (= 32768 in unsigned) | 321 SET_GPIO_BITS r3, r5, r4, 3, 1, r27 |
315 QBNE INPUT_NOT_ZERO, input, 0 | 322 SET_GPIO_BITS r3, r5, r4, 5, 2, r27 |
316 LDI output, 0 | 323 SET_GPIO_BITS r3, r5, r4, 4, 3, r27 |
317 QBA INT16_TO_FLOAT_DONE | 324 SET_GPIO_BITS r3, r5, r4, 1, 11, r27 |
318 INPUT_NOT_ZERO: | 325 SET_GPIO_BITS r3, r5, r4, 22, 12, r27 |
319 LDI r28, 32768 | 326 SET_GPIO_BITS r3, r5, r4, 24, 13, r27 |
320 QBNE INPUT_NOT_MIN, input, r28 | 327 SET_GPIO_BITS r3, r5, r4, 23, 14, r27 |
321 MOV output, 0xBF800000 // -1.0 | 328 SET_GPIO_BITS r3, r5, r4, 25, 15, r27 |
322 QBA INT16_TO_FLOAT_DONE | 329 //set the output enable register for gpio2. |
323 INPUT_NOT_MIN: | 330 MOV r2, GPIO2 | GPIO_OE //use r2 as a temp registerp |
324 // Check for negative values = values with bit 15 set | 331 SBBO r3, r2, 0, 4 //takes two cycles (10ns) |
325 MOV output, input | 332 //GPIO2-end |
326 QBBC NEGATIVE_DONE, output, 15 | 333 //r3 is now unused |
327 LDI r28, 0xFFFF | 334 |
328 XOR output, output, r28 | 335 //load current inputs in r2, r3 |
329 ADD output, output, 1 | 336 //r2 will contain GPIO1_DATAIN |
330 CLR output, 16 // Clear any carry bit | 337 //r3 will contain GPIO2_DATAIN |
331 NEGATIVE_DONE: | 338 //load the memory locations |
332 // Now we need to find the highest bit that is 1 in order to determine | 339 MOV r2, GPIO1 | GPIO_DATAIN |
333 // the exponent | 340 MOV r3, GPIO2 | GPIO_DATAIN |
334 LMBD r28, output, 1 | 341 //takes 375 nns to go through the next two instructions |
335 | 342 //read the datain |
336 // Calculate exponent field: 127 + 8 + (r28 - 23) = 112 + r28 | 343 LBBO r2, r2, 0, 4 |
337 ADD r27, r28, 112 | 344 LBBO r3, r3, 0, 4 |
338 | 345 //now read from r2 and r3 only the channels that are set as input in the lower word of r27 |
339 // Take 23 minus the result to get the shift | 346 // and set their value in the high word of r27 |
340 RSB r28, r28, 23 | 347 //GPIO1 |
341 LSL output, output, r28 | 348 READ_GPIO_BITS r2, 13, 4, r27 |
342 | 349 READ_GPIO_BITS r2, 12, 5, r27 |
343 // Now clear bit 23 (implicitly 1) and replace it with the exponent | 350 READ_GPIO_BITS r2, 28, 6, r27 |
344 CLR output, output, 23 | 351 READ_GPIO_BITS r2, 18, 7, r27 |
345 LSL r27, r27, 23 | 352 READ_GPIO_BITS r2, 15, 8, r27 |
346 OR output, output, r27 | 353 READ_GPIO_BITS r2, 14, 9, r27 |
347 | 354 READ_GPIO_BITS r2, 19, 10, r27 |
348 // Put the sign bit back in place | 355 //GPIO2 |
349 QBBC INT16_TO_FLOAT_DONE, input, 15 | 356 READ_GPIO_BITS r3, 2, 0, r27 |
350 SET output, 31 | 357 READ_GPIO_BITS r3, 3, 1, r27 |
351 INT16_TO_FLOAT_DONE: | 358 READ_GPIO_BITS r3, 5, 2, r27 |
352 .endm | 359 READ_GPIO_BITS r3, 4, 3, r27 |
353 | 360 READ_GPIO_BITS r3, 1, 11, r27 |
354 // Convert a 16-bit unsigned int to float. | 361 READ_GPIO_BITS r3, 22, 12, r27 |
355 .macro UINT16_TO_FLOAT | 362 READ_GPIO_BITS r3, 24, 13, r27 |
356 .mparam input, output | 363 READ_GPIO_BITS r3, 23, 14, r27 |
357 MOV output, input | 364 READ_GPIO_BITS r3, 25, 15, r27 |
358 | 365 //r2, r3 are now unused |
359 // Clear upper 16 bits | 366 |
360 LDI r27, 0xFFFF | 367 //now all the setdataout and cleardataout are ready to be written to the GPIO register. |
361 AND output, output, r27 | 368 //CLEARDATAOUT and SETDATAOUT are consecutive positions in memory, so we just write 8 bytes to CLEARDATAOUT. |
362 | 369 //We can do this because we chose cleardata and setdata registers for a given GPIO to be consecutive |
363 // If zero, we're done | 370 //load the memory addresses to be written to |
364 QBEQ UINT16_TO_FLOAT_DONE, output, 0 | 371 MOV r2, GPIO1 | GPIO_CLEARDATAOUT //use r2 as a temp register |
365 | 372 MOV r3, GPIO2 | GPIO_CLEARDATAOUT //use r3 as a temp register |
366 // Now we need to find the highest bit that is 1 in order to determine | 373 //write 8 bytes for each GPIO |
367 // the exponent | 374 //takes 30ns in total to go through the following two instructions |
368 LMBD r28, output, 1 | 375 SBBO r7, r2, 0, 8 //store r7 and r8 in GPIO1_CLEARDATAOUT and GPIO1_SETDATAOUT |
369 | 376 //takes 145ns to be effective when going low, 185ns when going high |
370 // Calculate exponent field: 127 + 7 + (r28 - 23) = 111 + r28 | 377 SBBO r4, r3, 0, 8 //store r4 and r5 in GPIO2_CLEARDATAOUT and GPIO2_SETDATAOUT |
371 ADD r27, r28, 111 | 378 //takes 95ns to be effective when going low, 130ns when going high |
372 | 379 //reversing the order of the two lines above will swap the performances between the GPIO modules |
373 // Take 23 minus the result to get the shift | 380 //i.e.: the first line will always take 145ns/185ns and the second one will always take 95ns/130ns, |
374 RSB r28, r28, 23 | 381 //regardless of whether the order is gpio1-gpio2 or gpio2-gpio1 |
375 LSL output, output, r28 | 382 JMP r28.w0 // go back to ADC_WRITE_AND_PROCESS_GPIO |
376 | 383 |
377 // Now clear bit 23 (implicitly 1) and replace it with the exponent | 384 .macro HANG //useful for debugging |
378 CLR output, output, 23 | 385 DALOOP: |
379 LSL r27, r27, 23 | 386 set r30.t14 |
380 OR output, output, r27 | 387 clr r30.t14 |
381 UINT16_TO_FLOAT_DONE: | 388 QBA DALOOP |
382 .endm | 389 .endm |
383 | 390 |
384 // Bring CS line low to write to DAC | 391 // Bring CS line low to write to DAC |
385 .macro DAC_CS_ASSERT | 392 .macro DAC_CS_ASSERT |
386 MOV r27, DAC_CS_PIN | 393 MOV r27, DAC_CS_PIN |
387 MOV r28, DAC_GPIO + GPIO_CLEARDATAOUT | 394 MOV r28, DAC_GPIO + GPIO_CLEARDATAOUT |
388 SBBO r27, r28, 0, 4 | 395 SBBO r27, r28, 0, 4 |
459 // Complete ADC write+read with chip select | 466 // Complete ADC write+read with chip select |
460 .macro ADC_WRITE | 467 .macro ADC_WRITE |
461 .mparam in, out | 468 .mparam in, out |
462 ADC_CS_ASSERT | 469 ADC_CS_ASSERT |
463 ADC_TX in | 470 ADC_TX in |
471 ADC_WAIT_FOR_FINISH | |
472 ADC_RX out | |
473 ADC_CS_UNASSERT | |
474 .endm | |
475 | |
476 // Complete ADC write+read with chip select and also performs IO for digital | |
477 .macro ADC_WRITE_GPIO | |
478 .mparam in, out, do_gpio | |
479 ADC_CS_ASSERT | |
480 ADC_TX in | |
481 QBBC GPIO_DONE, reg_flags, FLAG_BIT_USE_DIGITAL //skip if DIGITAL is disabled | |
482 AND r27, do_gpio, 0x3 // only do a DIGITAL every 2 SPI I/O | |
483 QBNE GPIO_DONE, r27, 0 | |
484 //from here to GPIO_DONE takes 1.8us, while usually ADC_WAIT_FOR_FINISH only waits for 1.14us. | |
485 //TODO: it would be better to split the DIGITAL stuff in two parts: | |
486 //- one taking place during DAC_WRITE which sets the GPIO_OE | |
487 //- and the other during ADC_WRITE which actually reads DATAIN and writes CLEAR/SET DATAOUT | |
488 //r27 is actually r27, so do not use r27 from here to ... | |
489 LBBO r27, reg_digital_current, 0, 4 | |
490 JAL r28.w0, DIGITAL // note that this is not called as a macro, but with JAL. r28 will contain the return address | |
491 SBBO r27, reg_digital_current, 0, 4 | |
492 //..here you can start using r27 again | |
493 ADD reg_digital_current, reg_digital_current, 4 //increment pointer | |
494 GPIO_DONE: | |
464 ADC_WAIT_FOR_FINISH | 495 ADC_WAIT_FOR_FINISH |
465 ADC_RX out | 496 ADC_RX out |
466 ADC_CS_UNASSERT | 497 ADC_CS_UNASSERT |
467 .endm | 498 .endm |
468 | 499 |
535 MOV reg_flags, 0 | 566 MOV reg_flags, 0 |
536 | 567 |
537 // Default number of channels in case SPI disabled | 568 // Default number of channels in case SPI disabled |
538 LDI reg_num_channels, 8 | 569 LDI reg_num_channels, 8 |
539 | 570 |
571 // Find out whether we should use DIGITAL | |
572 LBBO r2, reg_comm_addr, COMM_USE_DIGITAL, 4 | |
573 QBEQ DIGITAL_INIT_DONE, r2, 0 // if we use digital | |
574 SET reg_flags, reg_flags, FLAG_BIT_USE_DIGITAL | |
575 /* This block of code is not really needed, as the memory is initialized by ARM before the PRU is started. | |
576 Will leave it here for future reference | |
577 DIGITAL_INIT: //set the digital buffer to 0x0000ffff (all inputs), to prevent unwanted high outputs | |
578 //the loop is unrolled by a factor of four just to take advantage of the speed of SBBO on larger byte bursts, but there is no real need for it | |
579 MOV r2, 0x0000ffff //value to store. 0x0000ffff means all inputs | |
580 MOV r3, MEM_DIGITAL_BASE //start of the digital buffer | |
581 MOV r4, MEM_DIGITAL_BASE+2*MEM_DIGITAL_BUFFER1_OFFSET //end of the digital buffer | |
582 DIGITAL_INIT_BUFFER_LOOP: | |
583 SBBO r2, r3, 0, 4 | |
584 ADD r3, r3, 4 //increment pointer | |
585 QBGT DIGITAL_INIT_BUFFER_LOOP, r3, r4 //loop until we reach the end of the buffer | |
586 */ | |
587 DIGITAL_INIT_DONE: | |
540 // Find out whether we should use SPI ADC and DAC | 588 // Find out whether we should use SPI ADC and DAC |
541 LBBO r2, reg_comm_addr, COMM_USE_SPI, 4 | 589 LBBO r2, reg_comm_addr, COMM_USE_SPI, 4 |
542 QBEQ SPI_FLAG_CHECK_DONE, r2, 0 | 590 QBEQ SPI_FLAG_CHECK_DONE, r2, 0 |
543 SET reg_flags, reg_flags, FLAG_BIT_USE_SPI | 591 SET reg_flags, reg_flags, FLAG_BIT_USE_SPI |
544 | |
545 SPI_FLAG_CHECK_DONE: | 592 SPI_FLAG_CHECK_DONE: |
546 // If we don't use SPI, then skip all this init | 593 // If we don't use SPI, then skip all this init |
547 QBBC SPI_INIT_DONE, reg_flags, FLAG_BIT_USE_SPI | 594 QBBC SPI_INIT_DONE, reg_flags, FLAG_BIT_USE_SPI |
548 | 595 |
549 // Load the number of channels: valid values are 8, 4 or 2 | 596 // Load the number of channels: valid values are 8, 4 or 2 |
612 | 659 |
613 MOV r2, AD7699_CFG_MASK | (0x01 << AD7699_CHANNEL_OFFSET) | 660 MOV r2, AD7699_CFG_MASK | (0x01 << AD7699_CHANNEL_OFFSET) |
614 ADC_WRITE r2, r2 | 661 ADC_WRITE r2, r2 |
615 SPI_INIT_DONE: | 662 SPI_INIT_DONE: |
616 | 663 |
617 // Prepare McASP0 for audio | 664 // Prepare McASP0 for audio |
618 MCASP_REG_WRITE MCASP_GBLCTL, 0 // Disable McASP | 665 MCASP_REG_WRITE MCASP_GBLCTL, 0 // Disable McASP |
619 MCASP_REG_WRITE_EXT MCASP_SRCTL0, 0 // All serialisers off | 666 MCASP_REG_WRITE_EXT MCASP_SRCTL0, 0 // All serialisers off |
620 MCASP_REG_WRITE_EXT MCASP_SRCTL1, 0 | 667 MCASP_REG_WRITE_EXT MCASP_SRCTL1, 0 |
621 MCASP_REG_WRITE_EXT MCASP_SRCTL2, 0 | 668 MCASP_REG_WRITE_EXT MCASP_SRCTL2, 0 |
622 MCASP_REG_WRITE_EXT MCASP_SRCTL3, 0 | 669 MCASP_REG_WRITE_EXT MCASP_SRCTL3, 0 |
623 MCASP_REG_WRITE_EXT MCASP_SRCTL4, 0 | 670 MCASP_REG_WRITE_EXT MCASP_SRCTL4, 0 |
624 MCASP_REG_WRITE_EXT MCASP_SRCTL5, 0 | 671 MCASP_REG_WRITE_EXT MCASP_SRCTL5, 0 |
625 | 672 |
626 MCASP_REG_WRITE MCASP_PWRIDLESYSCONFIG, 0x02 // Power on | 673 MCASP_REG_WRITE MCASP_PWRIDLESYSCONFIG, 0x02 // Power on |
627 MCASP_REG_WRITE MCASP_PFUNC, 0x00 // All pins are McASP | 674 MCASP_REG_WRITE MCASP_PFUNC, 0x00 // All pins are McASP |
628 MCASP_REG_WRITE MCASP_PDIR, MCASP_OUTPUT_PINS // Set pin direction | 675 MCASP_REG_WRITE MCASP_PDIR, MCASP_OUTPUT_PINS // Set pin direction |
629 MCASP_REG_WRITE MCASP_DLBCTL, 0x00 | 676 MCASP_REG_WRITE MCASP_DLBCTL, 0x00 |
630 MCASP_REG_WRITE MCASP_DITCTL, 0x00 | 677 MCASP_REG_WRITE MCASP_DITCTL, 0x00 |
631 MCASP_REG_WRITE MCASP_RMASK, MCASP_DATA_MASK // 16 bit data receive | 678 MCASP_REG_WRITE MCASP_RMASK, MCASP_DATA_MASK // 16 bit data receive |
632 MCASP_REG_WRITE MCASP_RFMT, MCASP_DATA_FORMAT // Set data format | 679 MCASP_REG_WRITE MCASP_RFMT, MCASP_DATA_FORMAT // Set data format |
633 MCASP_REG_WRITE MCASP_AFSRCTL, 0x100 // I2S mode | 680 MCASP_REG_WRITE MCASP_AFSRCTL, 0x100 // I2S mode |
634 MCASP_REG_WRITE MCASP_ACLKRCTL, 0x80 // Sample on rising edge | 681 MCASP_REG_WRITE MCASP_ACLKRCTL, 0x80 // Sample on rising edge |
635 MCASP_REG_WRITE MCASP_AHCLKRCTL, 0x8001 // Internal clock, not inv, /2; irrelevant? | 682 MCASP_REG_WRITE MCASP_AHCLKRCTL, 0x8001 // Internal clock, not inv, /2; irrelevant? |
636 MCASP_REG_WRITE MCASP_RTDM, 0x03 // Enable TDM slots 0 and 1 | 683 MCASP_REG_WRITE MCASP_RTDM, 0x03 // Enable TDM slots 0 and 1 |
637 MCASP_REG_WRITE MCASP_RINTCTL, 0x00 // No interrupts | 684 MCASP_REG_WRITE MCASP_RINTCTL, 0x00 // No interrupts |
638 MCASP_REG_WRITE MCASP_XMASK, MCASP_DATA_MASK // 16 bit data transmit | 685 MCASP_REG_WRITE MCASP_XMASK, MCASP_DATA_MASK // 16 bit data transmit |
639 MCASP_REG_WRITE MCASP_XFMT, MCASP_DATA_FORMAT // Set data format | 686 MCASP_REG_WRITE MCASP_XFMT, MCASP_DATA_FORMAT // Set data format |
640 MCASP_REG_WRITE MCASP_AFSXCTL, 0x100 // I2S mode | 687 MCASP_REG_WRITE MCASP_AFSXCTL, 0x100 // I2S mode |
641 MCASP_REG_WRITE MCASP_ACLKXCTL, 0x00 // Transmit on rising edge, sync. xmit and recv | 688 MCASP_REG_WRITE MCASP_ACLKXCTL, 0x00 // Transmit on rising edge, sync. xmit and recv |
642 MCASP_REG_WRITE MCASP_AHCLKXCTL, 0x8001 // External clock from AHCLKX | 689 MCASP_REG_WRITE MCASP_AHCLKXCTL, 0x8001 // External clock from AHCLKX |
643 MCASP_REG_WRITE MCASP_XTDM, 0x03 // Enable TDM slots 0 and 1 | 690 MCASP_REG_WRITE MCASP_XTDM, 0x03 // Enable TDM slots 0 and 1 |
644 MCASP_REG_WRITE MCASP_XINTCTL, 0x00 // No interrupts | 691 MCASP_REG_WRITE MCASP_XINTCTL, 0x00 // No interrupts |
645 | 692 |
646 MCASP_REG_WRITE_EXT MCASP_SRCTL_R, 0x02 // Set up receive serialiser | 693 MCASP_REG_WRITE_EXT MCASP_SRCTL_R, 0x02 // Set up receive serialiser |
647 MCASP_REG_WRITE_EXT MCASP_SRCTL_X, 0x01 // Set up transmit serialiser | 694 MCASP_REG_WRITE_EXT MCASP_SRCTL_X, 0x01 // Set up transmit serialiser |
648 MCASP_REG_WRITE_EXT MCASP_WFIFOCTL, 0x00 // Disable FIFOs | 695 MCASP_REG_WRITE_EXT MCASP_WFIFOCTL, 0x00 // Disable FIFOs |
649 MCASP_REG_WRITE_EXT MCASP_RFIFOCTL, 0x00 | 696 MCASP_REG_WRITE_EXT MCASP_RFIFOCTL, 0x00 |
650 | 697 |
651 MCASP_REG_WRITE MCASP_XSTAT, 0xFF // Clear transmit errors | 698 MCASP_REG_WRITE MCASP_XSTAT, 0xFF // Clear transmit errors |
652 MCASP_REG_WRITE MCASP_RSTAT, 0xFF // Clear receive errors | 699 MCASP_REG_WRITE MCASP_RSTAT, 0xFF // Clear receive errors |
653 | 700 |
654 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 1) // Set RHCLKRST | 701 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 1) // Set RHCLKRST |
655 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 9) // Set XHCLKRST | 702 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 9) // Set XHCLKRST |
656 | 703 |
657 // The above write sequence will have temporarily changed the AHCLKX frequency | 704 // The above write sequence will have temporarily changed the AHCLKX frequency |
658 // The PLL needs time to settle or the sample rate will be unstable and possibly | 705 // The PLL needs time to settle or the sample rate will be unstable and possibly |
659 // cause an underrun. Give it ~1ms before going on. | 706 // cause an underrun. Give it ~1ms before going on. |
660 // 10ns per loop iteration = 10^-8s --> 10^5 iterations needed | 707 // 10ns per loop iteration = 10^-8s --> 10^5 iterations needed |
661 | 708 |
662 MOV r2, 1 << 28 | 709 MOV r2, 1 << 28 |
663 MOV r3, GPIO1 + GPIO_SETDATAOUT | 710 MOV r3, GPIO1 + GPIO_SETDATAOUT |
664 SBBO r2, r3, 0, 4 | 711 SBBO r2, r3, 0, 4 |
665 | 712 |
666 MOV r2, 100000 | 713 MOV r2, 100000 |
667 MCASP_INIT_WAIT: | 714 MCASP_INIT_WAIT: |
668 SUB r2, r2, 1 | 715 SUB r2, r2, 1 |
669 QBNE MCASP_INIT_WAIT, r2, 0 | 716 QBNE MCASP_INIT_WAIT, r2, 0 |
670 | 717 |
671 MOV r2, 1 << 28 | 718 MOV r2, 1 << 28 |
672 MOV r3, GPIO1 + GPIO_CLEARDATAOUT | 719 MOV r3, GPIO1 + GPIO_CLEARDATAOUT |
673 SBBO r2, r3, 0, 4 | 720 SBBO r2, r3, 0, 4 |
674 | 721 |
675 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 0) // Set RCLKRST | 722 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 0) // Set RCLKRST |
676 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 8) // Set XCLKRST | 723 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 8) // Set XCLKRST |
677 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 2) // Set RSRCLR | 724 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 2) // Set RSRCLR |
678 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 10) // Set XSRCLR | 725 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 10) // Set XSRCLR |
679 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 3) // Set RSMRST | 726 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 3) // Set RSMRST |
680 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 11) // Set XSMRST | 727 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 11) // Set XSMRST |
681 | 728 |
682 MCASP_REG_WRITE_EXT MCASP_XBUF, 0x00 // Write to the transmit buffer to prevent underflow | 729 MCASP_REG_WRITE_EXT MCASP_XBUF, 0x00 // Write to the transmit buffer to prevent underflow |
683 | 730 |
684 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 4) // Set RFRST | 731 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 4) // Set RFRST |
685 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 12) // Set XFRST | 732 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 12) // Set XFRST |
686 | 733 |
687 // Initialisation | 734 // Initialisation |
688 LBBO reg_frame_total, reg_comm_addr, COMM_BUFFER_FRAMES, 4 // Total frame count (SPI; 0.5x-2x for McASP) | 735 LBBO reg_frame_total, reg_comm_addr, COMM_BUFFER_FRAMES, 4 // Total frame count (SPI; 0.5x-2x for McASP) |
689 MOV reg_dac_buf0, 0 // DAC buffer 0 start pointer | 736 MOV reg_dac_buf0, 0 // DAC buffer 0 start pointer |
690 LSL reg_dac_buf1, reg_frame_total, 1 // DAC buffer 1 start pointer = N[ch]*2[bytes]*bufsize | 737 LSL reg_dac_buf1, reg_frame_total, 1 // DAC buffer 1 start pointer = N[ch]*2[bytes]*bufsize |
691 LMBD r2, reg_num_channels, 1 // Returns 1, 2 or 3 depending on the number of channels | 738 LMBD r2, reg_num_channels, 1 // Returns 1, 2 or 3 depending on the number of channels |
692 LSL reg_dac_buf1, reg_dac_buf1, r2 // Multiply by 2, 4 or 8 to get the N[ch] scaling above | 739 LSL reg_dac_buf1, reg_dac_buf1, r2 // Multiply by 2, 4 or 8 to get the N[ch] scaling above |
693 MOV reg_mcasp_buf0, 0 // McASP DAC buffer 0 start pointer | 740 MOV reg_mcasp_buf0, 0 // McASP DAC buffer 0 start pointer |
694 LSL reg_mcasp_buf1, reg_frame_total, r2 // McASP DAC buffer 1 start pointer = 2[ch]*2[bytes]*(N/4)[samples/spi]*bufsize | 741 LSL reg_mcasp_buf1, reg_frame_total, r2 // McASP DAC buffer 1 start pointer = 2[ch]*2[bytes]*(N/4)[samples/spi]*bufsize |
695 CLR reg_flags, reg_flags, FLAG_BIT_BUFFER1 // Bit 0 holds which buffer we are on | 742 CLR reg_flags, reg_flags, FLAG_BIT_BUFFER1 // Bit 0 holds which buffer we are on |
696 MOV r2, 0 | 743 MOV r2, 0 |
697 SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 // Start with frame count of 0 | 744 SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 // Start with frame count of 0 |
698 | 745 /* This block of code is not really needed, as the memory is initialized by ARM before the PRU is started. |
746 Will leave it here for future reference | |
747 //Initialise all SPI and audio buffers (DAC0, DAC1, ADC0, ADC1) to zero. | |
748 //This is useful for analog outs so they do not have spikes during the first buffer. | |
749 //This is not very useful for audio, as you still hear the initial "tumpf" when the converter starts | |
750 //and each sample in the DAC buffer is reset to 0 after it is written to the DAC. | |
751 | |
752 QBBC SPI_INIT_BUFFER_DONE, reg_flags, FLAG_BIT_USE_SPI | |
753 //Initialize SPI buffers | |
754 //compute the memory offset of the end of the audio buffer and store it in r4 | |
755 SUB r4, reg_dac_buf1, reg_dac_buf0 // length of the buffer, assumes reg_dac_buf1>ref_dac_buf0 | |
756 LSL r4, r4, 2 //length of four buffers (DAC0, DAC1, ADC0, ADC1) | |
757 ADD r4, reg_dac_buf0, r4 //total offset | |
758 MOV r2, 0// value to store | |
759 MOV r3, 0 // offset counter | |
760 SPI_INIT_BUFFER_LOOP: | |
761 SBCO r2, C_ADC_DAC_MEM, r3, 4 | |
762 ADD r3, r3, 4 | |
763 QBGT SPI_INIT_BUFFER_LOOP, r3, r4 | |
764 SPI_INIT_BUFFER_DONE: | |
765 | |
766 //Initialize audio buffers | |
767 //compute the memory offset of the end of the audio buffer and store it in r4 | |
768 SUB r4, reg_mcasp_buf1, reg_mcasp_buf0 // length of the buffer, assumes reg_mcasp_buf1>ref_mcasp_buf0 | |
769 LSL r4, r4, 2 //length of four buffers (DAC0, DAC1, ADC0, ADC1) | |
770 ADD r4, reg_mcasp_buf0, r4 //total offset | |
771 MOV r2, 0 // value to store | |
772 MOV r3, 0 // offset counter | |
773 MCASP_INIT_BUFFER_LOOP: | |
774 SBCO r2, C_MCASP_MEM, r3, 4 | |
775 ADD r3, r3, 4 | |
776 QBGT MCASP_INIT_BUFFER_LOOP, r3, r4 | |
777 */ | |
699 // Here we are out of sync by one TDM slot since the 0 word transmitted above will have occupied | 778 // Here we are out of sync by one TDM slot since the 0 word transmitted above will have occupied |
700 // the first output slot. Send one more word before jumping into the loop. | 779 // the first output slot. Send one more word before jumping into the loop. |
701 MCASP_DAC_WAIT_BEFORE_LOOP: | 780 MCASP_DAC_WAIT_BEFORE_LOOP: |
702 LBBO r2, reg_mcasp_addr, MCASP_XSTAT, 4 | 781 LBBO r2, reg_mcasp_addr, MCASP_XSTAT, 4 |
703 QBBC MCASP_DAC_WAIT_BEFORE_LOOP, r2, MCASP_XSTAT_XDATA_BIT | 782 QBBC MCASP_DAC_WAIT_BEFORE_LOOP, r2, MCASP_XSTAT_XDATA_BIT |
712 QBBC MCASP_ADC_WAIT_BEFORE_LOOP, r2, MCASP_RSTAT_RDATA_BIT | 791 QBBC MCASP_ADC_WAIT_BEFORE_LOOP, r2, MCASP_RSTAT_RDATA_BIT |
713 | 792 |
714 MCASP_REG_READ_EXT MCASP_RBUF, r2 | 793 MCASP_REG_READ_EXT MCASP_RBUF, r2 |
715 | 794 |
716 WRITE_ONE_BUFFER: | 795 WRITE_ONE_BUFFER: |
796 | |
717 // Write a single buffer of DAC samples and read a buffer of ADC samples | 797 // Write a single buffer of DAC samples and read a buffer of ADC samples |
718 // Load starting positions | 798 // Load starting positions |
719 MOV reg_dac_current, reg_dac_buf0 // DAC: reg_dac_current is current pointer | 799 MOV reg_dac_current, reg_dac_buf0 // DAC: reg_dac_current is current pointer |
720 LMBD r2, reg_num_channels, 1 // 1, 2 or 3 for 2, 4 or 8 channels | 800 LMBD r2, reg_num_channels, 1 // 1, 2 or 3 for 2, 4 or 8 channels |
721 LSL reg_adc_current, reg_frame_total, r2 | 801 LSL reg_adc_current, reg_frame_total, r2 |
724 MOV reg_mcasp_dac_current, reg_mcasp_buf0 // McASP: set current DAC pointer | 804 MOV reg_mcasp_dac_current, reg_mcasp_buf0 // McASP: set current DAC pointer |
725 LSL reg_mcasp_adc_current, reg_frame_total, r2 // McASP ADC: starts (N/2)*2*2*bufsize beyond DAC | 805 LSL reg_mcasp_adc_current, reg_frame_total, r2 // McASP ADC: starts (N/2)*2*2*bufsize beyond DAC |
726 LSL reg_mcasp_adc_current, reg_mcasp_adc_current, 1 | 806 LSL reg_mcasp_adc_current, reg_mcasp_adc_current, 1 |
727 ADC reg_mcasp_adc_current, reg_mcasp_adc_current, reg_mcasp_dac_current | 807 ADC reg_mcasp_adc_current, reg_mcasp_adc_current, reg_mcasp_dac_current |
728 MOV reg_frame_current, 0 | 808 MOV reg_frame_current, 0 |
729 | 809 QBBS DIGITAL_BASE_CHECK_SET, reg_flags, FLAG_BIT_BUFFER1 //check which buffer we are using for DIGITAL |
810 // if we are here, we are using buffer0 | |
811 MOV reg_digital_current, MEM_DIGITAL_BASE | |
812 QBA DIGITAL_BASE_CHECK_DONE | |
813 DIGITAL_BASE_CHECK_SET: //if we are here, we are using buffer1 | |
814 MOV reg_digital_current, MEM_DIGITAL_BASE+MEM_DIGITAL_BUFFER1_OFFSET //so adjust offset appropriately | |
815 DIGITAL_BASE_CHECK_DONE: | |
816 | |
730 WRITE_LOOP: | 817 WRITE_LOOP: |
731 // Write N channels to DAC from successive values in memory | 818 // Write N channels to DAC from successive values in memory |
732 // At the same time, read N channels from ADC | 819 // At the same time, read N channels from ADC |
733 // Unrolled by a factor of 2 to get high and low words | 820 // Unrolled by a factor of 2 to get high and low words |
734 MOV r1, 0 | 821 MOV r1, 0 |
803 // Now store the result and increment the pointer | 890 // Now store the result and increment the pointer |
804 SBCO reg_mcasp_adc_data, C_MCASP_MEM, reg_mcasp_adc_current, 4 | 891 SBCO reg_mcasp_adc_data, C_MCASP_MEM, reg_mcasp_adc_current, 4 |
805 ADD reg_mcasp_adc_current, reg_mcasp_adc_current, 4 | 892 ADD reg_mcasp_adc_current, reg_mcasp_adc_current, 4 |
806 MCASP_ADC_DONE: | 893 MCASP_ADC_DONE: |
807 QBBC SPI_SKIP_WRITE, reg_flags, FLAG_BIT_USE_SPI | 894 QBBC SPI_SKIP_WRITE, reg_flags, FLAG_BIT_USE_SPI |
808 | 895 |
809 // DAC: transmit low word (first in little endian) | 896 // DAC: transmit low word (first in little endian) |
810 MOV r2, 0xFFFF | 897 MOV r2, 0xFFFF |
811 AND r7, reg_dac_data, r2 | 898 AND r7, reg_dac_data, r2 |
812 LSL r7, r7, AD5668_DATA_OFFSET | 899 LSL r7, r7, AD5668_DATA_OFFSET |
813 MOV r8, (0x03 << AD5668_COMMAND_OFFSET) | 900 MOV r8, (0x03 << AD5668_COMMAND_OFFSET) |
824 SUB r7, reg_num_channels, 1 | 911 SUB r7, reg_num_channels, 1 |
825 AND r8, r8, r7 | 912 AND r8, r8, r7 |
826 LSL r8, r8, AD7699_CHANNEL_OFFSET | 913 LSL r8, r8, AD7699_CHANNEL_OFFSET |
827 MOV r7, AD7699_CFG_MASK | 914 MOV r7, AD7699_CFG_MASK |
828 OR r7, r7, r8 | 915 OR r7, r7, r8 |
829 ADC_WRITE r7, r7 | 916 |
917 //ssssssssssssssssssssssssssss | |
918 ADC_WRITE_GPIO r7, r7, r1 | |
830 | 919 |
831 // Mask out only the relevant 16 bits and store in reg_adc_data | 920 // Mask out only the relevant 16 bits and store in reg_adc_data |
832 MOV r2, 0xFFFF | 921 MOV r2, 0xFFFF |
833 AND reg_adc_data, r7, r2 | 922 AND reg_adc_data, r7, r2 |
834 | 923 |
870 // Repeat 4 times for 8 channels (2 samples per loop, r1 += 1 already happened) | 959 // Repeat 4 times for 8 channels (2 samples per loop, r1 += 1 already happened) |
871 // For 4 or 2 channels, repeat 2 or 1 times, according to flags | 960 // For 4 or 2 channels, repeat 2 or 1 times, according to flags |
872 ADD r1, r1, 1 | 961 ADD r1, r1, 1 |
873 QBNE ADC_DAC_LOOP, r1, reg_num_channels | 962 QBNE ADC_DAC_LOOP, r1, reg_num_channels |
874 QBA ADC_DAC_LOOP_DONE | 963 QBA ADC_DAC_LOOP_DONE |
875 | |
876 SPI_SKIP_WRITE: | 964 SPI_SKIP_WRITE: |
877 // We get here only if the SPI ADC and DAC are disabled | 965 // We get here only if the SPI ADC and DAC are disabled |
878 // Just keep the loop going for McASP | 966 // Just keep the loop going for McASP |
879 | 967 |
880 // Toggle the high/low word for McASP control (since we send one word out of | 968 // Toggle the high/low word for McASP control (since we send one word out of |
896 MOV reg_dac_buf0, reg_dac_buf1 | 984 MOV reg_dac_buf0, reg_dac_buf1 |
897 MOV reg_dac_buf1, r2 | 985 MOV reg_dac_buf1, r2 |
898 MOV r2, reg_mcasp_buf0 | 986 MOV r2, reg_mcasp_buf0 |
899 MOV reg_mcasp_buf0, reg_mcasp_buf1 | 987 MOV reg_mcasp_buf0, reg_mcasp_buf1 |
900 MOV reg_mcasp_buf1, r2 | 988 MOV reg_mcasp_buf1, r2 |
989 XOR reg_flags, reg_flags, (1 << FLAG_BIT_BUFFER1) //flip the buffer flag | |
901 | 990 |
902 // Notify ARM of buffer swap | 991 // Notify ARM of buffer swap |
903 XOR reg_flags, reg_flags, (1 << FLAG_BIT_BUFFER1) | |
904 AND r2, reg_flags, (1 << FLAG_BIT_BUFFER1) // Mask out every but low bit | 992 AND r2, reg_flags, (1 << FLAG_BIT_BUFFER1) // Mask out every but low bit |
905 SBBO r2, reg_comm_addr, COMM_CURRENT_BUFFER, 4 | 993 SBBO r2, reg_comm_addr, COMM_CURRENT_BUFFER, 4 |
906 | 994 MOV R31.b0, PRU1_ARM_INTERRUPT + 16 // Interrupt to host loop |
995 | |
907 // Increment the frame count in the comm buffer (for status monitoring) | 996 // Increment the frame count in the comm buffer (for status monitoring) |
908 LBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 | 997 LBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 |
909 ADD r2, r2, reg_frame_total | 998 ADD r2, r2, reg_frame_total |
910 SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 | 999 SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 |
911 | 1000 |
924 LBBO r2, reg_comm_addr, COMM_LED_PIN_MASK, 4 | 1013 LBBO r2, reg_comm_addr, COMM_LED_PIN_MASK, 4 |
925 MOV r1, GPIO_CLEARDATAOUT | 1014 MOV r1, GPIO_CLEARDATAOUT |
926 ADD r3, r3, r1 // Address for GPIO clear register | 1015 ADD r3, r3, r1 // Address for GPIO clear register |
927 SBBO r2, r3, 0, 4 // Clear GPIO pin | 1016 SBBO r2, r3, 0, 4 // Clear GPIO pin |
928 LED_BLINK_DONE: | 1017 LED_BLINK_DONE: |
929 | |
930 QBBC TESTLOW, reg_flags, FLAG_BIT_BUFFER1 | |
931 MOV r2, 1 << 28 | |
932 MOV r3, GPIO1 + GPIO_SETDATAOUT | |
933 SBBO r2, r3, 0, 4 | |
934 QBA TESTDONE | |
935 TESTLOW: | |
936 MOV r2, 1 << 28 | |
937 MOV r3, GPIO1 + GPIO_CLEARDATAOUT | |
938 SBBO r2, r3, 0, 4 | |
939 TESTDONE: | |
940 | |
941 // Check if we should finish: flag is zero as long as it should run | 1018 // Check if we should finish: flag is zero as long as it should run |
942 LBBO r2, reg_comm_addr, COMM_SHOULD_STOP, 4 | 1019 LBBO r2, reg_comm_addr, COMM_SHOULD_STOP, 4 |
943 QBEQ WRITE_ONE_BUFFER, r2, 0 | 1020 QBEQ WRITE_ONE_BUFFER, r2, 0 |
944 | 1021 |
945 CLEANUP: | 1022 CLEANUP: |
957 MOV r3, SPI_BASE + SPI_CH0CTRL | 1034 MOV r3, SPI_BASE + SPI_CH0CTRL |
958 LBBO r2, r3, 0, 4 | 1035 LBBO r2, r3, 0, 4 |
959 CLR r2, r2, 1 | 1036 CLR r2, r2, 1 |
960 SBBO r2, r3, 0, 4 | 1037 SBBO r2, r3, 0, 4 |
961 SPI_CLEANUP_DONE: | 1038 SPI_CLEANUP_DONE: |
962 | |
963 // Signal the ARM that we have finished | 1039 // Signal the ARM that we have finished |
964 MOV R31.b0, PRU0_ARM_INTERRUPT + 16 | 1040 MOV R31.b0, PRU0_ARM_INTERRUPT + 16 |
965 HALT | 1041 HALT |