📄 mp3.c
字号:
/*
* Copyright (c) 2003-2004 K. John '2B|!2B' Crispin
* Copyright (c) 2005 Stephan Dobretsberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
*
* Feedback, Bugs, ... mail stephan.dobretsberger@gmx.at
*
*/
// avr includes
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
// my lib header
#include "types.h"
#include "config.h"
#include "spi.h"
#include "delay.h"
#include "vs1001.h"
#include "mmc.h"
#include "fat.h"
#define PLAY_LED_ON cbi(LED_PORT, LED_PLAY_PIN)
#define PLAY_LED_OFF sbi(LED_PORT, LED_PLAY_PIN)
// our beeps
#define BEEP(x) { VS1001_volume(0x30, 0x30); \
beep(0x30, 70, x); \
VS1001_volume(player_volume, player_volume); \
}
// player states
#define IDLE 0
#define PLAYING_MMC 2
#define PLAYING_MMC_INIT 6
// Play modes
#define PS_SEQUENCE 0x01 // plays files in the order found. then the folders
#define PS_PLAYLIST 0x02 // the player found a playlist file on the mmc
// if the playlist file was not found the ps.pl_index is set to this
#define PLAYLIST_ERROR 0xff
#define PLAYLIST_NONE 0xfe
// what is the player doing atm ? and how is it doing it ?
typedef struct _P_STATE
{ // the current state
u08 state;
// what play mode are we using ?
u08 mode;
// what song are we on?
u08 file_index;
}PLAYER_STATE;
// holds the last value read from the button port
static u08 last_button = 0x00;
// the current volume of the player
static u08 player_volume = 0x00;
// the number of beeps to generate
static u08 num_beeps = 0;
// the last byte that we received
//static u08 u_static = 0x00;
// what are we doing atm ?
static PLAYER_STATE ps;
// our mp3 file ptr
static FILE fp;
#ifdef PLAYLIST_SUPPORT
bool playlist_open(FILE *stream)
{ // make sure the file is closed
fclose(stream);
// try to open the playlist file
return fopen("playlist.mu3", "r", stream);
};
// the index of the current playlist
u08 playlist_get_entry(FILE *stream)
{ // todo
};
#endif
// BEEP
void beep(u08 freq, u16 length, u08 intervals)
{ VS1001_SW_reset();
VS1001_send_zeros(32);
do
{ VS1001_sine(0x01, freq);
delay_ms(length);
VS1001_sine(0x00, 0x00);
delay_ms(length);
}while(--intervals);
};
// this function sets up the interrupt and ports used by the buttons
void setup_buttons(void)
{ // set ports for input
cbi(BUTTON_DDR, BTN_VOL_UP);
cbi(BUTTON_DDR, BTN_VOL_DOWN);
cbi(BUTTON_DDR, BTN_SONG_UP);
cbi(BUTTON_DDR, BTN_SONG_DOWN);
cbi(BUTTON_DDR, BTN_PLAY);
// enable pull-up (you don't need resistors on your PCB!)
sbi(BUTTON_PORT, BTN_VOL_UP);
sbi(BUTTON_PORT, BTN_VOL_DOWN);
sbi(BUTTON_PORT, BTN_SONG_UP);
sbi(BUTTON_PORT, BTN_SONG_DOWN);
sbi(BUTTON_PORT, BTN_PLAY);
// setup the led
sbi(LED_DDR, LED_PLAY_PIN);
PLAY_LED_ON;
};
// play the next file
void play_next(void)
{ ps.state = PLAYING_MMC_INIT;
fclose(&fp);
num_beeps = 1;
};
// go back a file
void play_prev(void)
{ ps.file_index--;
if(ps.file_index > 0) ps.file_index--;
// start player init process
ps.state = PLAYING_MMC_INIT;
fclose(&fp);
num_beeps = 2;
};
// turn up volume
void vol_up(void)
{ // check if we can go any louder
if(player_volume > 1) player_volume -= 2;
// set new volume
VS1001_volume(player_volume, player_volume);
};
// turn down volume
void vol_down(void)
{ // check if we can go any quiter
if(player_volume < 180) player_volume += 2;
// set new volume
VS1001_volume(player_volume, player_volume);
};
// this function processes the button messages
void process_buttons(void)
{ // find out which buttons were pressed
u08 tmp = inp(BUTTON_PIN);
// invert as 0 -> button pressed
tmp = ~tmp;
// make sure the button was not pressed before
u08 cleaned_val = tmp ^ last_button;
cleaned_val = cleaned_val & tmp;
// store current val as last val
last_button = tmp;
// button 1 was pressed -> song back
if(cleaned_val&(1<<BTN_SONG_DOWN)) play_prev();
// button 2 was pressed -> song next
if(cleaned_val&(1<<BTN_SONG_UP)) play_next();
// button 3 was pressed -> vol -
if(cleaned_val&(1<<BTN_VOL_DOWN)) vol_down();
// button 4 was pressed -> vol +
if(cleaned_val&(1<<BTN_VOL_UP)) vol_up();
// button 5 was pressed -> play/stop
if(cleaned_val&(1<<BTN_PLAY))
{ if((ps.state == PLAYING_MMC_INIT) || (ps.state == PLAYING_MMC))
{ // stop the player
ps.state = IDLE;
if (ps.file_index>0)
ps.file_index--;
PLAY_LED_OFF;
BEEP(3);
}
else
{ // go to start of file
ps.state = PLAYING_MMC_INIT;
num_beeps = 1;
}
}
}
int main (void)
{ // setup the player
ps.state = IDLE;
ps.mode = PS_SEQUENCE;
ps.file_index = 0;
// make sure the ptr for the mp3 file is setup correctly
fclose(&fp);
setup_buttons();
// give mmc time
delay_ms(1000);
// set the MMC pins
MMC_hw_init();
spi_init();
// init VS1001
VS1001_init();
VS1001_volume(player_volume, player_volume);
// setup mmc
MMC_init();
// setup fat layer
FAT_startup();
BEEP(3);
// show end of initialization
PLAY_LED_OFF;
num_beeps = 0;
while(1)
{ // has the user pressed a button ?
process_buttons();
// what state are we in ?
switch(ps.state)
{ // restart
case PLAYING_MMC_INIT:
// reset. decoder
VS1001_SW_reset();
// close last file
fclose(&fp);
// generate beep
BEEP(num_beeps);
// player led on
PLAY_LED_ON;
// find the next song
if(fopenc(ps.file_index,'r', "* MP3", &fp))
{ ps.state = PLAYING_MMC;
ps.file_index++;
}
else
{ ps.file_index = 0;
BEEP(6);
break;
}
// playing
case PLAYING_MMC:
if(!fplay_sector(&fp))
{ fclose(&fp);
ps.state = PLAYING_MMC_INIT;
num_beeps = 1;
PLAY_LED_OFF;
}
break;
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -