Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Made by Ben Duncan (C) */
- // Included header files
- #include <8051.h>
- #include <string.h>
- #include <stdio.h> /* for printf, printf_fast, etc */
- // Subroutine decleration
- extern void delay_ms(unsigned char ms);
- extern void restart(void);
- extern char key_char(void);
- extern void lcd_putchar(char c);
- extern void lcd_command(unsigned char cmd);
- extern void lcd_set_xy_raw(unsigned int x_and_y);
- extern char a2d(void);
- void delay(int s); // Integer seconds only delay
- void display_rules(void);
- void display_countdown(char count); // Displays a countdown from 'count' to 0
- void generate_player(void);
- void generate_enemies(void);
- // Memory map locations for TAD board
- #define DIL_SWITCH 0x0000 // DIL Switch at address 0000h
- #define DAC 0x0600 // DAC at address 0600h
- #define LCD_COMMAND_WR 0x0800 // Write LCD Command at address 0800h
- #define LCD_STATUS_RD 0x0801 // Read LCD Status at address 0801h
- #define LCD_DATA_WR 0x0802 // Write LCD Data at address 0802h
- #define LCD_DATA_RD 0x0803 // Read LCD Data at address 0803h
- #define COMPARATOR P3_5 // Comparator is set to bit P3.5
- // External data locations
- volatile xdata at DAC unsigned char dac;
- volatile xdata at LCD_COMMAND_WR unsigned char lcd_command_wr;
- volatile xdata at LCD_STATUS_RD unsigned char lcd_status_rd;
- volatile xdata at LCD_DATA_WR unsigned char lcd_data_wr;
- volatile xdata at LCD_DATA_RD unsigned char lcd_data_rd;
- // LCD commands
- #define LCD_CLEAR_CMD 0x01
- #define LCD_HOME_CMD 0x02
- #define LCD_ON_CMD 0x0C
- #define LCD_SHIFT_CMD 0x10
- #define LCD_CONFIG_CMD 0x38
- // Macro to merge two parameters into a single 16-bit parameter
- #define lcd_set_xy(x, y) (lcd_set_xy_raw((x) + ((y) << 8)))
- // LCD screen parameters
- #define LCD_HORIZ_SIZE 16
- #define LCD_VERT_SIZE 2
- #define LCD_BYTES_PER_LINE (128 / LCD_VERT_SIZE)
- // Send serial data to LCD or Serial Port
- bit print_to_lcd=0;
- // Interrupt declaration
- void ex0_isr(void) interrupt 0;
- void ex1_isr(void) interrupt 2;
- // Set the side of the 'track' the player is on
- bit player_side = 0; // Defaults to the right side '0'
- // Soft-enable/disables interrupts
- bit enable_interrupts;
- /* Player and characters */
- #define PLAYER "X"
- #define MINE "*"
- #define PLAYER_X 16 // Sets player to right of screen
- #define ENEMY_SPACES 12 // # spaces enemies can exist in
- #define ENEMY_START 0 // Start position of enemies
- #define ENEMY_END_ 11 // End position of enemies
- #define NUM_ENEMY_STR 1 // Number of enemy strings
- /* Enemy sprites */
- char enemy_track1[20] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0}; // Sprites of enemies on track 1
- char enemy_track2[20] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0}; // Sprites of enemies on track 2
- /* Keyboard character codes */
- #define BS_KEY 8
- #define ESC_KEY 27
- #define SPACE_KEY 32
- #define DEL_KEY 127
- /* Main code section */
- void main(){
- /* Initialise devices */
- enable_interrupts = 0; // Disallow interrupt functions to change 'player_side' state
- EA=1; // Configure interrupt 0 for falling edge on /INT0 (P3.2)
- EX0 = 1; // Enable EX0 Interrupt
- EX1 = 1; // Enable EX1 Interrupt
- lcd_command(LCD_HOME_CMD); // Initialise LCD
- lcd_command(LCD_CLEAR_CMD); // Clear LCD screen
- print_to_lcd=1; // Select LCD
- lcd_set_xy(0,0); // Select LCD character
- printf_fast("- Mine Dodger! -"); // Display first line of LCD
- lcd_set_xy(0,1); // Select LCD character
- printf_fast(" By Ben Duncan "); // Display second line of LCD
- delay(3); // Wait for 3 seconds
- lcd_command(LCD_CLEAR_CMD); // Clear LCD screen
- /* Main control loop that exits when 'esc' is pressed on the keyboard */
- do{
- enable_interrupts = 1; // Allow interrupt functions to change 'player_side' state
- generate_player(); // Print player to screen
- generate_enemies(); // Display enemies on LCD screen
- } while(key_char() != ESC_KEY); // When 'esc' is pressed escape loop
- }
- /* Subroutines for Display */
- void generate_enemies(void){
- int j,i;
- for(i=0; i<ENEMY_SPACES; i++){
- for(j=0; j<ENEMY_SPACES; j++){
- lcd_set_xy(i, 0); // Set position of line 1 of enemies
- printf_fast(enemy_track1[j]);
- lcd_set_xy(i, 1); // Set position of line 2 of enemies
- printf_fast(enemy_track2[j]);
- }
- speed_delay(1); // Delay for enemy speed
- i++ // Move enemies up one place on the screen
- if(i=>ENEMY_SPACES){ // If the next enemy moves past the end position
- i=0; // Start at 0 again
- }
- }
- }
- void generate_player(void){
- lcd_set_xy(PLAYER_X, player_side); // Place player on right of screen on 'player_side'
- printf_fast(PLAYER); // Print player (X)
- delay_ms(10); // Wait for LCD to refresh
- }
- void display_countdown(char count){ // Passes value of countdown
- int n; // Counting variable
- lcd_command(LCD_CLEAR_CMD); // Clear LCD screen
- for(n=count; n>0; n--){ // Count 5-0
- lcd_set_xy(0,0); // Select LCD character
- printf_fast("Start in: %d ", n); // Display first line of LCD
- delay(1); // Wait for 1 second
- }
- }
- void display_rules(void){
- lcd_command(LCD_CLEAR_CMD); // Clear LCD screen
- lcd_set_xy(0,0); // Select LCD character
- printf_fast("* are the mines "); // Display first line of LCD
- lcd_set_xy(0,1); // Select LCD character
- printf_fast(" & are dangerous"); // Display second line of LCD
- delay(5); // Wait for 5 seconds
- lcd_set_xy(0,0); // Select LCD character
- printf_fast("X is the vehicle"); // Display first line of LCD
- lcd_set_xy(0,1); // Select LCD character
- printf_fast("Avoid the mines!"); // Display second line of LCD
- delay(5); // Wait for 5 seconds
- }
- /* Subroutines for Interrupts */
- void ex0_isr(void) interrupt 0{ // 'Left' button
- if(enable_interrupts==1){ // If enabled
- if(player_side==1){ // If player on right
- player_side = 0; // Set player to left side
- lcd_set_xy(PLAYER_X,player_side); // Select location of player
- printf_fast(PLAYER); // Display player on screen
- }
- }
- }
- void ex1_isr(void) interrupt 2{ // 'Right' button
- if(enable_interrupts==1){ // If enabled
- if(player_side==0){ // If player on left
- player_side = 1; // Set player to right side
- lcd_set_xy(PLAYER_X,player_side); // Select location of player
- printf_fast(PLAYER); // Display player on screen
- }
- }
- }
- /* Subroutines to control and communicate with the LCD */
- void putchar(char c) // Write character to lcd or serial port
- {
- if (print_to_lcd) // If print_to_lcd is set then write to lcd
- {
- lcd_putchar(c);
- }
- else // Else write to the serial port
- {
- while(!TI); /* Wait for ready */
- TI=0;
- SBUF = c;
- }
- }
- char getchar(void) // Get character from serial port
- {
- char c;
- while(!RI);
- RI =0;
- c = SBUF;
- return c;
- }
- void restart(void) // Soft reset, jumps to address 0000h
- {
- _asm
- ljmp 0
- _endasm;
- }
- char key_char(void)
- {
- char c;
- if (RI)
- {
- RI = 0;
- c = SBUF;
- }
- return c;
- }
- char a2d(void)
- {
- unsigned char val=0;
- dac = 0;
- delay_ms(1);
- while (COMPARATOR == 1)
- {
- val = val + 1;
- dac = val;
- delay_ms(1); // Allow time for DAC to settle
- }
- return (val);
- }
- /* This is a simple delay based on a busy loop */
- /* with an 11.0592 MHz crystal, the delay lasts */
- /* for approximately 1 ms times the number passed */
- /* Of course, it will take longer if there are */
- /* interrupts occuring... */
- void delay_ms(unsigned char ms)
- {
- ms;
- _asm
- mov r0, dpl
- 00001$: mov r1, #250
- 00002$: nop
- djnz r1, 00002$
- djnz r0, 00001$
- ret
- _endasm;
- }
- void delay(int s){ // Wait for 1 second
- int i,j;
- for(j=0; j<4; j++){
- for(i=0; i<s; i++){ // Delays multiple times
- delay_ms(250); // Quater of a second
- }
- }
- }
- /* This C-only version is easier to read and understand, but it is
- * not as fast and efficient as the assembly version below. You
- * should normally use the optimized assembly version, but read
- * this one to understand the code.
- */
- volatile xdata at LCD_COMMAND_WR unsigned char lcd_command_wr;
- volatile xdata at LCD_STATUS_RD unsigned char lcd_status_rd;
- volatile xdata at LCD_DATA_WR unsigned char lcd_data_wr;
- volatile xdata at LCD_DATA_RD unsigned char lcd_data_rd;
- void lcd_busy(void)
- {
- while (lcd_status_rd & 0x80) ;
- }
- void lcd_command(unsigned char cmd)
- {
- lcd_busy();
- lcd_command_wr = cmd;
- }
- void lcd_putchar(char c)
- {
- lcd_busy();
- if (c=='\n') lcd_command_wr = LCD_CLEAR_CMD;
- else lcd_data_wr = c;
- }
- void lcd_set_xy_raw(unsigned int x_and_y)
- {
- unsigned char x, y;
- if ((x = x_and_y & 255) >= LCD_HORIZ_SIZE) x = LCD_HORIZ_SIZE - 1;
- if ((y = x_and_y >> 8) >= LCD_VERT_SIZE) y = LCD_VERT_SIZE - 1;
- lcd_busy();
- lcd_command_wr = (y * LCD_BYTES_PER_LINE + x) | 0x80;
- }
- // End
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement