Created
May 23, 2020 12:22
-
-
Save selimslab/d7fcdb0b904cb5fbfdd311438f2e7f8d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "headers/audio.h" | |
#define fifo_threshold 96 //Audio out fifo | |
/**************************************************************************************** | |
* For playing the audio contained in passed array | |
****************************************************************************************/ | |
void play_audio(int audio[],int audio_len) | |
{ | |
int fifospace; | |
int play = 1; | |
int buffer_index = 0; | |
volatile int *audio_ptr = (int *) AUDIO_BASE; // Audio port address | |
*(audio_ptr) = 0x8; // clear write FIFOs | |
*(audio_ptr) = 0x0; // deactivate clearing | |
fifospace = *(audio_ptr + 1); // read the audio port fifospace register | |
while(play) | |
{ | |
fifospace = *(audio_ptr + 1); // read the audio port fifospace register | |
if ( ((fifospace & 0x00FF0000) >> 4) >= fifo_threshold) // check WSRC, for < 75% full | |
{ | |
/* store data until the audio-out FIFO is full when the audio data is not finished*/ | |
while ( (fifospace & 0x00FF0000) && (buffer_index < audio_len) ) | |
{ | |
*(audio_ptr + 2) = audio[buffer_index]; //left data | |
*(audio_ptr + 3) = audio[buffer_index]; //right data | |
++buffer_index; | |
fifospace = *(audio_ptr + 1); // read the audio port fifospace register | |
} | |
if(buffer_index == audio_len) // end of audio data, finish playing and return to main! | |
{ | |
play = 0; | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "headers/address_map_arm.h" | |
#include "headers/data.h" | |
#include "vga.c" | |
#include "audio.c" | |
#include "interrupt.c" | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
# | |
define text_x 68# define score_x(text_x + 7)# define score_y 1 | |
# define green 0x3F03# define yellow 0xFFE0# define red 0xF800# define brown 0x5140# define blue 0x393B | |
int g = 1; | |
int box_size = 7; | |
void play_audio(int[], int); | |
int bufferPixels[76800]; | |
void keep_score() { | |
int score = 0; | |
int health = 100; | |
} | |
void draw_box(struct box b) { | |
if (!b.is_invisible) | |
VGA_box(b.x, b.y, b.x + b.width, b.y + b.height, b.color); | |
} | |
void draw(int image[]) { | |
int i, j, offset = 0; | |
int pixel[arr_size(image)]; | |
for (i = 0; i < 320; i++) | |
for (j = 0; j < 240; j++) { | |
pixel[offset] = image[offset]; | |
if (pixel[offset] != 0 & pixel[offset] != 65535) { | |
write_pixel(i, j, pixel[offset]); | |
} | |
offset++; | |
} | |
} | |
void delete_box(struct box b) { | |
recover_background(b.x, b.x + b.width, b.y, b.y + b.height); | |
} | |
void delete_hero() { | |
recover_background(osman.x, osman.x + osman.width - 1, osman.y, osman.y + osman.height - 1); | |
} | |
void init_hero() { | |
osman.x = 150; | |
osman.y = 30; | |
osman.alive = 1; | |
osman.speed_x = 0; | |
osman.speed_y = 0; | |
osman.acceleration = 4; | |
osman.max_speed = 20; | |
osman.width = 28; | |
osman.height = 30; | |
osman.score = 0; | |
}; | |
void draw_boxes() { | |
int i; | |
for (i = 0; i < box_size; i++) { | |
int x2 = boxes[i].x + boxes[i].width; | |
int y2 = boxes[i].y + boxes[i].height; | |
if (!boxes[i].is_invisible) | |
VGA_box(boxes[i].x, boxes[i].y, x2, y2, boxes[i].color); | |
} | |
} | |
void create_boxes() { | |
int i; | |
for (i = 0; i < box_size; i++) { | |
struct box new_box; | |
new_box.width = 50; | |
new_box.height = 5; | |
if (i == 5) { | |
new_box.x = 130; | |
} else { | |
boxes[i].x = rand() % (vga_width - boxes[i].width); | |
} | |
new_box.y = i * 30; | |
new_box.is_broken = 0; | |
new_box.is_moving = 0; | |
new_box.direction = 1; | |
new_box.is_invisible = 0; | |
new_box.color = green; | |
boxes[i] = new_box; | |
} | |
} | |
void box_fall(int disposition) { | |
osman.score += disposition; | |
int i; | |
for (i = 0; i < box_size; i++) { | |
delete_box(boxes[i]); | |
boxes[i].y = boxes[i].y + disposition; | |
if (boxes[i].y >= vga_height) { | |
boxes[i].y = 0; | |
boxes[i].x = rand() % (vga_width - boxes[i].width); | |
boxes[i].is_invisible = 0; | |
int broken = rand() % 100; | |
if (broken < 73) { | |
boxes[i].is_broken = 0; | |
boxes[i].is_moving = 0; | |
boxes[i].is_invisible = 0; | |
boxes[i].color = green; | |
} else if (broken < 92) { | |
boxes[i].is_broken = 0; | |
boxes[i].is_moving = 1; | |
boxes[i].is_invisible = 0; | |
boxes[i].color = blue; | |
} else { | |
boxes[i].is_broken = 1; | |
boxes[i].is_moving = 0; | |
boxes[i].is_invisible = 0; | |
boxes[i].color = brown; | |
} | |
} | |
draw_box(boxes[i]); | |
} | |
} | |
int update_hero_position() { | |
osman.y = osman.y + osman.speed_y / 10; | |
if (osman.x > vga_width) { | |
osman.x = 0; | |
} | |
if (osman.x < 0) { | |
osman.x = 320 - osman.width; | |
} | |
osman.speed_y = osman.speed_y + osman.acceleration; | |
if (osman.speed_y > osman.max_speed) { | |
osman.speed_y = osman.max_speed; | |
} | |
if (osman.y > vga_height) { | |
return 0; | |
osman.y = vga_height / 3; | |
} | |
if (osman.y < vga_height / 3) { | |
int tmp = osman.y; | |
osman.y = vga_height / 3; | |
box_fall(vga_height / 3 - tmp + 1); | |
} | |
return 1; | |
} | |
void jump_if_necessary() { | |
if (osman.speed_y < 0) | |
return; | |
bool shouldJump = 0; | |
int i; | |
for (i = 0; i < box_size; i++) //jump | |
{ | |
bool betweenX = (osman.x >= boxes[i].x && osman.x < boxes[i].x + boxes[i].width); | |
bool betweenX2 = (osman.x + osman.width >= boxes[i].x && osman.x + osman.width < boxes[i].x + boxes[i].width); | |
bool betweenY = (osman.y + osman.height >= boxes[i].y && osman.y + osman.height < boxes[i].y + boxes[i].height); | |
bool curShouldJump = ((betweenX | betweenX2) & betweenY); | |
if (curShouldJump & boxes[i].is_broken) { | |
delete_box(boxes[i]); | |
boxes[i].is_invisible = 1; | |
} | |
shouldJump = shouldJump | ((betweenX | betweenX2) & betweenY & (!boxes[i].is_broken)); | |
} | |
if (shouldJump) { | |
osman.speed_y = -100; | |
} | |
} | |
void update_box_positions() { | |
int i; | |
for (i = 0; i < box_size; i++) //jump | |
{ | |
if (boxes[i].is_moving) { | |
delete_box(boxes[i]); | |
boxes[i].x += boxes[i].direction; | |
} | |
if (boxes[i].x + boxes[i].width >= vga_width) { | |
boxes[i].x = vga_width - boxes[i].width; | |
boxes[i].direction *= -1; | |
} | |
if (boxes[i].x <= 0) { | |
boxes[i].x = 0; | |
boxes[i].direction *= -1; | |
} | |
} | |
} | |
void do_config() { | |
set_A9_IRQ_stack(); // initialize the stack pointer for IRQ mode | |
config_GIC(); // configure the general interrupt controller | |
config_PS2(); | |
enable_A9_interrupts(); // enable interrupts | |
} | |
void clear_screen() { | |
VGA_box(0, 0, vga_width, vga_height, 0); | |
} | |
void display_score() { | |
/* Score message to be displayed on the VGA screen */ | |
char text[10] = "SCORE:\0"; | |
char score[16]; | |
sprintf(score, "%d", osman.score); | |
VGA_text(text_x, score_y, text); | |
VGA_text(score_x, score_y, score); | |
} | |
int play() { | |
delete_hero(); //hero fall | |
update_box_positions(); | |
draw_boxes(); | |
int alive = update_hero_position(); | |
jump_if_necessary(); | |
draw_hero(osman, hero_matrix); | |
display_score(); | |
return alive; | |
} | |
void game_over_func() { | |
/* Score message to be displayed on the VGA screen */ | |
clear_screen(); | |
draw(game_over); | |
play_audio(audio_death, arr_size(audio_death)); // play death music | |
} | |
int main(void) { | |
do_config(); | |
while (1) { | |
start_game = 0; | |
osman.score = 0; | |
clear_screen(); | |
init_hero(); | |
draw(background); | |
create_boxes(); | |
draw_boxes(); | |
draw_hero(osman, hero_matrix); | |
play_audio(start_buffer, arr_size(start_buffer)); // play start music | |
int alive = 1; | |
while (alive) { | |
int k = 0; | |
while (k < 11999999) { | |
k++; | |
} | |
alive = play(); | |
if (!alive) { | |
game_over_func(); | |
long long int a = 0; | |
while (a < 2000000000) { | |
a++; | |
} | |
} | |
} | |
} | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "headers/globals.h" | |
void config_interrupt (int, int); | |
void write_bits(volatile int *, volatile int, volatile int); | |
void PS2_ISR(void); | |
// Define the exception handlers here | |
void __attribute__ ((interrupt)) __cs3_reset (void) | |
{ | |
while(1); | |
} | |
void __attribute__ ((interrupt)) __cs3_isr_undef (void) | |
{ | |
while(1); | |
} | |
void __attribute__ ((interrupt)) __cs3_isr_swi (void) | |
{ | |
while(1); | |
} | |
void __attribute__ ((interrupt)) __cs3_isr_pabort (void) | |
{ | |
while(1); | |
} | |
void __attribute__ ((interrupt)) __cs3_isr_dabort (void) | |
{ | |
while(1); | |
} | |
void __attribute__ ((interrupt)) __cs3_isr_irq (void) | |
{ | |
// Read the ICCIAR from the processor interface | |
int address = MPCORE_GIC_CPUIF + ICCIAR; | |
int int_ID = *((int *) address); | |
if (int_ID == PS2_IRQ) // check if interrupt is from the PS2 buttonboard | |
PS2_ISR(); | |
else | |
while (1); // if unexpected, then halt | |
// Write to the End of Interrupt Register (ICCEOIR) | |
address = MPCORE_GIC_CPUIF + ICCEOIR; | |
*((int *) address) = int_ID; | |
return; | |
} | |
void __attribute__ ((interrupt)) __cs3_isr_fiq (void) | |
{ | |
while(1); | |
} | |
/* | |
* Initialize the banked stack pointer register for IRQ mode | |
*/ | |
void set_A9_IRQ_stack(void) | |
{ | |
int stack, mode; | |
stack = A9_ONCHIP_END - 7; // top of A9 onchip memory, aligned to 8 bytes | |
/* change processor to IRQ mode with interrupts disabled */ | |
mode = INT_DISABLE | IRQ_MODE; | |
asm("msr cpsr, %[ps]" : : [ps] "r" (mode)); | |
/* set banked stack pointer */ | |
asm("mov sp, %[ps]" : : [ps] "r" (stack)); | |
/* go back to SVC mode before executing subroutine return! */ | |
mode = INT_DISABLE | SVC_MODE; | |
asm("msr cpsr, %[ps]" : : [ps] "r" (mode)); | |
} | |
/* | |
* Turn on interrupts in the ARM processor | |
*/ | |
void enable_A9_interrupts(void) | |
{ | |
int status = SVC_MODE | INT_ENABLE; | |
asm("msr cpsr,%[ps]" : : [ps]"r"(status)); | |
} | |
/* | |
* Configure the Generic Interrupt Controller (GIC) | |
*/ | |
void config_GIC(void) | |
{ | |
int address; // used to calculate register addresses | |
/* enable some examples of interrupts */ | |
config_interrupt(PS2_IRQ, CPU0); | |
// Set Interrupt Priority Mask Register (ICCPMR). Enable interrupts for lowest priority | |
address = MPCORE_GIC_CPUIF + ICCPMR; | |
*((int *) address) = 0xFFFF; | |
// Set CPU Interface Control Register (ICCICR). Enable signaling of interrupts | |
address = MPCORE_GIC_CPUIF + ICCICR; | |
*((int *) address) = ENABLE; | |
// Configure the Distributor Control Register (ICDDCR) to send pending interrupts to CPUs | |
address = MPCORE_GIC_DIST + ICDDCR; | |
*((int *) address) = ENABLE; | |
} | |
/* | |
* Configure registers in the GIC for individual interrupt IDs. | |
*/ | |
void config_interrupt (int int_ID, int CPU_target) | |
{ | |
int n, addr_offset, value, address; | |
/* Set Interrupt Processor Targets Register (ICDIPTRn) to cpu0. | |
* n = integer_div(int_ID / 4) * 4 | |
* addr_offet = #ICDIPTR + n | |
* value = CPU_target << ((int_ID & 0x3) * 8) | |
*/ | |
n = (int_ID >> 2) << 2; | |
addr_offset = ICDIPTR + n; | |
value = CPU_target << ((int_ID & 0x3) << 3); | |
/* Now that we know the register address and value, we need to set the correct bits in | |
* the GIC register, without changing the other bits */ | |
address = MPCORE_GIC_DIST + addr_offset; | |
write_bits((int *) address, 0xff << ((int_ID & 0x3) << 3), value); | |
/* Set Interrupt Set-Enable Registers (ICDISERn). | |
* n = (integer_div(in_ID / 32) * 4 | |
* addr_offset = 0x100 + n | |
* value = enable << (int_ID & 0x1F) */ | |
n = (int_ID >> 5) << 2; | |
addr_offset = ICDISER + n; | |
value = 0x1 << (int_ID & 0x1f); | |
/* Now that we know the register address and value, we need to set the correct bits in | |
* the GIC register, without changing the other bits */ | |
address = MPCORE_GIC_DIST + addr_offset; | |
write_bits((int *) address, 0x1 << (int_ID & 0x1f), value); | |
} | |
void write_bits(volatile int * addr, volatile int unmask, volatile int value) | |
{ | |
*addr = ((~unmask) & *addr) | value; | |
} | |
/* setup the PS/2 interrupts */ | |
void config_PS2() { | |
volatile int * PS2_ptr = (int *)PS2_BASE; // PS/2 port address | |
*(PS2_ptr) = 0xFF; /* reset */ | |
*(PS2_ptr + 1) = 0x1; /* write to the PS/2 Control register to enable interrupts */ | |
} | |
void PS2_ISR(void) | |
{ | |
volatile int *PS2_ptr = (int *)PS2_BASE; // PS/2 port address | |
int PS2_data, RAVAIL; | |
volatile char button=0; | |
PS2_data = *(PS2_ptr); // read the Data register in the PS/2 port | |
RAVAIL = (PS2_data & 0xFFFF0000) >> 16; // extract the RAVAIL field | |
if (RAVAIL > 0) | |
{ | |
/* always save the last three bytes received */ | |
button = PS2_data & 0xFF; | |
int i; | |
if (button == (char)0x74) // right arrow--right movement of our hero | |
{ | |
for(i=0;i<2;i++){ | |
move_hero(5); | |
} | |
} | |
else if (button == (char)0x6b) // left arrow--left movement of our hero | |
{ | |
for(i=0;i<2;i++){ | |
move_hero(-5); | |
} | |
} | |
else if (button == (char)0x5a) // enter button | |
{ | |
} | |
} | |
return; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/**************************************************************************************** | |
* Subroutine to send a string of text to the VGA monitor | |
****************************************************************************************/ | |
void VGA_text(int x, int y, char * text_ptr) | |
{ | |
int offset; | |
volatile char * character_buffer = (char *) FPGA_CHAR_BASE; // VGA character buffer | |
/* assume that the text string fits on one line */ | |
offset = (y << 7) + x; | |
while ( *(text_ptr) ) | |
{ | |
*(character_buffer + offset) = *(text_ptr); // write to the character buffer | |
++text_ptr; | |
++offset; | |
} | |
} | |
/**************************************************************************************** | |
* Draw a filled rectangle on the VGA monitor | |
****************************************************************************************/ | |
void VGA_box(int x1, int y1, int x2, int y2, short pixel_color) | |
{ | |
int pixel_ptr, row, col; | |
/* assume that the box coordinates are valid */ | |
for (row = y1; row <= y2; row++) | |
for (col = x1; col <= x2; ++col) | |
{ | |
pixel_ptr = FPGA_ONCHIP_BASE + (row << 10) + (col << 1); | |
*(short *)pixel_ptr = pixel_color; // set pixel color | |
} | |
} | |
/**************************************************************************************** | |
* Subroutine to show a string of HEX data on the HEX displays | |
****************************************************************************************/ | |
void HEX_PS2(char b1, char b2, char b3) | |
{ | |
volatile int * HEX3_HEX0_ptr = (int *) HEX3_HEX0_BASE; | |
volatile int * HEX5_HEX4_ptr = (int *) HEX5_HEX4_BASE; | |
/* SEVEN_SEGMENT_DECODE_TABLE gives the on/off settings for all segments in | |
* a single 7-seg display in the DE1-SoC Computer, for the hex digits 0 - F */ | |
unsigned char seven_seg_decode_table[] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C, 0x07, | |
0x7F, 0x67, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71 }; | |
unsigned char hex_segs[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
unsigned int shift_buffer, nibble; | |
unsigned char code; | |
int i; | |
shift_buffer = (b1 << 16) | (b2 << 8) | b3; | |
for ( i = 0; i < 6; ++i ) | |
{ | |
nibble = shift_buffer & 0x0000000F; // character is in rightmost nibble | |
code = seven_seg_decode_table[nibble]; | |
hex_segs[i] = code; | |
shift_buffer = shift_buffer >> 4; | |
} | |
/* drive the hex displays */ | |
*(HEX3_HEX0_ptr) = *(int *) (hex_segs); | |
*(HEX5_HEX4_ptr) = *(int *) (hex_segs+4); | |
} | |
int resample_rgb(int num_bits, int color) | |
{ | |
if (num_bits == 8) { | |
color = (((color >> 16) & 0x000000E0) | ((color >> 11) & 0x0000001C) | | |
((color >> 6) & 0x00000003)); | |
color = (color << 8) | color; | |
} else if (num_bits == 16) { | |
color = (((color >> 8) & 0x0000F800) | ((color >> 5) & 0x000007E0) | | |
((color >> 3) & 0x0000001F)); | |
} | |
return color; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment