Selectable Melody Player

copyright, Towanda L. Malone, Peter H. Anderson
Department of Electrical Engineering
Morgan State University, Baltimore, MD 21014
August 22, '96

This discussion deals with Holtek greeting card melody payers. It also deals with the use of a cadmium sulphide resistor in detecting changes in light and an audio amplifier kit marketed by Jameco.

All parts in this discussion are available from Jameco, except the Holtek melody payers which are available from DigiKey.

In Volume 1, the use of Holtek remote control encoders and decoders were discussed. In addition to these remote control devices, Holtek offers a product line of "melody" integrated circuits in a TO-92 package. These are simple three lead devices, +5V, ground and an output which continuously play such tunes as "Happy Birthday" which I assume were originally designed for greeting cards. A partial listing of different melodies which are available from Digikey at less than $1.00 each appears in Figure #1.

Our application in the Embedded Processor Control Laboratory at Morgan State University is somewhat frivolous. On opening a self service refrigerator, a magnet moves away from a Hall effect device, which turns a Darlngton transistor on, which operates a solid state AC relay, which turns on an incandescent lamp. The change in ambient light is sensed across the room using a cadmium sulfide resistor arrangement which is continually scanned a dedicated junk PC. The PC randomly selects a melody and plays it for a few seconds. This Rube Goldburg chain reaction serves my purpose as an educator as it demonstrates many concepts in a context which students readily grasp , but as I say, frivolous. However, you may have a practical application for the melody integrated circuits.

Please refer to the Figure #1.

A change in ambient light is detected using a cadmium sulphide resistor in a comparator circuit which is discussed elsewhere in this manual.

Any one of eight melody players may be gated to common audio amplifier using a CMOS 4051 analog multiplexer. The multiplexer is turned on or off by parallel output Data_3 and the channel is selected by outputs Data_0 through Data_2.

The output of the melody players is actually pulses; that is there are only two states; near 0.0 Volts and near 5.0 Volts which gives the chime like characteristic of the sound. Thus, this analog signal could be alternately multiplexed using an 8-input digital multiplexer; e.g., 74151.

It is noteworthy that we used Jameco 7 Watt amplifier kit (Jameco 127255) for the audio amplifier which costs less than $15.00. We use a lot of amplifiers and I have found that the prepackaged kit saves a lot of time over building it from scratch.

Program MELODY.C

In the idle mode, the dedicated junk PC, continuously samples the BSY input at nominally 100 samples per second, centennials voting on whether the last 100 samples were either at logic one ("light") or zero ("no light"). Note that in the program, some weighting is applied; e.g., a logic one is assumed if the 75 percent of the last 100 samples were at logic one. If the vote, is negative, the process continues.

However, if the vote is affirmative, the PC, accesses "shall_we_play" which returns a TRUE with a selected probability. If TRUE, the program randomly selects a number in the range 0 - 7, turns on the CMOS multiplexer by bringing the Inhibit input low and gates a melody on the selected channel through to a common audio amplifier. The melody is played briefly and is then turned off.

As the refrigerator door may still be open, the PC then sleeps for 20 secs, and then returns to polling the BSY input for the next opening of the door.

/*
** MELODY.C
**
** Constantly monitors BSY input.  If logic one (light present)
** on 75 or more samples of 100, shall_we_play routine is called
** which randomly returns TRUE.  If TRUE, a melody is randomly
** selected and played for a period of 10 to 20 seconds.
**
** Towanda Malone, Morgan State University, August 22, '96
**
*/

#include <stdio.h>                                            /* 1 */
#include <stdlib.h>                                           /* 2 */
#include <dos.h>                                              /* 3 */
                                                              /* 4 */
#define DATA 0x03bc                                           /* 5 */
#define STATUS DATA+1                                         /* 6 */
#define CONTROL DATA+2                                        /* 7 */
                                                              /* 8 */
#define NUM_MELODIES 8                                        /* 9 */
                                                              /* 10 */
#define TRUE 1                                                /* 11 */
#define FALSE 0                                               /* 12 */
                                                              /* 13 */
int should_we_play(float probability);                        /* 14 */
int melody_to_play(int num_melodies);                         /* 15 */
int light_detected(void);                                     /* 16 */
                                                              /* 17 */
void turn_on_amplifier(void);                                 /* 18 */
void turn_off_amplifier(void);                                /* 19 */
void play_melody(void);                                       /* 20 */
                                                              /* 21 */
int data = 0x00;  /* note global definition */                /* 22 */
                                                              /* 23 */
void main(void)                                               /* 24 */
{                                                             /* 25 */
   turn_off_amplifier();                                      /* 26 */
   randomize();                                               /* 27 */
   while(1)                                                   /* 28 */
   {                                                          /* 29 */
      if(light_detected)                                      /* 30 */
      {                                                       /* 31 */
         if (should_we_play(0.05))                            /* 32 */
         {                                                    /* 33 */
            play_melody();                                    /* 34 */
         }                                                    /* 35 */
      }                                                       /* 36 */
   }                                                          /* 37 */
}                                                             /* 38 */
                                                              /* 39 */
int should_we_play(float probability)                         /* 40 */
{                                                             /* 41 */
   /* returns TRUE with the passed probability.  For example  /* 42 */
   ** should_we_play(0.05) will on average return TRUE every  /* 44 */
   ** one of 20 calls.                                        /* 46 */
   */                                                         /* 47 */
                                                              /* 48 */
   if (random(1000) < (int) (probability * 1000))             /* 49 */
   {                                                          /* 50 */
      return(TRUE);                                           /* 51 */
   }                                                          /* 52 */
   else                                                       /* 53 */
   {                                                          /* 54 */
      return(FALSE);                                          /* 55 */
   }                                                          /* 56 */
}                                                             /* 57 */
                                                              /* 58 */
int melody_to_play(int num_melodies)                          /* 59 */
{                                                             /* 60 */
   /* returns the index of a randomly selected melody */      /* 61 */
   {                                                          /* 62 */
      return(random(num_melodies));                           /* 63 */
   }                                                          /* 64 */
}                                                             /* 65 */
                                                              /* 66 */
int light_detected(void)                                      /* 67 */
{                                                             /* 68 */
   /* scans BUSY lead 100 times.  if light is detected 75 or  /* 69 */
   ** more times returns TRUE.  otherwise, returns FALSE      /* 71 */
   */                                                         /* 72 */
                                                              /* 73 */
   int counter = 0x00, n;                                     /* 74 */
   for(n=0; n<100; n++)                                       /* 75 */
   {                                                          /* 76 */
      if ((( (inportb(STATUS)^0x80) >> 4) & 0x01) == 1)       /* 77 */
      {                                                       /* 78 */
         ++counter;                                           /* 79 */
      }                                                       /* 80 */
      delay(10); /* 100 samples over 1 second */              /* 81 */
   }                                                          /* 82 */
   if (counter >= 75)                                         /* 83 */
   {                                                          /* 84 */
      return(TRUE);                                           /* 85 */
   }                                                          /* 86 */
   else                                                       /* 87 */
   {                                                          /* 88 */
      return(FALSE);                                          /* 89 */
   }                                                          /* 90 */
}                                                             /* 91 */
                                                              /* 92 */
void turn_on_amplifier(void)                                  /* 93 */
{                                                             /* 94 */
   data = data & (~0x80);  /* bring INH low */                /* 95 */
   outportb(DATA, data);                                      /* 96 */
}                                                             /* 97 */
                                                              /* 98 */
                                                              /* 99 */
void turn_off_amplifier(void)                                 /* 100 */
{                                                             /* 101 */
   data = data | 0x80;                                        /* 102 */
   outportb(DATA, data);  /* bring INH high */                /* 103 */
}                                                             /* 104 */
                                                              /* 105 */
void play_melody(void)                                        /* 106 */
{                                                             /* 107 */
  /* plays random selected melody */                          /* 108 */
  int melody;                                                 /* 109 */
  melody = melody_to_play(NUM_MELODIES);                      /* 110 */
  data = data & (~0x07) | melody;                             /* 111 */
  outportb(DATA, data);                                       /* 112 */
  turn_on_amplifier();                                        /* 113 */
  sleep(10 + random(11));                                     /* 114 */
     /* play melody for 10 to 20 seconds */                   /* 115 */
  turn_off_amplifier();                                       /* 116 */
  sleep(20);                                                  /* 117 */
}                                                             /* 118 */