view main/robots/odr-display/menu.cpp @ 260:98dfb5a2c37a main

Latest code from Robothon.
author Bob Cook <bob@bobcookdev.com>
date Tue, 13 Oct 2015 19:17:17 -0700
parents
children
line wrap: on
line source

// ----------------------------------------------------------------------------------------
//
//  Copyright (C) 2014-2015 Bob Cook
//    
//  Bob Cook Development, Robotics Library
//  http://www.bobcookdev.com/rl/
// 
//  User interface menu functions for the Outdoor Robot user interface board.
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//
// ----------------------------------------------------------------------------------------

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

#include "func.h"
#include "leds.h"

#include "packages/avr/device/spinwait.h"

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

#include "packages/avr/lcd/ili9340/ili9340.h"

// always after other includes
#include "packages/avr/device/workaround34734.h"

// ----------------------------------------------------------------------------------------
//
//  The LCD display is 26 rows by 30 columns:
//
//                   1         2
//         012345678901234567890123456789
//         ||||||||||||||||||||||||||||||
//      0-|Outdoor Robot                H|- H = heartbeat spinner
//      1-|                              |-
//      2-|                              |-
//      3-|                              |-
//      4-|      motion controller       |-
//      5-|  f: +00 / +00  r: +00 / +00  |-
//      6-|                              |-
//      7-|       front obstacles        |-
//      8-|    000   000   000   000     |-
//      9-|                              |-
//     10-|        location (00)         |-
//      1-|  N 123 45.678  W 123 45.678  |-
//      2-|                              |-
//      3-|     origin (123.4) target    |-
//      4-| N 123 45.678    N 123 45.678 |-
//      5-| W 123 45.678    W 123 45.678 |-
//      6-|                              |-
//      7-|  inertial measurement unit   |-
//      8-|   Y +000  P +00.0  R +00.0   |-
//      9-|                              |-
//     20-|  +++++++ MENU ROW 1 +++++++  |-
//      1-|  +++++++ MENU ROW 2 ++++++>  |-
//      2-|                              |-
//      3-|                              |-
//      4-|                              |-
//      5-|       emergency active       |-
//         ||||||||||||||||||||||||||||||
//         012345678901234567890123456789
//                   1         2
//
// ----------------------------------------------------------------------------------------

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

const static uint8_t menu_state_idle           = 0;
const static uint8_t menu_state_button_pressed = 1;
const static uint8_t menu_state_button_left    = 2;
const static uint8_t menu_state_button_right   = 3;

const static uint8_t menu_select_stop     = 0;
const static uint8_t menu_select_wander   = 1;
const static uint8_t menu_select_line     = 2;
const static uint8_t menu_select_smbox    = 3;
const static uint8_t menu_select_waypts   = 4;
const static uint8_t menu_select_robothon = 5;
const static uint8_t menu_num_items       = 6;

const static uint8_t menu_select_animation_time = 3;

static uint8_t g_menu_state = menu_state_idle;
static uint8_t g_selection = menu_select_stop;
static uint8_t g_menu_timer;

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

static void write_menu_title( const prog_char* str )
{
    ili9340_write_pgm( PSTR("                          "),
                       2, 20, ili9340_color_white, ili9340_color_blue );

    ili9340_write_pgm( str, 2, 20, ili9340_color_white, ili9340_color_blue );
}

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

static void write_menu_entry( const prog_char* str, bool selected )
{
    if ( selected )
    {
        ili9340_write_pgm( PSTR("                        "),
                           3, 21, ili9340_color_blue, ili9340_color_white );

        ili9340_write_pgm( str, 4, 21, ili9340_color_blue, ili9340_color_white );
    }
    else
    {
        ili9340_write_pgm( PSTR("                        "),
                           3, 21, ili9340_color_white, ili9340_color_blue );

        ili9340_write_pgm( str, 4, 21, ili9340_color_white, ili9340_color_blue );
    }
}

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

static void write_arrow_left( bool selected )
{
    if ( selected )
    {
        ili9340_write( '<', 2, 21, ili9340_color_blue, ili9340_color_white );
    }
    else
    {
        ili9340_write( '<', 2, 21, ili9340_color_white, ili9340_color_blue );
    }
}

static void write_arrow_right( bool selected )
{
    if ( selected )
    {
        ili9340_write( '>', 27, 21, ili9340_color_blue, ili9340_color_white );
    }
    else
    {
        ili9340_write( '>', 27, 21, ili9340_color_white, ili9340_color_blue );
    }
}

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

static void selection_forward()
{
    g_selection++;
    g_selection %= menu_num_items;
}

static void selection_reverse()
{
    if ( g_selection == menu_select_stop )
    {
        g_selection = menu_num_items - 1;
    }
    else
    {
        --g_selection;
    }
}

static void selection_draw( bool selected )
{
    switch ( g_selection )
    {
        case menu_select_stop:
            write_menu_entry( PSTR("stop program"), selected );
            break;

        case menu_select_wander:
            write_menu_entry( PSTR("start wander"), selected );
            break;

        case menu_select_line:
            write_menu_entry( PSTR("straight line"), selected );
            break;

        case menu_select_smbox:
            write_menu_entry( PSTR("small box"), selected );
            break;

        case menu_select_waypts:
            write_menu_entry( PSTR("waypoints"), selected );
            break;

        case menu_select_robothon:
            write_menu_entry( PSTR("robothon"), selected );
            break;
    }
}

static void selection_made()
{
    switch ( g_selection )
    {
        case menu_select_stop:
            canmsg_send_stop_pgm();
            break;

        case menu_select_wander:
            canmsg_send_start_wander_pgm();
            break;

        case menu_select_line:
            canmsg_send_start_line_pgm();
            break;

        case menu_select_smbox:
            canmsg_send_start_smbox_pgm();
            break;

        case menu_select_waypts:
            break;

        case menu_select_robothon:
            canmsg_send_start_robothon_pgm();
            break;
    }
}

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

void menu_init()
{
    g_menu_state = menu_state_idle;
    g_selection  = menu_select_stop;

    write_menu_title( PSTR("menu") );
    write_arrow_left( false );
    write_arrow_right( false );
    selection_draw( false );
}

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

void menu_refresh()
{
    if ( g_menu_state == menu_state_idle )
    {
        if ( button_state() == button_center_e )
        {
            selection_draw( true );
            g_menu_state = menu_state_button_pressed;
            g_menu_timer = menu_select_animation_time;
        }
        else if ( button_state() == button_left_e )
        {
            write_arrow_left( true );
            g_menu_state = menu_state_button_left;
            g_menu_timer = menu_select_animation_time;
        }
        else if ( button_state() == button_right_e )
        {
            write_arrow_right( true );
            g_menu_state = menu_state_button_right;
            g_menu_timer = menu_select_animation_time;
        }
    }
    else if ( g_menu_state == menu_state_button_pressed )
    {
        if ( ! button_is_pressed() )
        {
            if ( --g_menu_timer == 0 )
            {
                selection_draw( false );
                g_menu_state = menu_state_idle;
                selection_made();
                g_selection = menu_select_stop;
                selection_draw( false );
            }
        }
    }
    else if ( g_menu_state == menu_state_button_left )
    {
        if ( ! button_is_pressed() )
        {
            if ( --g_menu_timer == 0 )
            {
                write_arrow_left( false );
                g_menu_state = menu_state_idle;
                selection_reverse();
                selection_draw( false );
            }
        }
    }
    else if ( g_menu_state == menu_state_button_right )
    {
        if ( ! button_is_pressed() )
        {
            if ( --g_menu_timer == 0 )
            {
                write_arrow_right( false );
                g_menu_state = menu_state_idle;
                selection_forward();
                selection_draw( false );
            }
        }
    }
}

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