
This project is a DIY mbed version of your favorite childhood game
Dependencies: mbed 4DGL-uLCD-SE LCD_fonts SDFileSystem MMA8452
Revision 0:bce994168592, committed 2019-04-14
- Comitter:
- aklaussen
- Date:
- Sun Apr 14 01:39:35 2019 +0000
- Commit message:
- publish working code;
Changed in this revision
--- /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; + }; + +