// ----------------------------------------------------------------------------------------
//
//  demos/cfax_iic_slave/main.cpp
//    
//  Bob Cook Development, Robotics Library
//  http://www.bobcookdev.com/rl/
//    
//  This file implements an I2C (TWI) bridge to the SparkFun CFAX Graphic LCD.
//
//  Copyright (C) 2009 Bob Cook
//
//      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., 
//      51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
// ----------------------------------------------------------------------------------------


#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

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

#include "packages/avr/device/adc.h"
#include "packages/avr/device/int_helpers.h"
#include "packages/avr/device/spinwait.h"
#include "packages/avr/lcd/cfax/cfax.h"

#include "packages/s3c2410a/cfax_iic/protocol.h"

#include "packages/common/util/misc.h"

#include "project_defs.h"

extern "C" {
#include "TWI_slave.h"
};


// ----------------------------------------------------------------------------------------

inline void led_off()
{
    PORTB |= ( 1 << PB1 );
}


inline void led_on()
{
    PORTB &= ~( 1 << PB1 );
}


// ----------------------------------------------------------------------------------------
//  do_line
// 
//      Handle the various types of painting a line.
//

static void do_line( const cfaxiic_cmd_t& command )
{
    if ( command.data.line.x0 == command.data.line.x1 )
    {
        cfax_line_v( command.data.line.x0, command.data.line.y0,
                     util_abs( command.data.line.y1 - command.data.line.y0 - 1 ),
                     command.data.line.state );
    }
    else if ( command.data.line.y0 == command.data.line.y1 )
    {
        cfax_line_h( command.data.line.x0, command.data.line.y0,
                     util_abs( command.data.line.x1 - command.data.line.x0 - 1 ),
                     command.data.line.state );
    }
    else
    {
        cfax_line( command.data.line.x0, command.data.line.y0,
                   command.data.line.x1, command.data.line.y1,
                   command.data.line.state );
    }
}


// ----------------------------------------------------------------------------------------
//  do_rect
// 

static void do_rect( const cfaxiic_cmd_t& command )
{
    cfax_rect( command.data.rect.x, command.data.rect.y,
               command.data.rect.w, command.data.rect.h );
}


// ----------------------------------------------------------------------------------------
//  do_fill
//

static void do_fill( const cfaxiic_cmd_t& command )
{
    cfax_fill( command.data.rect.x, command.data.rect.y,
               command.data.rect.w, command.data.rect.h );
}


// ----------------------------------------------------------------------------------------
//  do_erase
//

static void do_erase( const cfaxiic_cmd_t& command )
{
    cfax_erase( command.data.rect.x, command.data.rect.y,
                command.data.rect.w, command.data.rect.h );
}


// ----------------------------------------------------------------------------------------
//  do_touch
//

static void do_touch()
{
    cfaxiic_cmd_t response;
    response.command = CFAXIIC_RESPONSE_TOUCH;

    response.data.touch.state = cfax_touchscreen( &response.data.touch.x,
                                                  &response.data.touch.y );

    TWI_Start_Transceiver_With_Data( reinterpret_cast< uint8_t* >( &response ),
                                     sizeof( response.command ) + sizeof( response.data.touch ) );
    while ( TWI_Transceiver_Busy() );
}


// ----------------------------------------------------------------------------------------

int main()
{
    cli();
    interrupts_clear_all();
    sei();

    //--    Status LED: PORTB.1

    DDRB |= ( 1 << PB1 );
    led_off();

    adc_init();
    cfax_init();
    TWI_Slave_Initialise( (50<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) );

    cfax_write_pgm( PSTR("I2C Display Ready!"), 0, 0 );

    for ( ;; )
    {
        TWI_Start_Transceiver();

        cfaxiic_cmd_t command;
        memset( &command, 0, sizeof( command ) );

        uint8_t length;

        if ( ( length = TWI_Get_Data_From_Transceiver( reinterpret_cast< uint8_t* >( &command ), sizeof( command ) ) ) > 0 )
        {
            switch ( command.command )
            {
                case CFAXIIC_CMD_CLS:
                    cfax_clear_screen();
                    break;

                case CFAXIIC_CMD_TEXT:
                    cfax_write( command.data.text.text, command.data.text.x, command.data.text.y );
                    break;

                case CFAXIIC_CMD_LINE:
                    do_line( command );
                    break;

                case CFAXIIC_CMD_RECT:
                    do_rect( command );
                    break;

                case CFAXIIC_CMD_FILL:
                    do_fill( command );
                    break;

                case CFAXIIC_CMD_ERASE:
                    do_erase( command );
                    break;

                case CFAXIIC_CMD_TOUCH:
                    do_touch();
                    break;

                default:
                    break;
            }
        }
    }

    return 0;
}


// ----------------------------------------------------------------------------------------
//  end of main.cpp
// ----------------------------------------------------------------------------------------

