trunk/src/emu/sound/tms5220.c
| r18938 | r18939 | |
| 256 | 256 | * The second line is more accurate mathematically but not accurate to the patent |
| 257 | 257 | */ |
| 258 | 258 | #define INTERP_SHIFT >> tms->coeff->interp_coeff[tms->interp_period] |
| 259 | | //#define INTERP_SHIFT / (1<<tms->coeff->interp_coeff[tms->interp_period]) |
| 259 | //define INTERP_SHIFT / (1<<tms->coeff->interp_coeff[tms->interp_period]) |
| 260 | 260 | |
| 261 | 261 | /* Excitation hacks */ |
| 262 | 262 | /* The real chip uses an 8-bit excitation (shifted up to the top 8 bits) for |
| r18938 | r18939 | |
| 267 | 267 | * if not defined, acts as shown in patent */ |
| 268 | 268 | #undef UNVOICED_HACK |
| 269 | 269 | |
| 270 | | /* HACKS: VOICED waveform hacks; |
| 271 | | * if none defined, acts as shown in patent |
| 272 | | * if VOICED_INV_HACK defined, acts as shown in patent but the output is inverted |
| 273 | | * if VOICED_ZERO_HACK defined, acts as shown in patent, but the first and >=51 samples are 0x80 (-128) |
| 274 | | * if VOICED_PULSE_HACK defined, acts as a pulse waveform with a period of PWIDTH samples at PAMP, PWIDTH samples at ~PAMP, and the rest at 0 |
| 275 | | * if VOICED_PULSE_MONOPOLAR_HACK defined, acts as a pulse waveform with a period of PWIDTH samples at PAMP, and the rest at 0 |
| 276 | | * If you want this to sound like MGE, set VOICED_PULSE_MONOPOLAR_HACK to 1, PAMP to 0x3F and PWIDTH to 2, and set the perfect interpolation hack below on as well. |
| 277 | | */ |
| 278 | | #undef VOICED_INV_HACK |
| 279 | | #undef VOICED_ZERO_HACK |
| 280 | | #undef VOICED_PULSE_HACK |
| 281 | | #undef VOICED_PULSE_MONOPOLAR_HACK |
| 282 | | #undef PAMP |
| 283 | | #undef PWIDTH |
| 284 | | |
| 285 | 270 | /* Other hacks */ |
| 286 | | /* HACK: if defined, outputs the low 4 bits of the lattice filter to the i/o |
| 287 | | * or clip logic, even though the real hardware doesn't do this */ |
| 271 | /* HACK?: if defined, outputs the low 4 bits of the lattice filter to the i/o |
| 272 | * or clip logic, even though the real hardware doesn't do this... |
| 273 | * ...actually the tms5220c might legitamately do this! */ |
| 288 | 274 | #undef ALLOW_4_LSB |
| 289 | 275 | |
| 290 | 276 | /* HACK: if defined, uses impossibly perfect 'straight line' interpolation */ |
| r18938 | r18939 | |
| 423 | 409 | INT32 u[11]; |
| 424 | 410 | INT32 x[10]; |
| 425 | 411 | |
| 426 | | UINT16 RNG; /* the random noise generator configuration is: 1 + x + x^3 + x^4 + x^13 */ |
| 412 | UINT16 RNG; /* the random noise generator configuration is: 1 + x + x^3 + x^4 + x^13 */ |
| 427 | 413 | INT16 excitation_data; |
| 428 | 414 | |
| 429 | 415 | /* R Nabet : These have been added to emulate speech Roms */ |
| r18938 | r18939 | |
| 432 | 418 | UINT8 RDB_flag; /* whether we should read data register or status register */ |
| 433 | 419 | |
| 434 | 420 | /* io_ready: page 3 of the datasheet specifies that READY will be asserted until |
| 435 | | * data is available or processed by the system. |
| 436 | | */ |
| 421 | * data is available or processed by the system. |
| 422 | */ |
| 437 | 423 | UINT8 io_ready; |
| 438 | 424 | |
| 439 | 425 | /* flag for "true" timing involving rs/ws */ |
| r18938 | r18939 | |
| 444 | 430 | UINT8 read_latch; |
| 445 | 431 | UINT8 write_latch; |
| 446 | 432 | |
| 447 | | /* The TMS52xx has two different ways of providing output data: the |
| 448 | | analog speaker pin (which was usually used) and the Digital I/O pin. |
| 449 | | The internal DAC used to feed the analog pin is only 8 bits, and has the |
| 450 | | funny clipping/clamping logic, while the digital pin gives full 12? bit |
| 451 | | resolution of the output data. |
| 452 | | TODO: add a way to set/reset this other than the FORCE_DIGITAL define |
| 453 | | */ |
| 433 | /* The TMS52xx has two different ways of providing output data: the |
| 434 | analog speaker pin (which was usually used) and the Digital I/O pin. |
| 435 | The internal DAC used to feed the analog pin is only 8 bits, and has the |
| 436 | funny clipping/clamping logic, while the digital pin gives full 12? bit |
| 437 | resolution of the output data. |
| 438 | TODO: add a way to set/reset this other than the FORCE_DIGITAL define |
| 439 | */ |
| 454 | 440 | UINT8 digital_select; |
| 455 | 441 | device_t *device; |
| 456 | 442 | |
| r18938 | r18939 | |
| 460 | 446 | }; |
| 461 | 447 | |
| 462 | 448 | |
| 463 | | /* Pull in the ROM tables */ |
| 449 | // Pull in the ROM tables |
| 464 | 450 | #include "tms5110r.c" |
| 465 | 451 | |
| 466 | 452 | |
| r18938 | r18939 | |
| 568 | 554 | |
| 569 | 555 | /********************************************************************************************** |
| 570 | 556 | |
| 571 | | printbits helper function: takes a long int input and prints the resulting bits to stderr |
| 557 | printbits helper function: takes a long int input and prints the resulting bits to stderr |
| 572 | 558 | |
| 573 | | **********************************************************************************************/ |
| 559 | ***********************************************************************************************/ |
| 574 | 560 | |
| 575 | 561 | #ifdef DEBUG_PARSE_FRAME_DUMP_BIN |
| 576 | 562 | static void printbits(long data, int num) |
| r18938 | r18939 | |
| 606 | 592 | |
| 607 | 593 | /********************************************************************************************** |
| 608 | 594 | |
| 609 | | tms5220_data_write -- handle a write to the TMS5220 |
| 595 | tms5220_data_write -- handle a write to the TMS5220 |
| 610 | 596 | |
| 611 | 597 | ***********************************************************************************************/ |
| 612 | 598 | |
| r18938 | r18939 | |
| 617 | 603 | #endif |
| 618 | 604 | if (tms->speak_external) // If we're in speak external mode |
| 619 | 605 | { |
| 620 | | /* add this byte to the FIFO */ |
| 606 | // add this byte to the FIFO |
| 621 | 607 | if (tms->fifo_count < FIFO_SIZE) |
| 622 | 608 | { |
| 623 | 609 | tms->fifo[tms->fifo_tail] = data; |
| r18938 | r18939 | |
| 633 | 619 | #ifdef DEBUG_FIFO |
| 634 | 620 | logerror("data_write triggered talk status to go active!\n"); |
| 635 | 621 | #endif |
| 636 | | /* ...then we now have enough bytes to start talking; clear out the new frame parameters (it will become old frame just before the first call to parse_frame() ) */ |
| 637 | | /* TODO: the 3 lines below (and others) are needed for victory to not fail its selftest due to a sample ending too late, may require additional investigation */ |
| 622 | // ...then we now have enough bytes to start talking; clear out the new frame parameters (it will become old frame just before the first call to parse_frame() ) |
| 623 | // TODO: the 3 lines below (and others) are needed for victory to not fail its selftest due to a sample ending too late, may require additional investigation |
| 638 | 624 | tms->subcycle = tms->subc_reload; |
| 639 | 625 | tms->PC = 0; |
| 640 | 626 | tms->interp_period = reload_table[tms->tms5220c_rate&0x3]; // is this correct? should this be always 7 instead, so that the new frame is loaded quickly? |
| r18938 | r18939 | |
| 660 | 646 | |
| 661 | 647 | } |
| 662 | 648 | else //(! tms->speak_external) |
| 663 | | /* R Nabet : we parse commands at once. It is necessary for such commands as read. */ |
| 649 | // R Nabet : we parse commands at once. It is necessary for such commands as read. |
| 664 | 650 | process_command(tms,data); |
| 665 | 651 | } |
| 666 | 652 | |
| 667 | 653 | /********************************************************************************************** |
| 668 | 654 | |
| 669 | | update_status_and_ints -- check to see if the various flags should be on or off |
| 670 | | Description of flags, and their position in the status register: |
| 671 | | From the data sheet: |
| 672 | | bit D0(bit 7) = TS - Talk Status is active (high) when the VSP is processing speech data. |
| 673 | | Talk Status goes active at the initiation of a Speak command or after nine |
| 674 | | bytes of data are loaded into the FIFO following a Speak External command. It |
| 675 | | goes inactive (low) when the stop code (Energy=1111) is processed, or |
| 676 | | immediately by a buffer empty condition or a reset command. |
| 677 | | bit D1(bit 6) = BL - Buffer Low is active (high) when the FIFO buffer is more than half empty. |
| 678 | | Buffer Low is set when the "Last-In" byte is shifted down past the half-full |
| 679 | | boundary of the stack. Buffer Low is cleared when data is loaded to the stack |
| 680 | | so that the "Last-In" byte lies above the half-full boundary and becomes the |
| 681 | | eighth data byte of the stack. |
| 682 | | bit D2(bit 5) = BE - Buffer Empty is active (high) when the FIFO buffer has run out of data |
| 683 | | while executing a Speak External command. Buffer Empty is set when the last bit |
| 684 | | of the "Last-In" byte is shifted out to the Synthesis Section. This causes |
| 685 | | Talk Status to be cleared. Speed is terminated at some abnormal point and the |
| 686 | | Speak External command execution is terminated. |
| 655 | update_status_and_ints -- check to see if the various flags should be on or off |
| 656 | Description of flags, and their position in the status register: |
| 657 | From the data sheet: |
| 658 | bit D0(bit 7) = TS - Talk Status is active (high) when the VSP is processing speech data. |
| 659 | Talk Status goes active at the initiation of a Speak command or after nine |
| 660 | bytes of data are loaded into the FIFO following a Speak External command. It |
| 661 | goes inactive (low) when the stop code (Energy=1111) is processed, or |
| 662 | immediately by a buffer empty condition or a reset command. |
| 663 | bit D1(bit 6) = BL - Buffer Low is active (high) when the FIFO buffer is more than half empty. |
| 664 | Buffer Low is set when the "Last-In" byte is shifted down past the half-full |
| 665 | boundary of the stack. Buffer Low is cleared when data is loaded to the stack |
| 666 | so that the "Last-In" byte lies above the half-full boundary and becomes the |
| 667 | eighth data byte of the stack. |
| 668 | bit D2(bit 5) = BE - Buffer Empty is active (high) when the FIFO buffer has run out of data |
| 669 | while executing a Speak External command. Buffer Empty is set when the last bit |
| 670 | of the "Last-In" byte is shifted out to the Synthesis Section. This causes |
| 671 | Talk Status to be cleared. Speech is terminated at some abnormal point and the |
| 672 | Speak External command execution is terminated. |
| 687 | 673 | |
| 688 | 674 | ***********************************************************************************************/ |
| 689 | 675 | |
| r18938 | r18939 | |
| 694 | 680 | update_ready_state(tms); |
| 695 | 681 | |
| 696 | 682 | /* BL is set if neither byte 9 nor 8 of the fifo are in use; this |
| 697 | | translates to having fifo_count (which ranges from 0 bytes in use to 16 |
| 698 | | bytes used) being less than or equal to 8. Victory/Victorba depends on this. */ |
| 699 | | if (tms->fifo_count <= 8) |
| 700 | | { |
| 701 | | /* generate an interrupt if necessary; if /BL was inactive and is now active, set int. */ |
| 702 | | if (!tms->buffer_low) |
| 703 | | set_interrupt_state(tms, 1); |
| 704 | | tms->buffer_low = 1; |
| 683 | translates to having fifo_count (which ranges from 0 bytes in use to 16 |
| 684 | bytes used) being less than or equal to 8. Victory/Victorba depends on this. */ |
| 685 | if (tms->fifo_count <= 8) |
| 686 | { |
| 687 | // generate an interrupt if necessary; if /BL was inactive and is now active, set int. |
| 688 | if (!tms->buffer_low) |
| 689 | set_interrupt_state(tms, 1); |
| 690 | tms->buffer_low = 1; |
| 705 | 691 | } |
| 706 | 692 | else |
| 707 | 693 | tms->buffer_low = 0; |
| 708 | 694 | |
| 709 | 695 | /* BE is set if neither byte 15 nor 14 of the fifo are in use; this |
| 710 | | translates to having fifo_count equal to exactly 0 */ |
| 696 | translates to having fifo_count equal to exactly 0 */ |
| 711 | 697 | if (tms->fifo_count == 0) |
| 712 | 698 | { |
| 713 | | /* generate an interrupt if necessary; if /BE was inactive and is now active, set int. */ |
| 714 | | if (!tms->buffer_empty) |
| 715 | | set_interrupt_state(tms, 1); |
| 716 | | tms->buffer_empty = 1; |
| 717 | | } |
| 699 | // generate an interrupt if necessary; if /BE was inactive and is now active, set int. |
| 700 | if (!tms->buffer_empty) |
| 701 | set_interrupt_state(tms, 1); |
| 702 | tms->buffer_empty = 1; |
| 703 | } |
| 718 | 704 | else |
| 719 | 705 | tms->buffer_empty = 0; |
| 720 | 706 | |
| 721 | 707 | /* TS is talk status and is set elsewhere in the fifo parser and in |
| 722 | | the SPEAK command handler; however, if /BE is true during speak external |
| 723 | | mode, it is immediately unset here. */ |
| 708 | the SPEAK command handler; however, if /BE is true during speak external |
| 709 | mode, it is immediately unset here. */ |
| 724 | 710 | if ((tms->speak_external == 1) && (tms->buffer_empty == 1)) |
| 725 | 711 | { |
| 726 | | /* generate an interrupt: /TS was active, and is now inactive. */ |
| 712 | // generate an interrupt: /TS was active, and is now inactive. |
| 727 | 713 | if (tms->talk_status == 1) |
| 728 | 714 | { |
| 729 | 715 | tms->talk_status = tms->speak_external = 0; |
| r18938 | r18939 | |
| 731 | 717 | } |
| 732 | 718 | } |
| 733 | 719 | /* Note that TS being unset will also generate an interrupt when a STOP |
| 734 | | frame is encountered; this is handled in the sample generator code and not here */ |
| 720 | frame is encountered; this is handled in the sample generator code and not here */ |
| 735 | 721 | } |
| 736 | 722 | |
| 737 | 723 | /********************************************************************************************** |
| 738 | 724 | |
| 739 | | extract_bits -- extract a specific number of bits from the current input stream (FIFO or VSM) |
| 725 | extract_bits -- extract a specific number of bits from the current input stream (FIFO or VSM) |
| 740 | 726 | |
| 741 | 727 | ***********************************************************************************************/ |
| 742 | 728 | |
| 743 | 729 | static int extract_bits(tms5220_state *tms, int count) |
| 744 | 730 | { |
| 745 | | int val = 0; |
| 731 | int val = 0; |
| 746 | 732 | |
| 747 | 733 | if (tms->speak_external) |
| 748 | 734 | { |
| 749 | | /* extract from FIFO */ |
| 735 | // extract from FIFO |
| 750 | 736 | while (count--) |
| 751 | 737 | { |
| 752 | 738 | val = (val << 1) | ((tms->fifo[tms->fifo_head] >> tms->fifo_bits_taken) & 1); |
| r18938 | r18939 | |
| 763 | 749 | } |
| 764 | 750 | else |
| 765 | 751 | { |
| 766 | | /* extract from VSM (speech ROM) */ |
| 752 | // extract from VSM (speech ROM) |
| 767 | 753 | if (tms->intf->read) |
| 768 | 754 | val = (* tms->intf->read)(tms->device, count); |
| 769 | 755 | } |
| 770 | 756 | |
| 771 | | return val; |
| 757 | return val; |
| 772 | 758 | } |
| 773 | 759 | |
| 774 | 760 | /********************************************************************************************** |
| 775 | 761 | |
| 776 | | tms5220_status_read -- read status or data from the TMS5220 |
| 762 | tms5220_status_read -- read status or data from the TMS5220 |
| 777 | 763 | |
| 778 | 764 | ***********************************************************************************************/ |
| 779 | 765 | |
| r18938 | r18939 | |
| 809 | 795 | #ifdef DEBUG_PIN_READS |
| 810 | 796 | logerror("ready_read: ready pin read, io_ready is %d, fifo count is %d\n", tms->io_ready, tms->fifo_count); |
| 811 | 797 | #endif |
| 812 | | return ((tms->fifo_count < FIFO_SIZE)||(!tms->speak_external)) && tms->io_ready; |
| 798 | return ((tms->fifo_count < FIFO_SIZE)||(!tms->speak_external)) && tms->io_ready; |
| 813 | 799 | } |
| 814 | 800 | |
| 815 | 801 | |
| 816 | 802 | /********************************************************************************************** |
| 817 | 803 | |
| 818 | | tms5220_cycles_to_ready -- returns the number of cycles until ready is asserted |
| 819 | | NOTE: this function is deprecated and is known to be VERY inaccurate. |
| 820 | | Use at your own peril! |
| 804 | tms5220_cycles_to_ready -- returns the number of cycles until ready is asserted |
| 805 | NOTE: this function is deprecated and is known to be VERY inaccurate. |
| 806 | Use at your own peril! |
| 821 | 807 | |
| 822 | 808 | ***********************************************************************************************/ |
| 823 | 809 | |
| r18938 | r18939 | |
| 835 | 821 | int current_sample = ((tms->PC*(3-tms->subc_reload))+((tms->subc_reload?38:25)*tms->interp_period)); |
| 836 | 822 | answer = samples_per_frame-current_sample+8; |
| 837 | 823 | |
| 838 | | /* total number of bits available in current byte is (8 - tms->fifo_bits_taken) */ |
| 839 | | /* if more than 4 are available, we need to check the energy */ |
| 824 | // total number of bits available in current byte is (8 - tms->fifo_bits_taken) |
| 825 | // if more than 4 are available, we need to check the energy |
| 840 | 826 | if (tms->fifo_bits_taken < 4) |
| 841 | 827 | { |
| 842 | | /* read energy */ |
| 828 | // read energy |
| 843 | 829 | val = (tms->fifo[tms->fifo_head] >> tms->fifo_bits_taken) & 0xf; |
| 844 | 830 | if (val == 0) |
| 845 | 831 | /* 0 -> silence frame: we will only read 4 bits, and we will |
| 846 | | therefore need to read another frame before the FIFO is not |
| 847 | | full any more */ |
| 848 | | answer += 200; |
| 832 | * therefore need to read another frame before the FIFO is not |
| 833 | * full any more */ |
| 834 | answer += tms->subc_reload?200:304; |
| 849 | 835 | /* 15 -> stop frame, we will only read 4 bits, but the FIFO will |
| 850 | | we cleared */ |
| 851 | | /* otherwise, we need to parse the repeat flag (1 bit) and the |
| 852 | | pitch (6 bits), so everything will be OK. */ |
| 836 | * we cleared; otherwise, we need to parse the repeat flag (1 bit) |
| 837 | * and the pitch (6 bits), so everything will be OK. */ |
| 853 | 838 | } |
| 854 | 839 | } |
| 855 | 840 | |
| r18938 | r18939 | |
| 859 | 844 | |
| 860 | 845 | /********************************************************************************************** |
| 861 | 846 | |
| 862 | | tms5220_int_read -- returns the interrupt state of the TMS5220 |
| 847 | tms5220_int_read -- returns the interrupt state of the TMS5220 |
| 863 | 848 | |
| 864 | 849 | ***********************************************************************************************/ |
| 865 | 850 | |
| r18938 | r18939 | |
| 868 | 853 | #ifdef DEBUG_PIN_READS |
| 869 | 854 | logerror("int_read: irq pin read, state is %d\n", tms->irq_pin); |
| 870 | 855 | #endif |
| 871 | | return tms->irq_pin; |
| 856 | return tms->irq_pin; |
| 872 | 857 | } |
| 873 | 858 | |
| 874 | 859 | |
| 875 | 860 | /********************************************************************************************** |
| 876 | 861 | |
| 877 | | tms5220_process -- fill the buffer with a specific number of samples |
| 862 | tms5220_process -- fill the buffer with a specific number of samples |
| 878 | 863 | |
| 879 | 864 | ***********************************************************************************************/ |
| 880 | 865 | |
| 881 | 866 | static void tms5220_process(tms5220_state *tms, INT16 *buffer, unsigned int size) |
| 882 | 867 | { |
| 883 | | int buf_count=0; |
| 884 | | int i, bitout, zpar; |
| 885 | | INT32 this_sample; |
| 868 | int buf_count=0; |
| 869 | int i, bitout, zpar; |
| 870 | INT32 this_sample; |
| 886 | 871 | |
| 887 | | /* the following gotos are probably safe to remove */ |
| 888 | | /* if we're empty and still not speaking, fill with nothingness */ |
| 889 | | if (!tms->speaking_now) |
| 890 | | goto empty; |
| 872 | /* the following gotos are probably safe to remove */ |
| 873 | /* if we're empty and still not speaking, fill with nothingness */ |
| 874 | if (!tms->speaking_now) |
| 875 | goto empty; |
| 891 | 876 | |
| 892 | | /* if speak external is set, but talk status is not (yet) set, |
| 893 | | wait for buffer low to clear */ |
| 894 | | if (!tms->talk_status && tms->speak_external && tms->buffer_low) |
| 895 | | goto empty; |
| 877 | /* if speak external is set, but talk status is not (yet) set, |
| 878 | wait for buffer low to clear */ |
| 879 | if (!tms->talk_status && tms->speak_external && tms->buffer_low) |
| 880 | goto empty; |
| 896 | 881 | |
| 897 | | /* loop until the buffer is full or we've stopped speaking */ |
| 882 | /* loop until the buffer is full or we've stopped speaking */ |
| 898 | 883 | while ((size > 0) && tms->speaking_now) |
| 899 | | { |
| 900 | | /* if it is the appropriate time to update the old energy/pitch idxes, |
| 901 | | * i.e. when IP=7, PC=12, T=17, subcycle=2, do so. Since IP=7 PC=12 T=17 |
| 902 | | * is JUST BEFORE the transition to IP=0 PC=0 T=0 sybcycle=(0 or 1), |
| 903 | | * which happens 4 T-cycles later), we change on the latter.*/ |
| 904 | | if ((tms->interp_period == 0) && (tms->PC == 0) && (tms->subcycle < 2)) |
| 884 | { |
| 885 | /* if it is the appropriate time to update the old energy/pitch idxes, |
| 886 | * i.e. when IP=7, PC=12, T=17, subcycle=2, do so. Since IP=7 PC=12 T=17 |
| 887 | * is JUST BEFORE the transition to IP=0 PC=0 T=0 sybcycle=(0 or 1), |
| 888 | * which happens 4 T-cycles later), we change on the latter.*/ |
| 889 | if ((tms->interp_period == 0) && (tms->PC == 0) && (tms->subcycle < 2)) |
| 905 | 890 | { |
| 906 | 891 | tms->OLDE = (tms->new_frame_energy_idx == 0); |
| 907 | 892 | tms->OLDP = (tms->new_frame_pitch_idx == 0); |
| 908 | 893 | } |
| 909 | 894 | |
| 910 | | /* if we're ready for a new frame to be applied, i.e. when IP=0, PC=12, Sub=1 */ |
| 911 | | /* (In reality, the frame was really loaded incrementally during the entire IP=0 PC=x time period, but it doesn't affect anything until IP=0 PC=12 happens) */ |
| 912 | | if ((tms->interp_period == 0) && (tms->PC == 12) && (tms->subcycle == 1)) |
| 913 | | { |
| 895 | /* if we're ready for a new frame to be applied, i.e. when IP=0, PC=12, Sub=1 |
| 896 | * (In reality, the frame was really loaded incrementally during the entire IP=0 |
| 897 | * PC=x time period, but it doesn't affect anything until IP=0 PC=12 happens) |
| 898 | */ |
| 899 | if ((tms->interp_period == 0) && (tms->PC == 12) && (tms->subcycle == 1)) |
| 900 | { |
| 914 | 901 | // HACK for regression testing, be sure to comment out before release! |
| 915 | 902 | //tms->RNG = 0x1234; |
| 916 | 903 | // end HACK |
| r18938 | r18939 | |
| 952 | 939 | } |
| 953 | 940 | |
| 954 | 941 | /* in all cases where interpolation would be inhibited, set the inhibit flag; otherwise clear it. |
| 955 | | Interpolation inhibit cases: |
| 956 | | * Old frame was voiced, new is unvoiced |
| 957 | | * Old frame was silence/zero energy, new has nonzero energy |
| 958 | | * Old frame was unvoiced, new is voiced |
| 959 | | */ |
| 942 | Interpolation inhibit cases: |
| 943 | * Old frame was voiced, new is unvoiced |
| 944 | * Old frame was silence/zero energy, new has nonzero energy |
| 945 | * Old frame was unvoiced, new is voiced |
| 946 | */ |
| 960 | 947 | if ( ((OLD_FRAME_UNVOICED_FLAG == 0) && (NEW_FRAME_UNVOICED_FLAG == 1)) |
| 961 | 948 | || ((OLD_FRAME_UNVOICED_FLAG == 1) && (NEW_FRAME_UNVOICED_FLAG == 0)) |
| 962 | 949 | || ((OLD_FRAME_SILENCE_FLAG == 1) && (NEW_FRAME_SILENCE_FLAG == 0)) ) |
| r18938 | r18939 | |
| 1047 | 1034 | } |
| 1048 | 1035 | } |
| 1049 | 1036 | #endif |
| 1050 | | } |
| 1037 | } |
| 1051 | 1038 | |
| 1052 | | /* calculate the output */ |
| 1039 | // calculate the output |
| 1053 | 1040 | if (OLD_FRAME_UNVOICED_FLAG == 1) |
| 1054 | 1041 | { |
| 1055 | | /* generate unvoiced samples here */ |
| 1042 | // generate unvoiced samples here |
| 1056 | 1043 | #ifndef UNVOICED_HACK |
| 1057 | 1044 | if (tms->RNG & 1) |
| 1058 | 1045 | tms->excitation_data = ~0x3F; /* according to the patent it is (either + or -) half of the maximum value in the chirp table, so either 01000000(0x40) or 11000000(0xC0)*/ |
| 1059 | 1046 | else |
| 1060 | 1047 | tms->excitation_data = 0x40; |
| 1061 | | #else // hack to double unvoiced strength, doesn't match patent |
| 1048 | #else // hack to tweak unvoiced strength, doesn't match patent |
| 1062 | 1049 | if (tms->RNG & 1) |
| 1063 | | tms->excitation_data = ~0x7F; |
| 1050 | tms->excitation_data = 0; |
| 1064 | 1051 | else |
| 1065 | | tms->excitation_data = 0x80; |
| 1052 | tms->excitation_data = 0x40; |
| 1066 | 1053 | #endif |
| 1067 | | } |
| 1068 | | else /* (OLD_FRAME_UNVOICED_FLAG == 0) */ |
| 1069 | | { |
| 1070 | | /* generate voiced samples here */ |
| 1071 | | /* US patent 4331836 Figure 14B shows, and logic would hold, that a pitch based chirp |
| 1072 | | * function has a chirp/peak and then a long chain of zeroes. |
| 1073 | | * The last entry of the chirp rom is at address 0b110011 (51d), the 52nd sample, |
| 1074 | | * and if the address reaches that point the ADDRESS incrementer is |
| 1075 | | * disabled, forcing all samples beyond 51d to be == 51d |
| 1076 | | * (address 51d holds zeroes, which may or may not be inverted to -1) |
| 1077 | | */ |
| 1078 | | if (tms->pitch_count >= 51) |
| 1079 | | tms->excitation_data = tms->coeff->chirptable[51]; |
| 1080 | | else /*tms->pitch_count < 51*/ |
| 1081 | | tms->excitation_data = tms->coeff->chirptable[tms->pitch_count]; |
| 1082 | | #ifdef VOICED_INV_HACK |
| 1083 | | // invert waveform |
| 1084 | | if (tms->pitch_count >= 51) |
| 1085 | | tms->excitation_data = ~tms->coeff->chirptable[51]; |
| 1086 | | else /*tms->pitch_count < 51*/ |
| 1087 | | tms->excitation_data = ~tms->coeff->chirptable[tms->pitch_count]; |
| 1088 | | #endif |
| 1089 | | #ifdef VOICED_ZERO_HACK |
| 1090 | | // 0 and >=51 are -128, as implied by qboxpro tables |
| 1091 | | if ((tms->pitch_count == 0) | (tms->pitch_count >= 51)) |
| 1092 | | tms->excitation_data = -128; |
| 1093 | | else /*tms->pitch_count < 51 && > 0*/ |
| 1094 | | tms->excitation_data = tms->coeff->chirptable[tms->pitch_count]; |
| 1095 | | #endif |
| 1096 | | #ifdef VOICED_PULSE_HACK |
| 1097 | | // if pitch is between 1 and PWIDTH+1, out = PAMP, if between PWIDTH+1 and (2*PWIDTH)+1, out ~PAMP, else out = 0 |
| 1098 | | if (tms->pitch_count == 0) |
| 1099 | | tms->excitation_data = 0; |
| 1100 | | else if (tms->pitch_count < PWIDTH+1) |
| 1101 | | tms->excitation_data = PAMP; |
| 1102 | | else if (tms->pitch_count < (PWIDTH*2)+1) |
| 1103 | | tms->excitation_data = ~PAMP; |
| 1104 | | else |
| 1105 | | tms->excitation_data = 0; |
| 1106 | | #endif |
| 1107 | | #ifdef VOICED_PULSE_MONOPOLAR_HACK |
| 1108 | | // if pitch is between 1 and PWIDTH+1, out = PAMP, else out = 0 |
| 1109 | | if (tms->pitch_count == 0) |
| 1110 | | tms->excitation_data = 0; |
| 1111 | | else if (tms->pitch_count < PWIDTH+1) |
| 1112 | | tms->excitation_data = PAMP; |
| 1113 | | else |
| 1114 | | tms->excitation_data = 0; |
| 1115 | | #endif |
| 1116 | | } |
| 1054 | } |
| 1055 | else /* (OLD_FRAME_UNVOICED_FLAG == 0) */ |
| 1056 | { |
| 1057 | // generate voiced samples here |
| 1058 | /* US patent 4331836 Figure 14B shows, and logic would hold, that a pitch based chirp |
| 1059 | * function has a chirp/peak and then a long chain of zeroes. |
| 1060 | * The last entry of the chirp rom is at address 0b110011 (51d), the 52nd sample, |
| 1061 | * and if the address reaches that point the ADDRESS incrementer is |
| 1062 | * disabled, forcing all samples beyond 51d to be == 51d |
| 1063 | * (address 51d holds zeroes, which may or may not be inverted to -1) |
| 1064 | */ |
| 1065 | if (tms->pitch_count >= 51) |
| 1066 | tms->excitation_data = tms->coeff->chirptable[51]; |
| 1067 | else /*tms->pitch_count < 51*/ |
| 1068 | tms->excitation_data = tms->coeff->chirptable[tms->pitch_count]; |
| 1069 | } |
| 1117 | 1070 | |
| 1118 | | /* Update LFSR *20* times every sample (once per T cycle), like patent shows */ |
| 1071 | // Update LFSR *20* times every sample (once per T cycle), like patent shows |
| 1119 | 1072 | for (i=0; i<20; i++) |
| 1120 | 1073 | { |
| 1121 | | bitout = ((tms->RNG >> 12) & 1) ^ |
| 1122 | | ((tms->RNG >> 3) & 1) ^ |
| 1123 | | ((tms->RNG >> 2) & 1) ^ |
| 1124 | | ((tms->RNG >> 0) & 1); |
| 1125 | | tms->RNG <<= 1; |
| 1126 | | tms->RNG |= bitout; |
| 1074 | bitout = ((tms->RNG >> 12) & 1) ^ |
| 1075 | ((tms->RNG >> 3) & 1) ^ |
| 1076 | ((tms->RNG >> 2) & 1) ^ |
| 1077 | ((tms->RNG >> 0) & 1); |
| 1078 | tms->RNG <<= 1; |
| 1079 | tms->RNG |= bitout; |
| 1127 | 1080 | } |
| 1128 | 1081 | this_sample = lattice_filter(tms); /* execute lattice filter */ |
| 1129 | 1082 | #ifdef DEBUG_GENERATION_VERBOSE |
| r18938 | r18939 | |
| 1155 | 1108 | buffer[buf_count] = (this_sample<<1)|((this_sample&0x3E00)>>9); |
| 1156 | 1109 | #endif |
| 1157 | 1110 | } |
| 1158 | | /* Update all counts */ |
| 1111 | // Update all counts |
| 1159 | 1112 | |
| 1160 | | tms->subcycle++; |
| 1161 | | if ((tms->subcycle == 2) && (tms->PC == 12)) |
| 1162 | | { |
| 1163 | | tms->subcycle = tms->subc_reload; |
| 1164 | | tms->PC = 0; |
| 1165 | | tms->interp_period++; |
| 1166 | | tms->interp_period&=0x7; |
| 1167 | | } |
| 1168 | | else if (tms->subcycle == 3) |
| 1169 | | { |
| 1170 | | tms->subcycle = tms->subc_reload; |
| 1171 | | tms->PC++; |
| 1172 | | } |
| 1173 | | /* Circuit 412 in the patent ensures that when INHIBIT is true, |
| 1174 | | * during the period from IP=7 PC=12 T12, to IP=0 PC=12 T12, the pitch |
| 1175 | | * count is forced to 0; since the initial stop happens right before |
| 1176 | | * the switch to IP=0 PC=0 and this code is located after the switch would |
| 1177 | | * happen, we check for ip=0 inhibit=1, which covers that whole range. |
| 1178 | | * The purpose of Circuit 412 is to prevent a spurious click caused by |
| 1179 | | * the voiced source being fed to the filter before all the values have |
| 1180 | | * been updated during ip=0 when interpolation was inhibited. |
| 1181 | | */ |
| 1182 | | tms->pitch_count++; |
| 1183 | | if (tms->pitch_count >= tms->current_pitch) tms->pitch_count = 0; |
| 1184 | | if ((tms->interp_period == 0)&&(tms->inhibit==1)) tms->pitch_count = 0; |
| 1185 | | tms->pitch_count &= 0x1FF; |
| 1186 | | buf_count++; |
| 1187 | | size--; |
| 1188 | | } |
| 1113 | tms->subcycle++; |
| 1114 | if ((tms->subcycle == 2) && (tms->PC == 12)) |
| 1115 | { |
| 1116 | tms->subcycle = tms->subc_reload; |
| 1117 | tms->PC = 0; |
| 1118 | tms->interp_period++; |
| 1119 | tms->interp_period&=0x7; |
| 1120 | } |
| 1121 | else if (tms->subcycle == 3) |
| 1122 | { |
| 1123 | tms->subcycle = tms->subc_reload; |
| 1124 | tms->PC++; |
| 1125 | } |
| 1126 | /* Circuit 412 in the patent ensures that when INHIBIT is true, |
| 1127 | * during the period from IP=7 PC=12 T12, to IP=0 PC=12 T12, the pitch |
| 1128 | * count is forced to 0; since the initial stop happens right before |
| 1129 | * the switch to IP=0 PC=0 and this code is located after the switch would |
| 1130 | * happen, we check for ip=0 inhibit=1, which covers that whole range. |
| 1131 | * The purpose of Circuit 412 is to prevent a spurious click caused by |
| 1132 | * the voiced source being fed to the filter before all the values have |
| 1133 | * been updated during ip=0 when interpolation was inhibited. |
| 1134 | */ |
| 1135 | tms->pitch_count++; |
| 1136 | if (tms->pitch_count >= tms->current_pitch) tms->pitch_count = 0; |
| 1137 | if ((tms->interp_period == 0)&&(tms->inhibit==1)) tms->pitch_count = 0; |
| 1138 | tms->pitch_count &= 0x1FF; |
| 1139 | buf_count++; |
| 1140 | size--; |
| 1141 | } |
| 1189 | 1142 | |
| 1190 | 1143 | empty: |
| 1191 | 1144 | |
| 1192 | | while (size > 0) |
| 1193 | | { |
| 1194 | | tms->subcycle++; |
| 1195 | | if ((tms->subcycle == 2) && (tms->PC == 12)) |
| 1196 | | { |
| 1197 | | tms->subcycle = tms->subc_reload; |
| 1198 | | tms->PC = 0; |
| 1199 | | tms->interp_period++; |
| 1200 | | tms->interp_period&=0x7; |
| 1201 | | } |
| 1202 | | else if (tms->subcycle == 3) |
| 1203 | | { |
| 1204 | | tms->subcycle = tms->subc_reload; |
| 1205 | | tms->PC++; |
| 1206 | | } |
| 1145 | while (size > 0) |
| 1146 | { |
| 1147 | tms->subcycle++; |
| 1148 | if ((tms->subcycle == 2) && (tms->PC == 12)) |
| 1149 | { |
| 1150 | tms->subcycle = tms->subc_reload; |
| 1151 | tms->PC = 0; |
| 1152 | tms->interp_period++; |
| 1153 | tms->interp_period&=0x7; |
| 1154 | } |
| 1155 | else if (tms->subcycle == 3) |
| 1156 | { |
| 1157 | tms->subcycle = tms->subc_reload; |
| 1158 | tms->PC++; |
| 1159 | } |
| 1207 | 1160 | buffer[buf_count] = -1; /* should be just -1; actual chip outputs -1 every idle sample; (cf note in data sheet, p 10, table 4) */ |
| 1208 | | buf_count++; |
| 1209 | | size--; |
| 1210 | | } |
| 1161 | buf_count++; |
| 1162 | size--; |
| 1163 | } |
| 1211 | 1164 | } |
| 1212 | 1165 | |
| 1213 | 1166 | /********************************************************************************************** |
| 1214 | 1167 | |
| 1215 | | clip_analog -- clips the 14 bit return value from the lattice filter to its final 10 bit value (-512 to 511), and upshifts/range extends this to 16 bits |
| 1168 | clip_analog -- clips the 14 bit return value from the lattice filter to its final 10 bit value (-512 to 511), and upshifts/range extends this to 16 bits |
| 1216 | 1169 | |
| 1217 | 1170 | ***********************************************************************************************/ |
| 1218 | 1171 | |
| 1219 | 1172 | static INT16 clip_analog(INT16 cliptemp) |
| 1220 | 1173 | { |
| 1221 | | /* clipping, just like the patent shows: |
| 1222 | | the top 10 bits of this result are visible on the digital output IO pin. |
| 1223 | | next, if the top 3 bits of the 14 bit result are all the same, the lowest of those 3 bits plus the next 7 bits are the signed analog output, otherwise the low bits are all forced to match the inverse of the topmost bit, i.e.: |
| 1224 | | 1x xxxx xxxx xxxx -> 0b10000000 |
| 1225 | | 11 1bcd efgh xxxx -> 0b1bcdefgh |
| 1226 | | 00 0bcd efgh xxxx -> 0b0bcdefgh |
| 1227 | | 0x xxxx xxxx xxxx -> 0b01111111 |
| 1228 | | */ |
| 1174 | /* clipping, just like the patent shows: |
| 1175 | * the top 10 bits of this result are visible on the digital output IO pin. |
| 1176 | * next, if the top 3 bits of the 14 bit result are all the same, the lowest of those 3 bits plus the next 7 bits are the signed analog output, otherwise the low bits are all forced to match the inverse of the topmost bit, i.e.: |
| 1177 | * 1x xxxx xxxx xxxx -> 0b10000000 |
| 1178 | * 11 1bcd efgh xxxx -> 0b1bcdefgh |
| 1179 | * 00 0bcd efgh xxxx -> 0b0bcdefgh |
| 1180 | * 0x xxxx xxxx xxxx -> 0b01111111 |
| 1181 | */ |
| 1229 | 1182 | #ifdef DEBUG_CLIP |
| 1230 | 1183 | if ((cliptemp > 2047) || (cliptemp < -2048)) fprintf(stderr,"clipping cliptemp to range; was %d\n", cliptemp); |
| 1231 | 1184 | #endif |
| r18938 | r18939 | |
| 1250 | 1203 | |
| 1251 | 1204 | /********************************************************************************************** |
| 1252 | 1205 | |
| 1253 | | matrix_multiply -- does the proper multiply and shift |
| 1254 | | a is the k coefficient and is clamped to 10 bits (9 bits plus a sign) |
| 1255 | | b is the running result and is clamped to 14 bits. |
| 1256 | | output is 14 bits, but note the result LSB bit is always 1. |
| 1257 | | Because the low 4 bits of the result are trimmed off before |
| 1258 | | output, this makes almost no difference in the computation. |
| 1206 | matrix_multiply -- does the proper multiply and shift |
| 1207 | a is the k coefficient and is clamped to 10 bits (9 bits plus a sign) |
| 1208 | b is the running result and is clamped to 14 bits. |
| 1209 | output is 14 bits, but note the result LSB bit is always 1. |
| 1210 | Because the low 4 bits of the result are trimmed off before |
| 1211 | output, this makes almost no difference in the computation. |
| 1259 | 1212 | |
| 1260 | 1213 | **********************************************************************************************/ |
| 1261 | 1214 | static INT32 matrix_multiply(INT32 a, INT32 b) |
| r18938 | r18939 | |
| 1265 | 1218 | while (a<-512) { a+=1024; } |
| 1266 | 1219 | while (b>16383) { b-=32768; } |
| 1267 | 1220 | while (b<-16384) { b+=32768; } |
| 1268 | | result = ((a*b)>>9)|1; |
| 1221 | result = ((a*b)>>9)|1;//&(~1); |
| 1269 | 1222 | #ifdef VERBOSE |
| 1270 | 1223 | if (result>16383) fprintf(stderr,"matrix multiplier overflowed! a: %x, b: %x, result: %x", a, b, result); |
| 1271 | 1224 | if (result<-16384) fprintf(stderr,"matrix multiplier underflowed! a: %x, b: %x, result: %x", a, b, result); |
| r18938 | r18939 | |
| 1275 | 1228 | |
| 1276 | 1229 | /********************************************************************************************** |
| 1277 | 1230 | |
| 1278 | | lattice_filter -- executes one 'full run' of the lattice filter on a specific byte of |
| 1279 | | excitation data, and specific values of all the current k constants, and returns the |
| 1280 | | resulting sample. |
| 1231 | lattice_filter -- executes one 'full run' of the lattice filter on a specific byte of |
| 1232 | excitation data, and specific values of all the current k constants, and returns the |
| 1233 | resulting sample. |
| 1281 | 1234 | |
| 1282 | 1235 | ***********************************************************************************************/ |
| 1283 | 1236 | |
| 1284 | 1237 | static INT32 lattice_filter(tms5220_state *tms) |
| 1285 | 1238 | { |
| 1286 | | /* Lattice filter here */ |
| 1287 | | /* Aug/05/07: redone as unrolled loop, for clarity - LN*/ |
| 1288 | | /* Originally Copied verbatim from table I in US patent 4,209,804, now updated to be in same order as the actual chip does it, not that it matters. |
| 1289 | | notation equivalencies from table: |
| 1290 | | Yn(i) == tms->u[n-1] |
| 1291 | | Kn = tms->current_k[n-1] |
| 1292 | | bn = tms->x[n-1] |
| 1293 | | */ |
| 1294 | | tms->u[10] = matrix_multiply(tms->previous_energy, (tms->excitation_data<<6)); //Y(11) |
| 1295 | | tms->u[9] = tms->u[10] - matrix_multiply(tms->current_k[9], tms->x[9]); |
| 1296 | | tms->u[8] = tms->u[9] - matrix_multiply(tms->current_k[8], tms->x[8]); |
| 1297 | | tms->u[7] = tms->u[8] - matrix_multiply(tms->current_k[7], tms->x[7]); |
| 1298 | | tms->u[6] = tms->u[7] - matrix_multiply(tms->current_k[6], tms->x[6]); |
| 1299 | | tms->u[5] = tms->u[6] - matrix_multiply(tms->current_k[5], tms->x[5]); |
| 1300 | | tms->u[4] = tms->u[5] - matrix_multiply(tms->current_k[4], tms->x[4]); |
| 1301 | | tms->u[3] = tms->u[4] - matrix_multiply(tms->current_k[3], tms->x[3]); |
| 1302 | | tms->u[2] = tms->u[3] - matrix_multiply(tms->current_k[2], tms->x[2]); |
| 1303 | | tms->u[1] = tms->u[2] - matrix_multiply(tms->current_k[1], tms->x[1]); |
| 1304 | | tms->u[0] = tms->u[1] - matrix_multiply(tms->current_k[0], tms->x[0]); |
| 1305 | | tms->x[9] = tms->x[8] + matrix_multiply(tms->current_k[8], tms->u[8]); |
| 1306 | | tms->x[8] = tms->x[7] + matrix_multiply(tms->current_k[7], tms->u[7]); |
| 1307 | | tms->x[7] = tms->x[6] + matrix_multiply(tms->current_k[6], tms->u[6]); |
| 1308 | | tms->x[6] = tms->x[5] + matrix_multiply(tms->current_k[5], tms->u[5]); |
| 1309 | | tms->x[5] = tms->x[4] + matrix_multiply(tms->current_k[4], tms->u[4]); |
| 1310 | | tms->x[4] = tms->x[3] + matrix_multiply(tms->current_k[3], tms->u[3]); |
| 1311 | | tms->x[3] = tms->x[2] + matrix_multiply(tms->current_k[2], tms->u[2]); |
| 1312 | | tms->x[2] = tms->x[1] + matrix_multiply(tms->current_k[1], tms->u[1]); |
| 1313 | | tms->x[1] = tms->x[0] + matrix_multiply(tms->current_k[0], tms->u[0]); |
| 1314 | | tms->x[0] = tms->u[0]; |
| 1315 | | tms->previous_energy = tms->current_energy; |
| 1239 | // Lattice filter here |
| 1240 | // Aug/05/07: redone as unrolled loop, for clarity - LN |
| 1241 | /* Originally Copied verbatim from table I in US patent 4,209,804, now updated to be in same order as the actual chip does it, not that it matters. |
| 1242 | notation equivalencies from table: |
| 1243 | Yn(i) == tms->u[n-1] |
| 1244 | Kn = tms->current_k[n-1] |
| 1245 | bn = tms->x[n-1] |
| 1246 | */ |
| 1247 | tms->u[10] = matrix_multiply(tms->previous_energy, (tms->excitation_data<<6)); //Y(11) |
| 1248 | tms->u[9] = tms->u[10] - matrix_multiply(tms->current_k[9], tms->x[9]); |
| 1249 | tms->u[8] = tms->u[9] - matrix_multiply(tms->current_k[8], tms->x[8]); |
| 1250 | tms->u[7] = tms->u[8] - matrix_multiply(tms->current_k[7], tms->x[7]); |
| 1251 | tms->u[6] = tms->u[7] - matrix_multiply(tms->current_k[6], tms->x[6]); |
| 1252 | tms->u[5] = tms->u[6] - matrix_multiply(tms->current_k[5], tms->x[5]); |
| 1253 | tms->u[4] = tms->u[5] - matrix_multiply(tms->current_k[4], tms->x[4]); |
| 1254 | tms->u[3] = tms->u[4] - matrix_multiply(tms->current_k[3], tms->x[3]); |
| 1255 | tms->u[2] = tms->u[3] - matrix_multiply(tms->current_k[2], tms->x[2]); |
| 1256 | tms->u[1] = tms->u[2] - matrix_multiply(tms->current_k[1], tms->x[1]); |
| 1257 | tms->u[0] = tms->u[1] - matrix_multiply(tms->current_k[0], tms->x[0]); |
| 1258 | tms->x[9] = tms->x[8] + matrix_multiply(tms->current_k[8], tms->u[8]); |
| 1259 | tms->x[8] = tms->x[7] + matrix_multiply(tms->current_k[7], tms->u[7]); |
| 1260 | tms->x[7] = tms->x[6] + matrix_multiply(tms->current_k[6], tms->u[6]); |
| 1261 | tms->x[6] = tms->x[5] + matrix_multiply(tms->current_k[5], tms->u[5]); |
| 1262 | tms->x[5] = tms->x[4] + matrix_multiply(tms->current_k[4], tms->u[4]); |
| 1263 | tms->x[4] = tms->x[3] + matrix_multiply(tms->current_k[3], tms->u[3]); |
| 1264 | tms->x[3] = tms->x[2] + matrix_multiply(tms->current_k[2], tms->u[2]); |
| 1265 | tms->x[2] = tms->x[1] + matrix_multiply(tms->current_k[1], tms->u[1]); |
| 1266 | tms->x[1] = tms->x[0] + matrix_multiply(tms->current_k[0], tms->u[0]); |
| 1267 | tms->x[0] = tms->u[0]; |
| 1268 | tms->previous_energy = tms->current_energy; |
| 1316 | 1269 | #ifdef DEBUG_LATTICE |
| 1317 | 1270 | int i; |
| 1318 | 1271 | fprintf(stderr,"V:%04d ", tms->u[10]); |
| r18938 | r18939 | |
| 1323 | 1276 | if ((i % 5) == 0) fprintf(stderr,"\n"); |
| 1324 | 1277 | } |
| 1325 | 1278 | #endif |
| 1326 | | return tms->u[0]; |
| 1279 | return tms->u[0]; |
| 1327 | 1280 | } |
| 1328 | 1281 | |
| 1329 | 1282 | |
| 1330 | 1283 | /********************************************************************************************** |
| 1331 | 1284 | |
| 1332 | | process_command -- extract a byte from the FIFO and interpret it as a command |
| 1285 | process_command -- extract a byte from the FIFO and interpret it as a command |
| 1333 | 1286 | |
| 1334 | 1287 | ***********************************************************************************************/ |
| 1335 | 1288 | |
| r18938 | r18939 | |
| 1379 | 1332 | if (tms->talk_status == 0) /* TALKST must be clear for LA */ |
| 1380 | 1333 | { |
| 1381 | 1334 | /* tms5220 data sheet says that if we load only one 4-bit nibble, it won't work. |
| 1382 | | This code does not care about this. */ |
| 1335 | This code does not care about this. */ |
| 1383 | 1336 | if (tms->intf->load_address) |
| 1384 | 1337 | (*tms->intf->load_address)(tms->device, cmd & 0x0f); |
| 1385 | 1338 | tms->schedule_dummy_read = TRUE; |
| r18938 | r18939 | |
| 1431 | 1384 | } |
| 1432 | 1385 | tms->device->reset(); |
| 1433 | 1386 | break; |
| 1434 | | } |
| 1387 | } |
| 1435 | 1388 | |
| 1436 | | /* update the buffer low state */ |
| 1437 | | update_status_and_ints(tms); |
| 1389 | /* update the buffer low state */ |
| 1390 | update_status_and_ints(tms); |
| 1438 | 1391 | } |
| 1439 | 1392 | |
| 1440 | 1393 | /****************************************************************************************** |
| r18938 | r18939 | |
| 1450 | 1403 | // We actually don't care how many bits are left in the fifo here; the frame subpart will be processed normally, and any bits extracted 'past the end' of the fifo will be read as zeroes; the fifo being emptied will set the /BE latch which will halt speech exactly as if a stop frame had been encountered (instead of whatever partial frame was read); the same exact circuitry is used for both on the real chip, see us patent 4335277 sheet 16, gates 232a (decode stop frame) and 232b (decode /BE plus DDIS (decode disable) which is active during speak external). |
| 1451 | 1404 | |
| 1452 | 1405 | /* if the chip is a tms5220C, and the rate mode is set to that each frame (0x04 bit set) |
| 1453 | | has a 2 bit rate preceding it, grab two bits here and store them as the rate; */ |
| 1406 | has a 2 bit rate preceding it, grab two bits here and store them as the rate; */ |
| 1454 | 1407 | if ((tms->variant == SUBTYPE_TMS5220C) && (tms->tms5220c_rate & 0x04)) |
| 1455 | 1408 | { |
| 1456 | 1409 | indx = extract_bits(tms, 2); |
| r18938 | r18939 | |
| 1466 | 1419 | update_status_and_ints(tms); |
| 1467 | 1420 | if (!tms->talk_status) goto ranout; |
| 1468 | 1421 | |
| 1469 | | /* attempt to extract the energy index */ |
| 1422 | // attempt to extract the energy index |
| 1470 | 1423 | tms->new_frame_energy_idx = extract_bits(tms,tms->coeff->energy_bits); |
| 1471 | 1424 | #ifdef DEBUG_PARSE_FRAME_DUMP |
| 1472 | 1425 | printbits(tms->new_frame_energy_idx,tms->coeff->energy_bits); |
| r18938 | r18939 | |
| 1474 | 1427 | #endif |
| 1475 | 1428 | update_status_and_ints(tms); |
| 1476 | 1429 | if (!tms->talk_status) goto ranout; |
| 1477 | | /* if the energy index is 0 or 15, we're done */ |
| 1430 | // if the energy index is 0 or 15, we're done |
| 1478 | 1431 | if ((tms->new_frame_energy_idx == 0) || (tms->new_frame_energy_idx == 15)) |
| 1479 | 1432 | return; |
| 1480 | 1433 | |
| 1481 | 1434 | |
| 1482 | | /* attempt to extract the repeat flag */ |
| 1435 | // attempt to extract the repeat flag |
| 1483 | 1436 | rep_flag = extract_bits(tms,1); |
| 1484 | 1437 | #ifdef DEBUG_PARSE_FRAME_DUMP |
| 1485 | 1438 | printbits(rep_flag, 1); |
| 1486 | 1439 | fprintf(stderr," "); |
| 1487 | 1440 | #endif |
| 1488 | 1441 | |
| 1489 | | /* attempt to extract the pitch */ |
| 1442 | // attempt to extract the pitch |
| 1490 | 1443 | tms->new_frame_pitch_idx = extract_bits(tms,tms->coeff->pitch_bits); |
| 1491 | 1444 | #ifdef DEBUG_PARSE_FRAME_DUMP |
| 1492 | 1445 | printbits(tms->new_frame_pitch_idx,tms->coeff->pitch_bits); |
| r18938 | r18939 | |
| 1494 | 1447 | #endif |
| 1495 | 1448 | update_status_and_ints(tms); |
| 1496 | 1449 | if (!tms->talk_status) goto ranout; |
| 1497 | | /* if this is a repeat frame, just do nothing, it will reuse the old coefficients's */ |
| 1450 | // if this is a repeat frame, just do nothing, it will reuse the old coefficients |
| 1498 | 1451 | if (rep_flag) |
| 1499 | 1452 | return; |
| 1500 | 1453 | |
| 1501 | | /* extract first 4 K coefficients */ |
| 1454 | // extract first 4 K coefficients |
| 1502 | 1455 | for (i = 0; i < 4; i++) |
| 1503 | 1456 | { |
| 1504 | 1457 | tms->new_frame_k_idx[i] = extract_bits(tms,tms->coeff->kbits[i]); |
| r18938 | r18939 | |
| 1510 | 1463 | if (!tms->talk_status) goto ranout; |
| 1511 | 1464 | } |
| 1512 | 1465 | |
| 1513 | | /* if the pitch index was zero, we only need 4 K's... */ |
| 1466 | // if the pitch index was zero, we only need 4 K's... |
| 1514 | 1467 | if (tms->new_frame_pitch_idx == 0) |
| 1515 | 1468 | { |
| 1516 | 1469 | /* and the rest of the coefficients are zeroed, but that's done in the generator code */ |
| 1517 | 1470 | return; |
| 1518 | 1471 | } |
| 1519 | 1472 | |
| 1520 | | /* If we got here, we need the remaining 6 K's */ |
| 1473 | // If we got here, we need the remaining 6 K's |
| 1521 | 1474 | for (i = 4; i < tms->coeff->num_k; i++) |
| 1522 | 1475 | { |
| 1523 | 1476 | tms->new_frame_k_idx[i] = extract_bits(tms, tms->coeff->kbits[i]); |
| r18938 | r18939 | |
| 1538 | 1491 | |
| 1539 | 1492 | ranout: |
| 1540 | 1493 | #ifdef DEBUG_FRAME_ERRORS |
| 1541 | | logerror("Ran out of bits on a parse!\n"); |
| 1494 | logerror("Ran out of bits on a parse!\n"); |
| 1542 | 1495 | #endif |
| 1543 | 1496 | return; |
| 1544 | 1497 | } |
| r18938 | r18939 | |
| 1554 | 1507 | #ifdef DEBUG_PIN_READS |
| 1555 | 1508 | logerror("irq pin set to state %d\n", state); |
| 1556 | 1509 | #endif |
| 1557 | | if (!tms->irq_func.isnull() && state != tms->irq_pin) |
| 1558 | | tms->irq_func(!state); |
| 1559 | | tms->irq_pin = state; |
| 1510 | if (!tms->irq_func.isnull() && state != tms->irq_pin) |
| 1511 | tms->irq_func(!state); |
| 1512 | tms->irq_pin = state; |
| 1560 | 1513 | } |
| 1561 | 1514 | |
| 1562 | 1515 | /********************************************************************************************** |
| r18938 | r18939 | |
| 1682 | 1635 | tms->subc_reload = FORCE_SUBC_RELOAD; |
| 1683 | 1636 | tms->OLDE = tms->OLDP = 1; |
| 1684 | 1637 | tms->interp_period = reload_table[tms->tms5220c_rate&0x3]; |
| 1685 | | tms->RNG = 0x1FFF; |
| 1638 | tms->RNG = 0x1FFF; |
| 1686 | 1639 | memset(tms->u, 0, sizeof(tms->u)); |
| 1687 | 1640 | memset(tms->x, 0, sizeof(tms->x)); |
| 1688 | 1641 | |
| r18938 | r18939 | |
| 2215 | 2168 | void tms52xx_device::device_reset() |
| 2216 | 2169 | { |
| 2217 | 2170 | m_digital_select = FORCE_DIGITAL; // assume analog output |
| 2218 | | // initialize the FIFO */ |
| 2219 | | // memset(tms->fifo, 0, sizeof(tms->fifo)); |
| 2171 | // initialize the FIFO |
| 2172 | // should we do a memset here to clear the fifo contents? |
| 2220 | 2173 | m_fifo_head = 0; |
| 2221 | 2174 | m_fifo_tail = 0; |
| 2222 | 2175 | m_fifo_count = 0; |
| 2223 | 2176 | m_fifo_bits_taken = 0; |
| 2224 | 2177 | |
| 2225 | 2178 | // initialize the chip state |
| 2226 | | // Note that we do not actually clear IRQ on start-up: IRQ is even raised |
| 2227 | | // if m_buffer_empty or m_buffer_low are 0 |
| 2179 | /* Note that we do not actually clear IRQ on start-up: IRQ is even raised |
| 2180 | * if m_buffer_empty or m_buffer_low are 0 */ |
| 2228 | 2181 | m_speaking_now = false; |
| 2229 | 2182 | m_speak_external = false; |
| 2230 | 2183 | m_talk_status = false; |
| r18938 | r18939 | |
| 2360 | 2313 | // loop until the buffer is full or we've stopped speaking |
| 2361 | 2314 | while ((size > 0) && m_speaking_now) |
| 2362 | 2315 | { |
| 2363 | | // if it is the appropriate time to update the old energy/pitch idxes, |
| 2364 | | // i.e. when IP=7, PC=12, T=17, subcycle=2, do so. Since IP=7 PC=12 T=17 |
| 2365 | | // is JUST BEFORE the transition to IP=0 PC=0 T=0 sybcycle=(0 or 1), |
| 2366 | | // which happens 4 T-cycles later), we change on the latter. |
| 2316 | /* if it is the appropriate time to update the old energy/pitch idxes, |
| 2317 | * i.e. when IP=7, PC=12, T=17, subcycle=2, do so. Since IP=7 PC=12 T=17 |
| 2318 | * is JUST BEFORE the transition to IP=0 PC=0 T=0 sybcycle=(0 or 1), |
| 2319 | * which happens 4 T-cycles later), we change on the latter. |
| 2320 | */ |
| 2367 | 2321 | if ((m_interp_period == 0) && (m_PC == 0) && (m_subcycle < 2)) |
| 2368 | 2322 | { |
| 2369 | 2323 | m_OLDE = (m_new_frame_energy_idx == 0); |
| 2370 | 2324 | m_OLDP = (m_new_frame_pitch_idx == 0); |
| 2371 | 2325 | } |
| 2372 | 2326 | |
| 2373 | | //if we're ready for a new frame to be applied, i.e. when IP=0, PC=12, Sub=1 |
| 2374 | | // (In reality, the frame was really loaded incrementally during the |
| 2375 | | // entire IP=0 PC=x time period, but it doesn't affect anything until IP=0 PC=12 happens) |
| 2327 | /* if we're ready for a new frame to be applied, i.e. when IP=0, PC=12, Sub=1 |
| 2328 | * (In reality, the frame was really loaded incrementally during the |
| 2329 | * entire IP=0 PC=x time period, but it doesn't affect anything until IP=0 PC=12 happens) |
| 2330 | */ |
| 2376 | 2331 | if ((m_interp_period == 0) && (m_PC == 12) && (m_subcycle == 1)) |
| 2377 | 2332 | { |
| 2378 | 2333 | // HACK for regression testing, be sure to comment out before release! |
| r18938 | r18939 | |
| 2471 | 2426 | #ifdef PERFECT_INTERPOLATION_HACK |
| 2472 | 2427 | int samples_per_frame = (m_subc_reload!=0)? 175:266; // either (13 A cycles + 12 B cycles) * 7 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 7 interps for SPKSLOW |
| 2473 | 2428 | //int samples_per_frame = (m_subc_reload!=0)?200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW |
| 2474 | | int current_sample = (tms->subcycle - tms->subc_reload)+(tms->PC*(3-tms->subc_reload))+((tms->subc_reload?25:38)*((tms->interp_period-1)&7)); |
| 2429 | int current_sample = (m_subcycle - m_subc_reload)+(m_PC*(3-m_subc_reload))+((m_subc_reload?25:38)*((m_interp_period-1)&7)); |
| 2475 | 2430 | |
| 2476 | 2431 | zpar = M_OLD_FRAME_UNVOICED_FLAG; |
| 2477 | 2432 | //fprintf(stderr, "CS: %03d", current_sample); |
| r18938 | r18939 | |
| 2537 | 2492 | m_excitation_data = ~0x3F; // according to the patent it is (either + or -) half of the maximum value in the chirp table, so either 01000000(0x40) or 11000000(0xC0) |
| 2538 | 2493 | else |
| 2539 | 2494 | m_excitation_data = 0x40; |
| 2540 | | #else // hack to double unvoiced strength, doesn't match patent |
| 2495 | #else // hack to tweak unvoiced strength, doesn't match patent |
| 2541 | 2496 | if (m_RNG & 1) |
| 2542 | | m_excitation_data = ~0x7F; |
| 2497 | m_excitation_data = 0; |
| 2543 | 2498 | else |
| 2544 | | m_excitation_data = 0x80; |
| 2499 | m_excitation_data = 0x40; |
| 2545 | 2500 | #endif |
| 2546 | 2501 | } |
| 2547 | 2502 | else // (M_OLD_FRAME_UNVOICED_FLAG == false) |
| r18938 | r18939 | |
| 2558 | 2513 | m_excitation_data = m_coeff->chirptable[51]; |
| 2559 | 2514 | else // tms->pitch_count < 51 |
| 2560 | 2515 | m_excitation_data = m_coeff->chirptable[m_pitch_count]; |
| 2561 | | #ifdef VOICED_INV_HACK |
| 2562 | | // invert waveform |
| 2563 | | if (m_pitch_count >= 51) |
| 2564 | | m_excitation_data = ~m_coeff->chirptable[51]; |
| 2565 | | else // tms->pitch_count < 51 |
| 2566 | | m_excitation_data = ~m_coeff->chirptable[m_pitch_count]; |
| 2567 | | #endif |
| 2568 | | #ifdef VOICED_ZERO_HACK |
| 2569 | | // 0 and >=51 are -128, as implied by qboxpro tables |
| 2570 | | if ((m_pitch_count == 0) | (m_pitch_count >= 51)) |
| 2571 | | m_excitation_data = -128; |
| 2572 | | else /*tms->pitch_count < 51 && > 0*/ |
| 2573 | | m_excitation_data = m_coeff->chirptable[m_pitch_count]; |
| 2574 | | #endif |
| 2575 | | #ifdef VOICED_PULSE_HACK |
| 2576 | | // if pitch is between 1 and PWIDTH+1, out = PAMP, if between PWIDTH+1 and (2*PWIDTH)+1, out ~PAMP, else out = 0 |
| 2577 | | if (m_pitch_count == 0) |
| 2578 | | m_excitation_data = 0; |
| 2579 | | else if (m_pitch_count < PWIDTH+1) |
| 2580 | | m_excitation_data = PAMP; |
| 2581 | | else if (m_pitch_count < (PWIDTH*2)+1) |
| 2582 | | m_excitation_data = ~PAMP; |
| 2583 | | else |
| 2584 | | m_excitation_data = 0; |
| 2585 | | #endif |
| 2586 | | #ifdef VOICED_PULSE_MONOPOLAR_HACK |
| 2587 | | // if pitch is between 1 and PWIDTH+1, out = PAMP, else out = 0 |
| 2588 | | if (m_pitch_count == 0) |
| 2589 | | m_excitation_data = 0; |
| 2590 | | else if (m_pitch_count < PWIDTH+1) |
| 2591 | | m_excitation_data = PAMP; |
| 2592 | | else |
| 2593 | | m_excitation_data = 0; |
| 2594 | | #endif |
| 2595 | 2516 | } |
| 2596 | 2517 | |
| 2597 | 2518 | // Update LFSR *20* times every sample (once per T cycle), like patent shows |
| r18938 | r18939 | |
| 2651 | 2572 | m_subcycle = m_subc_reload; |
| 2652 | 2573 | m_PC++; |
| 2653 | 2574 | } |
| 2654 | | // Circuit 412 in the patent ensures that when INHIBIT is true, |
| 2655 | | // during the period from IP=7 PC=12 T12, to IP=0 PC=12 T12, the pitch |
| 2656 | | // count is forced to 0; since the initial stop happens right before |
| 2657 | | // the switch to IP=0 PC=0 and this code is located after the switch would |
| 2658 | | // happen, we check for ip=0 inhibit=1, which covers that whole range. |
| 2659 | | // The purpose of Circuit 412 is to prevent a spurious click caused by |
| 2660 | | // the voiced source being fed to the filter before all the values have |
| 2661 | | // been updated during ip=0 when interpolation was inhibited. |
| 2662 | | |
| 2575 | /* Circuit 412 in the patent ensures that when INHIBIT is true, |
| 2576 | * during the period from IP=7 PC=12 T12, to IP=0 PC=12 T12, the pitch |
| 2577 | * count is forced to 0; since the initial stop happens right before |
| 2578 | * the switch to IP=0 PC=0 and this code is located after the switch would |
| 2579 | * happen, we check for ip=0 inhibit=1, which covers that whole range. |
| 2580 | * The purpose of Circuit 412 is to prevent a spurious click caused by |
| 2581 | * the voiced source being fed to the filter before all the values have |
| 2582 | * been updated during ip=0 when interpolation was inhibited. |
| 2583 | */ |
| 2663 | 2584 | m_pitch_count++; |
| 2664 | 2585 | if (m_pitch_count >= m_current_pitch) m_pitch_count = 0; |
| 2665 | 2586 | if ((m_interp_period == 0) && m_inhibit) m_pitch_count = 0; |
| r18938 | r18939 | |
| 2699 | 2620 | |
| 2700 | 2621 | INT32 tms52xx_device::lattice_filter() |
| 2701 | 2622 | { |
| 2702 | | // Lattice filter here */ |
| 2703 | | // Aug/05/07: redone as unrolled loop, for clarity - LN |
| 2704 | | // Originally Copied verbatim from table I in US patent 4,209,804, now updated |
| 2705 | | // to be in same order as the actual chip does it, not that it matters. |
| 2706 | | // notation equivalencies from table: |
| 2707 | | // Yn(i) == m_u[n-1] |
| 2708 | | // Kn = m_current_k[n-1] |
| 2709 | | // bn = m_x[n-1] |
| 2623 | /* Lattice filter here */ |
| 2624 | /* Aug/05/07: redone as unrolled loop, for clarity - LN |
| 2625 | * Originally Copied verbatim from table I in US patent 4,209,804, now updated |
| 2626 | * to be in same order as the actual chip does it, not that it matters. |
| 2627 | * notation equivalencies from table: |
| 2628 | * Yn(i) == m_u[n-1] |
| 2629 | * Kn = m_current_k[n-1] |
| 2630 | * bn = m_x[n-1] |
| 2631 | */ |
| 2710 | 2632 | |
| 2711 | 2633 | m_u[10] = matrix_multiply(m_previous_energy, (m_excitation_data<<6)); //Y(11) |
| 2712 | 2634 | m_u[9] = m_u[10] - matrix_multiply(m_current_k[9], m_x[9]); |
| r18938 | r18939 | |
| 2771 | 2693 | #ifdef DEBUG_FIFO |
| 2772 | 2694 | logerror("tms52xx: data_write triggered talk status to go active!\n"); |
| 2773 | 2695 | #endif |
| 2774 | | // ...then we now have enough bytes to start talking; clear out |
| 2775 | | // the new frame parameters (it will become old frame just before the first call to parse_frame()) |
| 2776 | | // TODO: the 3 lines below (and others) are needed for victory |
| 2777 | | // to not fail its selftest due to a sample ending too late, may require additional investigation |
| 2696 | /* ...then we now have enough bytes to start talking; clear out |
| 2697 | * the new frame parameters (it will become old frame just before the first call to parse_frame()) |
| 2698 | * TODO: the 3 lines below (and others) are needed for victory |
| 2699 | * to not fail its selftest due to a sample ending too late, may require additional investigation */ |
| 2778 | 2700 | m_subcycle = m_subc_reload; |
| 2779 | 2701 | m_PC = 0; |
| 2780 | 2702 | m_interp_period = reload_table[m_tms5220c_rate & 0x3]; // is this correct? should this be always 7 instead, so that the new frame is loaded quickly? |
| r18938 | r18939 | |
| 2919 | 2841 | { |
| 2920 | 2842 | int indx, i, rep_flag; |
| 2921 | 2843 | |
| 2922 | | // We actually don't care how many bits are left in the fifo here; the |
| 2923 | | // frame subpart will be processed normally, and any bits extracted 'past |
| 2924 | | // the end' of the fifo will be read as zeroes; the fifo being emptied will |
| 2925 | | // set the /BE latch which will halt speech exactly as if a stop frame had |
| 2926 | | // been encountered (instead of whatever partial frame was read); the same |
| 2927 | | // exact circuitry is used for both on the real chip, see us patent 4335277 |
| 2928 | | // sheet 16, gates 232a (decode stop frame) and 232b (decode /BE plus DDIS |
| 2929 | | // (decode disable) which is active during speak external). |
| 2844 | /* We actually don't care how many bits are left in the fifo here; the |
| 2845 | * frame subpart will be processed normally, and any bits extracted 'past |
| 2846 | * the end' of the fifo will be read as zeroes; the fifo being emptied will |
| 2847 | * set the /BE latch which will halt speech exactly as if a stop frame had |
| 2848 | * been encountered (instead of whatever partial frame was read); the same |
| 2849 | * exact circuitry is used for both on the real chip, see us patent 4335277 |
| 2850 | * sheet 16, gates 232a (decode stop frame) and 232b (decode /BE plus DDIS |
| 2851 | * (decode disable) which is active during speak external). */ |
| 2930 | 2852 | |
| 2931 | | // if the chip is a tms5220C, and the rate mode is set to that each frame (0x04 bit set) |
| 2932 | | // has a 2 bit rate preceding it, grab two bits here and store them as the rate; |
| 2853 | /* if the chip is a tms5220C, and the rate mode is set to that each frame (0x04 bit set) |
| 2854 | * has a 2 bit rate preceding it, grab two bits here and store them as the rate; */ |
| 2933 | 2855 | if ((m_variant == SUBTYPE_TMS5220C) && (m_tms5220c_rate & 0x04)) |
| 2934 | 2856 | { |
| 2935 | 2857 | indx = extract_bits(2); |
| r18938 | r18939 | |
| 2972 | 2894 | #endif |
| 2973 | 2895 | update_status_and_ints(); |
| 2974 | 2896 | if (!m_talk_status) goto ranout; |
| 2975 | | // if this is a repeat frame, just do nothing, it will reuse the |
| 2976 | | // old coefficients's |
| 2897 | /* if this is a repeat frame, just do nothing, it will reuse the |
| 2898 | * old coefficients */ |
| 2977 | 2899 | if (rep_flag) return; |
| 2978 | 2900 | |
| 2979 | 2901 | // extract first 4 K coefficients |
| r18938 | r18939 | |
| 3039 | 2961 | bit D2(bit 5) = BE - Buffer Empty is active (high) when the FIFO buffer has run out of data |
| 3040 | 2962 | while executing a Speak External command. Buffer Empty is set when the last bit |
| 3041 | 2963 | of the "Last-In" byte is shifted out to the Synthesis Section. This causes |
| 3042 | | Talk Status to be cleared. Speed is terminated at some abnormal point and the |
| 2964 | Talk Status to be cleared. Speech is terminated at some abnormal point and the |
| 3043 | 2965 | Speak External command execution is terminated. |
| 3044 | 2966 | |
| 3045 | 2967 | ***********************************************************************************************/ |
| r18938 | r18939 | |
| 3049 | 2971 | // update flags and set ints if needed |
| 3050 | 2972 | update_ready_state(); |
| 3051 | 2973 | |
| 3052 | | // BL is set if neither byte 9 nor 8 of the fifo are in use; this |
| 3053 | | // translates to having fifo_count (which ranges from 0 bytes in use to 16 |
| 3054 | | // bytes used) being less than or equal to 8. Victory/Victorba depends on this. |
| 2974 | /* BL is set if neither byte 9 nor 8 of the fifo are in use; this |
| 2975 | * translates to having fifo_count (which ranges from 0 bytes in use to 16 |
| 2976 | * bytes used) being less than or equal to 8. Victory/Victorba depends on this. */ |
| 3055 | 2977 | if (m_fifo_count <= 8) |
| 3056 | 2978 | { |
| 3057 | 2979 | // generate an interrupt if necessary; if /BL was inactive and is now active, set int. |
| r18938 | r18939 | |
| 3061 | 2983 | else |
| 3062 | 2984 | m_buffer_low = false; |
| 3063 | 2985 | |
| 3064 | | // BE is set if neither byte 15 nor 14 of the fifo are in use; this |
| 3065 | | // translates to having fifo_count equal to exactly 0 */ |
| 2986 | /* BE is set if neither byte 15 nor 14 of the fifo are in use; this |
| 2987 | * translates to having fifo_count equal to exactly 0 */ |
| 3066 | 2988 | if (m_fifo_count == 0) |
| 3067 | 2989 | { |
| 3068 | 2990 | // generate an interrupt if necessary; if /BE was inactive and is now active, set int. |
| r18938 | r18939 | |
| 3072 | 2994 | else |
| 3073 | 2995 | m_buffer_empty = false; |
| 3074 | 2996 | |
| 3075 | | // TS is talk status and is set elsewhere in the fifo parser and in |
| 3076 | | // the SPEAK command handler; however, if /BE is true during speak external |
| 3077 | | // mode, it is immediately unset here. |
| 2997 | /* TS is talk status and is set elsewhere in the fifo parser and in |
| 2998 | * the SPEAK command handler; however, if /BE is true during speak external |
| 2999 | * mode, it is immediately unset here. */ |
| 3078 | 3000 | if (m_speak_external && m_buffer_empty) |
| 3079 | 3001 | { |
| 3080 | 3002 | // generate an interrupt: /TS was active, and is now inactive. |
| r18938 | r18939 | |
| 3084 | 3006 | set_interrupt_state(1); |
| 3085 | 3007 | } |
| 3086 | 3008 | } |
| 3087 | | // Note that TS being unset will also generate an interrupt when a STOP |
| 3088 | | // frame is encountered; this is handled in the sample generator code and not here */ |
| 3009 | /* Note that TS being unset will also generate an interrupt when a STOP |
| 3010 | * frame is encountered; this is handled in the sample generator code and not here */ |
| 3089 | 3011 | } |
| 3090 | 3012 | |
| 3091 | 3013 | /****************************************************************************** |
| r18938 | r18939 | |
| 3186 | 3108 | else |
| 3187 | 3109 | { |
| 3188 | 3110 | int val; |
| 3189 | | int samples_per_frame = (m_subc_reload!=0)? 200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW |
| 3111 | int samples_per_frame = (m_subc_reload!=0)?200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW |
| 3190 | 3112 | int current_sample = ((m_PC * (3-m_subc_reload)) + (((m_subc_reload!=0)? 38:25) * m_interp_period)); |
| 3191 | 3113 | answer = samples_per_frame - current_sample + 8; |
| 3192 | 3114 | |
| r18938 | r18939 | |
| 3200 | 3122 | // 0 -> silence frame: we will only read 4 bits, and we will |
| 3201 | 3123 | // therefore need to read another frame before the FIFO is not |
| 3202 | 3124 | // full any more |
| 3203 | | answer += 200; |
| 3125 | answer += (m_subc_reload!=0)?200:304; |
| 3204 | 3126 | // 15 -> stop frame, we will only read 4 bits, but the FIFO will |
| 3205 | 3127 | // we cleared |
| 3206 | 3128 | //otherwise, we need to parse the repeat flag (1 bit) and the |
| r18938 | r18939 | |
| 3291 | 3213 | #ifdef DEBUG_RS_WS |
| 3292 | 3214 | logerror("tms52xx: Scheduling ready cycle for /RS...\n"); |
| 3293 | 3215 | #endif |
| 3294 | | // upon /RS being activated, /READY goes inactive after 100 nsec from |
| 3295 | | // data sheet, through 3 asynchronous gates on patent. This is effectively |
| 3296 | | // within one clock, so we immediately set io_ready to 0 and activate the callback. */ |
| 3216 | /* upon /RS being activated, /READY goes inactive after 100 nsec from |
| 3217 | * data sheet, through 3 asynchronous gates on patent. This is effectively |
| 3218 | * within one clock, so we immediately set io_ready to 0 and activate the callback. */ |
| 3297 | 3219 | m_io_ready = 0; |
| 3298 | 3220 | update_ready_state(); |
| 3299 | | // How long does /READY stay inactive, when /RS is pulled low? |
| 3300 | | // I believe its almost always ~16 clocks (25 usec at 800khz as shown on the datasheet) |
| 3221 | /* How long does /READY stay inactive, when /RS is pulled low? |
| 3222 | * I believe its almost always ~16 clocks (25 usec at 800khz as shown on the datasheet) */ |
| 3301 | 3223 | m_ready_timer->adjust(attotime::from_hz(clock()/16)); |
| 3302 | 3224 | } |
| 3303 | 3225 | } |
| r18938 | r18939 | |
| 3347 | 3269 | #ifdef DEBUG_RS_WS |
| 3348 | 3270 | logerror("tms52xx: Scheduling ready cycle for /WS...\n"); |
| 3349 | 3271 | #endif |
| 3350 | | // upon /WS being activated, /READY goes inactive after 100 nsec |
| 3351 | | // from data sheet, through 3 asynchronous gates on patent. |
| 3352 | | // This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. |
| 3272 | /* upon /WS being activated, /READY goes inactive after 100 nsec |
| 3273 | * from data sheet, through 3 asynchronous gates on patent. |
| 3274 | * This is effectively within one clock, so we immediately set |
| 3275 | * io_ready to 0 and activate the callback. */ |
| 3353 | 3276 | m_io_ready = 0; |
| 3354 | 3277 | update_ready_state(); |
| 3355 | | // Now comes the complicated part: long does /READY stay inactive |
| 3356 | | // when /WS is pulled low? This depends ENTIRELY on the command written, |
| 3357 | | // or whether the chip is in speak external mode or not... |
| 3358 | | // Speak external mode: ~16 cycles |
| 3359 | | // Command Mode: |
| 3360 | | // SPK: ? cycles |
| 3361 | | // SPKEXT: ? cycles |
| 3362 | | // RDBY: between 60 and 140 cycles |
| 3363 | | // RB: ? cycles (80?) |
| 3364 | | // RST: between 60 and 140 cycles |
| 3365 | | // SET RATE (5220C only): ? cycles (probably ~16) |
| 3278 | /* Now comes the complicated part: long does /READY stay inactive |
| 3279 | * when /WS is pulled low? This depends ENTIRELY on the command written, |
| 3280 | * or whether the chip is in speak external mode or not... |
| 3281 | * Speak external mode: ~16 cycles |
| 3282 | * Command Mode: |
| 3283 | * SPK: ? cycles |
| 3284 | * SPKEXT: ? cycles |
| 3285 | * RDBY: between 60 and 140 cycles |
| 3286 | * RB: ? cycles (80?) |
| 3287 | * RST: between 60 and 140 cycles |
| 3288 | * SET RATE (5220C only): ? cycles (probably ~16) */ |
| 3366 | 3289 | |
| 3367 | 3290 | // TODO: actually HANDLE the timing differences! currently just assuming always 16 cycles |
| 3368 | 3291 | m_ready_timer->adjust(attotime::from_hz(clock()/16)); |