Mercurial > hg > beaglert
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 |