comparison pru_rtaudio.p @ 108:3068421c0737 ultra-staging

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