Space Invaders - Embedded Systems Project 15/16 - Avinash Patel 200860407
Dependencies: Joystick N5110 SDFileSystem mbed
Diff: main.cpp
- Revision:
- 0:427469992efe
- Child:
- 1:b300d052d549
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Mar 13 01:00:23 2016 +0000 @@ -0,0 +1,380 @@ +#include "mbed.h" +#include "N5110.h" + +#define EMPTY 0 + +//Joystick Class +class Joystick +{ +public: + Joystick(PinName x_axis_pin, PinName y_axis_pin, PinName button_pin) { + //Dynamically allocates the pins + x_axis_ = new AnalogIn(x_axis_pin); + y_axis_ = new AnalogIn(y_axis_pin); + button_ = new InterruptIn(button_pin); + } + + //Initalises the Joystick + //Sets up the ISRs and grabs the offsets for each axis + void init() { + //Sets up the button ISR + //DigitalOut* b = new DigitalOut(LED_BLUE); + + button_->mode(PullUp); + //read_ticker_->attach(this, &Joystick::read_ticker_isr, time); //Samples joystick every second + button_->fall(this, &Joystick::button_isr); + + //Initalises the vairables and flags + x_offset_ = 0; + y_offset_ = 0; + g_read_flag_ = 0; + g_button_flag_ = 0; + + //Samples the joystick 5 times and takes an average to get the offset + float x_sum = 0; + float y_sum = 0; + + for (int i = 0; i < 5; i++) { + x_sum += x_axis_->read(); + y_sum += y_axis_->read(); + } + + x_offset_ = 0.5f - x_sum/5.0f; + y_offset_ = 0.5f - y_sum/5.0f; + } + + //Take 5 readings and returns the average measurement, accounting for joystick offset x and y values + float GetXValue() { + + float x_sum = 0; + + for (int i = 0; i < 5; i++) { + x_sum += x_axis_->read(); + } + + float x_value = x_sum/5.0f + x_offset_; + + //Caps the value for the POT between 0 and 1 + if (x_value < 0.0f) { + return 0; + } else if (x_value > 1.0f) { + return 1; + } else { + return x_value; + } + } + + float GetYValue() { + + float y_sum = 0; + + for (int i = 0; i < 5; i++) { + y_sum += y_axis_->read(); + } + + float y_value = y_sum/5.0f + y_offset_; + + //Caps the value for the POT between 0 and 1 + if (y_value < 0.0f) { + return 0; + } else if (y_value > 1.0f) { + return 1; + } else { + return y_value; + } + } + + float ReadXAxis() { + return x_axis_->read(); + } + + float ReadYAxis() { + return y_axis_->read(); + } + + //Getter and setters for flags + int get_read_flag() { + return g_read_flag_; + } + + void set_read_flag(int value) { + g_read_flag_ = value; + } + + int get_button_flag() { + return g_button_flag_; + } + + void set_button_flag(int value) { + g_button_flag_ = value; + } + + //Ticker ISR Method + void read_ticker_isr() { + g_read_flag_ = 1; + } + +private: + //Button ISR Method + void button_isr() { + g_button_flag_ = 1; + } + +private: + //Pin inputs + AnalogIn* x_axis_; + AnalogIn* y_axis_; + InterruptIn* button_; + + //Ticker + Ticker* read_ticker_; + + //Stores X and Y offsets + float x_offset_; + float y_offset_; + + //Stores interrupt flags + volatile int g_read_flag_; + volatile int g_button_flag_; +}; + +// K64F on-board LEDs +DigitalOut r_led(LED_RED); +DigitalOut g_led(LED_GREEN); +DigitalOut b_led(LED_BLUE); + +// K64F on-board switches +InterruptIn sw2(SW2); +InterruptIn sw3(SW3); + +// UART connection for PC +Serial pc(USBTX,USBRX); + +//Joystick +Joystick joystick(PTC10, PTC11, PTB11); + +//LCD object +// VCC, SCE, RST, D/C, MOSI, SCLK, LED +N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3); + +//Ship bit-map and location +int ship_xpos = 24; +const int ship_ypos = 43; +Ticker move_ship; +const bool ship_bitmap[5][9] = { + {0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 1, 1, 0}, + {1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1, 1} +}; + +//Enemies +Ticker move_enemies; + +//Small Invader struct and bitmap +struct SmallInvader { + int x_pos; + int y_pos; + bool is_alive; +} small_invader[6]; +int no_of_small_invaders = 6; + +const bool small_invader_bitmap_1[6][8] = { + {0, 0, 0, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 1, 0}, + {1, 1, 0, 1, 1, 0, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1}, + {0, 1, 0, 1, 1, 0, 1, 0}, + {1, 0, 1, 0, 0, 1, 0, 1} +}; + +const bool small_invader_bitmap_2[6][8] = { + {0, 0, 0, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 1, 0}, + {1, 1, 0, 1, 1, 0, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1}, + {1, 0, 0, 0, 0, 0, 0, 1}, + {0, 1, 0, 0, 0, 0, 1, 0} +}; +bool small_invader_in_state2 = true; +short screen[84][48]; + +//ISR Flags +volatile bool g_move_ship_flag = true; +volatile bool g_move_enemies_flag = true; + +// function prototypes +// error function hangs flashing an LED +void error(); +// setup serial port +void init_serial(); +// set-up the on-board LEDs and switches +void init_K64F(); +// Added functions +void MoveShip(); +void InitSmallInvaders(); +void DrawSmallInvaders(); +//ISR's +void move_ship_isr(); +void move_enemies_isr(); + + +int row_no = 6; +int col_no = 8; + +int main() +{ + //Initalises the board and perhiperals + init_K64F(); + init_serial(); + lcd.init(); + lcd.clear(); + + move_ship.attach(&move_ship_isr, 0.1); + move_enemies.attach(&move_enemies_isr, 1); + + InitSmallInvaders(); + + lcd.refresh(); + + while (true) { + if (g_move_ship_flag) { + g_move_ship_flag = false; + + MoveShip(); + + lcd.refresh(); + } + + if (g_move_enemies_flag) { + g_move_enemies_flag = false; + + DrawSmallInvaders(); + + lcd.refresh(); + } + + sleep(); + } +} + +void init_K64F() +{ + // on-board LEDs are active-low, so set pin high to turn them off. + r_led = 1; + g_led = 1; + b_led = 1; + + // since the on-board switches have external pull-ups, we should disable the internal pull-down + // resistors that are enabled by default using InterruptIn + sw2.mode(PullNone); + sw3.mode(PullNone); + +} + +void error() +{ + while(1) { // if error, hang while flashing error message + r_led = 0; + wait(0.2); + r_led = 1; + wait(0.2); + } +} + +void init_serial() +{ + // set to highest baud - ensure terminal software matches + pc.baud(115200); +} + +void move_ship_isr() +{ + g_move_ship_flag = true; +} + +void MoveShip() +{ + //Clears the ship + for (int col = 0; col < 9; col++) { + for (int row = 0; row < 5; row++) { + if(ship_bitmap[row][col]) { + lcd.clearPixel(ship_xpos+col, ship_ypos+row); + } + } + } + + //Changes the position of the ship when the joystick is moved, capping at 0 and 75 so it always fits on the screen + if (joystick.GetXValue() < 0.25f) { + ship_xpos--; + if (ship_xpos < 0) { + ship_xpos = 0; + } + } else if (joystick.GetXValue() > 0.75f) { + ship_xpos++; + if (ship_xpos > 75) { + ship_xpos = 75; + } + } + + //Redraws the ship + for (int col = 0; col < 9; col++) { + for (int row = 0; row < 5; row++) { + if(ship_bitmap[row][col]) { + lcd.setPixel(ship_xpos+col, ship_ypos+row); + } + } + } +} + +void move_enemies_isr() +{ + g_move_enemies_flag = true; +} + +//Sets the position and aliveness of the small invaders +void InitSmallInvaders() +{ + for (int i = 0; i < no_of_small_invaders; i++) { + small_invader[i].x_pos = 2+ (i*12); + small_invader[i].y_pos = 7; + small_invader[i].is_alive = true; + } +} + +void DrawSmallInvaders() +{ + //For each small invader clear and redraws them if they're alive + for (int i = 0; i < no_of_small_invaders; i++) { + //Clears the enemy position + lcd.drawRect(small_invader[i].x_pos, small_invader[i].y_pos, 8, 6, 2); + + //Checks if the invader is alive + if (small_invader[i].is_alive) { + //Reads off the bitmap and sets the allowed pixels + int col = 0; + int row = 0; + //Flips the bitmap everytime the function is called + if (small_invader_in_state2) { + for (col = 0; col < col_no; col++) { + for (row = 0; row < row_no; row++) { + if(small_invader_bitmap_1[row][col]) { + lcd.setPixel(small_invader[i].x_pos + col, small_invader[i].y_pos + row); + } + } + } + } else { + for (col = 0; col < col_no; col++) { + for (row = 0; row < row_no; row++) { + if(small_invader_bitmap_2[row][col]) { + lcd.setPixel(small_invader[i].x_pos + col, small_invader[i].y_pos + row); + } + } + } + } + } + } + //Flips the flag so the bitmap can be switched + small_invader_in_state2 = !small_invader_in_state2; +} \ No newline at end of file