Mercurial > hg > beaglert
comparison pru_rtaudio.p @ 102:31ca45939a0c
Uniformed formatting of pru_rtaudio.p (had a busy day): indent is 4 spaces throughout, hopefully
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Mon, 27 Jul 2015 13:00:25 +0100 |
parents | b697e82ebb25 |
children | c706be7daad7 |
comparison
equal
deleted
inserted
replaced
101:04f894424a8c | 102:31ca45939a0c |
---|---|
382 //regardless of whether the order is gpio1-gpio2 or gpio2-gpio1 | 382 //regardless of whether the order is gpio1-gpio2 or gpio2-gpio1 |
383 JMP r28.w0 // go back to ADC_WRITE_AND_PROCESS_GPIO | 383 JMP r28.w0 // go back to ADC_WRITE_AND_PROCESS_GPIO |
384 | 384 |
385 .macro HANG //useful for debugging | 385 .macro HANG //useful for debugging |
386 DALOOP: | 386 DALOOP: |
387 set r30.t14 | 387 set r30.t14 |
388 clr r30.t14 | 388 clr r30.t14 |
389 QBA DALOOP | 389 QBA DALOOP |
390 .endm | 390 .endm |
391 | 391 |
392 // Bring CS line low to write to DAC | 392 // Bring CS line low to write to DAC |
393 .macro DAC_CS_ASSERT | 393 .macro DAC_CS_ASSERT |
394 MOV r27, DAC_CS_PIN | 394 MOV r27, DAC_CS_PIN |
395 MOV r28, DAC_GPIO + GPIO_CLEARDATAOUT | 395 MOV r28, DAC_GPIO + GPIO_CLEARDATAOUT |
396 SBBO r27, r28, 0, 4 | 396 SBBO r27, r28, 0, 4 |
397 .endm | 397 .endm |
398 | 398 |
399 // Bring CS line high at end of DAC transaction | 399 // Bring CS line high at end of DAC transaction |
400 .macro DAC_CS_UNASSERT | 400 .macro DAC_CS_UNASSERT |
401 MOV r27, DAC_CS_PIN | 401 MOV r27, DAC_CS_PIN |
402 MOV r28, DAC_GPIO + GPIO_SETDATAOUT | 402 MOV r28, DAC_GPIO + GPIO_SETDATAOUT |
403 SBBO r27, r28, 0, 4 | 403 SBBO r27, r28, 0, 4 |
404 .endm | 404 .endm |
405 | 405 |
406 // Write to DAC TX register | 406 // Write to DAC TX register |
407 .macro DAC_TX | 407 .macro DAC_TX |
408 .mparam data | 408 .mparam data |
410 .endm | 410 .endm |
411 | 411 |
412 // Wait for SPI to finish (uses RXS indicator) | 412 // Wait for SPI to finish (uses RXS indicator) |
413 .macro DAC_WAIT_FOR_FINISH | 413 .macro DAC_WAIT_FOR_FINISH |
414 LOOP: | 414 LOOP: |
415 LBBO r27, reg_spi_addr, SPI_CH0STAT, 4 | 415 LBBO r27, reg_spi_addr, SPI_CH0STAT, 4 |
416 QBBC LOOP, r27, 0 | 416 QBBC LOOP, r27, 0 |
417 .endm | 417 .endm |
418 | 418 |
419 // Read the RX word to clear | 419 // Read the RX word to clear |
420 .macro DAC_DISCARD_RX | 420 .macro DAC_DISCARD_RX |
421 LBBO r27, reg_spi_addr, SPI_CH0RX, 4 | 421 LBBO r27, reg_spi_addr, SPI_CH0RX, 4 |
422 .endm | 422 .endm |
423 | 423 |
424 // Complete DAC write with chip select | 424 // Complete DAC write with chip select |
425 .macro DAC_WRITE | 425 .macro DAC_WRITE |
426 .mparam reg | 426 .mparam reg |
427 DAC_CS_ASSERT | 427 DAC_CS_ASSERT |
428 DAC_TX reg | 428 DAC_TX reg |
429 DAC_WAIT_FOR_FINISH | 429 DAC_WAIT_FOR_FINISH |
430 DAC_CS_UNASSERT | 430 DAC_CS_UNASSERT |
431 DAC_DISCARD_RX | 431 DAC_DISCARD_RX |
432 .endm | 432 .endm |
433 | 433 |
434 // Bring CS line low to write to ADC | 434 // Bring CS line low to write to ADC |
435 .macro ADC_CS_ASSERT | 435 .macro ADC_CS_ASSERT |
436 MOV r27, ADC_CS_PIN | 436 MOV r27, ADC_CS_PIN |
437 MOV r28, ADC_GPIO + GPIO_CLEARDATAOUT | 437 MOV r28, ADC_GPIO + GPIO_CLEARDATAOUT |
438 SBBO r27, r28, 0, 4 | 438 SBBO r27, r28, 0, 4 |
439 .endm | 439 .endm |
440 | 440 |
441 // Bring CS line high at end of ADC transaction | 441 // Bring CS line high at end of ADC transaction |
442 .macro ADC_CS_UNASSERT | 442 .macro ADC_CS_UNASSERT |
443 MOV r27, ADC_CS_PIN | 443 MOV r27, ADC_CS_PIN |
444 MOV r28, ADC_GPIO + GPIO_SETDATAOUT | 444 MOV r28, ADC_GPIO + GPIO_SETDATAOUT |
445 SBBO r27, r28, 0, 4 | 445 SBBO r27, r28, 0, 4 |
446 .endm | 446 .endm |
447 | 447 |
448 // Write to ADC TX register | 448 // Write to ADC TX register |
449 .macro ADC_TX | 449 .macro ADC_TX |
450 .mparam data | 450 .mparam data |
451 SBBO data, reg_spi_addr, SPI_CH1TX, 4 | 451 SBBO data, reg_spi_addr, SPI_CH1TX, 4 |
452 .endm | 452 .endm |
453 | 453 |
454 // Wait for SPI to finish (uses RXS indicator) | 454 // Wait for SPI to finish (uses RXS indicator) |
455 .macro ADC_WAIT_FOR_FINISH | 455 .macro ADC_WAIT_FOR_FINISH |
456 LOOP: | 456 LOOP: |
457 LBBO r27, reg_spi_addr, SPI_CH1STAT, 4 | 457 LBBO r27, reg_spi_addr, SPI_CH1STAT, 4 |
458 QBBC LOOP, r27, 0 | 458 QBBC LOOP, r27, 0 |
459 .endm | 459 .endm |
460 | 460 |
461 // Read the RX word to clear; store output | 461 // Read the RX word to clear; store output |
462 .macro ADC_RX | 462 .macro ADC_RX |
463 .mparam data | 463 .mparam data |
464 LBBO data, reg_spi_addr, SPI_CH1RX, 4 | 464 LBBO data, reg_spi_addr, SPI_CH1RX, 4 |
465 .endm | 465 .endm |
466 | 466 |
467 // Complete ADC write+read with chip select | 467 // Complete ADC write+read with chip select |
468 .macro ADC_WRITE | 468 .macro ADC_WRITE |
469 .mparam in, out | 469 .mparam in, out |
470 ADC_CS_ASSERT | 470 ADC_CS_ASSERT |
471 ADC_TX in | 471 ADC_TX in |
472 ADC_WAIT_FOR_FINISH | 472 ADC_WAIT_FOR_FINISH |
473 ADC_RX out | 473 ADC_RX out |
474 ADC_CS_UNASSERT | 474 ADC_CS_UNASSERT |
475 .endm | 475 .endm |
476 | 476 |
477 // Complete ADC write+read with chip select and also performs IO for digital | 477 // Complete ADC write+read with chip select and also performs IO for digital |
478 .macro ADC_WRITE_GPIO | 478 .macro ADC_WRITE_GPIO |
479 .mparam in, out, do_gpio | 479 .mparam in, out, do_gpio |
480 ADC_CS_ASSERT | 480 ADC_CS_ASSERT |
481 ADC_TX in | 481 ADC_TX in |
482 QBBC GPIO_DONE, reg_flags, FLAG_BIT_USE_DIGITAL //skip if DIGITAL is disabled | 482 QBBC GPIO_DONE, reg_flags, FLAG_BIT_USE_DIGITAL //skip if DIGITAL is disabled |
483 AND r27, do_gpio, 0x3 // only do a DIGITAL every 2 SPI I/O | 483 AND r27, do_gpio, 0x3 // only do a DIGITAL every 2 SPI I/O |
484 QBNE GPIO_DONE, r27, 0 | 484 QBNE GPIO_DONE, r27, 0 |
485 //from here to GPIO_DONE takes 1.8us, while usually ADC_WAIT_FOR_FINISH only waits for 1.14us. | 485 //from here to GPIO_DONE takes 1.8us, while usually ADC_WAIT_FOR_FINISH only waits for 1.14us. |
486 //TODO: it would be better to split the DIGITAL stuff in two parts: | 486 //TODO: it would be better to split the DIGITAL stuff in two parts: |
487 //- one taking place during DAC_WRITE which sets the GPIO_OE | 487 //- one taking place during DAC_WRITE which sets the GPIO_OE |
488 //- and the other during ADC_WRITE which actually reads DATAIN and writes CLEAR/SET DATAOUT | 488 //- and the other during ADC_WRITE which actually reads DATAIN and writes CLEAR/SET DATAOUT |
489 //r27 is actually r27, so do not use r27 from here to ... | 489 //r27 is actually r27, so do not use r27 from here to ... |
490 LBBO r27, reg_digital_current, 0, 4 | 490 LBBO r27, reg_digital_current, 0, 4 |
491 JAL r28.w0, DIGITAL // note that this is not called as a macro, but with JAL. r28 will contain the return address | 491 JAL r28.w0, DIGITAL // note that this is not called as a macro, but with JAL. r28 will contain the return address |
492 SBBO r27, reg_digital_current, 0, 4 | 492 SBBO r27, reg_digital_current, 0, 4 |
493 //..here you can start using r27 again | 493 //..here you can start using r27 again |
494 ADD reg_digital_current, reg_digital_current, 4 //increment pointer | 494 ADD reg_digital_current, reg_digital_current, 4 //increment pointer |
495 GPIO_DONE: | 495 GPIO_DONE: |
496 ADC_WAIT_FOR_FINISH | 496 ADC_WAIT_FOR_FINISH |
497 ADC_RX out | 497 ADC_RX out |
498 ADC_CS_UNASSERT | 498 ADC_CS_UNASSERT |
499 .endm | 499 .endm |
500 | 500 |
501 // Write a McASP register | 501 // Write a McASP register |
502 .macro MCASP_REG_WRITE | 502 .macro MCASP_REG_WRITE |
503 .mparam reg, value | 503 .mparam reg, value |
504 MOV r27, value | 504 MOV r27, value |
505 SBBO r27, reg_mcasp_addr, reg, 4 | 505 SBBO r27, reg_mcasp_addr, reg, 4 |
506 .endm | 506 .endm |
507 | 507 |
508 // Write a McASP register beyond the 0xFF boundary | 508 // Write a McASP register beyond the 0xFF boundary |
509 .macro MCASP_REG_WRITE_EXT | 509 .macro MCASP_REG_WRITE_EXT |
510 .mparam reg, value | 510 .mparam reg, value |
511 MOV r27, value | 511 MOV r27, value |
512 MOV r28, reg | 512 MOV r28, reg |
513 ADD r28, reg_mcasp_addr, r28 | 513 ADD r28, reg_mcasp_addr, r28 |
514 SBBO r27, r28, 0, 4 | 514 SBBO r27, r28, 0, 4 |
515 .endm | 515 .endm |
516 | 516 |
517 // Read a McASP register | 517 // Read a McASP register |
518 .macro MCASP_REG_READ | 518 .macro MCASP_REG_READ |
519 .mparam reg, value | 519 .mparam reg, value |
520 LBBO value, reg_mcasp_addr, reg, 4 | 520 LBBO value, reg_mcasp_addr, reg, 4 |
521 .endm | 521 .endm |
522 | 522 |
523 // Read a McASP register beyond the 0xFF boundary | 523 // Read a McASP register beyond the 0xFF boundary |
524 .macro MCASP_REG_READ_EXT | 524 .macro MCASP_REG_READ_EXT |
525 .mparam reg, value | 525 .mparam reg, value |
526 MOV r28, reg | 526 MOV r28, reg |
527 ADD r28, reg_mcasp_addr, r28 | 527 ADD r28, reg_mcasp_addr, r28 |
528 LBBO value, r28, 0, 4 | 528 LBBO value, r28, 0, 4 |
529 .endm | 529 .endm |
530 | 530 |
531 // Set a bit and wait for it to come up | 531 // Set a bit and wait for it to come up |
532 .macro MCASP_REG_SET_BIT_AND_POLL | 532 .macro MCASP_REG_SET_BIT_AND_POLL |
533 .mparam reg, mask | 533 .mparam reg, mask |
534 MOV r27, mask | 534 MOV r27, mask |
535 LBBO r28, reg_mcasp_addr, reg, 4 | 535 LBBO r28, reg_mcasp_addr, reg, 4 |
536 OR r28, r28, r27 | 536 OR r28, r28, r27 |
537 SBBO r28, reg_mcasp_addr, reg, 4 | 537 SBBO r28, reg_mcasp_addr, reg, 4 |
538 POLL: | 538 POLL: |
539 LBBO r28, reg_mcasp_addr, reg, 4 | 539 LBBO r28, reg_mcasp_addr, reg, 4 |
540 AND r28, r28, r27 | 540 AND r28, r28, r27 |
541 QBEQ POLL, r28, 0 | 541 QBEQ POLL, r28, 0 |
542 .endm | 542 .endm |
543 | 543 |
544 START: | 544 START: |
545 // Set up c24 and c25 offsets with CTBIR register | 545 // Set up c24 and c25 offsets with CTBIR register |
546 // Thus C24 points to start of PRU0 RAM | 546 // Thus C24 points to start of PRU0 RAM |
547 MOV r3, 0x22020 // CTBIR0 | 547 MOV r3, 0x22020 // CTBIR0 |
548 MOV r2, 0 | 548 MOV r2, 0 |
549 SBBO r2, r3, 0, 4 | 549 SBBO r2, r3, 0, 4 |
550 | 550 |
551 // Set up c28 pointer offset for shared PRU RAM | 551 // Set up c28 pointer offset for shared PRU RAM |
552 MOV r3, 0x22028 // CTPPR0 | 552 MOV r3, 0x22028 // CTPPR0 |
553 MOV r2, 0x00000120 // To get address 0x00012000 | 553 MOV r2, 0x00000120 // To get address 0x00012000 |
554 SBBO r2, r3, 0, 4 | 554 SBBO r2, r3, 0, 4 |
555 | 555 |
556 // Load useful registers for addressing SPI | 556 // Load useful registers for addressing SPI |
557 MOV reg_comm_addr, SHARED_COMM_MEM_BASE | 557 MOV reg_comm_addr, SHARED_COMM_MEM_BASE |
558 MOV reg_spi_addr, SPI_BASE | 558 MOV reg_spi_addr, SPI_BASE |
559 MOV reg_mcasp_addr, MCASP_BASE | 559 MOV reg_mcasp_addr, MCASP_BASE |
560 | 560 |
561 // Set ARM such that PRU can write to registers | 561 // Set ARM such that PRU can write to registers |
562 LBCO r0, C4, 4, 4 | 562 LBCO r0, C4, 4, 4 |
563 CLR r0, r0, 4 | 563 CLR r0, r0, 4 |
564 SBCO r0, C4, 4, 4 | 564 SBCO r0, C4, 4, 4 |
565 | 565 |
566 // Clear flags | 566 // Clear flags |
567 MOV reg_flags, 0 | 567 MOV reg_flags, 0 |
568 | 568 // Default number of channels in case SPI disabled |
569 // Default number of channels in case SPI disabled | 569 LDI reg_num_channels, 8 |
570 LDI reg_num_channels, 8 | 570 |
571 | 571 // Find out whether we should use DIGITAL |
572 // Find out whether we should use DIGITAL | 572 LBBO r2, reg_comm_addr, COMM_USE_DIGITAL, 4 |
573 LBBO r2, reg_comm_addr, COMM_USE_DIGITAL, 4 | 573 QBEQ DIGITAL_INIT_DONE, r2, 0 // if we use digital |
574 QBEQ DIGITAL_INIT_DONE, r2, 0 // if we use digital | 574 SET reg_flags, reg_flags, FLAG_BIT_USE_DIGITAL |
575 SET reg_flags, reg_flags, FLAG_BIT_USE_DIGITAL | |
576 /* This block of code is not really needed, as the memory is initialized by ARM before the PRU is started. | 575 /* This block of code is not really needed, as the memory is initialized by ARM before the PRU is started. |
577 Will leave it here for future reference | 576 Will leave it here for future reference |
578 DIGITAL_INIT: //set the digital buffer to 0x0000ffff (all inputs), to prevent unwanted high outputs | 577 DIGITAL_INIT: //set the digital buffer to 0x0000ffff (all inputs), to prevent unwanted high outputs |
579 //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 | 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 |
580 MOV r2, 0x0000ffff //value to store. 0x0000ffff means all inputs | 579 MOV r2, 0x0000ffff //value to store. 0x0000ffff means all inputs |
581 MOV r3, MEM_DIGITAL_BASE //start of the digital buffer | 580 MOV r3, MEM_DIGITAL_BASE //start of the digital buffer |
582 MOV r4, MEM_DIGITAL_BASE+2*MEM_DIGITAL_BUFFER1_OFFSET //end of the digital buffer | 581 MOV r4, MEM_DIGITAL_BASE+2*MEM_DIGITAL_BUFFER1_OFFSET //end of the digital buffer |
583 DIGITAL_INIT_BUFFER_LOOP: | 582 DIGITAL_INIT_BUFFER_LOOP: |
584 SBBO r2, r3, 0, 4 | 583 SBBO r2, r3, 0, 4 |
585 ADD r3, r3, 4 //increment pointer | 584 ADD r3, r3, 4 //increment pointer |
586 QBGT DIGITAL_INIT_BUFFER_LOOP, r3, r4 //loop until we reach the end of the buffer | 585 QBGT DIGITAL_INIT_BUFFER_LOOP, r3, r4 //loop until we reach the end of the buffer |
587 */ | 586 */ |
588 DIGITAL_INIT_DONE: | 587 DIGITAL_INIT_DONE: |
589 // Find out whether we should use SPI ADC and DAC | 588 // Find out whether we should use SPI ADC and DAC |
590 LBBO r2, reg_comm_addr, COMM_USE_SPI, 4 | 589 LBBO r2, reg_comm_addr, COMM_USE_SPI, 4 |
591 QBEQ SPI_FLAG_CHECK_DONE, r2, 0 | 590 QBEQ SPI_FLAG_CHECK_DONE, r2, 0 |
592 SET reg_flags, reg_flags, FLAG_BIT_USE_SPI | 591 SET reg_flags, reg_flags, FLAG_BIT_USE_SPI |
593 SPI_FLAG_CHECK_DONE: | 592 SPI_FLAG_CHECK_DONE: |
594 // If we don't use SPI, then skip all this init | 593 // If we don't use SPI, then skip all this init |
595 QBBC SPI_INIT_DONE, reg_flags, FLAG_BIT_USE_SPI | 594 QBBC SPI_INIT_DONE, reg_flags, FLAG_BIT_USE_SPI |
596 | 595 |
597 // 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 |
598 LBBO reg_num_channels, reg_comm_addr, COMM_NUM_CHANNELS, 4 | 597 LBBO reg_num_channels, reg_comm_addr, COMM_NUM_CHANNELS, 4 |
599 QBGT SPI_NUM_CHANNELS_LT8, reg_num_channels, 8 // 8 > num_channels ? | 598 QBGT SPI_NUM_CHANNELS_LT8, reg_num_channels, 8 // 8 > num_channels ? |
600 LDI reg_num_channels, 8 // If N >= 8, N = 8 | 599 LDI reg_num_channels, 8 // If N >= 8, N = 8 |
601 QBA SPI_NUM_CHANNELS_DONE | 600 QBA SPI_NUM_CHANNELS_DONE |
602 SPI_NUM_CHANNELS_LT8: | 601 SPI_NUM_CHANNELS_LT8: |
603 QBGT SPI_NUM_CHANNELS_LT4, reg_num_channels, 4 // 4 > num_channels ? | 602 QBGT SPI_NUM_CHANNELS_LT4, reg_num_channels, 4 // 4 > num_channels ? |
604 LDI reg_num_channels, 4 // If N >= 4, N = 4 | 603 LDI reg_num_channels, 4 // If N >= 4, N = 4 |
605 QBA SPI_NUM_CHANNELS_DONE | 604 QBA SPI_NUM_CHANNELS_DONE |
606 SPI_NUM_CHANNELS_LT4: | 605 SPI_NUM_CHANNELS_LT4: |
607 LDI reg_num_channels, 2 // else N = 2 | 606 LDI reg_num_channels, 2 // else N = 2 |
608 SPI_NUM_CHANNELS_DONE: | 607 SPI_NUM_CHANNELS_DONE: |
609 | 608 |
610 // Init SPI clock | 609 // Init SPI clock |
611 MOV r2, 0x02 | 610 MOV r2, 0x02 |
612 MOV r3, CLOCK_BASE + CLOCK_SPI0 | 611 MOV r3, CLOCK_BASE + CLOCK_SPI0 |
613 SBBO r2, r3, 0, 4 | 612 SBBO r2, r3, 0, 4 |
614 | 613 |
615 // Reset SPI and wait for finish | 614 // Reset SPI and wait for finish |
616 MOV r2, 0x02 | 615 MOV r2, 0x02 |
617 SBBO r2, reg_spi_addr, SPI_SYSCONFIG, 4 | 616 SBBO r2, reg_spi_addr, SPI_SYSCONFIG, 4 |
618 | 617 |
619 SPI_WAIT_RESET: | 618 SPI_WAIT_RESET: |
620 LBBO r2, reg_spi_addr, SPI_SYSSTATUS, 4 | 619 LBBO r2, reg_spi_addr, SPI_SYSSTATUS, 4 |
621 QBBC SPI_WAIT_RESET, r2, 0 | 620 QBBC SPI_WAIT_RESET, r2, 0 |
622 | 621 |
623 // Turn off SPI channels | 622 // Turn off SPI channels |
624 MOV r2, 0 | 623 MOV r2, 0 |
625 SBBO r2, reg_spi_addr, SPI_CH0CTRL, 4 | 624 SBBO r2, reg_spi_addr, SPI_CH0CTRL, 4 |
626 SBBO r2, reg_spi_addr, SPI_CH1CTRL, 4 | 625 SBBO r2, reg_spi_addr, SPI_CH1CTRL, 4 |
627 | 626 |
628 // Set to master; chip select lines enabled (CS0 used for DAC) | 627 // Set to master; chip select lines enabled (CS0 used for DAC) |
629 MOV r2, 0x00 | 628 MOV r2, 0x00 |
630 SBBO r2, reg_spi_addr, SPI_MODULCTRL, 4 | 629 SBBO r2, reg_spi_addr, SPI_MODULCTRL, 4 |
631 | 630 |
632 // Configure CH0 for DAC | 631 // Configure CH0 for DAC |
633 MOV r2, (3 << 27) | (DAC_DPE << 16) | (DAC_TRM << 12) | ((DAC_WL - 1) << 7) | (DAC_CLK_DIV << 2) | DAC_CLK_MODE | (1 << 6) | 632 MOV r2, (3 << 27) | (DAC_DPE << 16) | (DAC_TRM << 12) | ((DAC_WL - 1) << 7) | (DAC_CLK_DIV << 2) | DAC_CLK_MODE | (1 << 6) |
634 SBBO r2, reg_spi_addr, SPI_CH0CONF, 4 | 633 SBBO r2, reg_spi_addr, SPI_CH0CONF, 4 |
635 | 634 |
636 // Configure CH1 for ADC | 635 // Configure CH1 for ADC |
637 MOV r2, (3 << 27) | (ADC_DPE << 16) | (ADC_TRM << 12) | ((ADC_WL - 1) << 7) | (ADC_CLK_DIV << 2) | ADC_CLK_MODE | 636 MOV r2, (3 << 27) | (ADC_DPE << 16) | (ADC_TRM << 12) | ((ADC_WL - 1) << 7) | (ADC_CLK_DIV << 2) | ADC_CLK_MODE |
638 SBBO r2, reg_spi_addr, SPI_CH1CONF, 4 | 637 SBBO r2, reg_spi_addr, SPI_CH1CONF, 4 |
639 | 638 |
640 // Turn on SPI channels | 639 // Turn on SPI channels |
641 MOV r2, 0x01 | 640 MOV r2, 0x01 |
642 SBBO r2, reg_spi_addr, SPI_CH0CTRL, 4 | 641 SBBO r2, reg_spi_addr, SPI_CH0CTRL, 4 |
643 SBBO r2, reg_spi_addr, SPI_CH1CTRL, 4 | 642 SBBO r2, reg_spi_addr, SPI_CH1CTRL, 4 |
644 | 643 |
645 // DAC power-on reset sequence | 644 // DAC power-on reset sequence |
646 MOV r2, (0x07 << AD5668_COMMAND_OFFSET) | 645 MOV r2, (0x07 << AD5668_COMMAND_OFFSET) |
647 DAC_WRITE r2 | 646 DAC_WRITE r2 |
648 | 647 |
649 // Initialise ADC | 648 // Initialise ADC |
650 MOV r2, AD7699_CFG_MASK | (0 << AD7699_CHANNEL_OFFSET) | (0 << AD7699_SEQ_OFFSET) | 649 MOV r2, AD7699_CFG_MASK | (0 << AD7699_CHANNEL_OFFSET) | (0 << AD7699_SEQ_OFFSET) |
651 ADC_WRITE r2, r2 | 650 ADC_WRITE r2, r2 |
652 | 651 |
653 // Enable DAC internal reference | 652 // Enable DAC internal reference |
654 MOV r2, (0x08 << AD5668_COMMAND_OFFSET) | (0x01 << AD5668_REF_OFFSET) | 653 MOV r2, (0x08 << AD5668_COMMAND_OFFSET) | (0x01 << AD5668_REF_OFFSET) |
655 DAC_WRITE r2 | 654 DAC_WRITE r2 |
656 | 655 |
657 // Read ADC ch0 and ch1: result is always 2 samples behind so start here | 656 // Read ADC ch0 and ch1: result is always 2 samples behind so start here |
658 MOV r2, AD7699_CFG_MASK | (0x00 << AD7699_CHANNEL_OFFSET) | 657 MOV r2, AD7699_CFG_MASK | (0x00 << AD7699_CHANNEL_OFFSET) |
659 ADC_WRITE r2, r2 | 658 ADC_WRITE r2, r2 |
660 | 659 |
661 MOV r2, AD7699_CFG_MASK | (0x01 << AD7699_CHANNEL_OFFSET) | 660 MOV r2, AD7699_CFG_MASK | (0x01 << AD7699_CHANNEL_OFFSET) |
662 ADC_WRITE r2, r2 | 661 ADC_WRITE r2, r2 |
663 SPI_INIT_DONE: | 662 SPI_INIT_DONE: |
664 | 663 |
665 // Prepare McASP0 for audio | 664 // Prepare McASP0 for audio |
666 MCASP_REG_WRITE MCASP_GBLCTL, 0 // Disable McASP | 665 MCASP_REG_WRITE MCASP_GBLCTL, 0 // Disable McASP |
667 MCASP_REG_WRITE_EXT MCASP_SRCTL0, 0 // All serialisers off | 666 MCASP_REG_WRITE_EXT MCASP_SRCTL0, 0 // All serialisers off |
668 MCASP_REG_WRITE_EXT MCASP_SRCTL1, 0 | 667 MCASP_REG_WRITE_EXT MCASP_SRCTL1, 0 |
669 MCASP_REG_WRITE_EXT MCASP_SRCTL2, 0 | 668 MCASP_REG_WRITE_EXT MCASP_SRCTL2, 0 |
670 MCASP_REG_WRITE_EXT MCASP_SRCTL3, 0 | 669 MCASP_REG_WRITE_EXT MCASP_SRCTL3, 0 |
671 MCASP_REG_WRITE_EXT MCASP_SRCTL4, 0 | 670 MCASP_REG_WRITE_EXT MCASP_SRCTL4, 0 |
672 MCASP_REG_WRITE_EXT MCASP_SRCTL5, 0 | 671 MCASP_REG_WRITE_EXT MCASP_SRCTL5, 0 |
673 | 672 |
674 MCASP_REG_WRITE MCASP_PWRIDLESYSCONFIG, 0x02 // Power on | 673 MCASP_REG_WRITE MCASP_PWRIDLESYSCONFIG, 0x02 // Power on |
675 MCASP_REG_WRITE MCASP_PFUNC, 0x00 // All pins are McASP | 674 MCASP_REG_WRITE MCASP_PFUNC, 0x00 // All pins are McASP |
676 MCASP_REG_WRITE MCASP_PDIR, MCASP_OUTPUT_PINS // Set pin direction | 675 MCASP_REG_WRITE MCASP_PDIR, MCASP_OUTPUT_PINS // Set pin direction |
677 MCASP_REG_WRITE MCASP_DLBCTL, 0x00 | 676 MCASP_REG_WRITE MCASP_DLBCTL, 0x00 |
678 MCASP_REG_WRITE MCASP_DITCTL, 0x00 | 677 MCASP_REG_WRITE MCASP_DITCTL, 0x00 |
679 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 |
680 MCASP_REG_WRITE MCASP_RFMT, MCASP_DATA_FORMAT // Set data format | 679 MCASP_REG_WRITE MCASP_RFMT, MCASP_DATA_FORMAT // Set data format |
681 MCASP_REG_WRITE MCASP_AFSRCTL, 0x100 // I2S mode | 680 MCASP_REG_WRITE MCASP_AFSRCTL, 0x100 // I2S mode |
682 MCASP_REG_WRITE MCASP_ACLKRCTL, 0x80 // Sample on rising edge | 681 MCASP_REG_WRITE MCASP_ACLKRCTL, 0x80 // Sample on rising edge |
683 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? |
684 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 |
685 MCASP_REG_WRITE MCASP_RINTCTL, 0x00 // No interrupts | 684 MCASP_REG_WRITE MCASP_RINTCTL, 0x00 // No interrupts |
686 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 |
687 MCASP_REG_WRITE MCASP_XFMT, MCASP_DATA_FORMAT // Set data format | 686 MCASP_REG_WRITE MCASP_XFMT, MCASP_DATA_FORMAT // Set data format |
688 MCASP_REG_WRITE MCASP_AFSXCTL, 0x100 // I2S mode | 687 MCASP_REG_WRITE MCASP_AFSXCTL, 0x100 // I2S mode |
689 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 |
690 MCASP_REG_WRITE MCASP_AHCLKXCTL, 0x8001 // External clock from AHCLKX | 689 MCASP_REG_WRITE MCASP_AHCLKXCTL, 0x8001 // External clock from AHCLKX |
691 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 |
692 MCASP_REG_WRITE MCASP_XINTCTL, 0x00 // No interrupts | 691 MCASP_REG_WRITE MCASP_XINTCTL, 0x00 // No interrupts |
693 | 692 |
694 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 |
695 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 |
696 MCASP_REG_WRITE_EXT MCASP_WFIFOCTL, 0x00 // Disable FIFOs | 695 MCASP_REG_WRITE_EXT MCASP_WFIFOCTL, 0x00 // Disable FIFOs |
697 MCASP_REG_WRITE_EXT MCASP_RFIFOCTL, 0x00 | 696 MCASP_REG_WRITE_EXT MCASP_RFIFOCTL, 0x00 |
698 | 697 |
699 MCASP_REG_WRITE MCASP_XSTAT, 0xFF // Clear transmit errors | 698 MCASP_REG_WRITE MCASP_XSTAT, 0xFF // Clear transmit errors |
700 MCASP_REG_WRITE MCASP_RSTAT, 0xFF // Clear receive errors | 699 MCASP_REG_WRITE MCASP_RSTAT, 0xFF // Clear receive errors |
701 | 700 |
702 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 |
703 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 |
704 | 703 |
705 // The above write sequence will have temporarily changed the AHCLKX frequency | 704 // The above write sequence will have temporarily changed the AHCLKX frequency |
706 // 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 |
707 // cause an underrun. Give it ~1ms before going on. | 706 // cause an underrun. Give it ~1ms before going on. |
708 // 10ns per loop iteration = 10^-8s --> 10^5 iterations needed | 707 // 10ns per loop iteration = 10^-8s --> 10^5 iterations needed |
709 | 708 |
710 MOV r2, 1 << 28 | 709 MOV r2, 1 << 28 |
711 MOV r3, GPIO1 + GPIO_SETDATAOUT | 710 MOV r3, GPIO1 + GPIO_SETDATAOUT |
712 SBBO r2, r3, 0, 4 | 711 SBBO r2, r3, 0, 4 |
713 | 712 |
714 MOV r2, 100000 | 713 MOV r2, 100000 |
715 MCASP_INIT_WAIT: | 714 MCASP_INIT_WAIT: |
716 SUB r2, r2, 1 | 715 SUB r2, r2, 1 |
717 QBNE MCASP_INIT_WAIT, r2, 0 | 716 QBNE MCASP_INIT_WAIT, r2, 0 |
718 | 717 |
719 MOV r2, 1 << 28 | 718 MOV r2, 1 << 28 |
720 MOV r3, GPIO1 + GPIO_CLEARDATAOUT | 719 MOV r3, GPIO1 + GPIO_CLEARDATAOUT |
721 SBBO r2, r3, 0, 4 | 720 SBBO r2, r3, 0, 4 |
722 | 721 |
723 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 |
724 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 |
725 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 |
726 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 |
727 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 |
777 QBGT MCASP_INIT_BUFFER_LOOP, r3, r4 | 776 QBGT MCASP_INIT_BUFFER_LOOP, r3, r4 |
778 */ | 777 */ |
779 // 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 |
780 // 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. |
781 MCASP_DAC_WAIT_BEFORE_LOOP: | 780 MCASP_DAC_WAIT_BEFORE_LOOP: |
782 LBBO r2, reg_mcasp_addr, MCASP_XSTAT, 4 | 781 LBBO r2, reg_mcasp_addr, MCASP_XSTAT, 4 |
783 QBBC MCASP_DAC_WAIT_BEFORE_LOOP, r2, MCASP_XSTAT_XDATA_BIT | 782 QBBC MCASP_DAC_WAIT_BEFORE_LOOP, r2, MCASP_XSTAT_XDATA_BIT |
784 | 783 |
785 MCASP_REG_WRITE_EXT MCASP_XBUF, 0x00 | 784 MCASP_REG_WRITE_EXT MCASP_XBUF, 0x00 |
786 | 785 |
787 // Likewise, read and discard the first sample we get back from the ADC. This keeps the DAC and ADC | 786 // Likewise, read and discard the first sample we get back from the ADC. This keeps the DAC and ADC |
788 // in sync in terms of which TDM slot we are reading (empirically found that we should throw this away | 787 // in sync in terms of which TDM slot we are reading (empirically found that we should throw this away |
789 // rather than keep it and invert the phase) | 788 // rather than keep it and invert the phase) |
790 MCASP_ADC_WAIT_BEFORE_LOOP: | 789 MCASP_ADC_WAIT_BEFORE_LOOP: |
791 LBBO r2, reg_mcasp_addr, MCASP_RSTAT, 4 | 790 LBBO r2, reg_mcasp_addr, MCASP_RSTAT, 4 |
792 QBBC MCASP_ADC_WAIT_BEFORE_LOOP, r2, MCASP_RSTAT_RDATA_BIT | 791 QBBC MCASP_ADC_WAIT_BEFORE_LOOP, r2, MCASP_RSTAT_RDATA_BIT |
793 | 792 |
794 MCASP_REG_READ_EXT MCASP_RBUF, r2 | 793 MCASP_REG_READ_EXT MCASP_RBUF, r2 |
795 | 794 |
796 WRITE_ONE_BUFFER: | 795 WRITE_ONE_BUFFER: |
797 | 796 |
798 // 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 |
799 // Load starting positions | 798 // Load starting positions |
800 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 |
801 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 |
802 LSL reg_adc_current, reg_frame_total, r2 | 801 LSL reg_adc_current, reg_frame_total, r2 |
803 LSL reg_adc_current, reg_adc_current, 2 // N * 2 * 2 * bufsize | 802 LSL reg_adc_current, reg_adc_current, 2 // N * 2 * 2 * bufsize |
804 ADD reg_adc_current, reg_adc_current, reg_dac_current // ADC: starts N * 2 * 2 * bufsize beyond DAC | 803 ADD reg_adc_current, reg_adc_current, reg_dac_current // ADC: starts N * 2 * 2 * bufsize beyond DAC |
805 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 |
806 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 |
807 LSL reg_mcasp_adc_current, reg_mcasp_adc_current, 1 | 806 LSL reg_mcasp_adc_current, reg_mcasp_adc_current, 1 |
808 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 |
809 MOV reg_frame_current, 0 | 808 MOV reg_frame_current, 0 |
810 QBBS DIGITAL_BASE_CHECK_SET, reg_flags, FLAG_BIT_BUFFER1 //check which buffer we are using for DIGITAL | 809 QBBS DIGITAL_BASE_CHECK_SET, reg_flags, FLAG_BIT_BUFFER1 //check which buffer we are using for DIGITAL |
811 // if we are here, we are using buffer0 | 810 // if we are here, we are using buffer0 |
812 MOV reg_digital_current, MEM_DIGITAL_BASE | 811 MOV reg_digital_current, MEM_DIGITAL_BASE |
813 QBA DIGITAL_BASE_CHECK_DONE | 812 QBA DIGITAL_BASE_CHECK_DONE |
814 DIGITAL_BASE_CHECK_SET: //if we are here, we are using buffer1 | 813 DIGITAL_BASE_CHECK_SET: //if we are here, we are using buffer1 |
815 MOV reg_digital_current, MEM_DIGITAL_BASE+MEM_DIGITAL_BUFFER1_OFFSET //so adjust offset appropriately | 814 MOV reg_digital_current, MEM_DIGITAL_BASE+MEM_DIGITAL_BUFFER1_OFFSET //so adjust offset appropriately |
816 DIGITAL_BASE_CHECK_DONE: | 815 DIGITAL_BASE_CHECK_DONE: |
817 | 816 |
818 WRITE_LOOP: | 817 WRITE_LOOP: |
819 // Write N channels to DAC from successive values in memory | 818 // Write N channels to DAC from successive values in memory |
820 // At the same time, read N channels from ADC | 819 // At the same time, read N channels from ADC |
821 // 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 |
822 MOV r1, 0 | 821 MOV r1, 0 |
823 ADC_DAC_LOOP: | 822 ADC_DAC_LOOP: |
824 QBBC SPI_DAC_LOAD_DONE, reg_flags, FLAG_BIT_USE_SPI | 823 QBBC SPI_DAC_LOAD_DONE, reg_flags, FLAG_BIT_USE_SPI |
825 // Load next 2 SPI DAC samples and store zero in their place | 824 // Load next 2 SPI DAC samples and store zero in their place |
826 LBCO reg_dac_data, C_ADC_DAC_MEM, reg_dac_current, 4 | 825 LBCO reg_dac_data, C_ADC_DAC_MEM, reg_dac_current, 4 |
827 MOV r2, 0 | 826 MOV r2, 0 |
828 SBCO r2, C_ADC_DAC_MEM, reg_dac_current, 4 | 827 SBCO r2, C_ADC_DAC_MEM, reg_dac_current, 4 |
829 ADD reg_dac_current, reg_dac_current, 4 | 828 ADD reg_dac_current, reg_dac_current, 4 |
830 SPI_DAC_LOAD_DONE: | 829 SPI_DAC_LOAD_DONE: |
831 | 830 |
832 // On even iterations, load two more samples and choose the first one | 831 // On even iterations, load two more samples and choose the first one |
833 // On odd iterations, transmit the second of the samples already loaded | 832 // On odd iterations, transmit the second of the samples already loaded |
834 // QBBS MCASP_DAC_HIGH_WORD, r1, 1 | 833 // QBBS MCASP_DAC_HIGH_WORD, r1, 1 |
835 QBBS MCASP_DAC_HIGH_WORD, reg_flags, FLAG_BIT_MCASP_HWORD | 834 QBBS MCASP_DAC_HIGH_WORD, reg_flags, FLAG_BIT_MCASP_HWORD |
836 MCASP_DAC_LOW_WORD: | 835 MCASP_DAC_LOW_WORD: |
837 // Load next 2 Audio DAC samples and store zero in their place | 836 // Load next 2 Audio DAC samples and store zero in their place |
838 LBCO reg_mcasp_dac_data, C_MCASP_MEM, reg_mcasp_dac_current, 4 | 837 LBCO reg_mcasp_dac_data, C_MCASP_MEM, reg_mcasp_dac_current, 4 |
839 MOV r2, 0 | 838 MOV r2, 0 |
840 SBCO r2, C_MCASP_MEM, reg_mcasp_dac_current, 4 | 839 SBCO r2, C_MCASP_MEM, reg_mcasp_dac_current, 4 |
841 ADD reg_mcasp_dac_current, reg_mcasp_dac_current, 4 | 840 ADD reg_mcasp_dac_current, reg_mcasp_dac_current, 4 |
842 | 841 |
843 // Mask out the low word (first in little endian) | 842 // Mask out the low word (first in little endian) |
844 MOV r2, 0xFFFF | 843 MOV r2, 0xFFFF |
845 AND r7, reg_mcasp_dac_data, r2 | 844 AND r7, reg_mcasp_dac_data, r2 |
846 | 845 |
847 QBA MCASP_WAIT_XSTAT | 846 QBA MCASP_WAIT_XSTAT |
848 MCASP_DAC_HIGH_WORD: | 847 MCASP_DAC_HIGH_WORD: |
849 // Take the high word of the previously loaded data | 848 // Take the high word of the previously loaded data |
850 LSR r7, reg_mcasp_dac_data, 16 | 849 LSR r7, reg_mcasp_dac_data, 16 |
851 | 850 |
852 // Every 2 channels we send one audio sample; this loop already | 851 // Every 2 channels we send one audio sample; this loop already |
853 // sends exactly two SPI channels. | 852 // sends exactly two SPI channels. |
854 // Wait for McASP XSTAT[XDATA] to set indicating we can write more data | 853 // Wait for McASP XSTAT[XDATA] to set indicating we can write more data |
855 MCASP_WAIT_XSTAT: | 854 MCASP_WAIT_XSTAT: |
856 LBBO r2, reg_mcasp_addr, MCASP_XSTAT, 4 | 855 LBBO r2, reg_mcasp_addr, MCASP_XSTAT, 4 |
857 QBBS START, r2, MCASP_XSTAT_XUNDRN_BIT // if underrun occurred, reset the PRU | 856 QBBS START, r2, MCASP_XSTAT_XUNDRN_BIT // if underrun occurred, reset the PRU |
858 QBBC MCASP_WAIT_XSTAT, r2, MCASP_XSTAT_XDATA_BIT | 857 QBBC MCASP_WAIT_XSTAT, r2, MCASP_XSTAT_XDATA_BIT |
859 | 858 |
860 MCASP_REG_WRITE_EXT MCASP_XBUF, r7 | 859 MCASP_REG_WRITE_EXT MCASP_XBUF, r7 |
861 | 860 |
862 // Same idea with ADC: even iterations, load the sample into the low word, odd | 861 // Same idea with ADC: even iterations, load the sample into the low word, odd |
863 // iterations, load the sample into the high word and store | 862 // iterations, load the sample into the high word and store |
864 // QBBS MCASP_ADC_HIGH_WORD, r1, 1 | 863 // QBBS MCASP_ADC_HIGH_WORD, r1, 1 |
865 QBBS MCASP_ADC_HIGH_WORD, reg_flags, FLAG_BIT_MCASP_HWORD | 864 QBBS MCASP_ADC_HIGH_WORD, reg_flags, FLAG_BIT_MCASP_HWORD |
866 MCASP_ADC_LOW_WORD: | 865 MCASP_ADC_LOW_WORD: |
867 // Start ADC data at 0 | 866 // Start ADC data at 0 |
868 LDI reg_mcasp_adc_data, 0 | 867 LDI reg_mcasp_adc_data, 0 |
869 | 868 |
870 // Now wait for a received word to become available from the audio ADC | 869 // Now wait for a received word to become available from the audio ADC |
871 MCASP_WAIT_RSTAT_LOW: | 870 MCASP_WAIT_RSTAT_LOW: |
872 LBBO r2, reg_mcasp_addr, MCASP_RSTAT, 4 | 871 LBBO r2, reg_mcasp_addr, MCASP_RSTAT, 4 |
873 QBBC MCASP_WAIT_RSTAT_LOW, r2, MCASP_RSTAT_RDATA_BIT | 872 QBBC MCASP_WAIT_RSTAT_LOW, r2, MCASP_RSTAT_RDATA_BIT |
874 | 873 |
875 // Mask low word and store in ADC data register | 874 // Mask low word and store in ADC data register |
876 MCASP_REG_READ_EXT MCASP_RBUF, r3 | 875 MCASP_REG_READ_EXT MCASP_RBUF, r3 |
877 MOV r2, 0xFFFF | 876 MOV r2, 0xFFFF |
878 AND reg_mcasp_adc_data, r3, r2 | 877 AND reg_mcasp_adc_data, r3, r2 |
879 QBA MCASP_ADC_DONE | 878 QBA MCASP_ADC_DONE |
880 | 879 |
881 MCASP_ADC_HIGH_WORD: | 880 MCASP_ADC_HIGH_WORD: |
882 // Wait for a received word to become available from the audio ADC | 881 // Wait for a received word to become available from the audio ADC |
883 MCASP_WAIT_RSTAT_HIGH: | 882 MCASP_WAIT_RSTAT_HIGH: |
884 LBBO r2, reg_mcasp_addr, MCASP_RSTAT, 4 | 883 LBBO r2, reg_mcasp_addr, MCASP_RSTAT, 4 |
885 QBBC MCASP_WAIT_RSTAT_HIGH, r2, MCASP_RSTAT_RDATA_BIT | 884 QBBC MCASP_WAIT_RSTAT_HIGH, r2, MCASP_RSTAT_RDATA_BIT |
886 | 885 |
887 // Read data and shift 16 bits to the left (into the high word) | 886 // Read data and shift 16 bits to the left (into the high word) |
888 MCASP_REG_READ_EXT MCASP_RBUF, r3 | 887 MCASP_REG_READ_EXT MCASP_RBUF, r3 |
889 LSL r3, r3, 16 | 888 LSL r3, r3, 16 |
890 OR reg_mcasp_adc_data, reg_mcasp_adc_data, r3 | 889 OR reg_mcasp_adc_data, reg_mcasp_adc_data, r3 |
891 | 890 |
892 // Now store the result and increment the pointer | 891 // Now store the result and increment the pointer |
893 SBCO reg_mcasp_adc_data, C_MCASP_MEM, reg_mcasp_adc_current, 4 | 892 SBCO reg_mcasp_adc_data, C_MCASP_MEM, reg_mcasp_adc_current, 4 |
894 ADD reg_mcasp_adc_current, reg_mcasp_adc_current, 4 | 893 ADD reg_mcasp_adc_current, reg_mcasp_adc_current, 4 |
895 MCASP_ADC_DONE: | 894 MCASP_ADC_DONE: |
896 QBBC SPI_SKIP_WRITE, reg_flags, FLAG_BIT_USE_SPI | 895 QBBC SPI_SKIP_WRITE, reg_flags, FLAG_BIT_USE_SPI |
897 | 896 |
898 // DAC: transmit low word (first in little endian) | 897 // DAC: transmit low word (first in little endian) |
899 MOV r2, 0xFFFF | 898 MOV r2, 0xFFFF |
900 AND r7, reg_dac_data, r2 | 899 AND r7, reg_dac_data, r2 |
901 LSL r7, r7, AD5668_DATA_OFFSET | 900 LSL r7, r7, AD5668_DATA_OFFSET |
902 MOV r8, (0x03 << AD5668_COMMAND_OFFSET) | 901 MOV r8, (0x03 << AD5668_COMMAND_OFFSET) |
903 OR r7, r7, r8 | 902 OR r7, r7, r8 |
904 LSL r8, r1, AD5668_ADDRESS_OFFSET | 903 LSL r8, r1, AD5668_ADDRESS_OFFSET |
905 OR r7, r7, r8 | 904 OR r7, r7, r8 |
906 DAC_WRITE r7 | 905 DAC_WRITE r7 |
907 | 906 |
908 // Read ADC channels: result is always 2 commands behind | 907 // Read ADC channels: result is always 2 commands behind |
909 // Start by reading channel 2 (result is channel 0) and go | 908 // Start by reading channel 2 (result is channel 0) and go |
910 // to N+2, but masking the channel number to be between 0 and N-1 | 909 // to N+2, but masking the channel number to be between 0 and N-1 |
911 LDI reg_adc_data, 0 | 910 LDI reg_adc_data, 0 |
912 ADD r8, r1, 2 | 911 ADD r8, r1, 2 |
913 SUB r7, reg_num_channels, 1 | 912 SUB r7, reg_num_channels, 1 |
914 AND r8, r8, r7 | 913 AND r8, r8, r7 |
915 LSL r8, r8, AD7699_CHANNEL_OFFSET | 914 LSL r8, r8, AD7699_CHANNEL_OFFSET |
916 MOV r7, AD7699_CFG_MASK | 915 MOV r7, AD7699_CFG_MASK |
917 OR r7, r7, r8 | 916 OR r7, r7, r8 |
918 | 917 |
919 //ssssssssssssssssssssssssssss | 918 ADC_WRITE_GPIO r7, r7, r1 |
920 ADC_WRITE_GPIO r7, r7, r1 | 919 |
921 | 920 // Mask out only the relevant 16 bits and store in reg_adc_data |
922 // Mask out only the relevant 16 bits and store in reg_adc_data | 921 MOV r2, 0xFFFF |
923 MOV r2, 0xFFFF | 922 AND reg_adc_data, r7, r2 |
924 AND reg_adc_data, r7, r2 | 923 // Increment channel index |
925 | 924 ADD r1, r1, 1 |
926 // Increment channel index | 925 |
927 ADD r1, r1, 1 | 926 // DAC: transmit high word (second in little endian) |
928 | 927 LSR r7, reg_dac_data, 16 |
929 // DAC: transmit high word (second in little endian) | 928 LSL r7, r7, AD5668_DATA_OFFSET |
930 LSR r7, reg_dac_data, 16 | 929 MOV r8, (0x03 << AD5668_COMMAND_OFFSET) |
931 LSL r7, r7, AD5668_DATA_OFFSET | 930 OR r7, r7, r8 |
932 MOV r8, (0x03 << AD5668_COMMAND_OFFSET) | 931 LSL r8, r1, AD5668_ADDRESS_OFFSET |
933 OR r7, r7, r8 | 932 OR r7, r7, r8 |
934 LSL r8, r1, AD5668_ADDRESS_OFFSET | 933 DAC_WRITE r7 |
935 OR r7, r7, r8 | 934 |
936 DAC_WRITE r7 | 935 // Read ADC channels: result is always 2 commands behind |
937 | 936 // Start by reading channel 2 (result is channel 0) and go |
938 // Read ADC channels: result is always 2 commands behind | 937 // to N+2, but masking the channel number to be between 0 and N-1 |
939 // Start by reading channel 2 (result is channel 0) and go | 938 ADD r8, r1, 2 |
940 // to N+2, but masking the channel number to be between 0 and N-1 | 939 SUB r7, reg_num_channels, 1 |
941 ADD r8, r1, 2 | 940 AND r8, r8, r7 |
942 SUB r7, reg_num_channels, 1 | 941 LSL r8, r8, AD7699_CHANNEL_OFFSET |
943 AND r8, r8, r7 | 942 MOV r7, AD7699_CFG_MASK |
944 LSL r8, r8, AD7699_CHANNEL_OFFSET | 943 OR r7, r7, r8 |
945 MOV r7, AD7699_CFG_MASK | 944 ADC_WRITE r7, r7 |
946 OR r7, r7, r8 | 945 |
947 ADC_WRITE r7, r7 | 946 // Move this result up to the 16 high bits |
948 | 947 LSL r7, r7, 16 |
949 // Move this result up to the 16 high bits | 948 OR reg_adc_data, reg_adc_data, r7 |
950 LSL r7, r7, 16 | 949 |
951 OR reg_adc_data, reg_adc_data, r7 | 950 // Store 2 ADC words in memory |
952 | 951 SBCO reg_adc_data, C_ADC_DAC_MEM, reg_adc_current, 4 |
953 // Store 2 ADC words in memory | 952 ADD reg_adc_current, reg_adc_current, 4 |
954 SBCO reg_adc_data, C_ADC_DAC_MEM, reg_adc_current, 4 | 953 |
955 ADD reg_adc_current, reg_adc_current, 4 | 954 // Toggle the high/low word for McASP control (since we send one word out of |
956 | 955 // 32 bits for each pair of SPI channels) |
957 // Toggle the high/low word for McASP control (since we send one word out of | 956 XOR reg_flags, reg_flags, (1 << FLAG_BIT_MCASP_HWORD) |
958 // 32 bits for each pair of SPI channels) | 957 |
959 XOR reg_flags, reg_flags, (1 << FLAG_BIT_MCASP_HWORD) | 958 // Repeat 4 times for 8 channels (2 samples per loop, r1 += 1 already happened) |
960 | 959 // For 4 or 2 channels, repeat 2 or 1 times, according to flags |
961 // Repeat 4 times for 8 channels (2 samples per loop, r1 += 1 already happened) | 960 ADD r1, r1, 1 |
962 // For 4 or 2 channels, repeat 2 or 1 times, according to flags | 961 QBNE ADC_DAC_LOOP, r1, reg_num_channels |
963 ADD r1, r1, 1 | 962 QBA ADC_DAC_LOOP_DONE |
964 QBNE ADC_DAC_LOOP, r1, reg_num_channels | |
965 QBA ADC_DAC_LOOP_DONE | |
966 SPI_SKIP_WRITE: | 963 SPI_SKIP_WRITE: |
967 // We get here only if the SPI ADC and DAC are disabled | 964 // We get here only if the SPI ADC and DAC are disabled |
968 // Just keep the loop going for McASP | 965 // Just keep the loop going for McASP |
969 | 966 |
970 // Toggle the high/low word for McASP control (since we send one word out of | 967 // Toggle the high/low word for McASP control (since we send one word out of |
971 // 32 bits for each pair of SPI channels) | 968 // 32 bits for each pair of SPI channels) |
972 XOR reg_flags, reg_flags, (1 << FLAG_BIT_MCASP_HWORD) | 969 XOR reg_flags, reg_flags, (1 << FLAG_BIT_MCASP_HWORD) |
973 | 970 |
974 ADD r1, r1, 2 | 971 ADD r1, r1, 2 |
975 QBNE ADC_DAC_LOOP, r1, reg_num_channels | 972 QBNE ADC_DAC_LOOP, r1, reg_num_channels |
976 | 973 |
977 ADC_DAC_LOOP_DONE: | 974 ADC_DAC_LOOP_DONE: |
978 // Increment number of frames, see if we have more to write | 975 // Increment number of frames, see if we have more to write |
979 ADD reg_frame_current, reg_frame_current, 1 | 976 ADD reg_frame_current, reg_frame_current, 1 |
980 QBNE WRITE_LOOP, reg_frame_current, reg_frame_total | 977 QBNE WRITE_LOOP, reg_frame_current, reg_frame_total |
981 | 978 |
982 WRITE_LOOP_DONE: | 979 WRITE_LOOP_DONE: |
983 // Now done, swap the buffers and do the next one | 980 // Now done, swap the buffers and do the next one |
984 // Use r2 as a temp register | 981 // Use r2 as a temp register |
985 MOV r2, reg_dac_buf0 | 982 MOV r2, reg_dac_buf0 |
986 MOV reg_dac_buf0, reg_dac_buf1 | 983 MOV reg_dac_buf0, reg_dac_buf1 |
987 MOV reg_dac_buf1, r2 | 984 MOV reg_dac_buf1, r2 |
988 MOV r2, reg_mcasp_buf0 | 985 MOV r2, reg_mcasp_buf0 |
989 MOV reg_mcasp_buf0, reg_mcasp_buf1 | 986 MOV reg_mcasp_buf0, reg_mcasp_buf1 |
990 MOV reg_mcasp_buf1, r2 | 987 MOV reg_mcasp_buf1, r2 |
991 XOR reg_flags, reg_flags, (1 << FLAG_BIT_BUFFER1) //flip the buffer flag | 988 XOR reg_flags, reg_flags, (1 << FLAG_BIT_BUFFER1) //flip the buffer flag |
992 | 989 |
993 // Notify ARM of buffer swap | 990 // Notify ARM of buffer swap |
994 AND r2, reg_flags, (1 << FLAG_BIT_BUFFER1) // Mask out every but low bit | 991 AND r2, reg_flags, (1 << FLAG_BIT_BUFFER1) // Mask out every but low bit |
995 SBBO r2, reg_comm_addr, COMM_CURRENT_BUFFER, 4 | 992 SBBO r2, reg_comm_addr, COMM_CURRENT_BUFFER, 4 |
996 MOV R31.b0, PRU1_ARM_INTERRUPT + 16 // Interrupt to host loop | 993 MOV R31.b0, PRU1_ARM_INTERRUPT + 16 // Interrupt to host loop |
997 | 994 |
998 // Increment the frame count in the comm buffer (for status monitoring) | 995 // Increment the frame count in the comm buffer (for status monitoring) |
999 LBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 | 996 LBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 |
1000 ADD r2, r2, reg_frame_total | 997 ADD r2, r2, reg_frame_total |
1001 SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 | 998 SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 |
1002 | 999 |
1003 // If LED blink enabled, toggle every 4096 frames | 1000 // If LED blink enabled, toggle every 4096 frames |
1004 LBBO r3, reg_comm_addr, COMM_LED_ADDRESS, 4 | 1001 LBBO r3, reg_comm_addr, COMM_LED_ADDRESS, 4 |
1005 QBEQ LED_BLINK_DONE, r3, 0 | 1002 QBEQ LED_BLINK_DONE, r3, 0 |
1006 MOV r1, 0x1000 | 1003 MOV r1, 0x1000 |
1007 AND r2, r2, r1 // Test (frame count & 4096) | 1004 AND r2, r2, r1 // Test (frame count & 4096) |
1008 QBEQ LED_BLINK_OFF, r2, 0 | 1005 QBEQ LED_BLINK_OFF, r2, 0 |
1009 LBBO r2, reg_comm_addr, COMM_LED_PIN_MASK, 4 | 1006 LBBO r2, reg_comm_addr, COMM_LED_PIN_MASK, 4 |
1010 MOV r1, GPIO_SETDATAOUT | 1007 MOV r1, GPIO_SETDATAOUT |
1011 ADD r3, r3, r1 // Address for GPIO set register | 1008 ADD r3, r3, r1 // Address for GPIO set register |
1012 SBBO r2, r3, 0, 4 // Set GPIO pin | 1009 SBBO r2, r3, 0, 4 // Set GPIO pin |
1013 QBA LED_BLINK_DONE | 1010 QBA LED_BLINK_DONE |
1014 LED_BLINK_OFF: | 1011 LED_BLINK_OFF: |
1015 LBBO r2, reg_comm_addr, COMM_LED_PIN_MASK, 4 | 1012 LBBO r2, reg_comm_addr, COMM_LED_PIN_MASK, 4 |
1016 MOV r1, GPIO_CLEARDATAOUT | 1013 MOV r1, GPIO_CLEARDATAOUT |
1017 ADD r3, r3, r1 // Address for GPIO clear register | 1014 ADD r3, r3, r1 // Address for GPIO clear register |
1018 SBBO r2, r3, 0, 4 // Clear GPIO pin | 1015 SBBO r2, r3, 0, 4 // Clear GPIO pin |
1019 LED_BLINK_DONE: | 1016 LED_BLINK_DONE: |
1020 // Check if we should finish: flag is zero as long as it should run | 1017 // Check if we should finish: flag is zero as long as it should run |
1021 LBBO r2, reg_comm_addr, COMM_SHOULD_STOP, 4 | 1018 LBBO r2, reg_comm_addr, COMM_SHOULD_STOP, 4 |
1022 QBEQ WRITE_ONE_BUFFER, r2, 0 | 1019 QBEQ WRITE_ONE_BUFFER, r2, 0 |
1023 | 1020 |
1024 CLEANUP: | 1021 CLEANUP: |
1025 MCASP_REG_WRITE MCASP_GBLCTL, 0x00 // Turn off McASP | 1022 MCASP_REG_WRITE MCASP_GBLCTL, 0x00 // Turn off McASP |
1026 | 1023 |
1027 // Turn off SPI if enabled | 1024 // Turn off SPI if enabled |
1028 QBBC SPI_CLEANUP_DONE, reg_flags, FLAG_BIT_USE_SPI | 1025 QBBC SPI_CLEANUP_DONE, reg_flags, FLAG_BIT_USE_SPI |
1029 | 1026 |
1030 MOV r3, SPI_BASE + SPI_CH0CONF | 1027 MOV r3, SPI_BASE + SPI_CH0CONF |
1031 LBBO r2, r3, 0, 4 | 1028 LBBO r2, r3, 0, 4 |
1032 CLR r2, r2, 13 | 1029 CLR r2, r2, 13 |
1033 CLR r2, r2, 27 | 1030 CLR r2, r2, 27 |
1034 SBBO r2, r3, 0, 4 | 1031 SBBO r2, r3, 0, 4 |
1035 | 1032 |
1036 MOV r3, SPI_BASE + SPI_CH0CTRL | 1033 MOV r3, SPI_BASE + SPI_CH0CTRL |
1037 LBBO r2, r3, 0, 4 | 1034 LBBO r2, r3, 0, 4 |
1038 CLR r2, r2, 1 | 1035 CLR r2, r2, 1 |
1039 SBBO r2, r3, 0, 4 | 1036 SBBO r2, r3, 0, 4 |
1040 SPI_CLEANUP_DONE: | 1037 SPI_CLEANUP_DONE: |
1041 // Signal the ARM that we have finished | 1038 // Signal the ARM that we have finished |
1042 MOV R31.b0, PRU0_ARM_INTERRUPT + 16 | 1039 MOV R31.b0, PRU0_ARM_INTERRUPT + 16 |
1043 HALT | 1040 HALT |