|
|
View previous topic :: View next topic |
Author |
Message |
saroch
Joined: 06 Oct 2004 Posts: 8
|
pls give me some suggestion about converting this to 16f877 |
Posted: Sun Nov 21, 2004 9:55 am |
|
|
Here is the code that i recieved form Mark and i wanna change this code for 16f877.
but when i try to change, so many problems have occured.
pls give me some suggestion to convert that code for 16f877.
thx everyone in advance |
|
|
saroch
Joined: 06 Oct 2004 Posts: 8
|
|
Posted: Sun Nov 21, 2004 9:56 am |
|
|
oh forgot the code
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"
#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
{
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[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 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 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 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 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 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--;
}
}
|
|
|
|
saroch
Joined: 06 Oct 2004 Posts: 8
|
|
Posted: Sun Nov 21, 2004 9:57 am |
|
|
oh forgot the 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"
#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
{
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[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 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 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 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 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 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--;
}
} |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Nov 21, 2004 2:08 pm |
|
|
What sort of problems did you have and what did you do to try and change it? I am not at home right now but I will look at it later. I thought I listed what needed to be done to change it but its been about a year since I did it. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Nov 21, 2004 9:19 pm |
|
|
Posted new code Below
Last edited by Mark on Mon Nov 22, 2004 12:23 pm; edited 1 time in total |
|
|
Guest
|
|
Posted: Sun Nov 21, 2004 9:47 pm |
|
|
If I don't want to use PICDEM2+ board, what is the circuit of this code?
thx |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
|
saroch
Joined: 06 Oct 2004 Posts: 8
|
|
Posted: Mon Nov 22, 2004 8:08 am |
|
|
Hi, Mark
I made a little change to your code.
So I don't worry about pushing button.
Code: |
void main(void)
{
TRISCbits.TRISC2 = 0;
InitTimer();
enable_interrupts(GLOBAL);
lcd_init();
Melody_Pointer = JINGLEBELLS;
display_melody_name();
while(1)
{
//Button_Task();
Melody_Task();
}
}
|
And I connect PIN17 (RC2/CCP1) to the speaker and grounded it.
But I still don't hear the sound !!!
pls help
thanks |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Nov 22, 2004 8:18 am |
|
|
What kind of speaker?
I think maybe you should just write a simple program to toggle pin_c2 and a few hundred Hz and see if you hear anything
Code: |
#include <16F877.h>
#device *=16
#case
#use delay(clock=20000000)
#fuses HS,NOWDT,NOPROTECT,NOLVP
#ZERO_RAM
//======================= MAIN ============================//
void main(void
{
while(1)
{
// Generate an 800Hz tone
output_toggle(PIN_C2);
delay_us(625);
}
}
|
|
|
|
saroch
Joined: 06 Oct 2004 Posts: 8
|
|
Posted: Mon Nov 22, 2004 11:02 am |
|
|
Hi, Mark
I try to make my new simple program based on your code.
Here is my code
Code: |
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#define CLOCKSPEED 20000000
#use delay(clock=CLOCKSPEED)
#define PRESCALE 16
#define N_C (((CLOCKSPEED/4)/1661.63)/PRESCALE)-1 //187.07
#define N_D (((CLOCKSPEED/4)/1893.66)/PRESCALE)-1 //164.02
#define N_E (((CLOCKSPEED/4)/2229.63)/PRESCALE)-1 //139.16
void main()
{
char mysong[6]={'C','E','C','E','D','E'};
char note;
int i,j;
setup_ccp1(CCP_PWM);
while( TRUE )
{
for (i=0;i<5;i++)
{
note=mysong[i];
switch (note)
{
case 'C' :
for (j=1;j<500;j++)
{
setup_timer_2(T2_DIV_BY_16, 255, 1);
set_pwm1_duty(376.25);
delay_ms(500);
}
break;
case 'D' :
for (j=1;j<500;j++)
{
setup_timer_2(T2_DIV_BY_16, N_D, 1);
set_pwm1_duty(330.05);
delay_ms(1);
}
break;
case 'E' :
for (j=1;j<500;j++)
{
setup_timer_2(T2_DIV_BY_16, 40, 1);
set_pwm1_duty(280.32);
delay_ms(1);
}
break;
}
}
}
}
|
Any number is unreasoned assumed.
BUT when I burn to PIC, I can hear only one long sound and never change to another frequency.
I think I stuck on the infinity loop.
pls help me correct that code
thx (again) |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Nov 22, 2004 11:24 am |
|
|
Code: | for (j=1;j<500;j++) |
J is defined as an 8-bit integer and results in an infinite loop. Change to 16 bit.
Also:
This gives you a single sound of 25 seconds....
and: Code: | set_pwm1_duty(376.25); |
Quote: | Syntax:
set_pwm1_duty (value)
set_pwm2_duty (value)
Parameters: value may be an 8 or 16 bit constant or variable. |
Your parameter is not an integer... |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Nov 22, 2004 11:34 am |
|
|
Code: | set_pwm1_duty(376.25); |
How can you have a float for a value? Not possible.
The little test program that I posted should generate a sound. That is what I am interested in. It proves that the speaker is connected and WILL produce sound. Does the LCD work or do you even have an LCD connected? |
|
|
saroch
Joined: 06 Oct 2004 Posts: 8
|
|
Posted: Mon Nov 22, 2004 11:51 am |
|
|
ckielstra,
Quote: |
This gives you a single sound of 25 seconds....
|
Why 25 sec
It is 0.5 sec, isn't it?
Mark,
Quote: |
The little test program that I posted should generate a sound. That is what I am interested in. It proves that the speaker is connected and WILL produce sound. Does the LCD work or do you even have an LCD connected?
|
I think that my speaker will have a problem and I didn't connect LCD also.
BIG THANKS TO BOTH OF YOU |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Nov 22, 2004 11:53 am |
|
|
You have the delay_ms(500) inside a loop of 500 so it is actually 250 seconds. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Nov 22, 2004 12:00 pm |
|
|
Ooops. |
|
|
|
|
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
|