📄 vga_example.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 + -