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