CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Conversion of Ringtone Code (PICC Lite) to CCS

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
lguancho



Joined: 08 Sep 2003
Posts: 5

View user's profile Send private message

Conversion of Ringtone Code (PICC Lite) to CCS
PostPosted: Thu Dec 11, 2003 10:33 pm     Reply with quote

Hi. I saw the melody code(Ringtone.C) in Beyondlogic website. Wonder anyone have successfully port the code into CCS C? Here is the full code:

include <pic.h>

#define TONE RB0

void InitTimer(void);
void delayms(unsigned char cnt);
void PlayNote(unsigned short note, unsigned char octave, unsigned int duration);

unsigned char beep;
unsigned char preloadTMR1L;
unsigned char preloadTMR1H;
unsigned short TMR0Count;
unsigned char beat_speed;

#define MissionImpossible

void main(void)
{
unsigned int pointer = 0;
unsigned int octave = 0;
unsigned int duration = 0;
unsigned short note = 0;
unsigned int defaultoctave = 0;
unsigned int defaultduration = 0;

#ifdef AxelF
/* AxelF */
const unsigned char static Melody[] = {"32p,8g,8p,16a#.,8p,16g,16p,16g,8c6,8g,8f,8g,8p,16d.6,8p,16g,16p,16g,8d#6,8d6,8a#,8g,8d6,8g6,16g,16f,16p,16f,8d,8a#,2g,4p,16f6,8d6,8c6,8a#,4g,8a#.,16g,16p,16g,8c6,8g,8f,4g,8d.6,16g,16p,16g,8d#6,86,8a#,8g,8d6,8g6,16g,16f,16p,16f,8d,8a#,2g"};
defaultoctave = 5;
defaultduration = 4;
beat_speed = 125;
#endif

#ifdef HappyBirthday
/* HappyBirthday */
const unsigned char static Melody[] = {"8g.,16g,a,g,c6,2b,8g.,16g,a,g,d6,2c6,8g.,16g,g6,e6,c6,b,a,8f6.,16f6,e6,c6,d6,2c6,8g.,16g,a,g,c6,2b,8g.,16g,a,g,d6,2c6,8g.,16g,g6,e6,c6,b,a,8f6.,16f6,e6,c6,d6,2c6"};
defaultoctave = 5;
defaultduration = 4;
beat_speed = 125;
#endif

#ifdef Itchy
/* Itchy & Scratcy */
const unsigned char static Melody[] = {"8c,8a5,4p,8c,8a,4p,8c,a5,8c,a5,8c,8a,4p,8p,8c,8d,8e,8p,8e,8f,8g,4p,8d,8c,4d,8f,4a#,4a,2c7"};
defaultoctave = 6;
defaultduration = 8;
beat_speed = 198;
#endif

#ifdef MissionImpossible
/* Mission Impossible */
const unsigned char static Melody[] = {"16d5,16d#5,16d5,16d#5,16d5,16d#5,16d5,16d5,16d#5,16e5,16f5,16f#5,16g5,8g5,4p,8g5,4p,8a#5,8p,8c6,8p,8g5,4p,8g5,4p,8f5,8p,8p,8g5,4p,4p,8a#5,8p,8c6,8p,8g5,4p,4p,8f5,8p,8f#5,8p,8a#5,8g5,1d5"};
defaultoctave = 6;
defaultduration = 4;
beat_speed = 150;
#endif

TRISB0 = 0; /* Make TONE an output */

beep = 0;

InitTimer();
PEIE = 1;
GIE = 1; /* Enable General Purpose Interrupts */

do {

octave = defaultoctave; /* Set Default Octave */

if ((Melody[pointer] == '3') && (Melody[pointer+1] == '2')) {
duration = 32;
pointer += 2;
}
else if ((Melody[pointer] == '1') && (Melody[pointer+1] == '6')) {
duration = 16;
pointer += 2;
}
else if (Melody[pointer] == '8') {
duration = 8;
pointer++;
}
else if (Melody[pointer] == '4') {
duration = 4;
pointer++;
}
else if (Melody[pointer] == '2') {
duration = 2;
pointer++;
}
else if (Melody[pointer] == '1') {
duration = 1;
pointer++;
} else duration = defaultduration;

if (Melody[pointer + 1] == '#') {

/* Process Sharps */

switch (Melody[pointer]) {
case 'a' : note = 10726;
break;
case 'c' : note = 9019;
break;
case 'd' : note = 8035;
break;
case 'f' : note = 6757;
break;
case 'g' : note = 6024;
break;
}
pointer +=2;

} else {

switch (Melody[pointer]) {
case 'a' : note = 11364;
break;
case 'b' : note = 10123;
break;
case 'c' : note = 9555;
break;
case 'd' : note = 8513;
break;
case 'e' : note = 7584;
break;
case 'f' : note = 7158;
break;
case 'g' : note = 6378;
break;
case 'p' : note = 0;
break;
}
pointer++;
}

if (Melody[pointer] == '.') {
/* Duration 1.5x */
duration = duration + 128;
pointer++;
}

if (Melody[pointer] == '4') {
octave = 4;
pointer++;
} else if (Melody[pointer] == '5') {
octave = 5;
pointer++;
} else if (Melody[pointer] == '6') {
octave = 6;
pointer++;
} else if (Melody[pointer] == '7') {
octave = 7;
pointer++;
}

if (Melody[pointer] == '.') {
/* Duration 1.5x */
duration = duration + 128;
pointer++;
}

PlayNote(note, octave, duration);



} while (Melody[pointer++] == ',');

/* Wait until last note has played */
while(TMR0Count) { };
beep = 0;

/* Loop */
while(1) {};
}

void PlayNote(unsigned short note, unsigned char octave, unsigned int duration)
{

/* Process octave */
switch (octave) {
case 4 : /* Do noting */
break;
case 5 : /* %2 */
note = note >> 1;
break;
case 6 : /* %4 */
note = note >> 2;
break;
case 7 : /* %8 */
note = note >> 4;
break;
}

/* Wait until last note has played */
while(TMR0Count) { };
beep = 0;

/* Process New Note Frequency */
if (note) {
note = ~note;
preloadTMR1L = (note & 0xFF);
preloadTMR1H = ((note & 0xFF00) >> 8);
}

/* Process Note Duration */
TMR0Count = 255/(duration & 0x7F);

/* If duration is 1.5x add .5 to duration */
if (duration & 0x80) TMR0Count = (TMR0Count + (TMR0Count >> 1));

if (note) beep = 1;
}

void InitTimer(void)
{
/* Initialise Timer 0 */
OPTION = 0b11010111; /* Set TMR0 to Internal CLk, 1:256 */
T0IF = 0; /* Clear TMR0 Flag, ready for use */
T0IE = 1; /* Enable Timer Overflow Interrupt */

/* Initialise Timer 1 */
T1CON = 0b00000001; /* Counter Enabled, Using Ext Pin 1:1 Prescaler */
TMR1IF = 0; /* Clear Flag */
TMR1IE = 1; /* Enable Interrupt */
}

void interrupt interr(void)
{
if (T0IF) {
TMR0 = beat_speed;
if (TMR0Count) TMR0Count--;
T0IF = 0;
}
if (TMR1IF) {
if (beep) TONE = !TONE;
else TONE = 0;
TMR1H = preloadTMR1H;
TMR1L = preloadTMR1L;
TMR1IF = 0; /* Clear Flag */
}
}


I am no good in interrupt programming. Just trying to learn it, but take time.

Anyone out there could help me?

Warmest Regards

Lim
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Fri Dec 12, 2003 6:57 am     Reply with quote

I used that to make a little Christmas Medoly generator for a little contest here at work. I ported it to the C18 compiler. I have been porting it to CCS for use in a PICDEM 2 PLUS board. I will post something a little later today.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Fri Dec 12, 2003 9:12 am     Reply with quote

Here it is. This code was actually converted from some other code that I used in a little demo. I modified it so that it will work with the PICDEM2 Plus board. It is written so that you can add other stuff without affecting the melody if you don't create routines that are excessively long or disable ints for periods of time or have excessively long interrupt routines. Read the comment at the top of the file. It tells the how to use it. The code also displays the name of the tune on the LCD. If you use the PICDEM2 Plus board, you will need to modify the lcd.c driver file that CCS provides. I will include the code necessary to change it also. I rewrote the declarations so that you don't have to modify their code. I downloaded most of the tunes from www.mrtones.com. Any RTTL string should work. You should be able to figure out how to change or add melodies from looking at the source code. It sure would be nice if CCS would get pointers to constants! It would make it so much easier and cleaner to code as well as the code savings. The C18 was far more efficient on this application.

Code:

/*****************************************************************************/
/*                                                                           */
/*            RTTTL Ring Tone Player for Microchip Microcontrollers          */
/*                                                                           */
/* This program was designed to run on the PICDEM2 Plus demo board from      */
/* Microchip.                                                                */
/*                                                                           */
/* Usage:                                                                    */
/*         S3 - Selects Melody                                               */
/*         S2 - Starts/Stops Melody                                          */
/*                                                                           */
/* This code was designed for a clock speed of 20MHz                         */
/* The target device was a PIC18F452.                                        */
/* You can use the PIC16F877 by changing the setup of CCP1 to                */
/* CCP_COMPARE_INT.  You will also need to toggle the output pin in the      */
/* CCP1 interrupt routine.                                                   */
/*                                                                           */
/* Many of the tunes were downloaded from "www.mrtones.com"                  */
/*****************************************************************************/
#case
#list
#include "18F452.h"
//#include "18F6720.h"
#device *=16

#define CLOCKSPEED     20000000
#define CCP_COMPARE_TOGGLE_MATCH        2

#use delay(CLOCK=CLOCKSPEED)
#fuses HS, NOWDT, NOLVP, PUT

// Include this file after our #use delay
#include "lcd.c"


#define TMR1_PRESCALE  8
#define NOTE_C_SHARP   (((CLOCKSPEED/4)/277.18)/TMR1_PRESCALE)            // 277.18Hz
#define NOTE_D_SHARP   (((CLOCKSPEED/4)/311.13)/TMR1_PRESCALE)            // 311.13 Hz
#define NOTE_F_SHARP   (((CLOCKSPEED/4)/369.99)/TMR1_PRESCALE)            // 369.99 Hz
#define NOTE_G_SHARP   (((CLOCKSPEED/4)/415.30)/TMR1_PRESCALE)            // 415.30 Hz
#define NOTE_A_SHARP   (((CLOCKSPEED/4)/466.16)/TMR1_PRESCALE)            // 466.16 Hz

#define NOTE_C         (((CLOCKSPEED/4)/261.63)/TMR1_PRESCALE)            // 261.63 Hz
#define NOTE_D         (((CLOCKSPEED/4)/293.66)/TMR1_PRESCALE)            // 293.66 Hz
#define NOTE_E         (((CLOCKSPEED/4)/329.63)/TMR1_PRESCALE)            // 329.63 Hz
#define NOTE_F         (((CLOCKSPEED/4)/349.23)/TMR1_PRESCALE)            // 349.23 Hz
#define NOTE_G         (((CLOCKSPEED/4)/392.00)/TMR1_PRESCALE)            // 392.00 Hz
#define NOTE_A         (((CLOCKSPEED/4)/440.00)/TMR1_PRESCALE)            // 440.00 Hz
#define NOTE_B         (((CLOCKSPEED/4)/493.88)/TMR1_PRESCALE)            // 493.88 Hz
#define NOTE_SILENCE   0         

#define DURATION_32   5    // Duration = 2^x
#define DURATION_16   4    // Duration = 2^x
#define DURATION_8    3    // Duration = 2^x
#define DURATION_4    2    // Duration = 2^x
#define DURATION_2    1    // Duration = 2^x
#define DURATION_1    0    // Duration = 2^x

typedef enum
{
  JOLLYOLDSTNICK,
  MOMMYKISSSANTA,
  LETITSNOW,
  AWAYINAMANGER,
  OCHRISTMASTREE,
  MERRYCHRISTMAS,
  SANTACOMING,
  OCOMEALLYEFAITHFUL,
  DECKTHEHALLS,
  SLEIGH,
  RUDOLPH,
  TWELVEDAYSOFCHRISTMAS,
  FROSTYTHESNOWMAN,
  SILENTNIGHT,
  JINGLEBELLS,
  LAST_MELODY
}MELODIES;

typedef struct
{
  int Head;
  int Tail;
  int Count;
} NOTESTAT;

typedef struct
{
  long note;
  long duration;
}NOTE_DEF;


struct
{
  int TRISC0:1;
  int TRISC1:1;
  int TRISC2:1;
  int TRISC3:1;
  int TRISC4:1;
  int TRISC5:1;
  int TRISC6:1;
  int TRISC7:1;
}TRISCbits;
#locate TRISCbits = 0xF94

long TMR1;
#locate TMR1 = 0xFCE

int TMR1L;
#locate TMR1L = 0xFCE

int TMR1H;
#locate TMR1H = 0xFCF

int TMR0;
#locate TMR0 = 0xFD6


#define   MAX_NOTE_BUFFER_SIZE  4
#define   NOTE_ROLLOVER_MASK     0b00000011
NOTE_DEF  NoteBuffer[MAX_NOTE_BUFFER_SIZE];
NOTESTAT  Notestat = {0,0,0};

long      DurationCount=0;
int       Tempo=0;
long      Note_Ticks=0;
MELODIES  Melody_Pointer;
long      Note_Index = 0xFFFF;
BOOLEAN   PlayMelodyFlag = TRUE;
int       Read_Button_Count = 0;

const struct
{
  char tune[107];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}JollyOldStNick ={
                   {"a,a,a,a,g,g,2g,f,f,f,f,1a,d,d,d,d,c,c,2f,g,f,g,a,1g,a,a,a,a,g,g,2g,f,f,f,f,1a,d,d,d,d,c,c,2f,g,f,g,a,1f,1p"},
                   5,
                   DURATION_4,
                   160
                 };

const struct
{
  char tune[263];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}MommyKissSanta ={
                   {"2c.,d,e,g,a,8c6,2b.,g,1e,a,g,e,c,a,g,e,8c.,1b.,f,e,d,d.,8c#.,2d.,8a.,16b.,8a.,g.,f#.,8a.,2g.,e,d,e,f#,g,a,g#,a,a#,b,a,f,8e,2d.,g,2c.,d,e,g,a,8c6,1b,g,1e,a,g,2e,16c,a,g,e,8c.,1a,16g#,8a.,16b,c6,8c.6,c6,8d.6,1b,f#,8a.,16a,g,f,8e,2d,8e.,2f,g,a,8c.6,a,2c6,2d6,1c6,1p"},
                   5,
                   DURATION_4,
                   160
                 };

const struct
{
  char tune[218];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}LetItSnow ={
              {"8c,8c,8c6,8c6,a#,a,g,f,2c,8c,16c,g.,8f,g.,8f,e,2c,d,8d6,8d6,c6,a#,a,2g.,8e.6,16d6,c6,8c.6,16a#,a,8a#.,16a,2f.,c,8c6,8c6,a#,a,g,f,2c,8c.,16c,g.,8f,g.,8f,e,2c,d,8d6,8d6,c6,a#,a,2g.,8e.6,16d6,c6,8c.6,16a#,a,8a.,16g,2f,1p"},
              5,
              DURATION_4,
              125
            };

const struct
{
  char tune[175];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}AwayInAManger ={
                  {"d6,d.6,8c6,b,b.,8a,g,g,f#,e,2d,d,d.,8e,d,d,a,f#,e,d,g,2b,d6,d.6,8c6,b,b.,8a,g,g,f#,e,2d,d,c.6,8b,a,b,a,g,a,e,f#,2g,d6,d.6,8c6,b,b.,8a,g,g,f#,e,2d,d,d.,8e,d,d,a,f#,e,d,g,2b,1p"},
                  5,
                  DURATION_4,
                  112
                };

const struct
{
  char tune[243];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}OChristmasTree = {
                    {"4c.,4f,f,4f.,4g.,4a,a,2a,16p,a.,g.,a.,4a#.,4e.,4g.,4f.,4c.,4f,f,4f.,4g.,4a,a,2a,16p,a.,g.,a.,4a#.,4e.,4g.,2f,16p,c.6,c.6,a.,2d6,16p,c.6,c.6,a#.,2a#,16p,a#.,a#.,g.,2c6,16p,a#.,a#.,a.,4a.,4c.,4f,f,4f.,4g.,4a,a,2a,16p,a.,g.,a.,4a#.,4e.,4g.,2f,1p"},
                    5,
                    DURATION_8,
                    160
                  };

const struct
{
  char tune[159];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}MerryChristmas = {
                    {"4c,4f,f,g,f,e,4d,4a#4,4d,4g,g,a,g,f,4e,4c,4e,4a,a,a#,a,g,4f,4d,c,c,4d,4g,4e,4f.,p,4c,4f,4f,4f,4e.,p,4e,4f,4e,4d,4c.,p,4c,4a,g,g,f,f,4c6,4c,c,c,4d,4g,4e,4f.,1p"},
                    5,
                    DURATION_8,
                    140
                  };

const struct
{
  char tune[110];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}SantaComing = {
                 {"4g,8e.,f.,4g,4g.,p,g.,8a.,b.,4c6,4c.6,8p,8e.,f.,4g,4g.,p,g.,8a.,g.,4f,4f.,8p,4e,4g,4c,4e,4d,4f.,8p,4b4,4c.,1p"},
                 5,
                 DURATION_16,
                 160
               };

const struct
{
  char tune[226];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}OComeAllYeFaithful = {
                        {"c.,4c.,g.5,c.,4d.,4g.5,e.,d.,e.,f.,e.,d.,c.,4c.,b.5,a.5,b.5,c.,d.,e.,4b.5,4a5,16g.5,4g.5,4p.,4g.,f.,e.,4f.,4e.,d.,e.,c.,d.,4b5,16a.5,g.5,c.,c.,b.5,c.,d.,4c.,g.5,e.,e.,d.,e.,f.,4e.,d.,e.,f.,e.,d.,c.,4b.5,c.,f.,e.,4d,16c.,4c,1p"},
                        6,
                        DURATION_8,
                        112
                      };

const struct
{
  char tune[156];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}DeckTheHalls = {
                  {"c6.,8a#,a,g,f,g,a,f,8g,8a,8a#,8g,a.,8g,f,e,2f,16p,c6.,8a#,a,g,f,g,a,f,8g,8a,8a#,8g,a.,8g,f,e,2f,16p,g.,8a,a#,g,a.,8a#,c6,g,8a,8b,c6,8d6,8e6,f6,e6,d6,2c6,1p"},
                  5,
                  DURATION_4,
                  160
                };

  /* Sleigh */
const struct
{
  char tune[202];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}Sleigh = {
            {"8b,8b,8b,8b,8c#6,b,g#,8e,8f#,8g#,f#,e,8c#,2b4,4p,b4,c#,e,g#,8b,8c#6,b,g#,f#,e,8f,f#,g#,f#,e,8c#,2e,8p,8b,8b,8b,8c#6,b,g#,8e,8f#,8g#,f#,e,8c#,2b4,4p,b4,c#,e,g#,8b,8c#6,b,g#,f#,e,8f#,f#,g#,f#,e,8c#,8e,1p"},
            5,
            DURATION_16,
            112
          };

  /* Rudolph */
const struct
{
  char tune[208];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}Rudolph = {
             {"d,e,16d,b.5,g.,e.,4d.,p.,d,16e,d,16e,d.,g.,4f#.,4p.,c,d.,16c,a.5,f#.,e.,4d.,p.,d,16e,d,16e,d.,e.,4b.5,4p.,d,e.,16d,b.5,g.,e.,d.,p.,d,16e,d,16e,d.,g.,f#.,4p.,c,d.,16c,a.5,f#.,e.,4d.,p.,d,16e,d,16e,d.,a.,g.,1p"},
             6,
             DURATION_8,
             112
           };

const struct
{
  char tune[175];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}TwelveDaysOfChristmas = {
                           {"c.,c.,8c,f.,f.,8f.,e.,f.,g.,a.,a#.,g.,4a,p,a#.,8c.6,d.6,a#.,a.,f.,8g.,4f.,8p,c.,c.,c.,f.,f.,f.,8f.,e.,f.,g.,a.,a#.,g.,4a.,8c.6,g.,a.,8a#.,a.,a#.,8c.6,d.6,a#.,a.,f.,8g.,4f.,1p"},
                           5,
                           DURATION_16,
                           112
                         };

const struct
{
  char tune[176];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}FrostyTheSnowman = {
                      {"g.,8p,e.,8f,g,c.6,8p,8b,8c6,d6,c6,b,a,2g,p,8b,8c6,d6,c6,b,a,8g,c6,e.,8g,8a,g,f,e,d,g.,2p,g.,8p,e.,8f,g,c.6,8p,8b,8c6,d6,c6,b,a,2g,p,8b,8c6,d6,c6,b,a,g,c6,e,8g,8a,g,f,e,d,c.,1p"},
                      5,
                      DURATION_4,
                      180
                    };
const struct
{
  char tune[192];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}SilentNight = {
                 {"f#.,8g#,f#,d#.,p.,f#.,8g#,f#,d#.,p.,2c#6,c#6,a#.,p.,2b,b,f#.,p.,2g#,g#,b.,8a#,g#,f#.,8g#,f#,d#.,p.,2g#,g#,b.,8a#,g#,f#.,8g#,f#,d#.,p.,2c#6,c#6,e.6,8c#6,a#,2b.,2d#6,p.,b,f#,d#,f#.,8e,c#,b.4,1p"},
                 5,
                 DURATION_4,
                 140
               };

const struct
{
  char tune[202];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}JingleBells = {
                 {"8e.,8e.,e.,8e.,8e.,e.,8e.,8g.,c,16d.,2e,p,8f.,8f.,f,16f.,8f.,8e.,8e.,16e.,16e.,8e.,8d.,8d.,8e.,d.,g.,8e.,8e.,e.,8e.,8e.,e.,8e.,8g.,c,16d.,2e,p,8f.,8f.,f,16f.,8f.,8e.,8e.,16e.,16e.,8g.,8g.,8f.,8d.,c.,1p"},
                 5,
                 DURATION_4,
                 180
               };

/* Function Prototypes */
void InitTimer(void);
int PlayMelody();
void PlayNote(long note, int octave, int duration);
char get_char_from_tune(long index);
int get_tempo(void);
int get_defaultoctave(void);
int get_defaultduration(void);
void display_melody_name(void);
void Melody_Task(void);
void Button_Task(void);
void Check_Button_Press(void);


//-----------------------------------------------------------------------------
// Start of Code
//-----------------------------------------------------------------------------


/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
void main(void)
{
  TRISCbits.TRISC2 = 0;     
  InitTimer();
  enable_interrupts(GLOBAL);
  lcd_init();
  Melody_Pointer = JINGLEBELLS;
  display_melody_name();
  while(1)
  {
    Button_Task();
    Melody_Task();
  }
}

/* *************************************************************************
  DESCRIPTION:  This function handles the playing of a melody
  RETURN:       True if the melody is still active or False if its complete
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
int PlayMelody(void)
{

  int octave = 0;
  int duration = 0;
  long note = 0;

  // Check for a valid Melody
  if (Melody_Pointer >= LAST_MELODY)
  {
    // Reset the Melody to the start
    Melody_Pointer = 0;
    Note_Index = 0xFFFF;
  }
   
  // Load notes while we have enough room
  while (Notestat.Count < MAX_NOTE_BUFFER_SIZE)
  {

    // Is this the first note?
    if (Note_Index == 0xFFFF)
    {
      display_melody_name();
      Tempo = get_tempo();
      Note_Index = 0;
    }

    // Set Default duration
    duration = get_defaultduration();
    // Set Default Octave
    octave = get_defaultoctave();    
 
    // Play a bit of slience between notes
    if (get_char_from_tune(Note_Index) == ',')
    {
      PlayNote(0, 4, DURATION_32);
      Note_Index++;
      return(TRUE);
    }

    // We are checking the duration
    else if ((get_char_from_tune(Note_Index) == '3') && (get_char_from_tune(Note_Index+1) == '2'))
    {
      duration = DURATION_32;
      Note_Index += 2;
    }
    else if ((get_char_from_tune(Note_Index) == '1') && (get_char_from_tune(Note_Index+1) == '6'))
    {
      duration = DURATION_16;
      Note_Index += 2;
    }
    else if (get_char_from_tune(Note_Index) == '8')
    {
      duration = DURATION_8;
      Note_Index++;
    }
    else if (get_char_from_tune(Note_Index) == '4')
    {
      duration = DURATION_4;
      Note_Index++;
    }
    else if (get_char_from_tune(Note_Index) == '2')
    {
      duration = DURATION_2;
      Note_Index++;
    }
    else if (get_char_from_tune(Note_Index) == '1')
    {
      duration = DURATION_1;
      Note_Index++;
    }

    // Now we get the note
    switch (get_char_from_tune(Note_Index++))
    {
      case 'c':
        if (get_char_from_tune(Note_Index) == '#')
        {
          note = NOTE_C_SHARP;
          Note_Index++;
        }
        else
          note = NOTE_C;
        break;
      case 'd':
        if (get_char_from_tune(Note_Index) == '#')
        {
          note = NOTE_D_SHARP;
          Note_Index++;
        }
        else
          note = NOTE_D;
        break;
      case 'e':
        note = NOTE_E;
        break;
      case 'f':
        if (get_char_from_tune(Note_Index) == '#')
        {
          note = NOTE_F_SHARP;
          Note_Index++;
        }
        else
          note = NOTE_F;
        break;
      case 'g':
        if (get_char_from_tune(Note_Index) == '#')
        {
          note = NOTE_G_SHARP;
          Note_Index++;
        }
        else
          note = NOTE_G;
        break;
      case 'a':
        if (get_char_from_tune(Note_Index) == '#')
        {
          note = NOTE_A_SHARP;
          Note_Index++;
        }
        else
          note = NOTE_A;
        break;
      case 'b':
        note = NOTE_B;
        break;
      case 'p': // slience
        note = NOTE_SILENCE;
        break;
    }
 
    // See if this note is 1.5x the duration
    if (get_char_from_tune(Note_Index) == '.')
    {
      // Use the MSB to signify 1.5x
      duration |= 0x80;
      Note_Index++;
    }

    // Get the octave
    switch (get_char_from_tune(Note_Index))
    { 
      case '4':
        octave = 4;
        Note_Index++;
        break;
      case '5':
        octave = 5;
        Note_Index++;
        break;
      case '6':
        octave = 6;
        Note_Index++;
        break;
      case '7':
        octave = 7;
        Note_Index++;
        break;
      default:
        break;
    }   

    // Sometimes the duration multiplier comes after the octave
    if (get_char_from_tune(Note_Index) == '.')
    {
      /* Duration 1.5x */
      duration |= 0x80;
      Note_Index++;
    } 
 
    // Play the note (we actually just load it in a buffer
    PlayNote(note, octave, duration);

    // Is this the end?
    if (get_char_from_tune(Note_Index) == 0)
    {
      Note_Index = 0xFFFF;
      return(FALSE);
    }
    return(TRUE);
  }
}

/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
void PlayNote(long note, int octave, int duration)
{
  long duration_count;

  // Process octave
  switch (octave)
  {
    case 4 :
      break;
    case 5 :
      note = note >> 1;
      break;
    case 6 :
      note = note >> 2;
      break;
    case 7 :
      note = note >> 4;
      break;
  }

  // Process Note Duration
  duration_count = 256;
  duration_count >>= (duration & 0x7F);

  // If duration is 1.5x add .5 to duration
  if (duration & 0x80)
    duration_count += (duration_count >> 1);   

  // Add the note to our buffer
  NoteBuffer[Notestat.Tail].note = note;
  NoteBuffer[Notestat.Tail].duration = duration_count;
  Notestat.Tail++;
  Notestat.Tail &= NOTE_ROLLOVER_MASK;
  Notestat.Count++;


/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
void InitTimer(void)
{
  setup_timer_0(RTCC_DIV_256 | RTCC_8_BIT);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
  setup_timer_2(T2_DIV_BY_4, 250, 5);

  enable_interrupts(INT_CCP1);
  enable_interrupts(INT_TIMER0);
  enable_interrupts(INT_TIMER2);
}


/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
char get_char_from_tune(long index)
{
  switch (Melody_Pointer)
  {
    case JOLLYOLDSTNICK:
      return (JollyOldStNick.tune[index]);
      break;
    case MOMMYKISSSANTA:
      return (MommyKissSanta.tune[index]);
      break;
    case LETITSNOW:
      return (LetItSnow.tune[index]);
      break;
    case AWAYINAMANGER:
      return (AwayInAManger.tune[index]);
      break;
    case OCHRISTMASTREE:
      return (OChristmasTree.tune[index]);
      break;
    case MERRYCHRISTMAS:
      return (MerryChristmas.tune[index]);
      break;
    case SANTACOMING:
      return (SantaComing.tune[index]);
      break;
    case OCOMEALLYEFAITHFUL:
      return (OComeAllYeFaithful.tune[index]);
      break;
    case DECKTHEHALLS:
      return (DeckTheHalls.tune[index]);
      break;
    case SLEIGH:
      return (Sleigh.tune[index]);
      break;
    case RUDOLPH:
      return (Rudolph.tune[index]);
      break;
    case TWELVEDAYSOFCHRISTMAS:
      return (TwelveDaysOfChristmas.tune[index]);
      break;
    case FROSTYTHESNOWMAN:
      return (FrostyTheSnowman.tune[index]);
      break;
    case SILENTNIGHT:
      return (SilentNight.tune[index]);
      break;
    case JINGLEBELLS:
      return (JingleBells.tune[index]);
      break;
    default:
      break;
  }
}

/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
int get_tempo(void)
{
  switch (Melody_Pointer)
  {
    case JOLLYOLDSTNICK:
      return (JollyOldStNick.tempo);
      break;
    case MOMMYKISSSANTA:
      return (MommyKissSanta.tempo);
      break;
    case LETITSNOW:
      return (LetItSnow.tempo);
      break;
    case AWAYINAMANGER:
      return (AwayInAManger.tempo);
      break;
    case OCHRISTMASTREE:
      return (OChristmasTree.tempo);
      break;
    case MERRYCHRISTMAS:
      return (MerryChristmas.tempo);
      break;
    case SANTACOMING:
      return (SantaComing.tempo);
      break;
    case OCOMEALLYEFAITHFUL:
      return (OComeAllYeFaithful.tempo);
      break;
    case DECKTHEHALLS:
      return (DeckTheHalls.tempo);
      break;
    case SLEIGH:
      return (Sleigh.tempo);
      break;
    case RUDOLPH:
      return (Rudolph.tempo);
      break;
    case TWELVEDAYSOFCHRISTMAS:
      return (TwelveDaysOfChristmas.tempo);
      break;
    case FROSTYTHESNOWMAN:
      return (FrostyTheSnowman.tempo);
      break;
    case SILENTNIGHT:
      return (SilentNight.tempo);
      break;
    case JINGLEBELLS:
      return (JingleBells.tempo);
      break;
    default:
      break;
  }
}

/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
int get_defaultoctave(void)
{
  switch (Melody_Pointer)
  {
    case JOLLYOLDSTNICK:
      return (JollyOldStNick.defaultoctave);
      break;
    case MOMMYKISSSANTA:
      return (MommyKissSanta.defaultoctave);
      break;
    case LETITSNOW:
      return (LetItSnow.defaultoctave);
      break;
    case AWAYINAMANGER:
      return (AwayInAManger.defaultoctave);
      break;
    case OCHRISTMASTREE:
      return (OChristmasTree.defaultoctave);
      break;
    case MERRYCHRISTMAS:
      return (MerryChristmas.defaultoctave);
      break;
    case SANTACOMING:
      return (SantaComing.defaultoctave);
      break;
    case OCOMEALLYEFAITHFUL:
      return (OComeAllYeFaithful.defaultoctave);
      break;
    case DECKTHEHALLS:
      return (DeckTheHalls.defaultoctave);
      break;
    case SLEIGH:
      return (Sleigh.defaultoctave);
      break;
    case RUDOLPH:
      return (Rudolph.defaultoctave);
      break;
    case TWELVEDAYSOFCHRISTMAS:
      return (TwelveDaysOfChristmas.defaultoctave);
      break;
    case FROSTYTHESNOWMAN:
      return (FrostyTheSnowman.defaultoctave);
      break;
    case SILENTNIGHT:
      return (SilentNight.defaultoctave);
      break;
    case JINGLEBELLS:
      return (JingleBells.defaultoctave);
      break;
    default:
      break;
  }
}

/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
int get_defaultduration(void)
{
  switch (Melody_Pointer)
  {
    case JOLLYOLDSTNICK:
      return (JollyOldStNick.defaultduration);
      break;
    case MOMMYKISSSANTA:
      return (MommyKissSanta.defaultduration);
      break;
    case LETITSNOW:
      return (LetItSnow.defaultduration);
      break;
    case AWAYINAMANGER:
      return (AwayInAManger.defaultduration);
      break;
    case OCHRISTMASTREE:
      return (OChristmasTree.defaultduration);
      break;
    case MERRYCHRISTMAS:
      return (MerryChristmas.defaultduration);
      break;
    case SANTACOMING:
      return (SantaComing.defaultduration);
      break;
    case OCOMEALLYEFAITHFUL:
      return (OComeAllYeFaithful.defaultduration);
      break;
    case DECKTHEHALLS:
      return (DeckTheHalls.defaultduration);
      break;
    case SLEIGH:
      return (Sleigh.defaultduration);
      break;
    case RUDOLPH:
      return (Rudolph.defaultduration);
      break;
    case TWELVEDAYSOFCHRISTMAS:
      return (TwelveDaysOfChristmas.defaultduration);
      break;
    case FROSTYTHESNOWMAN:
      return (FrostyTheSnowman.defaultduration);
      break;
    case SILENTNIGHT:
      return (SilentNight.defaultduration);
      break;
    case JINGLEBELLS:
      return (JingleBells.defaultduration);
      break;
    default:
      break;
  }
}

/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
void Melody_Task(void)
{
  if (PlayMelodyFlag)
  {
    if (!PlayMelody())
      Melody_Pointer++;
  }
}

/* *************************************************************************
  DESCRIPTION:  This function displays the title of the melody on the LCD
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
void display_melody_name(void)
{
  // Clear the screen and make sure that we are at the top
  lcd_putc("\f");
  lcd_gotoxy(0,1);

  // Use our global Melody_Pointer to determine the title of the current tune
  switch (Melody_Pointer)
  {
    case JOLLYOLDSTNICK:
      lcd_putc("Jolly Old\nSt Nick");
      break;
    case MOMMYKISSSANTA:
      lcd_putc("Mommy Kissing\nSanta Claus");
      break;
    case LETITSNOW:
      lcd_putc("Let It Snow");
      break;
    case AWAYINAMANGER:
      lcd_putc("Away In A Manger");
      break;
    case OCHRISTMASTREE:
      lcd_putc("O Christmas Tree");
      break;
    case MERRYCHRISTMAS:
      lcd_putc("We Wish You A\nMerry Christmas");
      break;
    case SANTACOMING:
      lcd_putc("Santa Claus Is\nComing To Town");
      break;
    case OCOMEALLYEFAITHFUL:
      lcd_putc("O Come All\nYe Faithful");
      break;
    case DECKTHEHALLS:
      lcd_putc("Deck The Halls");
      break;
    case SLEIGH:
      lcd_putc("Sleigh Ride");
      break;
    case RUDOLPH:
      lcd_putc("Rudolph");
      break;
    case TWELVEDAYSOFCHRISTMAS:
      lcd_putc("Twelve Days\nOf Christmas");
      break;
    case FROSTYTHESNOWMAN:
      lcd_putc("Frosty The\nSnowman");
      break;
    case SILENTNIGHT:
      lcd_putc("Silent Night");
      break;
    case JINGLEBELLS:
      lcd_putc("JingleBells");
      break;
     default:
       break;
  }
}

/* *************************************************************************
  DESCRIPTION:  Button Tasks
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
void Button_Task(void)
{
  if (!Read_Button_Count)
  {
    Read_Button_Count = 30;
    Check_Button_Press();
  }
}

/* *************************************************************************
  DESCRIPTION:  This function handles checking for button presses
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
void Check_Button_Press(void)
{
  static int debounce_count = 4;
  static int stable = 0xFF;
  static int last = 0xFF;
  int trans_low;
  int current = 0xFF;
  BOOLEAN change = FALSE;

  // Read the current state of the buttons
  if (!input(PIN_A4))
    bit_clear(current,2);

  if (!input(PIN_B0))
    bit_clear(current,3);

  // See if they have changed
  if (current != last)
  {
    last = current;
    change = TRUE;
  }

  // If they have changed then reset our counter
  if (change)
  {
    debounce_count = 4;
  }
  // Each time they are stable, then decrement our count
  else if (debounce_count)
  {
    debounce_count--;
  }
  // They have been stable long enough so act on them
  else if (current != stable)
  {
    // Get the high transitions
    trans_low = ((stable ^ current) & stable);

    if (bit_test(trans_low,2))
      PlayMelodyFlag = ! PlayMelodyFlag;
    if (bit_test(trans_low,3))
    {
      Melody_Pointer++;
      if (Melody_Pointer >= LAST_MELODY)
        Melody_Pointer = 0;
      Note_Index = 0xFFFF;
      display_melody_name();
    }
    stable = current;
  }
}

//----------------------------------------------------------------------------
// ISR routines
//----------------------------------------------------------------------------



#int_ccp1
/* *************************************************************************
  DESCRIPTION:  This function controls the PWM of the piezo speaker
  RETURN:       none
  ALGORITHM:    none
  NOTES:  If you do not wish to use C2 as the output, then you will need
          to toggle your output here.  Make sure that you change the CCP
          setup not to toggle the C2 output if this is the case
 *************************************************************************** */
void ccp1_isr (void)
{
  CCP_1 += Note_Ticks;
}

/* *************************************************************************
  DESCRIPTION:  This function is used to control the duration of the note
  RETURN:       none
  ALGORITHM:    none
  NOTES:  I store the notes in a buffer so that the main loop has other
          time to do stuff with out have to sit at wait for a note to
          complete.
 *************************************************************************** */
#int_timer0
void timer0_isr (void)
{
  // Preload a value for TMR0 so that we can control how long it takes to
  // trigger an interrupt
  TMR0 = Tempo;

  // Is a note playing?
  if (DurationCount)
  {
    DurationCount--;
    if (!DurationCount)
      setup_ccp1(CCP_OFF);
  }
  // Note is finished playing, do we have anymore in our buffer?
  else if (Notestat.Count)
  {
    DurationCount = NoteBuffer[Notestat.Head].duration;
    Note_Ticks = NoteBuffer[Notestat.Head].note;
    Notestat.Count--;
    Notestat.Head++;
    Notestat.Head &= NOTE_ROLLOVER_MASK;
    CCP_1 = TMR1 + Note_Ticks;
    if (Note_Ticks)
    {
      /* Setup the CCP module to toggle the output pin c2 */
      setup_ccp1(CCP_COMPARE_TOGGLE_MATCH);
    }
    // Nope, we are all through so disable the PWM
    else
    {
      setup_ccp1(CCP_OFF);
    }
  }
}

#int_timer2
/* *************************************************************************
  DESCRIPTION:  This function is our system tick set at 1ms
  RETURN:       none
  ALGORITHM:    none
  NOTES:        none
 *************************************************************************** */
void timer2_isr (void)
{
  if (Read_Button_Count)
  {
    Read_Button_Count--;
  }
}



Now Replace the declaration section of the lcd.c file with this:

Code:

// This structure is overlayed onto the data ports so that you may use
// whatever ports you desire
struct lcd_pin_map

  BOOLEAN dummy;      // PinA0 is not used
  BOOLEAN enable;     // PinA1
  BOOLEAN rw;         // PinA2
  BOOLEAN rs;         // PinA3
  int unusedA  : 4;   // The rest of portA
  int unusedB;        // portB is not used
  int unusedC;        // portC is not used
  int     data : 4;   // lower nibble of portD is used for data lines
  int unusedD  : 4;   // The rest of portD
} lcd;
#if defined(__PCH__)
  #locate lcd = 0xF80
#else
  #locate lcd = 5
#endif

struct lcd_tris_map
{
  BOOLEAN dummy;      // PinA0 is not used
  int control  : 3;
  int unusedA  : 4;   // The rest of portA
  int unusedB;        // portB is not used
  int unusedC;        // portC is not used
  int data     : 4;   // lower nibble of portD is used for data lines
  int unusedD  : 4;   // The rest of portD
} lcdtris;

#if defined(__PCH__)
  #locate lcdtris = 0xF92
#else
  #locate lcdtris = 0x85
#endif

#define set_tris_lcd(x) lcdtris.data = (x); lcdtris.control = 0;



#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line


BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                             // These bytes need to be sent to the LCD
                             // to start it up.


                             // The following are used for setting
                             // the I/O port direction register.

#define LCD_WRITE    0       // For write mode all pins are out
#define LCD_READ     15      // For read mode data pins are in


The next line should be the first line of the code:
Code:

BYTE lcd_read_byte() {


Regards,
Mark
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group