⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vga_example.c

📁 可配置的vga显示控制器
💻 C
字号:

#include <stdio.h>
#include <sys/alt_alarm.h>
#include "system.h"
#include "vga_controller.h"
#include "sys/alt_cache.h"
#include "vga_example.h"

#include "io.h"

void get_time_from_user(int *h, int *m, int *s);

int main()
{
  // VGA Device
  vga_controller_dev* vga;
 
  // VGA frame buffer
  vga_frame_buffer_struct* vga_frame_buffer;
  
  // Open the VGA controller peripheral
  printf("Initializing VGA controller.\n");
  vga = (vga_controller_dev*)alt_vga_open_dev("/dev/vga_controller_0");
  vga_frame_buffer = vga_init_no_interrupt( vga, HEAP );
  
  printf("Which demo would you like to run? Press the appropriate number.\n");
  printf(" 1.) Clock\n 2.) Rotating Cube\n - ");
  char ch[3];
  fgets( ch, sizeof(ch), stdin );
  
  switch ( ch[0] )
  {
    case '1':
      run_clock( vga_frame_buffer );
      break;
    case '2':
      run_rotate( vga_frame_buffer );
      break;
    default:
      break;
  }
    
  return 0;
}

point_3d_struct rotate_point(point_3d_struct* point, int angle, point_3d_struct* r)
{
   short int_cos_angle, int_sin_angle;
   point_3d_struct new_point;
   
   new_point.x = 0;
   new_point.y = 0;
   new_point.z = 0;
   int_cos_angle = int_cos(angle);
   int_sin_angle = int_sin(angle);
   
   new_point.x += (int_cos_angle + (1024 - int_cos_angle) * r->x * r->x) * point->x;
   new_point.x += ((1024 - int_cos_angle) * r->x * r->y - r->z * int_sin_angle) * point->y;
   new_point.x += ((1024 - int_cos_angle) * r->x * r->z + r->y * int_sin_angle) * point->z;
   new_point.x = new_point.x >> 10;

   new_point.y += ((1024 - int_cos_angle) * r->x * r->y + r->z * int_sin_angle) * point->x;
   new_point.y += (int_cos_angle + (1024 - int_cos_angle) * r->y * r->y) * point->y;
   new_point.y += ((1024 - int_cos_angle) * r->y * r->z - r->x * int_sin_angle) * point->z;
   new_point.y = new_point.y >> 10;

   new_point.z += ((1024 - int_cos_angle) * r->x * r->z - r->y * int_sin_angle) * point->x;
   new_point.z += ((1024 - int_cos_angle) * r->y * r->z + r->x * int_sin_angle) * point->y;
   new_point.z += (int_cos_angle + (1024 - int_cos_angle) * r->z * r->z) * point->z;
   new_point.z = new_point.z >> 10;
    
   return(new_point);
}

int int_sin( int deg )
{
  deg %= 360;
  if( deg < 0 )
    deg += 360;
  
  return(int_sin_array[deg]);
}

int int_cos( int deg )
{
  deg %= 360;
  if( deg < 0 )
    deg += 360;
  
  return(int_cos_array[deg]);
}

void draw_cube( point_3d_struct my_cube[8], 
                point_3d_struct axis_unit[3], 
                int angle, 
                int axis, 
                int color,
                vga_frame_buffer_struct* vga_frame_buffer )
{
  int i;
  point_3d_struct rotated_cube[8];  
  
  // Rotate and project each point of the cube
  for( i = 0; i < 8; i++ )
  {
    rotated_cube[i] = rotate_point( &my_cube[i], angle, &axis_unit[axis] );
    project( &rotated_cube[i], DISTANCE, vga_frame_buffer );
  }

  // Draw each edge of the cube (it has 12)
  for( i = 0; i < 4; i++ )
  {
    // Z plane
    vga_draw_line( rotated_cube[i].screen_x, rotated_cube[i].screen_y,
                   rotated_cube[i+4].screen_x, rotated_cube[i+4].screen_y,
                   1, color , vga_frame_buffer);
    // X plane
    vga_draw_line( rotated_cube[i*2].screen_x, rotated_cube[i*2].screen_y,
                   rotated_cube[(i*2)+1].screen_x, rotated_cube[(i*2)+1].screen_y,
                   1, color, vga_frame_buffer);
    // Y plane
    vga_draw_line( rotated_cube[((i|(i<<1))& 0x5)].screen_x, rotated_cube[((i|(i<<1))& 0x5)].screen_y,
                   rotated_cube[((i|(i<<1))& 0x5)+2].screen_x, rotated_cube[((i|(i<<1))& 0x5)+2].screen_y,
                   1, color, vga_frame_buffer);
  }
}

void run_rotate( vga_frame_buffer_struct* vga_frame_buffer )
{
  int angle, angle_prev, angle_prev2;
  int axis, axis_prev, axis_prev2;
  int i;
  int x, y, z;
  point_3d_struct my_cube[8];
  point_3d_struct axis_unit[3];
  
  rand_seed( 1234 );
    
  // Define unit vectors for each axis x,y,z.
  for(axis = 0; axis < 3; axis++ )
  {
    axis_unit[axis].x = ((0x1 >> axis) & 0x1);
    axis_unit[axis].y = ((0x2 >> axis) & 0x1);
    axis_unit[axis].z = ((0x4 >> axis) & 0x1);
  }

  // Define the points of a cube
  for(i = 0; i < 8; i++ )
  {
    x = (((i >> 0) & 0x1) * 2 * SIDE_LENGTH) + (-SIDE_LENGTH);
    y = (((i >> 1) & 0x1) * 2 * SIDE_LENGTH) + (-SIDE_LENGTH);
    z = (((i >> 2) & 0x1) * 2 * SIDE_LENGTH) + (-SIDE_LENGTH);
    my_cube[i].x = x;
    my_cube[i].y = y;
    my_cube[i].z = z;
  }
   
  
  // Rotate it.
  while(1)
  for( axis = 0; axis < 3; axis ++ )
  {
    for( angle = 0; angle < 360; angle+=3 )
    {
      // Erase the last cube that was drawn in this buffer
      draw_cube( my_cube, axis_unit, angle_prev2, axis_prev2, BLACK_24, vga_frame_buffer );

      
      // Now draw the new one
      draw_cube( my_cube, axis_unit, angle, axis, WHITE_24, vga_frame_buffer );
    
      // Flip the double buffers.
      vga_flip_frame_buffers( vga_frame_buffer );
    
      // Save the angles and axis so we can accurately erase next time
      angle_prev2 = angle_prev;
      angle_prev = angle;
      axis_prev2 = axis_prev;
      axis_prev = axis;
    
      // Wait until frame being displayed is done so we dont write to it
      // at the same time.
      while( IORD_32DIRECT( vga_frame_buffer->vga_controller_base, 0xC ) != 
                            (int)vga_frame_buffer->vga_frame0 );
//      usleep(30000);
    }
  }
}

int distort_cube( point_3d_struct my_cube[8] )
{
    int i;
    for( i = 0; i < 8; i++ )
    {
      my_cube[i].x += (((unsigned int)random()) % 3) - 1;
      my_cube[i].y += (((unsigned int)random()) % 3) - 1;
      my_cube[i].z += (((unsigned int)random()) % 3) - 1;
    }
}

void project(point_3d_struct* point, int dist, vga_frame_buffer_struct* vga_fb) {

  // Prevent a divide by zero
  if(point->z == 0)
  { 
    // Project the point  
    point->screen_x = point->x + (vga_fb->width / 2);
    point->screen_y = -point->y + (vga_fb->height / 2);
  }
  else
  {
    // Project the point  
    point->screen_x = ((point->x * dist) / (point->z + dist)) + (vga_fb->width / 2);
    point->screen_y = -((point->y * dist) / (point->z + dist)) + (vga_fb->height / 2);
  }
}


void run_clock( vga_frame_buffer_struct* vga_frame_buffer )
{
  // Local variables
  int bg_color;
  int i = 0;
  int last_tick = 0;
  int current_ticks = 0;
  int hours, minutes, seconds;
  char string[10];
  triangle_struct hour_hand, minute_hand;
  
  get_time_from_user(&hours, &minutes, &seconds);
  
  bg_color = (vga_frame_buffer->color_depth == 24) ? BLACK_24 : BLACK_16;

  vga_paint_block(0, 0, vga_frame_buffer->width, vga_frame_buffer->height, bg_color, vga_frame_buffer);

  for( i = 0; i < 2; i++ )
  {
    vga_draw_circle( CLOCK_CENTER_X, CLOCK_CENTER_Y, 
                   CLOCK_RADIUS, WHITE_24, 
                   DO_FILL, vga_frame_buffer);
    // Flip the double buffers.
    vga_flip_frame_buffers( vga_frame_buffer );
  }
                   
  // Initial hand locations
  map_hand(&minute_hand, seconds, 70, CLOCK_CENTER_X, CLOCK_CENTER_Y);
  minute_hand.fill = DO_FILL;
  map_hand(&hour_hand, seconds, 70, CLOCK_CENTER_X, CLOCK_CENTER_Y);
  hour_hand.fill = DO_FILL;
    
  while(1)
  {
    current_ticks = alt_nticks();
    if (current_ticks >= (last_tick + (alt_ticks_per_second())))
    {
      last_tick = current_ticks;
 
      increment_clock(&hours, &minutes, &seconds);
     
      // Erase the present hands
      vga_draw_circle( CLOCK_CENTER_X, CLOCK_CENTER_Y, 
                       CLOCK_RADIUS - CLOCK_RING_WIDTH, bg_color, 
                       DO_FILL, vga_frame_buffer);

      // Erase digital time
      vga_paint_block( CLOCK_CENTER_X-30, CLOCK_CENTER_Y + 120, 
                       CLOCK_CENTER_X+35, CLOCK_CENTER_Y + 135,
                       bg_color, vga_frame_buffer);
      
      // Redraw hour dots
      for( i = 0; i < 60; i+=5 )
      {
        vga_draw_circle( CLOCK_CENTER_X + clock_hand_array_70[i][0], 
                     CLOCK_CENTER_Y + clock_hand_array_70[i][1], 
                     4, WHITE_24, DO_FILL, vga_frame_buffer);
      }

      // Draw new hands
      map_hand(&minute_hand, minutes, 70, CLOCK_CENTER_X, CLOCK_CENTER_Y);
      map_hand(&hour_hand, (((hours*5)+(minutes/12))%60), 50, CLOCK_CENTER_X, CLOCK_CENTER_Y);

      minute_hand.col = BLUE_24;
      hour_hand.col = BLUE_24;

      vga_draw_triangle(&minute_hand, vga_frame_buffer);
      vga_draw_triangle(&hour_hand, vga_frame_buffer);
 
      vga_draw_circle( CLOCK_CENTER_X, CLOCK_CENTER_Y, 
                   5, BLUE_24, 
                   DO_FILL, vga_frame_buffer);     
      vga_draw_line((CLOCK_CENTER_X + clock_hand_array_70[seconds][0]), 
                    (CLOCK_CENTER_Y + clock_hand_array_70[seconds][1]),
                    (CLOCK_CENTER_X + clock_hand_array_5[(seconds + 30) % 60][0]), 
                    (CLOCK_CENTER_Y + clock_hand_array_5[(seconds + 30) % 60][1]),
                    1, RED_24, vga_frame_buffer);
      vga_draw_circle( CLOCK_CENTER_X, CLOCK_CENTER_Y, 
                   3, RED_24, 
                   DO_FILL, vga_frame_buffer);     
                    
      // Display digital time
      sprintf(string, "%2d:%2.2d:%2.2d\n", hours, minutes, seconds);
      vga_print_string (CLOCK_CENTER_X-30, CLOCK_CENTER_Y +120, WHITE_24, cour10_font, vga_frame_buffer, string);         
      
      // Flip the double buffers.
      vga_flip_frame_buffers( vga_frame_buffer );
      
      // Wait until frame being displayed is done so we dont write to it
      // at the same time.
      while( IORD_32DIRECT( vga_frame_buffer->vga_controller_base, 0xC ) != 
                            (int)vga_frame_buffer->vga_frame0 );
                 
    }
  }
}

void get_time_from_user(int *h, int *m, int *s)
{
  char string[10];

  fflush ( stdin );
  printf("What's the current time? (HH:MM:SS)\n- ");
  fgets( string, sizeof(string), stdin );
  if (string[0] != '\n')
  {
    sscanf (string,"%d:%d:%d", h, m, s);
  }
  else
  {
    *h = 12;
    *m = 0;
    *s = 0;
  }
}

void map_hand( triangle_struct* hand, int index, int hand_reach, 
               int center_x, int center_y )
{
  if(hand_reach == 70)
  {
    hand->vertex_x[0] = center_x + clock_hand_array_70[index][0];
    hand->vertex_y[0] = center_y + clock_hand_array_70[index][1];
  }
  else if (hand_reach == 50)
  {
    hand->vertex_x[0] = center_x + clock_hand_array_50[index][0];
    hand->vertex_y[0] = center_y + clock_hand_array_50[index][1];
  }
  hand->vertex_x[1] = center_x + clock_hand_array_5[(index+20) % 60][0];
  hand->vertex_y[1] = center_y + clock_hand_array_5[(index+20) % 60][1];
  hand->vertex_x[2] = center_x + clock_hand_array_5[(index+40) % 60][0];
  hand->vertex_y[2] = center_y + clock_hand_array_5[(index+40) % 60][1];
}

void increment_clock(int *h, int *m, int *s)
{
  if( *s >= 59 )
  {
    *s = 0;
    if( *m >= 59 )
    {
      *m = 0;
      if( *h >= 12 )
      {
        *h = 1;
      }
      else
      {
        *h += 1;
      }
    }
    else
    {
      *m += 1;
    }
  }
  else 
  {
    *s += 1;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -