Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion firmware/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ COUNTER_APP = 1
DMESG_APP = 1
PAGER_APP = 0
JUKEBOX_APP = 1
MUSIC_APP = 0

#Don't forget to set your timezone for Beats in config.h.
BEATS_APP = 0
Expand Down Expand Up @@ -114,7 +115,10 @@ ifeq ($(BEATS_APP),1)
APPS_OBJ += apps/beats.o
APPS_DEFINES += BEATS_APP
endif

ifeq ($(MUSIC_APP),1)
APPS_OBJ += apps/music.o
APPS_DEFINES += MUSIC_APP
endif


#GCC8 from Texas Instruments, not the GCC4 that ships with Debian.
Expand Down
6 changes: 6 additions & 0 deletions firmware/applist.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ const struct app subapps[]={
},
#endif

#ifdef MUSIC_APP
//MUSIC
{.name="music", .init=music_init, .draw=music_draw, .exit=music_exit,
.keypress=music_keypress, .fallthrough=music_fallthrough,
},
#endif

#ifdef CALIBRATE_APP
//CALIBRATE
Expand Down
2 changes: 1 addition & 1 deletion firmware/applist.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ extern const struct app clock_applet;
#include "apps/counter.h"
#include "apps/pager.h"
#include "apps/jukebox.h"

#include "apps/music.h"

/* For each application, the init() function is called at entry. The
draw() function is called four times per second. The exit()
Expand Down
257 changes: 257 additions & 0 deletions firmware/apps/music.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
/*! \file music.c
\brief Music Application

Plays music with the buzzer

*/

#include <stdio.h>
#include <string.h>
#include <msp430.h>

#include "api.h"

/*! this defines a song
* key defines the key press on the keypad
* */
typedef struct {
const char key;
const uint16_t *notes;
} music_t;

#define DURATION_100 0x2000
#define DURATION_200 0x4000
#define DURATION_400 0x6000
#define DURATION_800 0x8000
#define DURATION_1600 0xa000
#define DURATION_3200 0xc000
#define DURATION_6400 0xe000

#define TONE_MASK 0x1fff
#define DURATION_SHIFT 13
#define DURATION_MASK 0xe000

#define PAUSE 0

#define END 0

#define NUM_MUSIC (sizeof(music) / sizeof(music_t))

static const uint16_t zelda_lullaby[] = {
NOTE_E5 | DURATION_400, NOTE_G5 | DURATION_200,
NOTE_D5 | DURATION_400, NOTE_C5 | DURATION_100, NOTE_D5 | DURATION_100,
NOTE_E5 | DURATION_400, NOTE_G5 | DURATION_200,
NOTE_D5 | DURATION_100,
NOTE_E5 | DURATION_400, NOTE_G5 | DURATION_200,
NOTE_D6 | DURATION_400, NOTE_C6 | DURATION_200,
NOTE_G5 | DURATION_400, NOTE_F5 | DURATION_100, NOTE_E5 | DURATION_100,
NOTE_D5 | DURATION_100,
NOTE_E5 | DURATION_400, NOTE_G5 | DURATION_200,
NOTE_D5 | DURATION_400, NOTE_C5 | DURATION_100, NOTE_D5 | DURATION_100,
NOTE_E5 | DURATION_400, NOTE_G5 | DURATION_200,
NOTE_D5 | DURATION_100,
NOTE_E5 | DURATION_400, NOTE_G5 | DURATION_200,

NOTE_D6 | DURATION_400, NOTE_C6 | DURATION_200,
NOTE_G5 | DURATION_400, NOTE_F5 | DURATION_100, NOTE_E5 | DURATION_100,
NOTE_F5 | DURATION_100, NOTE_E5 | DURATION_100, NOTE_C5 | DURATION_400,
NOTE_F5 | DURATION_400, NOTE_E5 | DURATION_100, NOTE_D5 | DURATION_100,
NOTE_E5 | DURATION_100, NOTE_D5 | DURATION_100, NOTE_A4 | DURATION_400,
NOTE_G5 | DURATION_400, NOTE_F5 | DURATION_100, NOTE_E5 | DURATION_100,
NOTE_F5 | DURATION_100, NOTE_E5 | DURATION_100, NOTE_C5 | DURATION_200, NOTE_F5 | DURATION_200,
NOTE_C6 | DURATION_100,
END,
};

static const uint16_t zelda_song_of_storms[] = {
NOTE_D5 | DURATION_100,
NOTE_F5 | DURATION_100,
NOTE_D6 | DURATION_200,

NOTE_D5 | DURATION_100,
NOTE_F5 | DURATION_100,
NOTE_D6 | DURATION_200,

NOTE_E6 | DURATION_200,
NOTE_F6 | DURATION_100,
NOTE_E6 | DURATION_100,
NOTE_F6 | DURATION_100,
NOTE_E6 | DURATION_100,
NOTE_C6 | DURATION_100,
NOTE_A5 | DURATION_100,

NOTE_A5 | DURATION_200,
NOTE_D5 | DURATION_200,
NOTE_F5 | DURATION_100,
NOTE_G5 | DURATION_100,
NOTE_A5 | DURATION_400,

NOTE_A5 | DURATION_200,
NOTE_D5 | DURATION_200,
NOTE_F5 | DURATION_100,
NOTE_G5 | DURATION_100,
NOTE_E5 | DURATION_400,

NOTE_D5 | DURATION_100,
NOTE_F5 | DURATION_100,
NOTE_D6 | DURATION_200,

NOTE_D5 | DURATION_100,
NOTE_F5 | DURATION_100,
NOTE_D6 | DURATION_200,

NOTE_E6 | DURATION_200,
NOTE_F6 | DURATION_100,
NOTE_E6 | DURATION_100,
NOTE_F6 | DURATION_100,
NOTE_E6 | DURATION_100,
NOTE_C6 | DURATION_100,
NOTE_A5 | DURATION_100,

NOTE_A5 | DURATION_200,
NOTE_D5 | DURATION_200,
NOTE_F5 | DURATION_100,
NOTE_G5 | DURATION_100,
NOTE_A5 | DURATION_400,
NOTE_A5 | DURATION_200,
NOTE_D5 | DURATION_400,
END,
};

static const uint16_t zelda_item[] = {
NOTE_F5 | DURATION_200,
NOTE_FS5 | DURATION_200,
NOTE_G5 | DURATION_200,
NOTE_GS5 | DURATION_800,
END,
};

static const uint16_t zelda_secret[] = {
NOTE_G5 | DURATION_100,
NOTE_FS5 | DURATION_100,
NOTE_DS5 | DURATION_100,
NOTE_A4 | DURATION_100,
NOTE_GS4 | DURATION_100,
NOTE_E5 | DURATION_100,
NOTE_GS5 | DURATION_100,
NOTE_C6 | DURATION_100,
END,
};

static const uint16_t happy_birthday[] = {
NOTE_C5 | DURATION_100,
NOTE_C5 | DURATION_100,
NOTE_D5 | DURATION_200,
NOTE_C5 | DURATION_200,
NOTE_F5 | DURATION_200,
NOTE_E5 | DURATION_400,

NOTE_C5 | DURATION_100,
NOTE_C5 | DURATION_100,
NOTE_D5 | DURATION_200,
NOTE_C5 | DURATION_200,
NOTE_G5 | DURATION_200,
NOTE_F5 | DURATION_100,

NOTE_C5 | DURATION_100,
NOTE_C5 | DURATION_100,
NOTE_C6 | DURATION_200,
NOTE_A5 | DURATION_200,
NOTE_F5 | DURATION_200,
NOTE_E5 | DURATION_200,
NOTE_D5 | DURATION_200,

NOTE_AS5 | DURATION_100,
NOTE_AS5 | DURATION_100,
NOTE_A5 | DURATION_200,
NOTE_F5 | DURATION_200,
NOTE_G5 | DURATION_200,
NOTE_F5 | DURATION_200,
END,
};

static const uint16_t game_of_thrones[] = {
NOTE_G5 | DURATION_400, NOTE_C5 | DURATION_400,

NOTE_DS5 | DURATION_100, NOTE_F5 | DURATION_100, NOTE_G5 | DURATION_400, NOTE_C5 | DURATION_400, NOTE_DS5 | DURATION_100, NOTE_F5 | DURATION_100,
NOTE_D5 | DURATION_800,
NOTE_F5 | DURATION_400, NOTE_AS4 | DURATION_400,
NOTE_DS5 | DURATION_100, NOTE_D5 | DURATION_100, NOTE_F5 | DURATION_400, NOTE_AS4 | DURATION_400,
NOTE_DS5 | DURATION_100, NOTE_D5 | DURATION_100, NOTE_C5 | DURATION_800,

END,
};


/*! this is the music library */

static const music_t music[] = {
{ .key = '1', .notes = zelda_song_of_storms},
{ .key = '2', .notes = zelda_lullaby},
{ .key = '3', .notes = zelda_item},
{ .key = '4', .notes = zelda_secret},
{ .key = '5', .notes = happy_birthday},
{ .key = '6', .notes = game_of_thrones},
};


static void play_song(const music_t *music){
const uint16_t *ptr = music->notes;
while (*ptr != END){
tone(*ptr & TONE_MASK, (1 << (((*ptr & DURATION_MASK) >> DURATION_SHIFT) - 1)) * 100);

ptr++;
}
}


//! Enter the Music application.
void music_init(){
}

//! Exit the Music application.
int music_exit(){
return 0;
}

enum STATE { IDLE, ABOUT_TO_PLAY, PLAYING };

static enum STATE state = IDLE;
static uint8_t selected = 0;

//! Draw the Music screen.
void music_draw(){
switch (state){
case IDLE:
lcd_string("press bt");
break;

case ABOUT_TO_PLAY:
lcd_string("playing ");
state = PLAYING;
break;

case PLAYING:
play_song(&music[selected]);
state = IDLE;
break;
};
}

//! Keypress handler for the music applet.
int music_keypress(char ch){
for (int i = 0; i < NUM_MUSIC; i++){
if (ch == music[i].key){
selected = i;
state = ABOUT_TO_PLAY;
return 1;
}
}
return 0;
}


//! Fallthrough handler for the music applet.
int music_fallthrough(char ch){
return music_keypress(ch);
}
22 changes: 22 additions & 0 deletions firmware/apps/music.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*! \file music.h
\brief music Application

*/

//! Enter the music application.
void music_init();

//! Exit the music application.
int music_exit();

//! Draw the music screen.
void music_draw();

//! Handle an incoming packet.
void music_packetrx(uint8_t *packet, int len);

//! Keypress handler for the music applet.
int music_keypress(char ch);

//! Fallthrough handler for the music applet.
int music_fallthrough(char ch);