This project is a DIY mbed version of your favorite childhood game

Dependencies:   mbed 4DGL-uLCD-SE LCD_fonts SDFileSystem MMA8452

Files at this revision

API Documentation at this revision

Comitter:
aklaussen
Date:
Sun Apr 14 01:39:35 2019 +0000
Commit message:
publish working code;

Changed in this revision

4DGL-uLCD-SE.lib Show annotated file Show diff for this revision Revisions of this file
CursorController.cpp Show annotated file Show diff for this revision Revisions of this file
CursorController.h Show annotated file Show diff for this revision Revisions of this file
GettingStarted.html Show annotated file Show diff for this revision Revisions of this file
LCD_fonts.lib Show annotated file Show diff for this revision Revisions of this file
MMA8452.lib Show annotated file Show diff for this revision Revisions of this file
RPG/RPG.cpp Show annotated file Show diff for this revision Revisions of this file
RPG/RPG.h Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
SaveFile.cpp Show annotated file Show diff for this revision Revisions of this file
SaveFile.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mbed_config.h Show annotated file Show diff for this revision Revisions of this file
menu.cpp Show annotated file Show diff for this revision Revisions of this file
menu.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4DGL-uLCD-SE.lib	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/4180_1/code/4DGL-uLCD-SE/#2cb1845d7681
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CursorController.cpp	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,10 @@
+#include "CursorController.h"
+
+
+int CursorController::getX(){
+    return (int)(XPot * 128);
+    }
+
+int CursorController::getY(){
+    return (int)(YPot * 128);
+    }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CursorController.h	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,9 @@
+#include "mbed.h"
+class CursorController {
+    public:
+        AnalogIn XPot;
+        AnalogIn YPot;
+        CursorController():XPot(p19), YPot(p20){};
+        int getX();
+        int getY();
+    };
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GettingStarted.html	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html lang="en-US">
+    <head>
+        <meta charset="UTF-8">
+        <meta http-equiv="refresh"
+              content="1;url="https://os.mbed.com/docs/latest/tools/exporting.html>
+        <script type="text/javascript">
+            window.location.href = "https://os.mbed.com/docs/latest/tools/exporting.html"
+        </script>
+        <title>Page Redirection</title>
+    </head>
+    <body>
+        If you are not redirected automatically, please follow the
+        <a href='https://os.mbed.com/docs/v5.6/tools/exporting.html/'>link to the online exporter documentation</a>
+    </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LCD_fonts.lib	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/dreschpe/code/LCD_fonts/#d0b7d7bf1f56
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMA8452.lib	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/ashleymills/code/MMA8452/#a92a632a0cc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPG/RPG.cpp	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,83 @@
+/**
+* =============================================================================
+* Rotary Pulse Generator class (Version 0.0.1)
+* =============================================================================
+* Copyright (c) 2012 Christopher Anderson
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+* =============================================================================
+*/
+ 
+#include "RPG.h"
+#include "mbed.h"
+
+/**
+ * Constructor(Channel A input pin, Channel B input pin, Pushbutton input pin)
+ */
+RPG::RPG(PinName pA, PinName pB, PinName pPB)
+    : chRPG(pA, pB), PB(pPB)
+    {
+        chRPG.input();
+        chRPG.mode(PullUp);
+        PB.mode(PullUp);
+        wait_us(10);
+        RPGO = chRPG;
+    }
+    
+/**
+ *Destructor
+ */
+RPG::~RPG()
+{}
+
+/**
+ *reads and debounces push button returns bool result
+ */
+bool RPG::pb()
+{
+    int check = PB;
+    wait_us(5);
+    if((!check) && !PB)
+    {
+        return true;
+    }
+    else return false;
+}
+
+/**
+ *Determines direction of rotation returns:
+ *1 for clockwise
+ *-1 for counter-clockwise
+ *0 for no rotation
+ */
+int RPG::dir()
+{
+    int dir = 0;
+    RPGO = chRPG;
+    wait(.005);
+    RPGN = chRPG;
+    if(RPGN != RPGO)
+    {
+        if((RPGN & 1) != (RPGO >> 1)) dir = 1;
+        else dir = -1;
+    }
+    else dir = 0;
+    RPGO = RPGN;
+    return dir;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RPG/RPG.h	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,54 @@
+/**
+ * =============================================================================
+ * Rotary Pulse Generator class (Version 0.0.1)
+ * =============================================================================
+ * Copyright (c) 2012 Christopher Anderson
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ * =============================================================================
+ */
+ 
+#ifndef MBED_RPG_H
+#define MBED_RPG_H
+
+#include "mbed.h"
+
+/**
+ * Constructor(Channel A input pin, Channel B input pin, Pushbutton input pin)
+ */
+class RPG{
+public:
+    RPG(PinName pA, PinName pB, PinName pPB);
+    
+    //Destructor
+    ~RPG();
+    
+    //Get Direction 
+    int dir();
+    //Check Push Button
+    bool pb();
+
+    
+private:
+    BusInOut chRPG;
+    DigitalIn PB;
+    int RPGO;
+    int RPGN;
+};
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/aklaussen/code/SDFileSystem/#f90125a79901
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SaveFile.cpp	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,81 @@
+#include <vector>
+#include <string>
+
+
+#include "mbed.h"
+#include "uLCD_4DGL.h"
+#include "SDFileSystem.h"
+
+#include "SaveFile.h"
+
+extern uLCD_4DGL uLCD;
+extern SDFileSystem sd;
+
+int save_image() {
+    char fn[100];
+    sprintf(fn, "/sd/%d", get_highest_number(read_file_names()));
+    FILE *fp = fopen(fn, "wb");
+    if (fp == NULL) {
+        printf("Couldn't open file");
+        return -1;
+    }
+    printf("Grabbing Pixel Values!");
+    int pix_buf[128];
+    for (int i = 0; i < 128; i++) {
+        for (int j = 0; j < 128; j++) {
+            pix_buf[j] = color_convert(uLCD.read_pixel(i,j));
+            //printf("Pixel Color is 0x%08x\r\n", color_convert(pix_buf[j]));
+        }
+        //printf("Writing line %d", i);
+        fwrite(pix_buf, sizeof(int), 128, fp);
+    }
+    fclose(fp);  
+    return 0;
+    }
+
+int read_image(const char* fn) {
+    FILE * fp = fopen(fn, "rb");
+    if (fp == NULL)
+        return -1;
+    int pix = 0;
+    for (int i = 0; i < 128; i++) {
+        for (int j = 0; j < 128; j++) {
+            fread(&pix, sizeof(int), 1, fp);
+            uLCD.pixel(i, j, pix);
+        }
+    }
+
+ return 0;
+ }
+
+int color_convert(int pixel) {
+    int red_mask = 0xF800;
+    int green_mask = 0x7E0;
+    int blue_mask = 0x1F;
+    int red_value = (pixel & red_mask) >> 11;
+    int green_value = (pixel & green_mask) >> 5;
+    int blue_value = (pixel & blue_mask);
+    // Expand to 8-bit values.
+    int red   = red_value << 3;
+    int green = green_value << 2;
+    int blue  = blue_value << 3;
+    int color = (red << 16) | (green << 8) | (blue);
+    return color;
+    }
+std::vector<std::string> read_file_names()
+{
+    char* dir = "/sd/";
+    DIR *dp;
+    struct dirent *dirp;
+    dp = opendir(dir);
+  //read all directory and file names in current directory into filename vector
+    std::vector<std::string> filenames;
+    while((dirp = readdir(dp)) != NULL) {
+        filenames.push_back(string(dirp->d_name));
+    }
+    closedir(dp);
+    return filenames;
+}
+int get_highest_number (std::vector<std::string> filenames) {
+    return filenames.size(); 
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SaveFile.h	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,11 @@
+#include <vector>
+#include <string>
+
+// Some utilities for saving images off the screen 
+
+int save_image(); // save the current pixel values from the screen
+int read_image(const char * fn = "/sd/save"); // read from a file back into the screen pixel by pixel
+int color_convert(int); // unpack from RGB 565 to regular HEX RGB
+
+std::vector<std::string> read_file_names();
+int get_highest_number (std::vector<std::string> filenames);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,150 @@
+#include "mbed.h"
+#include "stdio.h"
+#include "uLCD_4DGL.h"
+#include "menu.h"
+#include "RPG.h"
+#include "CursorController.h"
+#include "math.h"
+#include "MMA8452.h"
+#include "SaveFile.h"
+#include "stdlib.h"
+#include "SDFileSystem.h"
+
+uLCD_4DGL uLCD(p13, p14, p15); // serial tx, serial rx, reset pin;
+SDFileSystem sd(p5, p6, p7, p8, "sd");
+Serial pc(USBTX, USBRX);
+
+BusIn bus1(p21, p22);
+BusIn bus2(p23, p18);
+BusIn bus3(p17, p16);
+int color;
+
+DigitalOut connectionLed(LED1);
+
+double x, y, z, accMag;
+
+MMA8452 acc(p28, p27, 100000);
+
+CursorController c;
+//intialize knobs
+AnalogIn left_pot(p20);
+AnalogIn right_pot(p19);
+InterruptIn push_button(p25, PullUp);
+
+volatile bool pushed = false;
+
+void button_cb() {
+    pushed = true;
+}
+
+std::string endLabel;
+int game_mode = 1;
+
+DigitalOut led1(LED1);
+DigitalOut led4(LED4);
+
+void new_game() 
+{
+    uLCD.background_color(BLACK);  
+    uLCD.cls();
+}
+
+void load_game(std::string fileName)
+{
+    uLCD.cls();
+    std::string base = "/sd/";
+    read_image((base.append(fileName)).c_str());
+}
+
+void save_game()
+{
+    save_image();
+}
+
+int main()
+{
+    uLCD.cls();
+    uLCD.baudrate(3000000); //jack up baud rate to max for fast display
+//    
+    int lastX, lastY, X, Y;
+    lastX = c.getX(); lastY = c.getY();
+    wait(.5);
+    
+    bus1.mode(PullUp);
+    bus2.mode(PullUp);
+    bus3.mode(PullUp);
+
+    
+    while(true) {
+        if (game_mode == 0) {
+            while (1) {
+                
+                X = c.getX(); Y = c.getY();
+                uLCD.line(lastX, lastY, X, Y, color);
+                //printf("Drew a line from (%d,%d) to (%d, %d)\r\n", lastX, lastY, X, Y);
+                lastX = X; lastY = Y;
+
+
+                // 5.  read the dip switches
+                // 6.  bit math that into three color values (top 2 bits of each color)
+                // 7.  update the color variables
+                
+                color = 0;
+                color |= (bus1 * 64);
+                color |= (bus2 * 64 * 2*2*2*2*2*2*2*2);
+                color |= (bus3 * 64 * 2*2*2*2*2*2*2*2 * 2*2*2*2*2*2*2*2);
+//                pc.printf("color: %x\r\n", color);
+        
+                // 8.  read the IMU
+                // 9.  decide if the acceleration magnitude is great enough to clear
+                //     todo: debounce???
+                // 10. if so, clear LCD screen
+                acc.readXYZGravity(&x,&y,&z);
+                accMag = sqrt(x*x + y*y + z*z);
+                if(accMag > 2.5) {
+                    uLCD.cls();
+                }
+                
+                if (pushed) {
+                    wait(0.5);
+                    pushed = false;
+                    // write image to SD card
+                    save_game();
+                    game_mode = 1;
+                    break;
+                }
+            }
+        } else {
+            uLCD.background_color(BLACK);
+            uLCD.cls();
+            pc.printf("Initializing menu...\r\n");
+            push_button.fall(&button_cb);
+            Menu* main_menu = new Menu();
+            main_menu->add_child(new Menu("END", "Start New"));
+            main_menu->add_child(new Menu("menu1", "Load Picture"));
+            // connect to file system
+            // build menu tree
+            main_menu->entries[1]->add_child(new Menu("sm1", "Go Back", Menu::go_back));
+            char buffer [9000];
+            for (int i = 0; i < get_highest_number(read_file_names()); i++) {
+                sprintf(buffer, "%d", i);
+                pc.printf("adding file %d", i);
+                std::string filename = buffer;
+                main_menu->entries[1]->add_child(new Menu("END", buffer));            
+            }
+            main_menu->set_active();
+            endLabel = Menu::run();  
+            pc.printf("menu terminated with message: \r\n");
+            pc.printf(endLabel.c_str());
+            pc.printf("\r\n");
+            
+            if (endLabel == "Start New") {
+                new_game();
+            }
+            else {
+                load_game(endLabel);
+            }
+            game_mode = 0; //start game
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_config.h	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,50 @@
+/*
+ * mbed SDK
+ * Copyright (c) 2017 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Automatically generated configuration file.
+// DO NOT EDIT, content will be overwritten.
+
+#ifndef __MBED_CONFIG_DATA__
+#define __MBED_CONFIG_DATA__
+
+// Configuration parameters
+#define MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED           0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX                8                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE        9600                                                                           // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO          0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_DECODE_HTTP_URL_STR       "\nFor more info, visit: https://armmbed.github.io/mbedos-error/?error=0x%08X" // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED  0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_HIST_ENABLED              0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_HIST_SIZE                 4                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_REBOOT_MAX                1                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED 0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR        0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN          16                                                                             // set by library:platform
+#define MBED_CONF_PLATFORM_POLL_USE_LOWPOWER_TIMER         0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_BAUD_RATE                 9600                                                                           // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL           0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES          0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES      0                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT             1                                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_USE_MPU                         1                                                                              // set by library:platform
+#define MBED_CONF_TARGET_BOOT_STACK_SIZE                   0x1000                                                                         // set by target:Target
+#define MBED_CONF_TARGET_DEEP_SLEEP_LATENCY                0                                                                              // set by target:Target
+#define MBED_CONF_TARGET_MPU_ROM_END                       0x0fffffff                                                                     // set by target:Target
+#define MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE    ETHERNET                                                                       // set by target:LPC1768
+#define MBED_CONF_TARGET_US_TICKER_TIMER                   3                                                                              // set by target:LPC1768
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/menu.cpp	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,102 @@
+#include "mbed.h"
+#include "uLCD_4DGL.h"
+
+#include <string>
+#include <vector>
+
+#include "menu.h"
+
+//devices declared in main
+extern AnalogIn left_pot;
+extern AnalogIn right_pot;
+extern uLCD_4DGL uLCD;
+extern bool pushed;
+
+
+//constructors
+Menu::Menu (std::string name,
+            std::string label,
+            void (*onClick)()) {
+                this->name = name;
+                this->label = label;
+                this->parent = parent;
+                this->onClick = onClick;                   
+                }
+    
+//static initialization
+int Menu::selected_entry = 0;
+Menu* Menu::active_menu = NULL;
+    
+void Menu::go_back(){
+    active_menu = active_menu->parent;
+    active_menu->draw();
+    active_menu->draw_cursor();
+    }
+void Menu::set_active(){
+    active_menu = this;
+    }
+
+void Menu::draw(){
+    uLCD.cls();
+    uLCD.color(GREEN);
+    uLCD.locate(0,0);
+    //print each of the sub-entries
+    for(int i = 0; i < this->entries.size(); i++) {
+        uLCD.printf("  %s\n", this->entries[i]->label.c_str());
+        }
+    }
+void Menu::clear_cursor(){
+    uLCD.locate(0, Menu::selected_entry);
+    uLCD.color(BLACK);
+    uLCD.printf("*");
+    }
+void Menu::draw_cursor() {
+    uLCD.locate(0, Menu::selected_entry);
+    uLCD.color(GREEN);
+    uLCD.printf("*");
+    }
+void Menu::update_cursor() {
+    int new_selection = (int)(left_pot * Menu::active_menu->entries.size());
+    if (new_selection == Menu::active_menu->entries.size()) new_selection--;
+    if (new_selection != Menu::selected_entry) {
+        clear_cursor();
+        selected_entry = new_selection;
+        draw_cursor();
+    }
+}
+std::string Menu::run() {
+    active_menu->draw();
+    draw_cursor();
+    while(1) {
+        update_cursor();
+        if(pushed) {
+            wait(.5);
+            pushed = false;
+            //if(active_menu->entries.size() == 0)
+             //   uLCD.printf("No Entries!");
+            if (active_menu->entries[selected_entry]->select() == 1)
+                continue;
+            else
+                return active_menu->entries[selected_entry]->label;
+            }   
+        }
+    }
+int Menu::select() {
+    if (name == "END") {
+        return 0;
+    }
+    if (onClick != NULL) {
+        onClick();
+        return 1;
+    } else {
+        set_active();
+        draw();
+        return 1;        
+                
+    }
+    
+    }
+void Menu::add_child(Menu* child) {
+    entries.push_back(child);
+    child->parent = this;
+    }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/menu.h	Sun Apr 14 01:39:35 2019 +0000
@@ -0,0 +1,37 @@
+#include <string>
+#include <vector>
+#include <memory>
+
+class Menu {
+    public:
+        //methods
+        int select();
+        void draw();
+        void update_selection();
+        void set_active();
+        void add_child(Menu* child);
+        //static methods
+        static void go_back();
+        static void clear_cursor();
+        static void draw_cursor();
+        static void update_cursor();
+        static std::string run();
+        
+        //members
+        std::string name;
+        std::string label;
+        Menu * parent;
+        std::vector<Menu*> entries;
+        void (*onClick) ();
+       
+        //constructors
+        Menu (std::string name="",
+              std::string label="",
+              void (*onClick)()=NULL);
+        
+    private:
+        static Menu* active_menu;
+        static int selected_entry;
+    };
+
+