/************************************************************************************
Copyright (c) 2001-2007 University of Washington Extension.
Module Name:
tasks.c
Module Description:
The tasks that are executed by the test application.
************************************************************************************/
#include "includes.h" // OS includes
#include "print.h"
#include "init.h"
#include "driver.h"
#include "drv_spi.h"
#include "drv_mp3.h"
#include "mp3/train_crossing.h"
#define PLAY_SINE_TEST 1
#define CONTINUOUS 1
// allocate the stacks for each task
static OS_STK TaskPlayStk[APP_TASK_DEFAULT_STK_SIZE];
//static OS_STK TaskMonStk[APP_TASK_DEFAULT_STK_SIZE];
// Buffer for making calls to the MP3 driver
#define MP3BUFFERSIZE 256
INT8U buffer[MP3BUFFERSIZE];
// task prototypes
void PlayTask(void* pdata);
void MonTask(void* pdata);
static INT32U GetMP3(INT8U* pBuffer, INT32U Length, BOOLEAN Start);
void print_f(char *format, ...);
static void SetLED(BOOLEAN On);
//state variable to track CPU usage
static INT32U State = 0;
OS_EVENT * SemPrint;
//get external reference to the print buffer
PRINT_BUFFER();
// Create the driver table. Only need to set the drivers Init functions
OSDRV_DRIVER_ENTRY DriverTable[] =
{
// Init Config, Context Initialized, RefCount
{ { Spi_Init, NULL, NULL, NULL, NULL, NULL }, { 0 }, NULL, FALSE, 0 },
{ { Mp3_Init, NULL, NULL, NULL, NULL, NULL }, { 0 }, NULL, FALSE, 0 }
// add additional drivers here
};
#define DRIVER_COUNT (sizeof(DriverTable)/sizeof(OSDRV_DRIVER_ENTRY))
/************************************************************************************
This task is the initial task running, started by main(). It starts
the system tick timer and creates all the other tasks. Then it deletes itself.
************************************************************************************/
void StartupTask(void* pdata)
{
INT8U err;
print_f("StartupTask: begin\n\r");
print_f("StartupTask: tick timer\n\r");
// Initialize BSP functions
//BSP_Init();
// Start the system tick
InitializeTimerTick();
// re-init the UART so we can use the serial port
//initUART0(38400, UART_8N1, UART_FIFO_OFF, getFcclk());
print_f("StartupTask: After initUART\n\r");
// initialize the driver sub-system
err = OSDRV_SubsysInit(DriverTable, DRIVER_COUNT);
if (err != OS_DRV_NO_ERR)
{
print_f("StartupTask: Failed to initialize driver subsystem: %d\n\r", err);
//park here
while (TRUE)
;
}
SemPrint = OSSemCreate(1);
// create the the test tasks
// we have OS_STK_GROWTH set to 1, so the stack grows from high to low
print_f("StartupTask: Creating the tasks...\n\r");
OSTaskCreate(PlayTask,
(void*) 0,
(void*) &TaskPlayStk[APP_TASK_DEFAULT_STK_SIZE - 1],
PRIO_5);
#ifdef OS_TASK_STAT_EN
//create a CPU monitor task
//OSStatInit();
// OSTaskCreate(MonTask, (void*)0, (void*)&TaskMonStk[APP_TASK_DEFAULT_STK_SIZE-1], APP_TASK_MON_PRIO);
#endif //OS_TASK_STAT_EN
// delete ourselves, letting the work be done in the new tasks.
print_f("StartupTask: deleting self\n\r");
OSTaskDel(OS_PRIO_SELF);
}
/************************************************************************************
PlayTask - output some sounds
************************************************************************************/
void PlayTask(void* pdata)
{
INT8U err;
HANDLE hSpi; //handle to SPI driver
HANDLE hMp3; //handle to MP3 driver
INT32U length;
// VS1002 commands
const INT8U SineWave[] = { 0x53, 0xEF, 0x6E, 0x44, 0x00, 0x00, 0x00, 0x00 };
const INT8U Deact[] = { 0x45, 0x78, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00 };
const INT8U ModeTest[] = { 0x02, 0x00, 0x08, 0x20 };
const INT8U ModePlay[] = { 0x02, 0x00, 0x08, 0x00 };
const INT8U SoftReset[] = { 0x02, 0x00, 0x08, 0x04 };
INT32U DataMode = 1;
INT32U ii;
BOOLEAN start;
OSSemPend(SemPrint, 0, &err);
print_f("PlayTask: begin\n\r");
OSSemPost(SemPrint);
//set states as we go along so we track CPU uasge better
State = 1;
//get a handles to the SPI and MP3 drivers
hSpi = Open(SPI_DRV0, OSDRV_WRITE | OSDRV_EXCLUSIVE);
if (hSpi == OS_DRV_INVALID_HANDLE)
{
print_f("PlayTask: failed to open SPI driver\n\r");
OSTaskDel(OS_PRIO_SELF);
}
hMp3 = Open(MP3_DRV0, OSDRV_WRITE | OSDRV_EXCLUSIVE);
if (hMp3 == OS_DRV_INVALID_HANDLE)
{
print_f("PlayTask: failed to open MP3 driver\n\r");
OSTaskDel(OS_PRIO_SELF);
}
//tell the MP3 driver which SPI port driver to use
length = sizeof(HANDLE);
err = Ioctl(hMp3, IOCTL_MP3_SET_SPI, &hSpi, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed to set SPI port to open MP3 driver, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
// Reset the MP3 chip
length = sizeof(SoftReset);
memcpy(buffer, SoftReset, length);
err = Write(hMp3, buffer, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed write, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
#if PLAY_SINE_TEST
// Allow tests
length = sizeof(ModeTest);
memcpy(buffer, ModeTest, length);
err = Write(hMp3, buffer, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed write, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
// Set to data mode
DataMode = 1;
length = sizeof(DataMode);
err = Ioctl(hMp3, IOCTL_MP3_SET_DATA_MODE, &DataMode, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed to set data mode, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
State = 2;
for (ii = 0; ii < 3; ii++)
{
State = 3;
OSSemPend(SemPrint, 0, &err);
print_f("PlayTask: playing\n\r");
OSSemPost(SemPrint);
// Play test sound (note, first time through the chip may not play)
length = sizeof(SineWave);
memcpy(buffer, SineWave, length);
err = Write(hMp3, buffer, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed write, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
SetLED(0);
OSTimeDlyHMSM(0, 0, 5, 000);
OSSemPend(SemPrint, 0, &err);
print_f("PlayTask: stopping\n\r");
OSSemPost(SemPrint);
// Stop
length = sizeof(Deact);
memcpy(buffer, Deact, length);
err = Write(hMp3, buffer, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed write, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
SetLED(1);
OSTimeDlyHMSM(0, 0, 2, 000);
}
#endif //PLAY_SINE_TEST
State = 4;
// Set to cmd mode
DataMode = 0;
length = sizeof(DataMode);
err = Ioctl(hMp3, IOCTL_MP3_SET_DATA_MODE, &DataMode, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed to set data mode, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
// Set to play mode
length = sizeof(ModePlay);
memcpy(buffer, ModePlay, length);
err = Write(hMp3, buffer, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed write, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
// Set to data mode
DataMode = 1;
length = sizeof(DataMode);
err = Ioctl(hMp3, IOCTL_MP3_SET_DATA_MODE, &DataMode, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed to set data mode, err: %d\n\r", err);
OSTaskDel(OS_PRIO_SELF);
}
// Loop though the data until done
start = TRUE;
while (TRUE)
{
INT32U len;
State = 5;
len = GetMP3(buffer, MP3BUFFERSIZE, start);
start = FALSE;
SetLED(1);
if (len > 0)
{
length = len;
err = Write(hMp3, buffer, &length);
if (err != OS_DRV_NO_ERR)
{
print_f("PlayTask: failed write, err: %d\n\r", err);
while (TRUE)
; //park here on error
}
}
SetLED(0);
if (len < MP3BUFFERSIZE)
{
//we are done with file
#ifdef CONTINUOUS
start = TRUE;
OSSemPend(SemPrint, 0, &err);
print_f("PlayTask: restarting\n\r");
OSSemPost(SemPrint);
#else //CONTINUOUS
break;
#endif //CONTINUOUS
}
}
State = 6;
OSSemPend(SemPrint, 0, &err);
print_f("PlayTask: exiting\n\r");
OSSemPost(SemPrint);
OSTaskDel(OS_PRIO_SELF);
}
/************************************************************************************
GetMP3 - get MP3 buffers
pBuffer = buffer to fill
Length - size to fill
Start - TRUE start at beginning of file
return - number of bytes returned. If less than Length, then end of file.
************************************************************************************/
INT32U GetMP3(INT8U* pBuffer, INT32U Length, BOOLEAN Start)
{
static INT32U current = 0;
static INT32U count = 0;
INT32U len;
if (Start)
{
current = 0;
}
count++;
len = (Length + current) < sizeof(Wave) ? Length : sizeof(Wave) - current;
if (((current) >= (sizeof(Wave) - 100)) || (len > 256))
{
INT32U tmp;
tmp = len;
}
memcpy(pBuffer, &Wave[current], len);
if (((current) >= (sizeof(Wave) - 100)) || (len > 256))
{
INT32U tmp;
tmp = len;
}
current += len;
return len;
}
/************************************************************************************
MonTask - monitor the CPU usage
************************************************************************************/
void MonTask(void* pdata)
{
INT8U err;
//give system time to get initial values
OSTimeDlyHMSM(0, 0, 1, 000);
while (TRUE)
{
OSSemPend(SemPrint, 0, &err);
print_f("MonTask: cpu %%: %d, state: %d\n\r", OSCPUUsage, State);
OSSemPost(SemPrint);
OSTimeDlyHMSM(0, 0, 1, 000);
}
}
/************************************************************************************
Toggle the LED next to the display (labeled SD)
************************************************************************************/
static void SetLED(BOOLEAN On)
{
if (On) {
FIO1SET_bit.P1_5 = 1;
} else {
FIO1CLR_bit.P1_5 = 1;
}
}
/************************************************************************************
Print a formated string. Uses temporary stack buffer.
************************************************************************************/
void print_f(char *format, ...)
{
char buf[80];
va_list args;
va_start(args, format);
vsnprintf(buf, 80, format, args);
printString(buf);
va_end(args);
}