Subversion Repositories shark

Rev

Rev 1485 | Rev 1487 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Project: S.Ha.R.K.
 *
 * Coordinators:
 *   Giorgio Buttazzo    <giorgio@sssup.it>
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *
 * Authors     :
 *   Giacomo Guidi       <giacomo@gandalf.sssup.it>
 *
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
 *
 * http://www.sssup.it
 * http://retis.sssup.it
 * http://shark.sssup.it
 */


/*
 * Copyright (C) 2003 Giacomo Guidi
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#include "kernel/kern.h"
#include "stdlib.h"
#include "unistd.h"

#include "drivers/shark_keyb26.h"
#include "drivers/shark_videodev26.h"
#include "drivers/shark_fb26.h"

#include "tracer.h"

#define WIDTH 640
#define HEIGHT 480
#define BYTES_PP 2

//#define COLOR
#define MAX_SPEED

#define FRAME_GRABBER_NUMBER 0

#define FG_PERIOD 40000 //ONLY IF MAX_SPEED IS DISABLED
#define FG_WCET 30000
#define FG_W 320               
#define FG_H 240

void program_end(void *arg)
{

  sys_end();
 
}

void elaborate_image(void *imageptr);

void start_frame_grabber(PID elaborate_task_PID, int channel, struct video_buffer *fbuf) {

  struct video_window win;
  struct video_channel chan;
  struct video_tuner tuner;
  struct video_picture vpic;
  int res;

  /* Init videodev driver */
  VIDEODEV26_open(FRAME_GRABBER_NUMBER);

  /* Select the input channel */
  res = VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCGCHAN,(unsigned long)&chan);
  //cprintf("res = %d\n",res);

  chan.channel = channel;
  chan.type = VIDEO_VC_TUNER;
  chan.norm = VIDEO_TYPE_CAMERA;
                                                                                                                             
  res = VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCSCHAN,(unsigned long)&chan);
  //cprintf("res = %d\n",res);

  /* Enable the tuner */

  tuner.tuner = 0;
  tuner.mode = VIDEO_MODE_PAL;

  res = VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCSTUNER,(unsigned long)&tuner);
  //cprintf("res = %d\n",res);

  /* Select palette and depth */
  res = VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCGPICT,(unsigned long)&vpic);
  //cprintf("res = %d\n",res);  

  #ifdef COLOR
        vpic.palette = VIDEO_PALETTE_RGB24;
        vpic.depth = 24;
  #else
        vpic.palette = VIDEO_PALETTE_GREY;
        vpic.depth = 8;
  #endif

  vpic.brightness = 35000;
  vpic.hue = 32000;
  vpic.contrast = 32000;
  vpic.colour = 32000;                          
                                                                                                 
  res = VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCSPICT,(unsigned long)&vpic);
  //cprintf("res = %d\n",res);

  res = VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCGWIN,(unsigned long)&win);
  //cprintf("res = %d\n",res);
 
  win.x = 0;
  win.y = 0;
  win.width = FG_W;
  win.height = FG_H;

  res = VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCSWIN,(unsigned long)&win);
  //cprintf("res = %d\n",res);

  /* Set the buffer */
  res = VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCSFBUF,(unsigned long)(fbuf));
  //cprintf("res = %d\n",res);

  /* IMPORTANT: Set the aperiodic elaboration task
   * This is a SHARK change on VIDIOCSYNC. When the
   * new frame is ready, the task elaborate_task_PID
   * is activated. Elabortate_task must be aperiodic !!
   * To link the task to BTTV use this function: */


  VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCSYNC,(unsigned long)(elaborate_task_PID));

}

/* Check if the frame grabber is ready */
volatile int ready_to_grab = 1;

void grab_command(void *arg) {

  SYS_FLAGS f;

  f = kern_fsave();

  int on = 1;
  VIDEODEV26_ioctl(FRAME_GRABBER_NUMBER,VIDIOCCAPTURE,(unsigned long)&on);

  kern_frestore(f);

}

/* Elaboration task, it is called when the frame
   grabber buffer is ready */

TASK elaborate_task(void *arg) {

  struct video_buffer *fbuf = (struct video_buffer *)(arg);

  while(1) {

    elaborate_image(fbuf->base);
    //cprintf("E");
 
    //Text version
    //printf_xy(1,20,WHITE,"%08x",
    //    *(unsigned int *)(fbuf->base+50*320*3+50*3));    

    ready_to_grab = 1;

    #ifdef MAX_SPEED
      grab_command(NULL);
    #endif

    task_testcancel();
    task_endcycle();

  }

  return NULL;

}

/* Send the grab command */
TASK grab_task(void *arg) {

  while(1) {

    if (ready_to_grab) {
     
      /* Grab */
      grab_command(NULL);

      //cprintf("G");

      ready_to_grab = 0;

    } else {

      //cprintf("S");
      /* Frame skipped */

    }

    task_testcancel();
    task_endcycle();
                                                                                                                             
  }
                                                                                                                             
  return NULL;

}

extern void *video_memory;

void elaborate_image(void *imageptr)
{

  WORD x,y;
  BYTE *col;

  #ifdef COLOR

    for(y = 0; y < FG_H; y++)
      for(x = 0; x < FG_W; x++) {

        col = (BYTE *)(imageptr + y * FG_W * 3 + x * 3);
        *(WORD *)(video_memory + y*(WIDTH*2) + (x*2)) = (WORD)rgb16(*(BYTE *)(col+2),*(BYTE *)(col+1),*(BYTE *)(col+0));

    }

  #else

    for(y = 0; y < FG_H; y++)
      for(x = 0; x < FG_W; x++) {
                                                                                                                             
        col = (BYTE *)(imageptr + y * FG_W + x);
        *(WORD *)(video_memory + y*(WIDTH*2) + (x*2)) = (WORD)rgb16(*(BYTE *)(col),*(BYTE *)(col),*(BYTE *)(col));
                                                                                                                             
    }

  #endif

}

int main(int argc, char **argv)
{

  HARD_TASK_MODEL gt;
  SOFT_TASK_MODEL et;
  PID grab_task_pid,elaborate_task_pid;

  struct video_buffer fbuf;
  int channel = 0;

  if (argc < 2) {
        sys_shutdown_message("ERROR: Enter the input channel [ex> %s 0]\n",argv[0]);
        sys_end();
  }

  channel = atoi(argv[1]);

  soft_task_default_model(et);
  #ifndef MAX_SPEED
    soft_task_def_period(et,FG_PERIOD);
  #else
    /* The period must be less than the frame rate (around 40000 us) */
    soft_task_def_period(et,35000);
  #endif
  soft_task_def_arg(et,(void *)(&fbuf));
  soft_task_def_met(et,FG_WCET);
  soft_task_def_aperiodic(et);
  soft_task_def_ctrl_jet(et);
 
  hard_task_default_model(gt);
  hard_task_def_mit(gt,FG_PERIOD);
  hard_task_def_wcet(gt,5000);
  hard_task_def_ctrl_jet(gt);
 
  grab_task_pid = task_create("GrabTask",grab_task,&gt,NULL);
  if (grab_task_pid == NIL) {
        sys_shutdown_message("ERROR: Cannot create grab task\n");
        sys_end();
  }

  elaborate_task_pid = task_create("ElaborateTask",elaborate_task,&et,NULL);
  if (grab_task_pid == NIL) {
        sys_shutdown_message("ERROR: Cannot create elaborate task\n");
        sys_end();
  }

  #ifdef COLOR

        fbuf.base = malloc(FG_W*FG_H*3);
        fbuf.height = FG_H;
        fbuf.width = FG_W;
        fbuf.bytesperline = FG_W*3;
        fbuf.depth = 24;

  #else

        fbuf.base = malloc(FG_W*FG_H);
        fbuf.height = FG_H;
        fbuf.width = FG_W;
        fbuf.bytesperline = FG_W;
        fbuf.depth = 8;

  #endif

  start_frame_grabber(elaborate_task_pid,channel,&fbuf);

  #ifndef MAX_SPEED
    /* Activate periodic grabbing */
    task_activate(grab_task_pid);
  #else
    /* Grab */
    grab_command(NULL);
  #endif

  while(keyb_getch(BLOCK) != ESC);

  #ifndef MAX_SPEED
    task_kill(grab_task_pid);
  #endif

  sleep(1);

  sys_end();

  return 0;

}