📄 frankmp3.c
字号:
/******************************************************************************
Title: Frank's MP3 Player Main C file
Author: Frank Van Hooft
Date: 21 Aug 2004
This file is the main C file for the MP3 player project.
(This file is larger than it appears due to #include's at the very end.)
This software requires the drive to be formatted with FAT32, and to be
jumpered as a master.
Interrupts: Five irqs are enabled. One is receive characters
on uart 0 - the debug port. When a key is pressed on the debug port the
AVR prints out a bunch of debugging info and then halts. One irq is to
receive characters on uart 1 - the pushbuttons. The third irq is external
interrupt 6 - usb cable detect, which when triggered takes over the processor.
The fourth is timer/counter 1 output compare A, used to generate a periodic
100ms interrupt for use as a timebase. The fifth is timer/counter 3
input capture, used for the IR remote control detection.
******************************************************************************/
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "frankmp3.h"
#include "fvhmp3c.h"
#include "sta-init.c"
/* Frank's MP3 functions prototypes for external assembler functions */
extern void Q_init_all(void);
extern void IDE_init(void);
extern void GetFatParams(void);
extern u08 SeekSectorC (u32 startsector, u08 numsectors);
extern void FAT32_init(void);
extern void IDE_AutoPD(void);
extern void IDE_Standby(void);
extern void UART_init(void);
extern void General_init(void);
extern void UART_TxCharWaitC(u08); /* waits for the uart hardware to be ready - very slow */
extern void UART1_TxCharWaitC(u08);
extern void UART_PutHexWaitC(u08); /* waits for UART hardware - very slow */
extern void StreamFileC(void);
extern void Delayms(u08);
extern u08 Q_read_C(u08 queue[]); /* reads a byte from the specified queue */
extern u08 Q_CheckEmptyC(u08 queue[]); /* checks if the specified queue is empty or not */
extern u16 Q_HowMuchDataC(u08 queue[]); /* returns number of data bytes in specified queue */
extern u08 Q_clear_C(u08 queue[]); /* clears the specified queue */
extern void ResetAVR (void); /* simply does a jump to main */
extern u08 Q_Read_FILO_C (u08 queue[]); /* does a "reverse read" of the specified queue */
extern u08 IDE_read8_C (u08 ideaddress); /* reads byte from the specified drive register */
extern u16 IDE_read16_C (u08 idereg); /* reads a word from the specified IDE drive register address */
extern void IDE_Write8_C (u08 ideaddress, u08 data); /* write a byte to the specified IDE drive register */
// substitute my old assembler eeprom read routine with the new WINAVR provided routine
//extern u08 EEPROM_ReadC (u16 eeprom_address); // assembler version for eeprom read
#define EEPROM_ReadC(addr) eeprom_read_byte((uint8_t*)(addr))
/* externally allocated variables used in this file */
extern volatile u08 SEC_PER_CLUS; /* drive number of sectors per cluster */
extern volatile u16 FAT_START_SEC; /* start of FAT sector number */
extern volatile u32 DIR_START_SEC; /* start of root directory sector number */
extern volatile u08 FINDFILE_RET_NAME[]; /* string where FINDFILE returns file name */
extern volatile u32 FINDFILE_RET_CLUS; /* FindFile returns: next file starting cluster number */
extern volatile u32 FINDFILE_RET_SIZE; /* FindFile returns: next file size in bytes */
extern volatile u08 FINDFILE_ST; /* FindFile state variable */
extern volatile u08 STREAMFILE_ST; /* StreamFile state variable */
extern volatile u32 STREAMFILE_FILESZ; /* StreamFile size of file to stream in bytes */
extern volatile u32 STREAMFILE_CLUS; /* StreamFile file to stream cluster number */
extern volatile u08 *STREAMFILE_QPOINTER; /* StreamFile pointer to the queue to stream file into */
extern volatile u08 STREAMFILE_CMD; /* StreamFile command byte - command StreamFile what to do */
extern volatile u08 MP3DATAQ[]; /* The famous MP3 data queue */
extern volatile u08 ReadQstatus; /* gives status of last queue read operation by Q_read_C() */
extern volatile u32 CURRENT_DIRCL; /* Cluster number for start of current directory */
extern volatile u32 FINDFILE_CLUS; /* FindFile current directory cluster */
extern volatile u16 FINDFILE_OFSET; /* FindFile offset into the above directory cluster */
extern volatile u08 SEEKSECT_ST; /* SeekSector state variable */
extern volatile u08 CALNXCL_ST; /* CalcNextCluster state variable */
extern volatile u32 CALNXCL_SN; /* CalcNextCluster sector number */
/* Global variables allocated & defined in this file */
volatile u16 NumMP3files; /* Number of MP3 files in the directory */
volatile u16 FileNumber, StepSize; /* file number currently being played in current directory 1.., also StepSize used in Random mode */
volatile u08 PC_Command, PC_Flag_Repeat, PC_Flag_Mode; /* used by PlayControl */
// PC_Flag_Mode: 0=normal, non-zero=random
volatile u08 FeedSTcodec_Command; /* Command byte for FeedSTcodec */
volatile u08 PlayControlState; /* state variable for PlayControl state machine */
volatile u08 ButtonPress; // holds the current user pushbutton pressed
volatile u32 FINDFILE_PREV_CLUS; /* FindFile previous directory cluster */
volatile u08 Tick100ms; // Timebase - incremented every 100ms by timer0 interrupt
volatile u16 IR_RX_period; // Length of received IR period.
volatile u08 IRdecode_cnt[IR_numcodes]; // IR decode count byte remembers where we are in IR period sequences
volatile u08 IRdecode_time; // used for IR decoder timeout timer
volatile u08 IRtrain_debug; // flag set means to dump remote-control period data while training
volatile u08 StepSizeStartTime; // used by CycleStepSize to know how long pushbutton depressed
// Menu structures. There is a typedef defining the structure of a single menu item. It's a
// linked-list arrangement, with pointers to the next & previous structures. Also a pointer
// to the name (string) of the menu item, and a pointer to the function to execute if the
// user selects this menu item.
//
// If you want to add another menu item, do this:
// - create a new menu display name string, and a new menu function
// - copy&paste a new menu entry into the array of structures
// - make sure it points to the menu items above & below it
// - edit the structures above & below it to make them point to your new menu item.
// - double-check your new entry points to its name string & its menu function
// Here are the menu display name strings (stored in flash)
const char Menu0Name[] PROGMEM = "** EXIT MENUS AND **** RETURN TO PLAYER **";
const char Menu1Name[] PROGMEM = "Change Current Directory";
const char Menu2Name[] PROGMEM = "Display Number of Files in Current Directory";
const char Menu3Name[] PROGMEM = " Change Player Output (volume) level";
const char Menu4Name[] PROGMEM = "Learn IR Remote Control";
// Here are the function prototypes for the menu functions
void NULLfunction (void);
void ChangeDir (void);
void DisplayNumDirFiles (void);
void OutputLevel (void);
void LearnRemoteControl(void);
// Structure type - this is the definition of a single menu entry
typedef void (*FnPtr)(void); // define a function pointer type of: void functionname(void)
typedef struct M_STRUCT
{
struct M_STRUCT *next; // point to next menu structure
struct M_STRUCT *prev; // point to previous menu structure
char *name; // point to display name of menu item
FnPtr function;
} MENU_STRUCT;
// Here are the actual menu entries, one per line. They are stored in flash. (Array of structures)
MENU_STRUCT m_array[] PROGMEM = {
{ &m_array[1], &m_array[4], (char*)&Menu0Name[0], NULLfunction },
{ &m_array[2], &m_array[0], (char*)&Menu1Name[0], ChangeDir },
{ &m_array[3], &m_array[1], (char*)&Menu2Name[0], DisplayNumDirFiles },
{ &m_array[4], &m_array[2], (char*)&Menu3Name[0], OutputLevel },
{ &m_array[0], &m_array[3], (char*)&Menu4Name[0], LearnRemoteControl }
};
// Defines for indexing into these structures. If you change the menu structure typedef you MUST change these.
#define NextMenu 0 /* Menu structure index for pointer to next menu structure */
#define PrevMenu 2 /* Menu structure index for pointer to previous menu structure */
#define MenuString 4 /* Menu structure index for pointer to item description string */
#define MenuFn 6 /* Menu structure index for pointer to menu function */
// End of menu structures.
// IR training structures. Used to allow the user to scroll through a list of player functions
// (play, stop, next, etc) to select which one s/he wants to train the IR remote control
// receiver for. These structures are very similar to the "Menu items" structures above.
// There is a typedef defining the structure of a single function. It's a
// linked-list arrangement, with pointers to the next & previous structures. Also a pointer
// to the name (string) of the player function, and the eeprom offset for where the resultant
// data is to be stored.
//
// If you want to add another function item, do this:
// - create a new function display name string, and a new eeprom offset
// - copy&paste a new function entry into the array of structures
// - make sure it points to the function items above & below it
// - edit the structures above & below it to make them point to your new function item.
// - double-check your new entry points to its name string & its eeprom offset.
// Here are the function display name strings (stored in flash)
const char Func0Name[] PROGMEM = " Power (on/off)";
const char Func1Name[] PROGMEM = " Play";
const char Func2Name[] PROGMEM = " Stop";
const char Func3Name[] PROGMEM = " Next";
const char Func4Name[] PROGMEM = " Back";
const char Func5Name[] PROGMEM = " Mode (random, etc)";
// Structure type - this is the definition of a single menu entry
typedef struct F_STRUCT
{
struct F_STRUCT *next; // point to next function structure
struct F_STRUCT *prev; // point to previous function structure
char *name; // point to display name of function item
u16 eeprom_offset; // eeprom offset for result IR function training data
} FUNC_STRUCT;
// Here are the actual player function entries, one per line. They are stored in flash. (Array of structures)
FUNC_STRUCT f_array[] PROGMEM = {
{ &f_array[1], &f_array[5], (char*)&Func0Name[0], IRcode_pwr },
{ &f_array[2], &f_array[0], (char*)&Func1Name[0], IRcode_play },
{ &f_array[3], &f_array[1], (char*)&Func2Name[0], IRcode_stop },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -