コード例 #1
0
ファイル: LaosMenu.cpp プロジェクト: blinkingnoise/Firmware
/**
*** Handle menu system
*** Read keys, and plan next action on the screen, output screen if 
*** something changed
**/
void LaosMenu::Handle() {
    int xt, yt, zt, nodisplay = 0;
    extern LaosFileSystem sd;
    extern LaosMotion *mot;
    extern GlobalConfig *cfg;
    static int count=0;
    
    int c = dsp->read();
    if ( count++ > 10) count = 0; // screen refresh counter (refresh once every 10 cycles(
    
    if ( c ) timeout = 10;  // keypress timeout counter
    else if ( timeout ) timeout--;
    
    if ( screen != prevscreen ) waitup = 1; // after a screen change: wait for a key release, mask current keypress
    if ( waitup && timeout) // if we have to wait for key-up, 
        c = 0;                 // cancel the keypress
    if ( waitup && !timeout ) waitup=0;
    
    if ( !timeout )  // increase speed if we keep button pressed longer
        speed = 3;
    else {
        speed = speed * 2;
        if ( speed >= 100 ) speed = 100;
    }

    if ( c || screen != prevscreen || count >9 ) {

        switch ( screen ) {
            case STARTUP:
                if ( sarg == NULL ) sarg = (char*) VERSION_STRING;
                break;
            case MAIN:
                switch ( c ) {
                    case K_RIGHT: menu+=1; waitup=1; break;
                    case K_LEFT: menu-=1; waitup=1; break;
                    case K_UP: lastscreen=MAIN; screen=MOVE; menu=MAIN; break;
                    case K_DOWN: lastscreen=MAIN; screen=MOVE; menu=MAIN; break;
                    case K_OK: screen=menu; waitup=1; lastscreen=MAIN; break;
                    case K_CANCEL: menu=MAIN; break;
                    case K_FUP: lastscreen=MAIN; screen=FOCUS; menu=MAIN; break;
                    case K_FDOWN: lastscreen=MAIN; screen=FOCUS; menu=MAIN; break;
                    case K_ORIGIN: lastscreen=MAIN; screen=ORIGIN; waitup=1; break;
                }
                if (menu==0) menu = (sizeof(menus) / sizeof(menus[0])) -1;
                if (menu==(sizeof(menus) / sizeof(menus[0]))) menu = 1;
                sarg = (char*)menus[menu];
                args[0] = menu;
                break;
                
            case RUN: // START JOB select job to run
                if (strlen(jobname) == 0) getprevjob(jobname); 
                switch ( c ) {
                    case K_OK: screen=RUNNING; break;
                    case K_UP: case K_FUP: getprevjob(jobname); waitup = 1; break; // next job
                    case K_RIGHT: screen=DELETE; waitup=1; break;
                    case K_DOWN: case K_FDOWN: getnextjob(jobname); waitup = 1; break;// prev job
                    case K_CANCEL: screen=1; waitup = 1; break;
                }
                sarg = (char *)&jobname;
                break;

            case DELETE: // DELETE JOB select job to run
                switch ( c ) {
                    case K_OK: removefile(jobname); screen=lastscreen; waitup = 1;
                        break; // INSERT: delete current job
                    case K_UP: case K_FUP: getprevjob(jobname); waitup = 1; break; // next job
                    case K_DOWN: case K_FDOWN: getnextjob(jobname); waitup = 1; break;// prev job
                    case K_LEFT: screen=RUN; waitup=1; break;
                    case K_CANCEL: screen=lastscreen; waitup = 1; break;
                }
                sarg = (char *)&jobname;
                break;
                
            case MOVE: // pos xy
                mot->getPosition(&x, &y, &z);
                xt = x; yt= y;
                switch ( c ) {
                    case K_DOWN: 
                        // swap movement if y.home == y.max
                        if( cfg->yhome == cfg->ymax )
                            y-=100*speed;
                         else   
                            y+=100*speed; 
                        break;
                    case K_UP:
                        // swap movement if y.home == y.max
                        if( cfg->yhome == cfg->ymax )
                            y+=100*speed;     
                        else    
                            y-=100*speed;  
                        break;
                    case K_LEFT:
                        // swap movement if x.home == x.max
                        if( cfg->xhome == cfg->xmax )
                            x+=100*speed; 
                        else
                            x-=100*speed;
                        break;
                    case K_RIGHT:
                        // swap movement if x.home == x.max
                        if( cfg->xhome == cfg->xmax )
                            x-=100*speed; 
                        else
                            x+=100*speed;
                        break;
                    case K_OK: case K_CANCEL: screen=MAIN; waitup=1; break;
                    case K_FUP: screen=FOCUS; break; 
                    case K_FDOWN: screen=FOCUS; break;
                    case K_ORIGIN: screen=ORIGIN; break;
                }


                // limits
                if( x >= cfg->xmax )
                    x = cfg->xmax;
                if( x <= 0 )
                    x = 0;

                if( y >= cfg->ymax )
                    y = cfg->ymax;
                if( y <= 0 )
                    y = 0;

                if  ((mot->queue() < 5) && ( (x!=xt) || (y != yt) )) {
                    mot->moveTo(x, y, z, speed/2);
                    printf("Move: %d %d %d %d\n", x,y,z, speed);
                } else {
                    // if (! mot->ready()) 
                    // printf("Buffer vol\n");
                }
                args[0]=x-xoff;
                args[1]=y-yoff;
                break;

            case FOCUS: // focus
                mot->getPosition(&x, &y, &z);
        zt = z;
                switch ( c ) {
                    case K_FUP: z+=cfg->zspeed*speed; if (z>cfg->zmax) z=cfg->zmax; break;
                    case K_FDOWN: z-=cfg->zspeed*speed; if (z<0) z=0; break;
                    case K_LEFT: break;
                    case K_RIGHT: break;
                    case K_UP: z+=cfg->zspeed*speed; if (z>cfg->zmax) z=cfg->zmax; break;
                    case K_DOWN: z-=cfg->zspeed*speed; if (z<0) z=0; break;
                    case K_ORIGIN: screen=ORIGIN; break;
                    case K_OK: case K_CANCEL: screen=MAIN; waitup=1; break;
                    case 0: break;
                    default: screen=MAIN; waitup=1; break;
                }
                if ( mot->ready() && (z!=zt) ) 
                {
                  mot->moveTo(x, y, z, speed);
                  printf("Move: %d %d %d %d\n", x,y,z, speed);
                }
                args[0]=z-zoff;
                break;

            case HOME:// home
                switch ( c ) {
                    case K_OK: screen=HOMING; break;
                    case K_CANCEL: screen=MAIN; menu=MAIN; waitup=1; break;
                }
                break;

            case ORIGIN: // origin
                switch ( c ) {
                    case K_CANCEL: screen=MAIN; menu=MAIN; waitup=1; break;
                    case K_OK:
                    case K_ORIGIN:
                        xoff = x;
                        yoff = y; 
                        zoff = z; 
                        mot->setOrigin(x,y,z);
                        screen = lastscreen;
                        waitup = 1;
                        break;
                }
                break;

            case DELETE_ALL: // Delete all files
                switch ( c ) {
                    case K_OK: // delete current job
                        cleandir(); 
                        screen=MAIN; 
                        waitup = 1; 
                        strcpy(jobname, "");
                        break; 
                    case K_CANCEL: screen=MAIN; waitup = 1; break;
                }
                break;

            case IP: // IP
                int myip[4], mynm[4], mygw[4], mydns[4];
                IpParse(cfg->ip, myip);
                IpParse(cfg->nm, mynm);
                IpParse(cfg->gw, mygw);
                IpParse(cfg->dns, mydns);
                switch ( c ) {
                    case K_RIGHT: ipfield++; waitup=1; break;
                    case K_LEFT: ipfield--; waitup=1; break;
                    case K_OK: screen=MAIN; menu=MAIN; break; 
                    case K_CANCEL: screen=MAIN; menu=MAIN; break; 
                }
                ipfield %= 4;
                sarg = (char*)ipfields[ipfield];
                switch (ipfield) {
                    case 0: memcpy(args, myip, 4*sizeof(int) ); break;
                    case 1: memcpy(args, mynm, 4*sizeof(int) ); break;
                    case 2: memcpy(args, mygw, 4*sizeof(int) ); break;
                    case 3: memcpy(args, mydns, 4*sizeof(int) ); break;
                    default: memset(args, 0, 4*sizeof(int)); break;
                }
                break;

            case REBOOT: // RESET MACHINE
                mbed_reset();
                break;

/*
            case IO: // IO
                switch ( c ) {
                    case K_RIGHT: iofield++; waitup=1; break;
                    case K_LEFT: iofield--; waitup=1; break;
                    case K_OK: screen=lastscreen; break; 
                    case K_CANCEL: screen=lastscreen; break;
                }
                iofield %= sizeof(iofields)/sizeof(char*);
                sarg = (char*)iofields[iofield];
                args[0] = ipfield;
                args[1] = ipfield;
                break;

            case POWER: // POWER
                switch ( c ) {
                    case K_RIGHT: powerfield++; waitup=1; break;
                    case K_LEFT: powerfield--; waitup=1; break;
                    case K_UP: power[powerfield % 4] += speed; break; 
                    case K_DOWN: power[powerfield % 4] -= speed; break;
                    case K_OK: screen=lastscreen; break;
                    case K_CANCEL: screen=lastscreen; break;
                }
                powerfield %= 4;
                args[1] = powerfield;
                sarg = (char*)powerfields[powerfield];
                args[0] = power[powerfield];
                break;
*/
            case HOMING: // Homing screen
                x = cfg->xhome;
                y = cfg->yhome;
                while ( !mot->isStart() );
                mot->home(cfg->xhome,cfg->yhome,cfg->zhome);
                screen=lastscreen;
                break;

            case RUNNING: // Screen while running
                switch ( c ) {
                    /* case K_CANCEL:
                        while (mot->queue());
                        mot->reset();
                        if (runfile != NULL) fclose(runfile);
                        runfile=NULL; screen=MAIN; menu=MAIN;
                        break; */
                    default:
                        if (runfile == NULL) {
                            runfile = sd.openfile(jobname, "rb");
                            if (! runfile) 
                              screen=MAIN;
                            else
                               mot->reset();
                        } else {
                        		#ifdef READ_FILE_DEBUG
                        			printf("Parsing file: \n");
                        		#endif
                            while ((!feof(runfile)) && mot->ready()) {
                                mot->write(readint(runfile));
                                if(dsp->read_nb() == K_CANCEL) {
                                   while (mot->queue());
                                   mot->reset();
                                   fseek(runfile, 0, SEEK_END);
                                }
                            }
                            #ifdef READ_FILE_DEBUG
                                    printf("File parsed \n");
                                #endif
                            if (feof(runfile) && mot->ready()) {
                                fclose(runfile);
                                runfile = NULL;
                                mot->moveTo(cfg->xrest, cfg->yrest, cfg->zrest);
                                screen=MAIN;
                            } else {
                                nodisplay = 1;
                            }
                        }
                }
                break;

            default:
                screen = MAIN;
                break;
        }
        if (nodisplay == 0) {
            dsp->ShowScreen(screens[screen], args, sarg);
        }
         prevscreen = screen;
    }

}
コード例 #2
0
ファイル: global.cpp プロジェクト: hschoel/Firmware
/**
*** Global config
*** Config settings into global Config struct
**/
GlobalConfig::GlobalConfig(char *filename)
{
    char val[32];
    printf("\r\nOpen config file: '%s'\r\n", filename);
    ConfigFile cfg(filename);
    if ( !cfg.IsOpen() )
    {
        printf("File does not exists. Using defaults\n");
    }

    // IP settings
    cfg.Value("net.ip", val, sizeof(val), "192.168.0.111");
    IpParse(val, ip);
    cfg.Value("net.mask", val, sizeof(val), "255.255.255.0");
    IpParse(val, nm);
    cfg.Value("net.gateway", val, sizeof(val), "192.168.0.1");
    IpParse(val, gw);
    cfg.Value("net.dns", val, sizeof(val), "192.168.0.1");
    IpParse(val, dns);
    cfg.Value("net.port", &port, 69);
    cfg.Value("net.dhcp", &dhcp, 0);

    // features
    cfg.Value("sys.autohome", &autohome, 0);
    cfg.Value("sys.autozhome", &autozhome, 0);
    cfg.Value("sys.nodisplay", &nodisplay, 1);
    cfg.Value("sys.i2cbaud", &i2cbaud, 9600);
    cfg.Value("sys.cleandir", &cleandir, 1);

    // Laser
    cfg.Value("laser.enable", &lenable, 1); // laser enable polarity [0/1]
    cfg.Value("laser.on", &lon, 1);         // laser on polarity [0/1]
    cfg.Value("laser.pwm.min", &pwmmin, 0); // pwm at minimum power [0..100]
    cfg.Value("laser.pwm.max", &pwmmax, 0); // pwm at maximum power [0..100]
    cfg.Value("laser.pwm.freq", &pwmfreq, 20000); // pwm frequency [Hz]

    // rest position (after homing)
    cfg.Value("x.rest", &xrest, 0);
    cfg.Value("y.rest", &yrest, 0);
    cfg.Value("z.rest", &zrest, 0);
    cfg.Value("e.rest", &erest, 0);
// (homing) direction
    cfg.Value("x.homedir", &xhomedir, 0);
    cfg.Value("y.homedir", &yhomedir, 0);
    cfg.Value("z.homedir", &zhomedir, 0);
    cfg.Value("e.homedir", &ehomedir, 0);

    cfg.Value("x.invert", &xinv, 0);
    cfg.Value("y.invert", &yinv, 0);
    cfg.Value("z.invert", &zinv, 0);
    cfg.Value("e.invert", &einv, 0);


    // (homing)sensor polarity
    cfg.Value("x.pol", &xpol, 0);
    cfg.Value("y.pol", &ypol, 0);
    cfg.Value("z.pol", &zpol, 0);
    cfg.Value("e.pol", &epol, 0);

    // Scaling [steps/meter]
    cfg.Value("x.scale", &xscale, 200000);
    cfg.Value("y.scale", &yscale, 200000);
    cfg.Value("z.scale", &zscale, 200000);
    cfg.Value("e.scale", &escale, 200000);

    // max axis speed [mm/sec]
    cfg.Value("x.speed", &xspeed, 100);
    cfg.Value("y.speed", &yspeed, 100);
    cfg.Value("z.speed", &zspeed, 100);
    cfg.Value("e.speed", &espeed, 100);

    // max axis acceleration [mm/sec2]
    cfg.Value("x.accel", &xaccel, 2000);
    cfg.Value("y.accel", &yaccel, 2000);
    cfg.Value("z.accel", &zaccel, 2000);
    cfg.Value("e.accel", &eaccel, 2000);

    // max axis speed [mm/sec]
    // home positions [um]
    cfg.Value("x.home", &xhome, 0);
    cfg.Value("y.home", &yhome, 0);
    cfg.Value("z.home", &zhome, 100000);
    cfg.Value("e.home", &ehome, 0);

    // min and max [um]
    cfg.Value("x.max", &xmax, 1E6);
    cfg.Value("y.max", &ymax, 1E6);
    cfg.Value("z.max", &zmax, 200000);
    cfg.Value("e.max", &emax, 1E6);
    cfg.Value("x.min", &xmin, 0);
    cfg.Value("y.min", &ymin, 0);
    cfg.Value("z.min", &zmin, 0);
    cfg.Value("e.min", &emin, 0);

    // motion settings: enable output state
    cfg.Value("motion.homespeed", &homespeed, 10); // speed during homing [mm/sec]
    cfg.Value("motion.zhomespeed", &zhomespeed, 10); // z-axis speed during homing [mm/sec]
    cfg.Value("motion.speed", &speed, 100);   // max speed [mm/sec]
    cfg.Value("motion.accel", &accel, 100); // accelleration [mm/sec2]
    cfg.Value("motion.enable", &enable, 0); // enable output polarity [0/1]
    cfg.Value("motion.tolerance", &tolerance, 50); // cornering tolerance [1/1000 units]
}
コード例 #3
0
ファイル: LaosMenu.cpp プロジェクト: LaosLaser/Firmware
/**
*** Handle menu system
*** Read keys, and plan next action on the screen, output screen if 
*** something changed
**/
void LaosMenu::Handle() {
//    int xt, yt, zt, 
    int nodisplay = 0;
    extern LaosFileSystem sd;
    extern LaosMotion *mot;
    extern GlobalConfig *cfg;
    static int count=0;
    
    int c = dsp->read();
    if ( count++ > 10) count = 0; // screen refresh counter (refresh once every 10 cycles(
    
    if ( c ) timeout = 10;  // keypress timeout counter
    else if ( timeout ) timeout--;
    
    if ( screen != prevscreen ) waitup = 1; // after a screen change: wait for a key release, mask current keypress
    if ( waitup && timeout) // if we have to wait for key-up, 
        c = 0;                 // cancel the keypress
    if ( waitup && !timeout ) waitup=0;
    
    if ( !timeout )
    {
        // keyboard timeout (i.e. all keys are released):
        // reset jog/focus speed:
        speed = 3;
    }

    if( (c != 0) || (timeout == 0))
    {
        if(m_PrevKey != c)
        {
            // and when starting a new move, wait till the previous movements are completely finished.
            // This is needed, otherwise back-and-forth moves could result in a far move being
            // done at a low speed, which would take a long time to finish:
            m_MoveWaitTillQueueEmpty = true;        
        }
        m_PrevKey = c;
    }

    if ( c || screen != prevscreen || count >9 ) {

        switch ( screen ) {
            case STARTUP:
                if ( sarg == NULL ) sarg = (char*) VERSION_STRING;
                break;
            case MAIN:
                switch ( c ) {
                    case K_RIGHT: menu+=1; waitup=1; break;
                    case K_LEFT: menu-=1; waitup=1; break;
                    case K_UP: lastscreen=MAIN; screen=MOVE; menu=MAIN; break;
                    case K_DOWN: lastscreen=MAIN; screen=MOVE; menu=MAIN; break;
                    case K_OK: screen=menu; waitup=1; lastscreen=MAIN; break;
                    case K_CANCEL: menu=MAIN; break;
                    case K_FUP: lastscreen=MAIN; screen=FOCUS; menu=MAIN; break;
                    case K_FDOWN: lastscreen=MAIN; screen=FOCUS; menu=MAIN; break;
                    case K_ORIGIN: lastscreen=MAIN; screen=ORIGIN; waitup=1; break;
                }
                if (menu==0) menu = (sizeof(menus) / sizeof(menus[0])) -1;
                if (menu==(sizeof(menus) / sizeof(menus[0]))) menu = 1;
                sarg = (char*)menus[menu];
                args[0] = menu;
                break;
                
            case RUN: // START JOB select job to run
                if (strlen(jobname) == 0) getprevjob(jobname); 
                switch ( c ) {
                    case K_OK: screen = ANALYZING; m_StageAfterAnalyzing = RUNNING; break;
                    case K_UP: case K_FUP: getprevjob(jobname); waitup = 1; break; // next job
                    case K_RIGHT: screen=BOUNDARIES; waitup=1; break;
                    case K_DOWN: case K_FDOWN: getnextjob(jobname); waitup = 1; break;// prev job
                    case K_CANCEL: screen=1; waitup = 1; break;
                }
                sarg = (char *)&jobname;
                break;

            case DELETE: // DELETE JOB select job to run
                switch ( c ) {
                    case K_OK: removefile(jobname); screen=lastscreen; waitup = 1;
                        break; // INSERT: delete current job
                    case K_UP: case K_FUP: getprevjob(jobname); waitup = 1; break; // next job
                    case K_DOWN: case K_FDOWN: getnextjob(jobname); waitup = 1; break;// prev job
                    case K_LEFT: screen=BOUNDARIES; waitup=1; break;
                    case K_CANCEL: screen=lastscreen; waitup = 1; break;
                }
                sarg = (char *)&jobname;
                break;
                
            case MOVE: // pos xy
                {
                    int x,y,z;
                    int numinqueue=mot->queue();
                    mot->getCurrentPositionRelativeToOrigin(&x, &y, &z);
                    int xt = x;
                    int yt= y;
                    switch ( c ) {
                        case K_DOWN: y-=100*speed; break;
                        case K_UP: y+=100*speed;  break;
                        case K_LEFT: x-=100*speed; break;
                        case K_RIGHT: x+=100*speed;  break;
                        case K_OK: case K_CANCEL: screen=MAIN; waitup=1; break;
//                        case K_FUP: screen=FOCUS; break; 
                        case K_FUP:
                            // use the Focus Up button to display debugging data for the stepper interrupt:
                            st_debug();
                            screen=FOCUS; 
                            break;
                        case K_FDOWN: screen=FOCUS; break;
                        case K_ORIGIN: screen=ORIGIN; break;
                    }
                    printf("Move: c: %d, numinqueue: %d, xt: %d, yt: %d,  waitempty: %d\n", 
                        c, numinqueue, xt, yt, m_MoveWaitTillQueueEmpty? 1:0);
                    int maxinqueue=m_MoveWaitTillQueueEmpty? 1:5;

                    /* 
                       Currently (Jan 2015) an old version of grbl is used in Laos. This version is buggy
                       in the sense that there is no proper synchronization between the stepper interrupt and the
                       main thread. When adding a new move to the queue through plan_buffer_line(), planner_recalculate()
                       is called. This updates the acceleration profile of existing moves in the queue,
                       potentially including the move which is currently being executed by the stepper interrupt.
                       Due to the lack of synchronization this will lead to problems, including potential crashes or
                       hanging. This problem in particular manifests itself during jogging, because the queue is nearly
                       emtpy and there's a big chance the frontmost item in the stepper queue will be updated.
                       During regular laser cutting the problem is less likely to occur since the queue will continuously
                       be kept nearly full. Recalculation will only affect some of the last moves in the queue.

                       The real fix for this bug would be to update grbl to the latest version, this seems to include
                       proper synchronization. For now we work around the problem by wating for the queue to empty
                       before adding new jog moves. This results in sloppy jogging (continuous stops & moves) but at
                       least it doesn't crash the machine.
                       -joostn
                    */

                    // always wait till queue is emptied:
                    // just remove this line if grbl ever gets updated:
                    maxinqueue=1;

                    if  ((numinqueue < maxinqueue) && ( (x!=xt) || (y != yt) )) {
                        m_MoveWaitTillQueueEmpty=false;
                        mot->moveToRelativeToOrigin(x, y, z, speed);
                        printf("Move: %d %d %d %d\n", x,y,z, speed);
                        speed=speed*3;
                        if(speed > 100) speed=100;
                    } else {
                        // if (! mot->ready()) 
                        // printf("Buffer vol\n");
                    }
                    args[0]=x;
                    args[1]=y;
                }
                break;

            case FOCUS: // focus
                {

                    int x,y,z;
                    mot->getCurrentPositionRelativeToOrigin(&x, &y, &z);
                    int zt = z;
                    switch ( c ) {
                        case K_FUP: z+=cfg->zspeed*speed; if (z>cfg->zmax) z=cfg->zmax; break;
                        case K_FDOWN: z-=cfg->zspeed*speed; if (z<0) z=0; break;
                        case K_LEFT: break;
                        case K_RIGHT: break;
                        case K_UP: z+=cfg->zspeed*speed; if (z>cfg->zmax) z=cfg->zmax; break;
                        case K_DOWN: z-=cfg->zspeed*speed; if (z<0) z=0; break;
                        case K_ORIGIN: screen=ORIGIN; break;
                        case K_OK: case K_CANCEL: screen=MAIN; waitup=1; break;
                        case 0: break;
                        default: screen=MAIN; waitup=1; break;
                    }
                    int numinqueue=mot->queue();
                    if ( mot->ready() && (z!=zt) && (numinqueue == 0) ) 
                    {
                      mot->moveToRelativeToOrigin(x, y, z, speed);
                      printf("Focus: %d %d %d %d\n", x,y,z, speed);
                        speed=speed*3;
                        if(speed > 100) speed=100;
                    }
                    args[0]=z;
                }
                break;

            case HOME:// home
                switch ( c ) {
                    case K_OK: screen=HOMING; break;
                    case K_CANCEL: screen=MAIN; menu=MAIN; waitup=1; break;
                }
                break;

            case ERROR:
                switch ( c ) {
                    case K_OK:
                    case K_CANCEL: 
                        screen=MAIN;
                        waitup=1; 
                        break;
                }
                break;

            case ORIGIN: // origin
                switch ( c ) {
                    case K_CANCEL: screen=MAIN; menu=MAIN; waitup=1; break;
                    case K_OK:
                    case K_ORIGIN:
                        if(cfg->BedHeight() == 0)
                        {
                            screen=ERROR;
                            sarg=(char*)"bedheight unknwn";
                        }
                        else
                        {
                            mot->MakeCurrentPositionOrigin();
                            screen = lastscreen;
                        }
                        waitup = 1;
                        break;
                }
                break;

            case DELETE_ALL: // Delete all files
                switch ( c ) {
                    case K_OK: // delete current job
                        cleandir(); 
                        screen=MAIN; 
                        waitup = 1; 
                        strcpy(jobname, "");
                        break; 
                    case K_CANCEL: screen=MAIN; waitup = 1; break;
                }
                break;

            case IP: // IP
                int myip[4], mynm[4], mygw[4], mydns[4];
                IpParse(cfg->ip, myip);
                IpParse(cfg->nm, mynm);
                IpParse(cfg->gw, mygw);
                IpParse(cfg->dns, mydns);
                switch ( c ) {
                    case K_RIGHT: ipfield++; waitup=1; break;
                    case K_LEFT: ipfield--; waitup=1; break;
                    case K_OK: screen=MAIN; menu=MAIN; break; 
                    case K_CANCEL: screen=MAIN; menu=MAIN; break; 
                }
                ipfield %= 4;
                sarg = (char*)ipfields[ipfield];
                switch (ipfield) {
                    case 0: memcpy(args, myip, 4*sizeof(int) ); break;
                    case 1: memcpy(args, mynm, 4*sizeof(int) ); break;
                    case 2: memcpy(args, mygw, 4*sizeof(int) ); break;
                    case 3: memcpy(args, mydns, 4*sizeof(int) ); break;
                    default: memset(args, 0, 4*sizeof(int)); break;
                }
                break;

            case REBOOT: // RESET MACHINE
                mbed_reset();
                break;

/*
            case IO: // IO
                switch ( c ) {
                    case K_RIGHT: iofield++; waitup=1; break;
                    case K_LEFT: iofield--; waitup=1; break;
                    case K_OK: screen=lastscreen; break; 
                    case K_CANCEL: screen=lastscreen; break;
                }
                iofield %= sizeof(iofields)/sizeof(char*);
                sarg = (char*)iofields[iofield];
                args[0] = ipfield;
                args[1] = ipfield;
                break;

            case POWER: // POWER
                switch ( c ) {
                    case K_RIGHT: powerfield++; waitup=1; break;
                    case K_LEFT: powerfield--; waitup=1; break;
                    case K_UP: power[powerfield % 4] += speed; break; 
                    case K_DOWN: power[powerfield % 4] -= speed; break;
                    case K_OK: screen=lastscreen; break;
                    case K_CANCEL: screen=lastscreen; break;
                }
                powerfield %= 4;
                args[1] = powerfield;
                sarg = (char*)powerfields[powerfield];
                args[0] = power[powerfield];
                break;
*/
            case HOMING: // Homing screen
                while ( !mot->isStart() );
                mot->home(cfg->xhome,cfg->yhome,cfg->zhome);
                screen=lastscreen;
                break;

            case RUNNING: // Screen while running
                switch ( c ) {
                    /* case K_CANCEL:
                        while (mot->queue());
                        mot->reset();
                        if (runfile != NULL) fclose(runfile);
                        runfile=NULL; screen=MAIN; menu=MAIN;
                        break; */
                    default:
                        if (runfile == NULL) {
                            runfile = sd.openfile(jobname, "rb");
                            if (! runfile) 
                              screen=MAIN;
                            else
                               mot->reset();
                        } else {
                                #ifdef READ_FILE_DEBUG
                                    printf("Parsing file: \n");
                                #endif
                            while ((!feof(runfile)) && mot->ready()) {
                                mot->write(readint(runfile));
                                if(cfg->disablecancelcheck == false)
                                {
                                    if(dsp->read_nb() == K_CANCEL) {
                                       while (mot->queue());
                                       mot->reset();
                                       fseek(runfile, 0, SEEK_END);
                                    }
                                }
                            }
                            #ifdef READ_FILE_DEBUG
                                    printf("File parsed \n");
                                #endif
                            if (feof(runfile) && mot->ready()) {
                                fclose(runfile);
                                runfile = NULL;
                                mot->moveToAbsolute(cfg->xrest, cfg->yrest, cfg->zrest);
                                screen=MAIN;
                            } else {
                                nodisplay = 1;
                            }
                        }
                }
                break;
                
            case BOUNDARIES:
                if (strlen(jobname) == 0) getprevjob(jobname); 
                switch ( c ) {
                    case K_OK: 
                        screen = ANALYZING; m_StageAfterAnalyzing = CALCULATEDBOUNDARIES; break;
                    case K_UP: case K_FUP: getprevjob(jobname); waitup = 1; break; // next job
                    case K_DOWN: case K_FDOWN: getnextjob(jobname); waitup = 1; break;// prev job
                    case K_LEFT: screen=RUN; waitup=1; break;
                    case K_RIGHT: screen=DELETE; waitup=1; break;
                    case K_CANCEL: screen=lastscreen; waitup = 1; break;
                }
                sarg = (char *)&jobname;
                break;

            case ANALYZING: // determine the boundaries of the file. This is done prior to running, and when executing the BOUNDAIES function
                // m_StageAfterAnalyzing is set to the menu stage that will be executed after this (RUNNING or CALCULATEDBOUNDARIES)
                runfile = sd.openfile(jobname, "rb");
                if (! runfile)
                {
                    screen=MAIN;
                }
                else
                {
                    // when running we need the bounds including all moves
                    // when executing BOUNDARIES we only need the actual lasered area
                    bool boundsOnlyWithLaserOn = (m_StageAfterAnalyzing == CALCULATEDBOUNDARIES);
                    m_Extent.Reset(boundsOnlyWithLaserOn);
                    while (!feof(runfile))
                    {
                        m_Extent.Write(readint(runfile));
                    }
                    fclose(runfile);
                    runfile = NULL;
                    int fileMinx, fileMiny, fileMaxx, fileMaxy;
                    LaosExtent::TError err=m_Extent.GetBoundary(fileMinx, fileMiny, fileMaxx, fileMaxy);
                    bool outOfBounds=false;
                    if(!err)
                    {
                        int minx, miny, minz, maxx, maxy, maxz;
                        mot->getLimitsRelative(&minx, &miny, &minz, &maxx, &maxy, &maxz);
                        if( (fileMinx < minx) || (fileMiny < miny) || 
                            (fileMaxx > maxx) || (fileMaxy > maxy) )
                        {
                            outOfBounds = true;
                        }
                    }
                    if(outOfBounds)
                    {
                        screen=ERROR;
                        sarg=(char*)"Limit overrun";
                        waitup=1;                        
                    }
                    else
                    {
                        if(m_StageAfterAnalyzing == CALCULATEDBOUNDARIES)
                        {
                            args[0]=(fileMinx+500)/1000;
                            args[1]=(fileMiny+500)/1000;
                            args[2]=((fileMaxx-fileMinx)+500)/1000;
                            args[3]=((fileMaxy-fileMiny)+500)/1000;
                            screen=CALCULATEDBOUNDARIES;
                            m_SubStage=0;
                        }
                        else if(m_StageAfterAnalyzing == RUNNING)
                        {
                            screen=RUNNING;
                        }
                        else
                        {
                            screen = MAIN;
                        }
                        waitup=1;
                    }
                }
                break;

            case CALCULATEDBOUNDARIES: // Screen after calculating the boundaries of a file
                if(m_SubStage == 0)
                {
                    m_Extent.ShowBoundaries(mot);
                    m_SubStage++;
                }
                else
                {
                    switch ( c ) {
                        case K_OK:
                        case K_CANCEL:
                         screen=MAIN;
                         break;
                    }
                    break;
                }
                break;

            case LASERTEST: 
                enable = !cfg->enable;
                switch ( c ) {
                    case K_OK: 
                        waitup = 1;
                        if(m_LaserTestTime > 0)
                        {
                            double p = (double)(cfg->pwmmin/100.0 + ((m_LaserTestPower/100.0)*((cfg->pwmmax - cfg->pwmmin)/100.0)));
                            pwm = p;
                            *laser = LASERON;
                            wait_ms(m_LaserTestTime);
                            *laser = LASEROFF;
                            pwm = cfg->pwmmax / 100.0;  // set pwm to max;
                        }
                        break; 
                    case K_UP: case K_FUP:
                        if(m_LaserTestPower <= 3)
                        {
                            m_LaserTestPower++;
                        }
                        else
                        {
                            m_LaserTestPower += (m_LaserTestPower>>1);
                            if(m_LaserTestPower > 100) m_LaserTestPower=100;
                        }
                        break;
                    case K_DOWN: case K_FDOWN: 
                        if(m_LaserTestPower <= 4)
                        {
                            m_LaserTestPower--;
                            if(m_LaserTestPower < 0) m_LaserTestPower=0;
                        }
                        else
                        {
                            m_LaserTestPower -= (m_LaserTestPower>>2);
                        }
                        break;
                    case K_RIGHT:
                        if(m_LaserTestTime <= 3)
                        {
                            m_LaserTestTime++;
                        }
                        else
                        {
                            m_LaserTestTime += (m_LaserTestTime>>1);
                            if(m_LaserTestTime > 250) m_LaserTestTime=250;
                        }
                        break;
                    case K_LEFT: 
                        if(m_LaserTestTime <= 4)
                        {
                            m_LaserTestTime--;
                            if(m_LaserTestTime < 0) m_LaserTestTime=0;
                        }
                        else
                        {
                            m_LaserTestTime -= (m_LaserTestTime>>2);
                        }
                        break;
                    case K_CANCEL: 
                        {
                            enable = cfg->enable;
                            // home the machine:
                            while ( !mot->isStart() );
                            mot->home(cfg->xhome,cfg->yhome,cfg->zhome);
                            screen=MAIN;
                            m_LaserTestPower=0;
                            m_LaserTestTime=0;
                            waitup = 1;
                        }
                        break;
                }
                args[0]=m_LaserTestTime;
                args[1]=m_LaserTestPower;
                break;
                

            default:
                screen = MAIN;
                break;
        }
        if (nodisplay == 0) {
            dsp->ShowScreen(screens[screen], args, sarg);
        }
         prevscreen = screen;
    }

}