// run the n'th command in the menu
int8_t
Menu::_call(uint8_t n, uint8_t argc)
{
    func fn;

    pgm_read_block(&_commands[n].func, &fn, sizeof(fn));
    return(fn(argc, &_argv[0]));
}
Example #2
0
/*
  run one tick
  this will run as many scheduler tasks as we can in the specified time
 */
void AP_Scheduler::run(uint16_t time_available)
{
    uint32_t run_started_usec = hal.scheduler->micros();
    uint32_t now = run_started_usec;

    for (uint8_t i=0; i<_num_tasks; i++) {
        uint16_t dt = _tick_counter - _last_run[i];
        uint16_t interval_ticks = pgm_read_word(&_tasks[i].interval_ticks);
        if (dt >= interval_ticks) {
            // this task is due to run. Do we have enough time to run it?
            _task_time_allowed = pgm_read_word(&_tasks[i].max_time_micros);

            if (dt >= interval_ticks*2) {
                // we've slipped a whole run of this task!
                if (_debug > 1) {
                    hal.console->printf_P(PSTR("Scheduler slip task[%u] (%u/%u/%u)\n"),
                                          (unsigned)i, 
                                          (unsigned)dt,
                                          (unsigned)interval_ticks,
                                          (unsigned)_task_time_allowed);
                }
            }
            
            if (_task_time_allowed <= time_available) {
                // run it
                _task_time_started = now;
                task_fn_t func;
                pgm_read_block(&_tasks[i].function, &func, sizeof(func));
                current_task = i;
                func();
                current_task = -1;
                
                // record the tick counter when we ran. This drives
                // when we next run the event
                _last_run[i] = _tick_counter;
                
                // work out how long the event actually took
                now = hal.scheduler->micros();
                uint32_t time_taken = now - _task_time_started;
                
                if (time_taken > _task_time_allowed) {
                    // the event overran!
                    if (_debug > 2) {
                        hal.console->printf_P(PSTR("Scheduler overrun task[%u] (%u/%u)\n"),
                                              (unsigned)i, 
                                              (unsigned)time_taken,
                                              (unsigned)_task_time_allowed);
                    }
                }
                if (time_taken >= time_available) {
                    goto update_spare_ticks;
                }
                time_available -= time_taken;
            }
        }
    }

    // update number of spare microseconds
    _spare_micros += time_available;

update_spare_ticks:
    _spare_ticks++;
    if (_spare_ticks == 32) {
        _spare_ticks /= 2;
        _spare_micros /= 2;
    }
}