Subversion Repositories FlightCtrl

Rev

Rev 325 | Blame | Last modification | View Log | RSS feed

/***************************************************************
 *
 * minimal canvas to test Abstraction layer on various Phones
 *                                                          
 * Author:        Marcus -LiGi- Bueschleb                    
 * Project-Start: 9/2007                                    
 * Mailto:        ligi@smart4mobile.de                      
 * Licence:       Creative Commons / Non Commercial
 *                ( see README for exact terms of usage)
 * Big Up:        Holger&Ingo                                
 ***************************************************************/


import javax.microedition.lcdui.*;
import javax.microedition.rms.*;


public class MKMiniCanvas
    extends Canvas
    implements Runnable
{

    // name/handle for the recordStore to memorize some stuff
    private final static String RECORD_STORE_NAME="bluetoothurl";
   
    private BTSearcher bt_scanner;
    public MKCommunicator mk=null;
    private MKStatistics mk_stat=null;
    private MKParamsEditor params_editor=null;


    private String err="";
    private DUBwise root;

    private Image bg_img;
    private Image bt_img;
    private Image lcd_img;
    private Image load_img;


    public int[] nick_line_pos_data;
    public int[] roll_line_pos_data;

    public int[] accnick_line_pos_data;
    public int[] accroll_line_pos_data;

    public int lcd_char_width=0;
    public int lcd_char_height=0;

    public int frame_pos=0;
   
    int line_scaler=20;

    public int line_middle_y;

    boolean quit=false;
    boolean rescan=true;
    int bg_offset=0;

    // variable to hold the current state
    public int state=-1;
 
    // id  for each state - must just be uniq - order isnt important
    public final static int STATEID_SCANNING         =0;
    public final static int STATEID_DEVICESELECT     =1;
    public final static int STATEID_MAINMENU         =2;
    public final static int STATEID_MOTORTEST        =3;
    public final static int STATEID_SELECT_PARAMSET  =4;
    public final static int STATEID_EDIT_PARAMS      =5;
    public final static int STATEID_HANDLE_PARAMS    =6;
    public final static int STATEID_FLIGHTVIEW       =7;


    public boolean fullscreen=false;
    public int act_motor=0;
    public int act_motor_increase=0;
    public boolean motor_test_sel_all=false;

    public String[] main_menu_items={"Telemetry" , "Motor Test" , "Flight Settings","(NA)Tool Settings","Proxy","Change Device" , "Quit " };
    public final static int MAINMENU_TELEMETRY     =0;
    public final static int MAINMENU_MOTORTES      =1;
    public final static int MAINMENU_PARAMS        =2;
    public final static int MAINMENU_SETTINGS      =3;
    public final static int MAINMENU_PROXY         =4;
    public final static int MAINMENU_DEVICESELECT  =5;
    public final static int MAINMENU_QUIT          =6;
   
    int local_max=-1;

    int y_off=0;
    int spacer=0;
    int[] motor_test = {0,0,0,0};
   

    String[] menu_items;
    int act_menu_select=0;
   
    String[] lcd_lines =null;

    public void paint_menu(Graphics g)
    {
        for ( int i=0;i<menu_items.length;i++)
            lcd_lines[i]=(act_menu_select==i?"# ":"  ") + menu_items[i];       
        paint_lcd(g,true);
    }

    public void menu_keypress(int keyCode)
    {
        switch (getGameAction (keyCode))
            {
            case UP:
                if (act_menu_select!=0) act_menu_select--;
                else
                    act_menu_select=menu_items.length-1;
                break;
               
            case DOWN:
                if (act_menu_select<(menu_items.length-1)) act_menu_select++;
                else act_menu_select=0;
                break;
       
            }

    }



    public void paint_lcd(Graphics g,boolean bottomup)
    {
        int y;

        for(int i=0;i<lcd_lines.length;i++)
            for (int pos=0;pos<20;pos++)
            {
                if (bottomup)
                    y=this.getHeight()-(lcd_lines.length-i)*lcd_char_height;
                else
                    y=i*lcd_char_height;
                g.setClip((lcd_img.getWidth()/222)*pos,y,(lcd_img.getWidth()/222),lcd_img.getHeight());
                g.drawImage(lcd_img,(lcd_img.getWidth()/222)*pos-((pos<lcd_lines[i].length()?lcd_lines[i].charAt(pos):' ')-' ')*(lcd_img.getWidth()/222),y,g.TOP | g.LEFT);
               
            }
    }

    public MKMiniCanvas(DUBwise _root)
    {

        root=_root;

        bt_scanner = new BTSearcher();
        params_editor = new MKParamsEditor(this);
        mk = new MKCommunicator();
        mk_stat= new MKStatistics(mk);

        try
            {
                // load all needed images
                lcd_img=Image.createImage("/lcd.png");
                bt_img=Image.createImage("/bt.png");
                bg_img=Image.createImage("/bg.jpg");               
                load_img=Image.createImage("/load.png");
            }
        catch (Exception e)
            {
                err+=e.toString();
            }

        lcd_char_width=lcd_img.getWidth()/222;
        lcd_char_height=lcd_img.getHeight();
           

        nick_line_pos_data=new int[bg_img.getWidth()];
        roll_line_pos_data=new int[bg_img.getWidth()];
        accnick_line_pos_data=new int[bg_img.getWidth()];
        accroll_line_pos_data=new int[bg_img.getWidth()];
           
        for (int c=0;c<bg_img.getWidth();c++)
            {
                nick_line_pos_data[c]=-1;
                roll_line_pos_data[c]=-1;
                accnick_line_pos_data[c]=-1;
                accroll_line_pos_data[c]=-1;
            }
           
       
        try
            {
                RecordStore recStore = RecordStore.openRecordStore(RECORD_STORE_NAME , true );

                if (recStore.getNumRecords()==2)
                    {

                        //byte[] recData = new byte[recStore.getRecordSize(1)];
                        //int len = recStore.getRecord(1, recData, 0);

                        //byte[] recData2 = new byte[recStore.getRecordSize(2)];
                        //int len2 = recStore.getRecord(2, recData, 0);
                       
                        byte[] url_data=recStore.getRecord(1);
                        byte[] name_data=recStore.getRecord(2);

                        connect_mk(new String(url_data, 0, url_data.length),new String(name_data, 0, name_data.length));

                    }
                recStore.closeRecordStore();
            }
        catch (Exception e)
            {
                err+=e.toString();
            }

        chg_state((mk.force_disconnect)?STATEID_SCANNING:STATEID_MAINMENU);


       
        new Thread(this).start();

    }


   
    /****************************** Thread ******************/
    // ticking runnable Section
    public void run()
    {


        while(true)
            {
                repaint();
                serviceRepaints();

                long loopStartTime = System.currentTimeMillis();
                long sleeptime=0;
                // ticked thing
       
                frame_pos++;

                switch(state)
                    {
                    case STATEID_MOTORTEST:

                        if (motor_test_sel_all)
                            for (int m=0;m<4;m++)
                                {
                                    motor_test[m]+=act_motor_increase;
                                    if (motor_test[m]<0)motor_test[m]=0;
                                }
                        else
                            {
                                motor_test[act_motor]+=act_motor_increase;
                                if (motor_test[act_motor]<0)motor_test[act_motor]=0;
                            }

                        mk.motor_test(motor_test);
                        break;

                    case STATEID_SCANNING:
                        intro_str_delay--;
                        if (intro_str_delay<0)
                            {
                                intro_str_delay=1;
                                if (intro_str_pos>intro_str.length())
                                    intro_str_pos=0;
                                lcd_lines[3]=intro_str.substring(intro_str_pos,  (((intro_str_pos+20)>intro_str.length())?intro_str.length():intro_str_pos+20));
                                intro_str_pos++;
                            }
               
                        if (!bt_scanner.searching)
                                chg_state(STATEID_DEVICESELECT);

                       
                        break;


                       
                    }

                try {
                    nick_line_pos_data[-bg_offset] = mk.debug_data.nick_int();
                    roll_line_pos_data[-bg_offset] = mk.debug_data.roll_int();
                    accnick_line_pos_data[-bg_offset] = mk.debug_data.accnick();
                    accroll_line_pos_data[-bg_offset] = mk.debug_data.accroll();
                }
                catch (Exception e)
                    {
                        err+=e.toString();
                    }

               

               
                if (quit)
                    {


                       
                        try
                            {
                                RecordStore.deleteRecordStore(RECORD_STORE_NAME);
                                RecordStore recStore = RecordStore.openRecordStore(RECORD_STORE_NAME, true );
                                recStore.addRecord(mk.mk_url.getBytes(), 0, mk.mk_url.getBytes().length);
                                recStore.addRecord(mk.name.getBytes(), 0, mk.name.getBytes().length);
                                recStore.closeRecordStore();

                            }
                        catch (Exception e)
                            {
                                err+=e.toString();
                            }

                        root.quit();
                    }
                if (rescan)
                    {
                       
                        rescan=false;
                    }

                try {
                    //rescan=false;
                    bg_offset--;
                    if (bg_offset==-bg_img.getWidth())
                        bg_offset=0;
                    com.nokia.mid.ui.DeviceControl.setLights(0,100);
                    //bt.tick();
                    // every state has sth to do in tick section
                }
                catch (Exception e)
                    {
                       
                    }
             

                //                System.gc();
           

       
                       
                sleeptime=1000/ 15 - (int) (System.currentTimeMillis()- loopStartTime);
               
               
                if (sleeptime<0)
                    sleeptime=100; // everyone has fi sleep
               
                try { Thread.sleep(sleeptime); }
                catch (Exception e)
                    {
                        err="Problem Sleeping ";
                    }

            }
    }

     



    // drawing section
    public void paint(Graphics g) {
        y_off=0;
        try {
       
            if (mk!=null)
                {
                    line_middle_y=this.getHeight()/2;
                    if (local_max<Math.abs(mk.debug_data.nick_int()))
                        local_max=Math.abs(mk.debug_data.nick_int());
                    if (local_max<Math.abs(mk.debug_data.roll_int()))
                        local_max=Math.abs(mk.debug_data.roll_int());
                    if (local_max<Math.abs(mk.debug_data.accnick()))
                        local_max=Math.abs(mk.debug_data.accnick());
                    if (local_max<Math.abs(mk.debug_data.accroll()))
                        local_max=Math.abs(mk.debug_data.accroll());
                    line_scaler= local_max/(this.getHeight()/2)+1;
                }
            spacer=(g.getFont().getHeight());
            g.setColor(0xFFFFFF);
            g.fillRect(0,0,this.getWidth(),this.getHeight());
            g.drawImage(bg_img,bg_offset,0, g.TOP | g.LEFT);

            if (bg_offset+bg_img.getWidth()<this.getWidth())
                g.drawImage(bg_img,bg_offset+bg_img.getWidth(),0, g.TOP | g.LEFT);


            g.setColor(0x000000);

            switch(state)
                {
                case STATEID_MOTORTEST:
                    for (int bar=0;bar<4;bar++)
                        {
                            g.setColor(((bar==act_motor)|motor_test_sel_all)?0x44CC44:0x4444DD);  
                            g.fillRect(this.getWidth()/(8*2)+bar*2*this.getWidth()/8,10,this.getWidth()/8,20+motor_test[bar]);
                            g.setColor(0x000000);
                            g.drawString(""+motor_test[bar] ,this.getWidth()/8+bar*2*this.getWidth()/8,10,Graphics.TOP | Graphics.HCENTER);
                            if(bar!=4)                      g.drawString(""+mk.debug_data.motor_val(bar) ,this.getWidth()/8+bar*2*this.getWidth()/8,30,Graphics.TOP | Graphics.HCENTER);
                        }
                    break;

                case STATEID_EDIT_PARAMS:
                    params_editor.paint(g);
                    break;

                case STATEID_SCANNING:
                    paint_lcd(g,true);

                    g.setClip(this.getWidth()/2-load_img.getWidth()/6,this.getHeight()/2-load_img.getHeight()/8, load_img.getWidth()/4,load_img.getHeight()/3);;
                    g.drawImage(load_img,this.getWidth()/2-load_img.getWidth()/8 - ((((frame_pos/3)%12)%4)*(load_img.getWidth()/4)) ,this.getHeight()/2-load_img.getHeight()/6- ((((frame_pos/3)%12)/4)*(load_img.getHeight()/3)), g.TOP | g.LEFT);
                    g.drawImage(bt_img,this.getWidth()/2 ,this.getHeight()/2 , g.HCENTER | g.VCENTER);
                    break;
               
                case STATEID_MAINMENU: 
                    g.drawString("MK-Connection(" + (mk.connected?("open"+((System.currentTimeMillis()- mk.connection_start_time)/1000)+"s"):"close")+"):",0,y_off,Graphics.TOP | Graphics.LEFT);
                    y_off+=spacer;
                    g.drawString(" Name:" + mk.name,0,y_off,Graphics.TOP | Graphics.LEFT);
                    y_off+=spacer;
                    g.drawString(" URL:" + mk.mk_url,0,y_off,Graphics.TOP | Graphics.LEFT);
                    y_off+=spacer;
                    g.drawString(" Version:" + mk.version.str,0,y_off,Graphics.TOP | Graphics.LEFT);
                    y_off+=spacer;
                    g.drawString("Packet Traffic:",0,y_off,Graphics.TOP | Graphics.LEFT);
                    y_off+=spacer;
                    g.drawString( " debug:"+mk.debug_data_count+ " LCD:" + mk.lcd_data_count + " vers:" + mk.version_data_count,0,y_off,Graphics.TOP | Graphics.LEFT);
                    y_off+=spacer;
                    g.drawString( " other:"+mk.other_data_count+" params:"+mk.params_data_count,0,y_off,Graphics.TOP | Graphics.LEFT);




                    // falltru wanted
                case STATEID_SELECT_PARAMSET:
                case STATEID_HANDLE_PARAMS:
               
                case STATEID_DEVICESELECT:
                    paint_menu(g);
                    break;
                   
                case STATEID_FLIGHTVIEW:
                   
                    g.drawString(mk.version.str+"(d"+mk.debug_data_count+ "l" + mk.lcd_data_count+  "v" + mk.version_data_count+"o"+mk.other_data_count+"p"+mk.params_data_count+")",0,y_off,Graphics.TOP | Graphics.LEFT);

                    y_off+=spacer;

                    g.drawString("n:"+mk.debug_data.nick_int() + " r:"+mk.debug_data.roll_int() + " an:"+mk.debug_data.accnick() + " ar:"+mk.debug_data.accroll() ,0,y_off,Graphics.TOP | Graphics.LEFT);
                    y_off+=spacer;
                   
                   
                    g.drawString("m1:"+mk.debug_data.motor_val(0) + " m2:"+mk.debug_data.motor_val(1)+" m3:"+mk.debug_data.motor_val(2) + " m4:"+mk.debug_data.motor_val(3) ,0,y_off,Graphics.TOP | Graphics.LEFT);
                    y_off+=spacer;
                   
                    if (mk.connected)
                        {
                            g.drawString("time conn:" +((System.currentTimeMillis()- mk.connection_start_time)/1000)+"s" ,0,y_off,Graphics.TOP | Graphics.LEFT);
                            y_off+=spacer;
                            g.drawString("time motor>15:" +(mk_stat.motor_on_time/1000) +"s" ,0,y_off,Graphics.TOP | Graphics.LEFT);
                            y_off+=spacer;
                            g.drawString("time motor=15:" +(mk_stat.motor_stand_time/1000) +"s" ,0,y_off,Graphics.TOP | Graphics.LEFT);
                        }


                    y_off=this.getHeight()-4*lcd_img.getHeight();
                   
                    for ( int foo=0;foo<4;foo++)
                        {
                            for (int x=0;x<20;x++)
                                {
                                    g.setClip((lcd_img.getWidth()/222)*x,y_off,(lcd_img.getWidth()/222),lcd_img.getHeight());
                                            g.drawImage(lcd_img,(lcd_img.getWidth()/222)*x-(mk.LCD.LCD_str[foo].charAt(x)-' ')*(lcd_img.getWidth()/222),y_off, g.TOP | g.LEFT);

                                        }
                                    y_off+=lcd_img.getHeight();
                                }

                            g.setClip(0,0,this.getWidth(),this.getHeight());

               


               
                    // draw lines

                    for ( int x=0;x<this.getWidth();x++)

                        {

                            int p= (((-bg_offset+x-this.getWidth()-5)));
                            if (p<1)
                                p+=bg_img.getWidth();
                            p%=(bg_img.getWidth()-1);

                            g.setColor(0x156315);              
                            draw_graph_part(g,x,nick_line_pos_data[p]/line_scaler,nick_line_pos_data[p+1]/line_scaler);
                            g.setColor(0xCC1315);
                            draw_graph_part(g,x,roll_line_pos_data[p]/line_scaler,roll_line_pos_data[p+1]/line_scaler);
                            g.setColor(0xf8ef02);              
                            draw_graph_part(g,x,accnick_line_pos_data[p]/line_scaler,accnick_line_pos_data[p+1]/line_scaler);
                            g.setColor(0x19194d);
                            draw_graph_part(g,x,accroll_line_pos_data[p]/line_scaler,accroll_line_pos_data[p+1]/line_scaler);
               

           
                        }

                }

               

        } catch (Exception e) {}
    }

    private void connect_mk(String url,String name)
    {
        mk.connect_to(url,name);

    }

    public void draw_graph_part(Graphics g,int x,int y1,int y2)
    {
        g.fillRect(x,line_middle_y-y1,2,2 );
        if (y1>y2)
            g.fillRect(x,line_middle_y-y1,2,y1-y2);
        else
            g.fillRect(x,line_middle_y-y2,2,y2-y1);
    }

    /*********************************************** input Section **********************************************/


    public final String intro_str="   Digital Ufo Broadcasting with intelligent service equipment by Marcus -LiGi- Bueschleb ; Big Up Holger / Ingo for the MikroKopter Project (http://www.mikrokopter.de) ";

    int intro_str_pos=0;
    int intro_str_delay=3;

    public void chg_state(int next_state)
    {
        act_menu_select=0;
        // prepare next state
        switch(next_state)
            {
            case STATEID_SCANNING:
                lcd_lines=new String[4];
                lcd_lines[0]="Scanning for Devices";
                lcd_lines[1]="                    ";
                lcd_lines[2]="DUBwise v0.40       ";
                lcd_lines[3]=intro_str.substring(0,20);
                mk.close_connections(true);
               
                bt_scanner.search();
                break;

            case STATEID_HANDLE_PARAMS:
                menu_items=new String[2];
                menu_items[0]="write to MK";
                menu_items[1]="Discard";
                lcd_lines=new String[2];

                break;

            case STATEID_SELECT_PARAMSET:
                menu_items=new String[5];
                for (int i=0;i<5;i++)
                    menu_items[i]=mk.params.names[i];

                lcd_lines=new String[5];
                break;

            case STATEID_DEVICESELECT:
                menu_items=new String[bt_scanner.remote_device_count+1];
                for (int i=0;i<bt_scanner.remote_device_count;i++)
                    menu_items[i]=bt_scanner.remote_device_name[i];
                menu_items[bt_scanner.remote_device_count]="scan again";
                lcd_lines=new String[bt_scanner.remote_device_count+1];
                break;

            case STATEID_MAINMENU:
                menu_items=main_menu_items;
                lcd_lines=new String[menu_items.length];
                break;

            }
               
        // switch state
        state=next_state;
    }


    public void keyReleased(int keyCode)
    {
       
        switch(state)
            {
            case STATEID_MOTORTEST:
                act_motor_increase=0;
                break;
            }

    }

    public void keyPressed(int keyCode)
    {
       
        if (keyCode==KEY_STAR)
            {
                if (state==STATEID_EDIT_PARAMS)
                    chg_state(STATEID_HANDLE_PARAMS);
                else
                    chg_state(STATEID_MAINMENU);
                   
                return;
            }
        if (keyCode==KEY_POUND)
            {
                fullscreen=!fullscreen;
                setFullScreenMode(fullscreen);
                return;
            }
        switch(state)
            {
            case STATEID_MOTORTEST:
                switch (getGameAction (keyCode))
                            {
                            case UP:
                                act_motor_increase=-1;
                                break;
                       
                            case DOWN:
                                act_motor_increase=1;
                                break;

                            case FIRE:
                                motor_test_sel_all=!motor_test_sel_all;
                                break;

                            case LEFT:
                                act_motor--;
                                if (act_motor<0) {act_motor=0; chg_state(STATEID_MAINMENU); }
                                break;

                            case RIGHT:
                                act_motor++;
                                act_motor%=4;
                                break;
                            }

                break;
            case STATEID_HANDLE_PARAMS:
                if ( getGameAction (keyCode)==FIRE )
                    switch(act_menu_select)
                        {
                        case 0:
                            mk.write_params();
                        default:
                            chg_state(STATEID_MAINMENU);
                        }
                else
                    menu_keypress(keyCode);
                break;
            case STATEID_MAINMENU:
                if ( getGameAction (keyCode)==FIRE )
                    switch(act_menu_select)
                        {

                        case MAINMENU_TELEMETRY :
                            chg_state(STATEID_FLIGHTVIEW);
                            break;

                        case  MAINMENU_MOTORTES :
                            chg_state(STATEID_MOTORTEST);
                            break;

                        case MAINMENU_PARAMS :
                            chg_state(STATEID_SELECT_PARAMSET);
                            break;
                        case MAINMENU_SETTINGS:
                            break;
                        case MAINMENU_PROXY:
                            mk.do_proxy("socket://192.168.1.42:2323");
                            break;

                        case MAINMENU_DEVICESELECT:
                            chg_state(STATEID_SCANNING);
                            break;

                        case  MAINMENU_QUIT:
                            quit=true;
                            break;
                           
                        }
                else menu_keypress(keyCode);
                break;

            case STATEID_SELECT_PARAMSET:
                if ( getGameAction (keyCode)==FIRE )
                    {              
                        mk.params.act_paramset=act_menu_select;
                        chg_state(STATEID_EDIT_PARAMS);
                    }
                else menu_keypress(keyCode);
                break;
            case STATEID_DEVICESELECT:
                /*
                if ((keyCode >= this.KEY_NUM0) && (keyCode < this.KEY_NUM0+bt_scanner.remote_device_count))
                    {
                    connect_mk("btspp://"+bt_scanner.remote_device_mac[keyCode-this.KEY_NUM0] + ":1",bt_scanner.remote_device_name[keyCode-this.KEY_NUM0]);
                    chg_state(STATEID_MAINMENU);
                    }
                else
                */


                if ( getGameAction (keyCode)==FIRE )
                    {              

                        if (bt_scanner.remote_device_count > act_menu_select)
                            {
                                connect_mk("btspp://"+bt_scanner.remote_device_mac[act_menu_select] + ":1",bt_scanner.remote_device_name[act_menu_select]);
                                chg_state(STATEID_MAINMENU);
                            }
                        else
                            chg_state(STATEID_SCANNING);
                    }
                else menu_keypress(keyCode);
               
                break;

            case STATEID_EDIT_PARAMS:
                params_editor.keypress(keyCode,getGameAction (keyCode)) ;
                break;

            case STATEID_FLIGHTVIEW:

                switch (getGameAction (keyCode))
                    {
                    case UP:
                        mk.LCD.LCD_PREVPAGE();
                        break;
                       
                    case DOWN:
                        mk.LCD.LCD_NEXTPAGE();
                        break;

                    case LEFT:
                        chg_state(STATEID_MAINMENU);
                        break;
                       
                    }
                break;
            }
   
       

    }

 






}