acidice333
Joined: 14 Oct 2006 Posts: 33
|
RTTTL player and USB? |
Posted: Wed Jan 11, 2012 2:03 pm |
|
|
I grabbed the RTTTL ringtone player src someone supplied on here and it works great Im having troubles getting it to work with USB.
It works until I uncomment the code for the usb_enumuerated() then it just plays the first 3 notes and repeats the 1st note forever.
Can I get this working like that?
Code: |
#include <18F4550.h>
#device *=16
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,MCLR
#use delay(clock=48000000)
// CCS Library dynamic defines
#define USB_CONFIG_HID_TX_SIZE 20 // to pc
#define USB_CONFIG_HID_RX_SIZE 20 // from pc
// CCS USB Libraries
#include <pic18_usb.h> //Microchip 18Fxx5x hardware layer for usb.c
#include "usb_desc_hid.h"
#include <usb.c> //handles usb setup tokens and get descriptor reports
#include "tones.h"
#int_timer0
void rtcc_isr(void)
{
//set_rtcc(RTCC_PRESET);
//update_switch_status(); // Poll the switches
// 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_ccp2(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_2 = TMR1 + Note_Ticks;
if (Note_Ticks)
{
/* Setup the CCP module to toggle the output pin c2 */
setup_ccp2(CCP_COMPARE_TOGGLE_MATCH);
}
// Nope, we are all through so disable the PWM
else
{
setup_ccp2(CCP_OFF);
}
}
}
#int_ccp2
void ccp2_isr (void)
{
CCP_2 += Note_Ticks;
}
int8 in_data[20];
void main() {
usb_init_cs();
enable_interrupts(GLOBAL);
TRISCbits.TRISC2 = 0;
inittimer();
Melody_Pointer = JINGLEBELLS;
while(true) {
melody_task();
usb_task();
//if (usb_enumerated()) {
//if (usb_kbhit(1)) {
// usb_get_packet(1, in_data, USB_CONFIG_HID_RX_SIZE);
//}
//}
}
}
|
tones.h:
Code: |
#define CLOCKSPEED 48000000
#define CCP_COMPARE_TOGGLE_MATCH 2
#define TMR1_PRESCALE 1
#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
{
JINGLEBELLS,
LAST_MELODY
}MELODIES;
typedef struct
{
int Head;
int Tail;
int Count;
} NOTESTATR;
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];
NOTESTATR 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[202];
int defaultoctave;
int defaultduration;
int tempo;
}JingleBellsss = {
{"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
};
const struct
{
char tune[192];
int16 defaultoctave;
int16 defaultduration;
int16 tempo;
}JingleBellss = {
{"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
};
/* 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);
/* *************************************************************************
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_INTERNAL | RTCC_DIV_1);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //8 ;
enable_interrupts(INT_CCP2);
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 JINGLEBELLS:
return (JingleBellss.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 JINGLEBELLS:
return (JingleBellss.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 JINGLEBELLS:
return (JingleBellss.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 JINGLEBELLS:
return (JingleBellss.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 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_B7))
bit_clear(current,2);
if (!input(PIN_B6))
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;
}
}
|
|
|