Lab4

Dependencies:   EasyVR mbed

main.cpp

Committer:
cmiller86
Date:
2015-10-19
Revision:
1:a10f4330a948
Parent:
0:0420a5989bff

File content as of revision 1:a10f4330a948:

/*
 * Documentation:
 * http://www.zagrosrobotics.com/files/easyvr-user-manual-30.pdf
 */

#include "easyvr.h"

#define BUF_SIZE 32
#define NUM_NOTES 8

EasyVR easyVR( p28, p27 );
Serial term( USBTX, USBRX );
PwmOut speaker( p21 );
InterruptIn hold_button( p8 );

// C major scale starting at C4
char *note_table[] = { "C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5" };
float freq_table[] = { 261.63, 293.66, 329.63, 349.23, 392.0, 440.0, 493.88, 523.25 };

char note_buffer[BUF_SIZE];
short note_buffer_pos = 0;
bool do_read = false;

void print_error( int error )
{
    switch( error )
    {
        case ERR_DATACOL_TOO_NOISY:
            term.printf( "Too noisy, try again\r\n" );
            break;
        case ERR_DATACOL_TOO_SOFT:
            term.printf( "Spoke too softly, try again\r\n" );
            break;
        case ERR_DATACOL_TOO_LOUD:
            term.printf( "Spoke too loudly, try again\r\n" );
            break;
        case ERR_DATACOL_TOO_SOON:
            term.printf( "Spoke too soon, try again\r\n" );
            break;
        case ERR_DATACOL_TOO_CHOPPY:
            term.printf( "Too complex, try again\r\n" );
            break;
        case ERR_RECOG_FAIL:
            term.printf( "Recognition failed, try again\r\n" );
            break;
        case ERR_RECOG_LOW_CONF:
            term.printf( "Recognition result status: doubtful, try again\r\n" );
            break;
        case ERR_RECOG_MID_CONF:
            term.printf( "Recognition result status: maybe, try again\r\n" );
            break;
        case ERR_RECOG_BAD_TEMPLATE:
            term.printf( "Invalid command stored in memory\r\n" );
            break;
        case ERR_RECOG_DURATION:
            term.printf( "Bad duration patterns\r\n" );
            break;
        case ERR_SYNTH_BAD_VERSION:
            term.printf( "Bad release number in speech file\r\n" );
            break;
        case ERR_SYNTH_BAD_MSG:
            term.printf( "Bad data in speech file\r\n" );
            break;
        case ERR_NOT_A_WORD:
            term.printf( "Spoken word is not in vocabulary\r\n" );
            break;
        default:
            break;
    }
}

void add_command( int index )
{    
    char command_num = i2a( index );
    char note        = note_table[index][0];
    char scale       = (char)( note_table[index][1] + 17 );
    
    char err;
    
    easyVR.send( CMD_GROUP_SD );
    easyVR.send( i2a( 1 ) );
    easyVR.send( command_num );
    
    if( ( err = easyVR.receive() ) != STS_SUCCESS )
        term.printf( "(in add_command( %s ) line %d) Error %c\r\n", note_table[index], __LINE__, err );
    
    easyVR.send( CMD_NAME_SD );
    easyVR.send( i2a( 1 ) );
    easyVR.send( command_num );
    easyVR.send( i2a( 3 ) );
    easyVR.send( note );
    easyVR.send( '^' );
    easyVR.send( scale );
    
    if( ( err = easyVR.receive() ) != STS_SUCCESS )
        term.printf( "(in add_command( %s ) line %d) Error %c\r\n", note_table[index], __LINE__, err );
}

char train_command( int index )
{
    char command_num = i2a( index );
    char note        = note_table[index][0];
    char scale       = (char)( note_table[index][1] + 17 );
    
    term.printf( "Please say: %s\r\n", note_table[index] );

    easyVR.send( CMD_TRAIN_SD );
    easyVR.send( i2a( 1 ) );
    easyVR.send( command_num );
    
    char recv, err, retval;
    
    switch( ( recv = easyVR.receive() ) )
    {
        case STS_SUCCESS:
            term.printf( "Successfully trained command %c^%c\r\n", note, scale );
            retval = recv;
            break;
        case STS_RESULT:
            easyVR.send( ARG_ACK );
            err = a2i( easyVR.receive() );
            term.printf( "Successfully trained command %c^%c, but similar to SD command %d\r\n", note, scale, err );
            retval = STS_SUCCESS;
            break;
        case STS_SIMILAR:
            easyVR.send( ARG_ACK );
            err = a2i( easyVR.receive() );
            term.printf( "Successfully trained command %c^%c, but similar to SI command %d\r\n", note, scale, err );
            retval = STS_SUCCESS;
            break;
        case STS_TIMEOUT:
            term.printf( "Timed out trying to train %c^%c!\r\n", note, scale );
            retval = recv;
            break;
        case STS_ERROR:      
            easyVR.send( ARG_ACK );
            err = a2i( easyVR.receive() ) * 16;
            easyVR.send( ARG_ACK );
            err += a2i( easyVR.receive() );
            print_error( err );
            retval = err;
            break;
        default:
            term.printf( "(in train_command( %s ) line %d) Error %c\r\n", note_table[index], __LINE__, recv );
            retval = recv;
            break;
    }
    
    return retval;
}

void enable_read()
{
    do_read = true;
}

void play_buffer()
{
    do_read = false;
    easyVR.send( CMD_BREAK );
    
    for( int i = 0; i < note_buffer_pos; i++ )
    {
        speaker.period( 1.0 / freq_table[note_buffer[i]] );
        speaker = 0.25;
        wait( 0.5 );
    }
    
    speaker = 0;
    note_buffer_pos = 0;
}

int main( void )
{
    term.baud( 19200 );
    
    easyVR.wakeup();
    easyVR.setup( 0, 3 );
    
    char err;
    
    easyVR.baud( 9600 );
    easyVR.send( CMD_BAUDRATE );
    easyVR.send( i2a( 12 ) );
    
    if( ( err = easyVR.receive() ) != STS_SUCCESS )
        term.printf( "(in main() line %d) Error: %c\r\n", __LINE__, err );
    
    easyVR.send( CMD_LEVEL );
    easyVR.send( i2a( 1 ) );
    
    if( ( err = easyVR.receive() ) != STS_SUCCESS )
        term.printf( "(in main() line %d) Error: %c\r\n", __LINE__, err );
    
    /*
    int result;
    
    for( int i = 0; i < NUM_NOTES; i++ )
    {
        add_command( i );
        
        do
        {
            result = train_command( i );
            wait( 0.5 );
        } while( result != STS_SUCCESS );
    }
    */
    
    hold_button.rise( enable_read );
    hold_button.fall( play_buffer );
    
    char note, recv;
    
    while( 1 )
    {
        while( do_read )
        {
            term.printf( "Ready!\r\n" );
            
            easyVR.send( CMD_RECOG_SI );
            easyVR.send( i2a( 3 ) );
            
            switch( ( recv = easyVR.receive() ) )
            {
                case STS_SIMILAR:
                    easyVR.send( ARG_ACK );
                    note = a2i( easyVR.receive() );
                    
                    if( note < NUM_NOTES )
                    {
                        term.printf( "Heard: %s\r\n", note_table[note] );
                        
                        if( note_buffer_pos < BUF_SIZE )
                        {
                            note_buffer[note_buffer_pos] = note;
                            note_buffer_pos++;
                        }
                        else
                            term.printf( "Buffer full\r\n" );
                    }
                    else
                        term.printf( "Heard SI command %d\r\n", note );
                    
                    break;
                /*
                case STS_SIMILAR:
                    easyVR.send( ARG_ACK );
                    err = a2i( easyVR.receive() );
                    term.printf( "Heard similar to SI command %d\r\n", err );
                    break;
                */
                case STS_TIMEOUT:
                    term.printf( "Timed out\r\n" );
                    break;
                case STS_ERROR:
                    easyVR.send( ARG_ACK );
                    err = a2i( easyVR.receive() ) * 16;
                    easyVR.send( ARG_ACK );
                    err += a2i( easyVR.receive() );
                    print_error( err );
                    break;
                default:
                    if( recv != STS_INTERR )
                        term.printf( "(in main() line %d) Error %c\r\n", __LINE__, recv );
                    
                    break;
            }
        }
    }
}