comparison pru_rtaudio.p @ 21:0d80ff9e2227

Add float<->int macros to PRU code (still to integrate); formatting cleanups
author andrewm
date Sun, 08 Feb 2015 00:20:01 +0000
parents 6adb088196a7
children 472e892c6e41
comparison
equal deleted inserted replaced
15:901d205d1a3c 21:0d80ff9e2227
203 #define reg_comm_addr r25 // Memory address for communicating with ARM 203 #define reg_comm_addr r25 // Memory address for communicating with ARM
204 #define reg_spi_addr r26 // Base address for SPI 204 #define reg_spi_addr r26 // Base address for SPI
205 // r27, r28 used in macros 205 // r27, r28 used in macros
206 #define reg_mcasp_addr r29 // Base address for McASP 206 #define reg_mcasp_addr r29 // Base address for McASP
207 207
208 // Convert float to 16-bit int, multiplying by 32768
209 // Converts -1.0 to 1.0 to a full 16-bit range
210 // input and output can safely be the same register
211 .macro FLOAT_TO_INT16
212 .mparam input, output
213 // int exponent = ((input >> 23) & 0xFF)
214 LSR r27, input, 23 // exponent goes in r27
215 AND r27, r27, 0xFF
216
217 // Actual exponent is 127 less than the above; below -15 we
218 // should return 0. So check if it is less than 112.
219 QBLE EXPONENT_GREQ_MINUS15, r27, 112
220 LDI output, 0
221 QBA FLOAT_TO_INT16_DONE
222 EXPONENT_GREQ_MINUS15:
223
224 // Next check if exponent is greater than or equal to 0 (i.e.
225 // 127 in our adjusted version. If so we return the max.
226 QBGT EXPONENT_LT_ZERO, r27, 127
227 QBBS NEGATIVE_MAX, input, 31 // Is sign negative?
228 LDI output, 32767 // Max positive value
229 QBA FLOAT_TO_INT16_DONE
230 NEGATIVE_MAX:
231 LDI output, 32768 // Actually will be -32768 in signed
232 QBA FLOAT_TO_INT16_DONE
233 EXPONENT_LT_ZERO:
234
235 // Mask out the mantissa and shift
236 // int mantissa = (input & 0x7FFFFF) | (1 << 23)
237 MOV r28, 0x007FFFFF
238 AND r28, r28, input
239 SET r28, 23
240
241 // Shift right by -(exponent - 127 - 8) to produce an int
242 // after effectively multiplying by 2^15
243 // ---> (135 - exponent)
244 RSB r27, r27, 135
245 LSR r28, r28, r27
246
247 // Finally, check the sign bit and invert if needed
248 QBBS NEGATIVE_RESULT, input, 31
249 // Positive result: but might be 32768 so needs checking
250 LDI r27, 0x7FFF
251 MIN output, r27, r28
252 QBA FLOAT_TO_INT16_DONE
253 NEGATIVE_RESULT:
254 // Take negative: invert the bits and add 1
255 LDI r27, 0xFFFF
256 XOR r28, r28, r27
257 ADD r28, r28, 1
258 CLR output, r28, 16 // Clear carry bit if present
259 FLOAT_TO_INT16_DONE:
260 .endm
261
262
263 // Convert float to 16-bit unsigned int, multiplying by 65536
264 // Converts 0.0 to 1.0 to a full 16-bit range
265 // input and output can safely be the same register
266 .macro FLOAT_TO_UINT16
267 .mparam input, output
268 QBBC NONNEGATIVE, input, 31 // Is sign negative?
269 LDI output, 0 // All < 0 inputs produce 0 output
270 QBA FLOAT_TO_UINT16_DONE
271 NONNEGATIVE:
272 // int exponent = ((input >> 23) & 0xFF)
273 LSR r27, input, 23 // exponent goes in r27
274 AND r27, r27, 0xFF
275
276 // Actual exponent is 127 less than the above; below -16 we
277 // should return 0. So check if it is less than 111.
278 QBLE EXPONENT_GREQ_MINUS16, r27, 111
279 LDI output, 0
280 QBA FLOAT_TO_UINT16_DONE
281 EXPONENT_GREQ_MINUS16:
282
283 // Next check if exponent is greater than or equal to 0 (i.e.
284 // 127 in our adjusted version. If so we return the max.
285 QBGT EXPONENT_LT_ZERO, r27, 127
286 LDI output, 65535 // Max positive value
287 QBA FLOAT_TO_UINT16_DONE
288 EXPONENT_LT_ZERO:
289
290 // Mask out the mantissa and shift
291 // int mantissa = (input & 0x7FFFFF) | (1 << 23)
292 MOV r28, 0x007FFFFF
293 AND r28, r28, input
294 SET r28, 23
295
296 // Shift right by -(exponent - 127 - 7) to produce an int
297 // after effectively multiplying by 2^16
298 // ---> (134 - exponent)
299 RSB r27, r27, 134
300 LSR r28, r28, r27
301
302 // Check for 65536 and clip at 65535
303 LDI r27, 0xFFFF
304 MIN output, r27, r28
305 FLOAT_TO_UINT16_DONE:
306 .endm
307
308
309 // Convert a 16-bit int to float. This macro assumes that the upper
310 // 16 bits of input are 0 and may behave strangely if this is not the case.
311 // input and output must be different registers
312 .macro INT16_TO_FLOAT
313 .mparam input, output
314 // Check edge cases first: 0 and -32768 (= 32768 in unsigned)
315 QBNE INPUT_NOT_ZERO, input, 0
316 LDI output, 0
317 QBA INT16_TO_FLOAT_DONE
318 INPUT_NOT_ZERO:
319 LDI r28, 32768
320 QBNE INPUT_NOT_MIN, input, r28
321 MOV output, 0xBF800000 // -1.0
322 QBA INT16_TO_FLOAT_DONE
323 INPUT_NOT_MIN:
324 // Check for negative values = values with bit 15 set
325 MOV output, input
326 QBBC NEGATIVE_DONE, output, 15
327 LDI r28, 0xFFFF
328 XOR output, output, r28
329 ADD output, output, 1
330 CLR output, 16 // Clear any carry bit
331 NEGATIVE_DONE:
332 // Now we need to find the highest bit that is 1 in order to determine
333 // the exponent
334 LMBD r28, output, 1
335
336 // Calculate exponent field: 127 + 8 + (r28 - 23) = 112 + r28
337 ADD r27, r28, 112
338
339 // Take 23 minus the result to get the shift
340 RSB r28, r28, 23
341 LSL output, output, r28
342
343 // Now clear bit 23 (implicitly 1) and replace it with the exponent
344 CLR output, output, 23
345 LSL r27, r27, 23
346 OR output, output, r27
347
348 // Put the sign bit back in place
349 QBBC INT16_TO_FLOAT_DONE, input, 15
350 SET output, 31
351 INT16_TO_FLOAT_DONE:
352 .endm
353
354 // Convert a 16-bit unsigned int to float.
355 .macro UINT16_TO_FLOAT
356 .mparam input, output
357 MOV output, input
358
359 // Clear upper 16 bits
360 LDI r27, 0xFFFF
361 AND output, output, r27
362
363 // If zero, we're done
364 QBEQ UINT16_TO_FLOAT_DONE, output, 0
365
366 // Now we need to find the highest bit that is 1 in order to determine
367 // the exponent
368 LMBD r28, output, 1
369
370 // Calculate exponent field: 127 + 7 + (r28 - 23) = 111 + r28
371 ADD r27, r28, 111
372
373 // Take 23 minus the result to get the shift
374 RSB r28, r28, 23
375 LSL output, output, r28
376
377 // Now clear bit 23 (implicitly 1) and replace it with the exponent
378 CLR output, output, 23
379 LSL r27, r27, 23
380 OR output, output, r27
381 UINT16_TO_FLOAT_DONE:
382 .endm
208 383
209 // Bring CS line low to write to DAC 384 // Bring CS line low to write to DAC
210 .macro DAC_CS_ASSERT 385 .macro DAC_CS_ASSERT
211 MOV r27, DAC_CS_PIN 386 MOV r27, DAC_CS_PIN
212 MOV r28, DAC_GPIO + GPIO_CLEARDATAOUT 387 MOV r28, DAC_GPIO + GPIO_CLEARDATAOUT
437 612
438 MOV r2, AD7699_CFG_MASK | (0x01 << AD7699_CHANNEL_OFFSET) 613 MOV r2, AD7699_CFG_MASK | (0x01 << AD7699_CHANNEL_OFFSET)
439 ADC_WRITE r2, r2 614 ADC_WRITE r2, r2
440 SPI_INIT_DONE: 615 SPI_INIT_DONE:
441 616
442 // Prepare McASP0 for audio 617 // Prepare McASP0 for audio
443 MCASP_REG_WRITE MCASP_GBLCTL, 0 // Disable McASP 618 MCASP_REG_WRITE MCASP_GBLCTL, 0 // Disable McASP
444 MCASP_REG_WRITE_EXT MCASP_SRCTL0, 0 // All serialisers off 619 MCASP_REG_WRITE_EXT MCASP_SRCTL0, 0 // All serialisers off
445 MCASP_REG_WRITE_EXT MCASP_SRCTL1, 0 620 MCASP_REG_WRITE_EXT MCASP_SRCTL1, 0
446 MCASP_REG_WRITE_EXT MCASP_SRCTL2, 0 621 MCASP_REG_WRITE_EXT MCASP_SRCTL2, 0
447 MCASP_REG_WRITE_EXT MCASP_SRCTL3, 0 622 MCASP_REG_WRITE_EXT MCASP_SRCTL3, 0
448 MCASP_REG_WRITE_EXT MCASP_SRCTL4, 0 623 MCASP_REG_WRITE_EXT MCASP_SRCTL4, 0
449 MCASP_REG_WRITE_EXT MCASP_SRCTL5, 0 624 MCASP_REG_WRITE_EXT MCASP_SRCTL5, 0
450 625
451 MCASP_REG_WRITE MCASP_PWRIDLESYSCONFIG, 0x02 // Power on 626 MCASP_REG_WRITE MCASP_PWRIDLESYSCONFIG, 0x02 // Power on
452 MCASP_REG_WRITE MCASP_PFUNC, 0x00 // All pins are McASP 627 MCASP_REG_WRITE MCASP_PFUNC, 0x00 // All pins are McASP
453 MCASP_REG_WRITE MCASP_PDIR, MCASP_OUTPUT_PINS // Set pin direction 628 MCASP_REG_WRITE MCASP_PDIR, MCASP_OUTPUT_PINS // Set pin direction
454 MCASP_REG_WRITE MCASP_DLBCTL, 0x00 629 MCASP_REG_WRITE MCASP_DLBCTL, 0x00
455 MCASP_REG_WRITE MCASP_DITCTL, 0x00 630 MCASP_REG_WRITE MCASP_DITCTL, 0x00
456 MCASP_REG_WRITE MCASP_RMASK, MCASP_DATA_MASK // 16 bit data receive 631 MCASP_REG_WRITE MCASP_RMASK, MCASP_DATA_MASK // 16 bit data receive
457 MCASP_REG_WRITE MCASP_RFMT, MCASP_DATA_FORMAT // Set data format 632 MCASP_REG_WRITE MCASP_RFMT, MCASP_DATA_FORMAT // Set data format
458 MCASP_REG_WRITE MCASP_AFSRCTL, 0x100 // I2S mode 633 MCASP_REG_WRITE MCASP_AFSRCTL, 0x100 // I2S mode
459 MCASP_REG_WRITE MCASP_ACLKRCTL, 0x80 // Sample on rising edge 634 MCASP_REG_WRITE MCASP_ACLKRCTL, 0x80 // Sample on rising edge
460 MCASP_REG_WRITE MCASP_AHCLKRCTL, 0x8001 // Internal clock, not inv, /2; irrelevant? 635 MCASP_REG_WRITE MCASP_AHCLKRCTL, 0x8001 // Internal clock, not inv, /2; irrelevant?
461 MCASP_REG_WRITE MCASP_RTDM, 0x03 // Enable TDM slots 0 and 1 636 MCASP_REG_WRITE MCASP_RTDM, 0x03 // Enable TDM slots 0 and 1
462 MCASP_REG_WRITE MCASP_RINTCTL, 0x00 // No interrupts 637 MCASP_REG_WRITE MCASP_RINTCTL, 0x00 // No interrupts
463 MCASP_REG_WRITE MCASP_XMASK, MCASP_DATA_MASK // 16 bit data transmit 638 MCASP_REG_WRITE MCASP_XMASK, MCASP_DATA_MASK // 16 bit data transmit
464 MCASP_REG_WRITE MCASP_XFMT, MCASP_DATA_FORMAT // Set data format 639 MCASP_REG_WRITE MCASP_XFMT, MCASP_DATA_FORMAT // Set data format
465 MCASP_REG_WRITE MCASP_AFSXCTL, 0x100 // I2S mode 640 MCASP_REG_WRITE MCASP_AFSXCTL, 0x100 // I2S mode
466 MCASP_REG_WRITE MCASP_ACLKXCTL, 0x00 // Transmit on rising edge, sync. xmit and recv 641 MCASP_REG_WRITE MCASP_ACLKXCTL, 0x00 // Transmit on rising edge, sync. xmit and recv
467 MCASP_REG_WRITE MCASP_AHCLKXCTL, 0x8001 // External clock from AHCLKX 642 MCASP_REG_WRITE MCASP_AHCLKXCTL, 0x8001 // External clock from AHCLKX
468 MCASP_REG_WRITE MCASP_XTDM, 0x03 // Enable TDM slots 0 and 1 643 MCASP_REG_WRITE MCASP_XTDM, 0x03 // Enable TDM slots 0 and 1
469 MCASP_REG_WRITE MCASP_XINTCTL, 0x00 // No interrupts 644 MCASP_REG_WRITE MCASP_XINTCTL, 0x00 // No interrupts
470 645
471 MCASP_REG_WRITE_EXT MCASP_SRCTL_R, 0x02 // Set up receive serialiser 646 MCASP_REG_WRITE_EXT MCASP_SRCTL_R, 0x02 // Set up receive serialiser
472 MCASP_REG_WRITE_EXT MCASP_SRCTL_X, 0x01 // Set up transmit serialiser 647 MCASP_REG_WRITE_EXT MCASP_SRCTL_X, 0x01 // Set up transmit serialiser
473 MCASP_REG_WRITE_EXT MCASP_WFIFOCTL, 0x00 // Disable FIFOs 648 MCASP_REG_WRITE_EXT MCASP_WFIFOCTL, 0x00 // Disable FIFOs
474 MCASP_REG_WRITE_EXT MCASP_RFIFOCTL, 0x00 649 MCASP_REG_WRITE_EXT MCASP_RFIFOCTL, 0x00
475 650
476 MCASP_REG_WRITE MCASP_XSTAT, 0xFF // Clear transmit errors 651 MCASP_REG_WRITE MCASP_XSTAT, 0xFF // Clear transmit errors
477 MCASP_REG_WRITE MCASP_RSTAT, 0xFF // Clear receive errors 652 MCASP_REG_WRITE MCASP_RSTAT, 0xFF // Clear receive errors
478 653
479 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 1) // Set RHCLKRST 654 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 1) // Set RHCLKRST
480 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 9) // Set XHCLKRST 655 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 9) // Set XHCLKRST
481 656
482 // The above write sequence will have temporarily changed the AHCLKX frequency 657 // The above write sequence will have temporarily changed the AHCLKX frequency
483 // The PLL needs time to settle or the sample rate will be unstable and possibly 658 // The PLL needs time to settle or the sample rate will be unstable and possibly
484 // cause an underrun. Give it ~1ms before going on. 659 // cause an underrun. Give it ~1ms before going on.
485 // 10ns per loop iteration = 10^-8s --> 10^5 iterations needed 660 // 10ns per loop iteration = 10^-8s --> 10^5 iterations needed
486 661
487 MOV r2, 1 << 28 662 MOV r2, 1 << 28
488 MOV r3, GPIO1 + GPIO_SETDATAOUT 663 MOV r3, GPIO1 + GPIO_SETDATAOUT
489 SBBO r2, r3, 0, 4 664 SBBO r2, r3, 0, 4
490 665
491 MOV r2, 100000 666 MOV r2, 100000
492 MCASP_INIT_WAIT: 667 MCASP_INIT_WAIT:
493 SUB r2, r2, 1 668 SUB r2, r2, 1
494 QBNE MCASP_INIT_WAIT, r2, 0 669 QBNE MCASP_INIT_WAIT, r2, 0
495 670
496 MOV r2, 1 << 28 671 MOV r2, 1 << 28
497 MOV r3, GPIO1 + GPIO_CLEARDATAOUT 672 MOV r3, GPIO1 + GPIO_CLEARDATAOUT
498 SBBO r2, r3, 0, 4 673 SBBO r2, r3, 0, 4
499 674
500 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 0) // Set RCLKRST 675 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 0) // Set RCLKRST
501 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 8) // Set XCLKRST 676 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 8) // Set XCLKRST
502 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 2) // Set RSRCLR 677 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 2) // Set RSRCLR
503 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 10) // Set XSRCLR 678 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 10) // Set XSRCLR
504 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 3) // Set RSMRST 679 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 3) // Set RSMRST
505 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 11) // Set XSMRST 680 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 11) // Set XSMRST
506 681
507 MCASP_REG_WRITE_EXT MCASP_XBUF, 0x00 // Write to the transmit buffer to prevent underflow 682 MCASP_REG_WRITE_EXT MCASP_XBUF, 0x00 // Write to the transmit buffer to prevent underflow
508 683
509 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 4) // Set RFRST 684 MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 4) // Set RFRST
510 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 12) // Set XFRST 685 MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 12) // Set XFRST
511 686
512 // Initialisation 687 // Initialisation
513 LBBO reg_frame_total, reg_comm_addr, COMM_BUFFER_FRAMES, 4 // Total frame count (SPI; 0.5x-2x for McASP) 688 LBBO reg_frame_total, reg_comm_addr, COMM_BUFFER_FRAMES, 4 // Total frame count (SPI; 0.5x-2x for McASP)
514 MOV reg_dac_buf0, 0 // DAC buffer 0 start pointer 689 MOV reg_dac_buf0, 0 // DAC buffer 0 start pointer
515 LSL reg_dac_buf1, reg_frame_total, 1 // DAC buffer 1 start pointer = N[ch]*2[bytes]*bufsize 690 LSL reg_dac_buf1, reg_frame_total, 1 // DAC buffer 1 start pointer = N[ch]*2[bytes]*bufsize
516 LMBD r2, reg_num_channels, 1 // Returns 1, 2 or 3 depending on the number of channels 691 LMBD r2, reg_num_channels, 1 // Returns 1, 2 or 3 depending on the number of channels
517 LSL reg_dac_buf1, reg_dac_buf1, r2 // Multiply by 2, 4 or 8 to get the N[ch] scaling above 692 LSL reg_dac_buf1, reg_dac_buf1, r2 // Multiply by 2, 4 or 8 to get the N[ch] scaling above
518 MOV reg_mcasp_buf0, 0 // McASP DAC buffer 0 start pointer 693 MOV reg_mcasp_buf0, 0 // McASP DAC buffer 0 start pointer
519 LSL reg_mcasp_buf1, reg_frame_total, r2 // McASP DAC buffer 1 start pointer = 2[ch]*2[bytes]*(N/4)[samples/spi]*bufsize 694 LSL reg_mcasp_buf1, reg_frame_total, r2 // McASP DAC buffer 1 start pointer = 2[ch]*2[bytes]*(N/4)[samples/spi]*bufsize
520 CLR reg_flags, reg_flags, FLAG_BIT_BUFFER1 // Bit 0 holds which buffer we are on 695 CLR reg_flags, reg_flags, FLAG_BIT_BUFFER1 // Bit 0 holds which buffer we are on
521 MOV r2, 0 696 MOV r2, 0
522 SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 // Start with frame count of 0 697 SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 // Start with frame count of 0
523 698
524 // Here we are out of sync by one TDM slot since the 0 word transmitted above will have occupied 699 // Here we are out of sync by one TDM slot since the 0 word transmitted above will have occupied
525 // the first output slot. Send one more word before jumping into the loop. 700 // the first output slot. Send one more word before jumping into the loop.
526 MCASP_DAC_WAIT_BEFORE_LOOP: 701 MCASP_DAC_WAIT_BEFORE_LOOP:
527 LBBO r2, reg_mcasp_addr, MCASP_XSTAT, 4 702 LBBO r2, reg_mcasp_addr, MCASP_XSTAT, 4