Space Invaders - Embedded Systems Project 15/16 - Avinash Patel 200860407

Dependencies:   Joystick N5110 SDFileSystem mbed

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