$PAGINATE
$title(Arnold 5 test)
$subtitle(Test of sound chip electronics)
$copyright(Copyright (c) 1989, 1990, Amstrad plc.)
$pagewidth=131

        PUBLIC  UpperSoundTest         ;called indirectly from TESTPACK
                                        ; out of MainMenuTable

        EXTERN  SetCursorPos            ;SUPPORT
        EXTERN  ScreenPrintChar         ;SUPPORT
        EXTERN  PrintStringHL           ;SUPPORT
        EXTERN  PrintAHex               ;SUPPORT
        EXTERN  ProgramNote             ;SUPPORT
        EXTERN  KeyboardReadNoDelay     ;SUPPORT
        EXTERN  WriteAyChip             ;SUPPORT
        EXTERN  .PlayChannelAMess       ;MESSAGES
        EXTERN  .PlayChannelBMess       ;MESSAGES
        EXTERN  .PlayChannelCMess       ;MESSAGES
        EXTERN  .PlayAnBMess            ;MESSAGES
        EXTERN  .PlayAnCMess            ;MESSAGES
        EXTERN  .PlayBnCMess            ;MESSAGES
        EXTERN  .PlayAnBnCMess          ;MESSAGES
        EXTERN  .PlayEnvelopesMess      ;MESSAGES
        EXTERN  .EnvelopeEqualMess      ;MESSAGES
        EXTERN  .EnvelopeBackMess       ;MESSAGES
        EXTERN  .EnvelopeShapeTable     ;MESSAGES
        EXTERN  .TestStereoMess         ;MESSAGES

        EXTERN  ?TempSPStore            ;TESTVARS

        INCLUDE "Equates.inc"           ;"" mean in current dir

        DEFSEG  FloppyDiskTest, CLASS=CODE

        SEG     FloppyDiskTest

;==============
UpperSoundTest:
;==============
;
; This is one of those tests where we cannot tell whether things are working
; or not. It is up to the user to spot errors - I just hope they don't give
; Richard "I can't hear any problem" Altwasser the job !
;
; The test will work as follows. Print a message on screen to say that
; Channel A is playing. Run up a couple of scales on A. Do the same for
; B and then C.
;
; Next we print a message to say that we are testing the stereo effect and
; then program A and C to play a constant International A but before
; switching on the enables we program C's amplitude to 0. We then enter a
; loop reducing A's amplitude and increasing C's. This should result in a
; noticeable stereo effect as the sound moves from left to right (or vicky
; verky).
;
; Now we say we are testing channel combinations A+B and play a 2 note chord
; on A+B. The same is repeated for B+C and A+C and finally A+B+C
;
        ld      (?TempSPStore),sp               ;so an ESC exit can be made

        ld      de,00200h
        call    SetCursorPos

        ld      hl,.PlayChannelAMess
        ld      b,1                             ;to screen only
        call    PrintStringHL                   ;let user know whats appenin

        ld      d,7
        ld      e,03Fh
        call    WriteAYChip                     ;all sounds off

        ld      b,1                             ;channel A
        ld      hl,GO1                          ;a nice sounding note
        call    ProgramNote

        ld      b,1                             ;enable channel A
        ld      a,16                            ;a crotchet length
        call    _SoundEnDelDis                  ;give them time to here it

        ld      hl,.PlayChannelBMess
        ld      b,1                             ;to screen only
        call    PrintStringHL                   ;let user know whats appenin
        ld      b,2                             ;channel B
        ld      hl,AO1                           ;a nice sounding note
        call    ProgramNote
        ld      b,2                             ;enable channel B
        ld      a,16                            ;a crotchet length
        call    _SoundEnDelDis                  ;give them time to here it

        ld      hl,.PlayChannelCMess
        ld      b,1                             ;to screen only
        call    PrintStringHL                   ;let user know whats appenin
        ld      b,4                             ;channel C
        ld      hl,FO1                           ;a nice sounding note
        call    ProgramNote
        ld      b,4                             ;enable channel C
        ld      a,16                            ;a crotchet length
        call    _SoundEnDelDis                  ;give them time to here it


        ld      hl,.PlayAnBMess
        ld      b,1
        call    PrintStringHL
        ld      hl,GO0
        ld      b,1                             ;channel A
        call    ProgramNote
        ld      hl,CO1
        ld      b,2                             ;channel B
        call    ProgramNote
        ld      a,16                            ;crotchet
        ld      b,3                             ;chans A and B
        call    _SoundEnDelDis

        ld      hl,.PlayAnCMess
        ld      b,1
        call    PrintStringHL
        ld      hl,CO1
        ld      b,1                             ;channel A
        call    ProgramNote
        ld      hl,FO1
        ld      b,4                             ;channel C
        call    ProgramNote
        ld      a,16                            ;crotchet
        ld      b,5                             ;chans A and C
        call    _SoundEnDelDis

        ld      hl,.PlayBnCMess
        ld      b,1
        call    PrintStringHL
        ld      hl,CO1
        ld      b,2                             ;channel B
        call    ProgramNote
        ld      hl,FO1
        ld      b,4                             ;channel C
        call    ProgramNote
        ld      a,16                            ;crotchet
        ld      b,6                             ;chans B and C
        call    _SoundEnDelDis


        ld      hl,.TestStereoMess
        ld      b,1
        call    PrintStringHL                   ;let the user know wots appenin

        ld      b,5                             ;channels A and C
        ld      hl,CO0
        call    ProgramNote                     ;both A and C set to play note at
                                                ;amplitude 0Fh
;a,b,g,-g,d
        ld      bc,00F00h                       ;A and C amplitudes
_SoundStereoLoop:
        push    bc
        ld      d,8                             ;channel A amplitude
        ld      e,b
        call    WriteAYChip                     ;set it equal to B (down counter)
        pop     bc
        push    bc
        ld      d,10                            ;channel C amplitude
        ld      e,c
        call    WriteAYChip                     ;set it equal to C (up counter)
        ld      b,5                             ;switch on A and C
        ld      a,4                             ;semi-quaver delay
        call    _SoundEnDelDis
        pop     bc
        inc     c                               ;C (channel C amplitude) goes up
        djnz    _SoundStereoLoop                ;B (A amplitude) goes down


        ld      hl,.PlayAnBnCMess
        ld      b,1
        call    PrintStringHL
        ld      hl,CO0
        ld      b,1                             ;channel A
        call    ProgramNote
        ld      hl,EO0
        ld      b,2                             ;channel B
        call    ProgramNote
        ld      hl,GO0
        ld      b,4                             ;channel C
        call    ProgramNote
        ld      a,16                            ;crotchet
        ld      b,7                             ;chans A, B and C
        call    _SoundEnDelDis

        ld      hl,.PlayAnBnCMess
        ld      b,1
        call    PrintStringHL
        ld      hl,CO0
        ld      b,1                             ;channel A
        call    ProgramNote
        ld      hl,FO0
        ld      b,2                             ;channel B
        call    ProgramNote
        ld      hl,AO0
        ld      b,4                             ;channel C
        call    ProgramNote
        ld      a,16                            ;crotchet
        ld      b,7                             ;chans A, B and C
        call    _SoundEnDelDis

        ld      hl,.PlayAnBnCMess
        ld      b,1
        call    PrintStringHL
        ld      hl,DO0
        ld      b,1                             ;channel A
        call    ProgramNote
        ld      hl,GO0
        ld      b,2                             ;channel B
        call    ProgramNote
        ld      hl,BO0
        ld      b,4                             ;channel C
        call    ProgramNote
        ld      a,16                            ;crotchet
        ld      b,7                             ;chans A, B and C
        call    _SoundEnDelDis

        ld      hl,.PlayAnBnCMess
        ld      b,1
        call    PrintStringHL
        ld      hl,EO0
        ld      b,1                             ;channel A
        call    ProgramNote
        ld      hl,GO0
        ld      b,2                             ;channel B
        call    ProgramNote
        ld      hl,CO1
        ld      b,4                             ;channel C
        call    ProgramNote
        ld      a,16                            ;crotchet
        ld      b,7                             ;chans A, B and C
        call    _SoundEnDelDis

;
; Now gonna try doing some enveloped notes on all channels
;
        ld      hl,.PlayEnvelopesMess
        ld      b,1
        call    PrintStringHL

        ld      hl,CO1
        ld      b,7                             ;channels A, B and C
        call    ProgramNote

        ld      d,11
        ld      e,208                           ;2000 MOD 256
        call    WriteAYChip                     ;fine of envelope period=100
        ld      d,12
        ld      e,7
        call    WriteAYChip                     ;coarse=7 (int(2000/256))
        ld      d,8
        ld      e,10h                           ;set envelope bit in amplitude
        call    WriteAYChip
        ld      d,9
        ld      e,10h                           ;set envelope bit in amplitude
        call    WriteAYChip
        ld      d,10
        ld      e,10h                           ;set envelope bit in amplitude
        call    WriteAYChip

        ld      d,13
        ld      e,8
_SoundEnvelopesLoop:
        push    de
        ld      hl,.EnvelopeBackMess
        ld      b,1
        call    PrintStringHL
        pop     de
        push    de
        ld      a,e
        push    af
        call    PrintAHex                       ;on return A still has env num.
        ld      hl,.EnvelopeEqualMess
        ld      b,1
        call    PrintStringHL
        pop     af
        sub     8                               ;make 8..F into 0..7
        ld      l,a
        ld      h,0                             ;doin 16 bit indexin summs
        add     hl,hl
        add     hl,hl
        add     hl,hl                           ;there are 8 bytes per string
        ld      bc,.EnvelopeShapeTable
        add     hl,bc                           ;HL points at 6 byte string to
        ld      b,1                             ;print to screen
        call    PrintStringHL
        pop     de
        push    de
        call    WriteAYChip                     ;setup for ramps
        ld      b,7                             ;all 3 channels
        ld      a,64                            ;a good long time
        call    _SoundEnDelDis
        ld      a,2
        call    _SoundDelay
        pop     de
        inc     e
        ld      a,e
        cp      16
        jr      nz,_SoundEnvelopesLoop

_SoundEndTest:
        ld      d,7
        ld      e,03fh
        call    WriteAYChip                     ;disable all channels

        ld      d,8
        ld      e,0
        call    WriteAYChip                     ;set chan A ampl. to 0

        ld      d,9
        ld      e,0
        call    WriteAYChip

        ld      d,10
        ld      e,0
        call    WriteAYChip

        ret


_SoundEnDelDis:
;
; For most notes we want to Enable the channel (in B), delay for the note
; length in A then Disable all channels.
;
        push    af
        call    _SoundEnables                   ;for channel B
        pop     af
        call    _SoundDelay
        ld      b,0
        call    _SoundEnables
        ret

_SoundDelay:
;
; Once a note or notes start to play (after the call to _SoundEnables), this
; delay is entered to allow the note to play on for a while. A determines
; the length with A=1=Semi-quaver, 2=Quaver, 4=Minim (isn't it?), 16=Crotchet
; etc. After the delay has elapsed the user will no doubt call _SoundEnables
; again to stop one or more notes playing.
;
        push    af
        ld      bc,100                    ;a magic number
_SoundDelayBCLoop:
        push    bc
        call    KeyboardReadNoDelay
        cp      66
        jr      z,_SoundKeyPressed
        cp      76
        jr      z,_SoundKeyPressed
        pop     bc
        dec     bc
        ld      a,b
        or      c
        jr      nz,_SoundDelayBCLoop
        pop     af
        dec     a
        jr      nz,_SoundDelay
        ret

_SoundKeyPressed:
        ld      hl,(?TempSPStore)       ;saves having to balance the stack
        ld      sp,hl
        jr      _SoundEndTest

_SoundEnables:
;
; Starts the note(s) playing by setting the enables bit(s) in the AY register
; number 7. The value in A is just plonked straight into the register so it is
; up to the caller to understand the significance of the bits A:0..A:2 are the
; enables for A..C while A:3..A:5 are the noise bits for A..C. A6 sets the I/O
; direction of port A and should always be 0 (input) cos that's where the
; keyboard columns are read (in fact I'll make sure it's 0).
;
; Just one last point of interest - the dozy chip uses inverse logic so 0 is
; ON and 1 is OFF so we invert the byte
;
        ld      a,b
        xor     0FFh
        res     6,a                     ;make sure I/O is input.

        ld      e,a
        ld      d,7                     ;the AY enables register
        call    WriteAYChip

        ret

        END
