Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 9696b01 in mainline


Ignore:
Timestamp:
2014-11-14T17:25:28Z (6 years ago)
Author:
Martin Decky <martin@…>
Branches:
master
Children:
1ab8539
Parents:
a047aaa
Message:

adapt the barber pole frame rate in the range of 1 to 25 fps

Location:
uspace
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/barber/barber.c

    ra047aaa r9696b01  
    4040#include <task.h>
    4141#include <loc.h>
     42#include <stats.h>
    4243#include <fibril_synch.h>
    4344#include <io/pixel.h>
     
    5354#define FRAMES  30
    5455
     56#define MIN_FPS  1
     57#define MAX_FPS  25
     58
     59#define MIN_LOAD  (LOAD_UNIT / 4)
     60#define MAX_LOAD  (LOAD_UNIT / 3)
     61
    5562#define FRAME_WIDTH   59
    5663#define FRAME_HEIGHT  192
    5764
    58 #define PERIOD  1000000
    59 #define COLORS  7
     65#define LED_PERIOD  1000000
     66#define LED_COLORS  7
     67
     68typedef struct {
     69        link_t link;
     70        service_id_t svc_id;
     71        async_sess_t *sess;
     72} led_dev_t;
    6073
    6174static char *winreg = NULL;
    62 static fibril_timer_t *timer = NULL;
     75
     76static fibril_timer_t *led_timer = NULL;
    6377static list_t led_devs;
    64 
    65 static canvas_t *frame_canvas;
    66 static surface_t *frames[FRAMES];
    67 
    68 static pixel_t colors[COLORS] = {
     78static unsigned int led_color = 0;
     79
     80static pixel_t led_colors[LED_COLORS] = {
    6981        PIXEL(0xff, 0xff, 0x00, 0x00),
    7082        PIXEL(0xff, 0x00, 0xff, 0x00),
     
    7688};
    7789
     90static fibril_timer_t *frame_timer = NULL;
     91static canvas_t *frame_canvas;
     92static surface_t *frames[FRAMES];
     93
    7894static unsigned int frame = 0;
    79 static unsigned int color = 0;
    80 
    81 typedef struct {
    82         link_t link;
    83         service_id_t svc_id;
    84         async_sess_t *sess;
    85 } led_dev_t;
    86 
    87 static void timer_callback(void *data)
    88 {
    89         pixel_t next_color = colors[color];
    90        
    91         color++;
    92         if (color >= COLORS)
    93                 color = 0;
    94        
    95         list_foreach(led_devs, link, led_dev_t, dev) {
    96                 if (dev->sess)
    97                         led_dev_color_set(dev->sess, next_color);
    98         }
    99        
    100         frame++;
    101         if (frame >= FRAMES)
    102                 frame = 0;
    103        
    104         update_canvas(frame_canvas, frames[frame]);
    105        
    106         fibril_timer_set(timer, PERIOD, timer_callback, NULL);
    107 }
    108 
    109 static void loc_callback(void)
    110 {
    111         category_id_t led_cat;
    112         int rc = loc_category_get_id("led", &led_cat, IPC_FLAG_BLOCKING);
    113         if (rc != EOK)
    114                 return;
    115        
    116         service_id_t *svcs;
    117         size_t count;
    118         rc = loc_category_get_svcs(led_cat, &svcs, &count);
    119         if (rc != EOK)
    120                 return;
    121        
    122         for (size_t i = 0; i < count; i++) {
    123                 bool known = false;
    124                
    125                 /* Determine whether we already know this device. */
    126                 list_foreach(led_devs, link, led_dev_t, dev) {
    127                         if (dev->svc_id == svcs[i]) {
    128                                 known = true;
    129                                 break;
    130                         }
    131                 }
    132                
    133                 if (!known) {
    134                         led_dev_t *dev = (led_dev_t *) calloc(1, sizeof(led_dev_t));
    135                         if (!dev)
    136                                 continue;
    137                        
    138                         link_initialize(&dev->link);
    139                         dev->svc_id = svcs[i];
    140                         dev->sess = loc_service_connect(EXCHANGE_SERIALIZE, svcs[i], 0);
    141                        
    142                         list_append(&dev->link, &led_devs);
    143                 }
    144         }
    145        
    146         // FIXME: Handle LED device removal
    147        
    148         free(svcs);
    149 }
     95static unsigned int fps = MIN_FPS;
     96
     97static void led_timer_callback(void *);
     98static void frame_timer_callback(void *);
    15099
    151100static bool decode_frames(void)
     
    192141}
    193142
     143static void plan_led_timer(void)
     144{
     145        fibril_timer_set(led_timer, LED_PERIOD, led_timer_callback, NULL);
     146}
     147
     148static load_t get_load(void)
     149{
     150        size_t count;
     151        load_t *load = stats_get_load(&count);
     152        load_t load_val;
     153       
     154        if ((load != NULL) && (count > 0)) {
     155                load_val = load[0];
     156                free(load);
     157        } else
     158                load_val = 0;
     159       
     160        return load_val;
     161}
     162
     163static void plan_frame_timer(suseconds_t render_time)
     164{
     165        /*
     166         * Crank up the FPS unless we lack
     167         * behind with the rendering and
     168         * unless the load is not above
     169         * a lower threshold.
     170         */
     171       
     172        suseconds_t delta = 1000000 / fps;
     173        load_t load = get_load();
     174       
     175        if ((delta >= render_time) && (load < MIN_LOAD))
     176                fps++;
     177       
     178        if (fps > MAX_FPS)
     179                fps = MAX_FPS;
     180       
     181        /*
     182         * If we lack behind then immediately
     183         * go to the lowest FPS.
     184         */
     185       
     186        if (delta < render_time)
     187                fps = MIN_FPS;
     188       
     189        /*
     190         * Crank down the FPS if the current
     191         * load is above an upper threshold.
     192         */
     193       
     194        if (load > MAX_LOAD)
     195                fps--;
     196       
     197        if (fps < MIN_FPS)
     198                fps = MIN_FPS;
     199       
     200        delta = 1000000 / fps;
     201       
     202        fibril_timer_set(frame_timer, delta, frame_timer_callback, NULL);
     203}
     204
     205static void led_timer_callback(void *data)
     206{
     207        pixel_t next_led_color = led_colors[led_color];
     208       
     209        led_color++;
     210        if (led_color >= LED_COLORS)
     211                led_color = 0;
     212       
     213        list_foreach(led_devs, link, led_dev_t, dev) {
     214                if (dev->sess)
     215                        led_dev_color_set(dev->sess, next_led_color);
     216        }
     217       
     218        plan_led_timer();
     219}
     220
     221static void frame_timer_callback(void *data)
     222{
     223        struct timeval prev;
     224        getuptime(&prev);
     225       
     226        frame++;
     227        if (frame >= FRAMES)
     228                frame = 0;
     229       
     230        update_canvas(frame_canvas, frames[frame]);
     231       
     232        struct timeval cur;
     233        getuptime(&cur);
     234       
     235        plan_frame_timer(tv_sub(&cur, &prev));
     236}
     237
     238static void loc_callback(void)
     239{
     240        category_id_t led_cat;
     241        int rc = loc_category_get_id("led", &led_cat, IPC_FLAG_BLOCKING);
     242        if (rc != EOK)
     243                return;
     244       
     245        service_id_t *svcs;
     246        size_t count;
     247        rc = loc_category_get_svcs(led_cat, &svcs, &count);
     248        if (rc != EOK)
     249                return;
     250       
     251        for (size_t i = 0; i < count; i++) {
     252                bool known = false;
     253               
     254                /* Determine whether we already know this device. */
     255                list_foreach(led_devs, link, led_dev_t, dev) {
     256                        if (dev->svc_id == svcs[i]) {
     257                                known = true;
     258                                break;
     259                        }
     260                }
     261               
     262                if (!known) {
     263                        led_dev_t *dev = (led_dev_t *) calloc(1, sizeof(led_dev_t));
     264                        if (!dev)
     265                                continue;
     266                       
     267                        link_initialize(&dev->link);
     268                        dev->svc_id = svcs[i];
     269                        dev->sess = loc_service_connect(EXCHANGE_SERIALIZE, svcs[i], 0);
     270                       
     271                        list_append(&dev->link, &led_devs);
     272                }
     273        }
     274       
     275        // FIXME: Handle LED device removal
     276       
     277        free(svcs);
     278}
     279
    194280int main(int argc, char *argv[])
    195281{
     
    206292        }
    207293       
    208         timer = fibril_timer_create(NULL);
    209         if (!timer) {
    210                 printf("Unable to create timer.\n");
     294        led_timer = fibril_timer_create(NULL);
     295        if (!led_timer) {
     296                printf("Unable to create LED timer.\n");
     297                return 1;
     298        }
     299       
     300        frame_timer = fibril_timer_create(NULL);
     301        if (!frame_timer) {
     302                printf("Unable to create frame timer.\n");
    211303                return 1;
    212304        }
     
    235327        window_exec(main_window);
    236328       
    237         fibril_timer_set(timer, PERIOD, timer_callback, NULL);
     329        plan_led_timer();
     330        plan_frame_timer(0);
    238331       
    239332        task_retval(0);
  • uspace/lib/c/generic/stats.c

    ra047aaa r9696b01  
    316316void stats_print_load_fragment(load_t upper, unsigned int dec_length)
    317317{
    318         /* Magic value from BSD */
    319         load_t lower = 65536;
    320        
    321318        /* Print the whole part */
    322         printf("%u.", upper / lower);
    323        
    324         load_t rest = (upper % lower) * 10;
     319        printf("%u.", upper / LOAD_UNIT);
     320       
     321        load_t rest = (upper % LOAD_UNIT) * 10;
    325322       
    326323        unsigned int i;
    327324        for (i = 0; i < dec_length; i++) {
    328                 printf("%u", rest / lower);
    329                 rest = (rest % lower) * 10;
     325                printf("%u", rest / LOAD_UNIT);
     326                rest = (rest % LOAD_UNIT) * 10;
    330327        }
    331328}
  • uspace/lib/c/include/stats.h

    ra047aaa r9696b01  
    4343#include <abi/sysinfo.h>
    4444
     45#define LOAD_UNIT  65536
     46
    4547extern stats_cpu_t *stats_get_cpus(size_t *);
    4648extern stats_physmem_t *stats_get_physmem(void);
Note: See TracChangeset for help on using the changeset viewer.