RANPW

A versatile platform inspired by Tamagotchi, featuring games and productivity apps, powered by the mbed NXP LPC1768.

Project Overview

The central concept behind the RANPW project is to create a dynamic, Tamagotchi-inspired tool enriched with a selection of games (LCatch, Pong, and LockY) and productivity applications (Cronometer and Termometer). This versatile platform encourages high modularity, enabling individuals with basic C++ knowledge to seamlessly develop and incorporate their custom apps and games. RANPW is designed to operate on the mbed NXP LPC1768 microcontroller, coupled with the mbed application board.

Used Hardware and Library

LCD: C12832

The 32x128 pixel LCD display serves as the primary visual interface for all interactions within the application. To achieve seamless control over the display, I’ve customized the C12832.h library to ensure compatibility with the project’s broader software ecosystem.

Joystick

The joystick plays a pivotal role in navigating through all application interfaces. Its management is facilitated through the APIs provided directly by “mbed.h,” which can be accessed here.

Potentiometer

Both potentiometers are integral to specific user interactions, with one notably enhancing gameplay in the LockY game. The control of these potentiometers is streamlined through the APIs provided by “mbed.h,” as detailed here.

Temperature sensor: LM75BD

The LM75BD temperature sensor is utilized in the “Termometer” application to capture environmental temperature data. The sensor is integrated into the project using the LM75B.h library, with minor modifications to ensure compatibility with the Embed OS CE platform.

Accelerometer: MMA7660

The MMA7660 accelerometer contributes significantly to user interactions, particularly in the Hell and Pong games. To collect data from this component, the MMA7660.h library has been employed with slight modifications to align it with the project’s requirements.

Software

Thread Overview

At startup, RANPW initializes three distinct threads to manage various aspects of its functionality:

Thread 1: User Interface and Interaction

This thread is responsible for overseeing the entire user interface and facilitating interaction with end-users. It dynamically creates and initializes instances of all apps and games while orchestrating their display on the LCD screen. Further insights into this thread’s workings can be found in the Ranpw.h and Ranpw.cpp files.

Thread 2: Kraken’s Management

Thread 2 operates on a straightforward principle, employing basic rand() functions to introduce wait times of 1 to 5 minutes. During these intervals, it randomly decreases the pet’s hunger by a value ranging from 1 to 5. Should the hunger level plummet to zero, the pet’s life diminishes at varying rates—1, 2, or 3 points per minute. Conversely, if hunger surpasses 20, the pet gains 1 life point. Notably, both life and hunger levels have a cap of 25. Detailed insights into this thread’s functionality are available in the live() function within Kraken.cpp.

Thread 3: Data Saving Management

Thread 3 operates with a clear focus on data integrity. It consistently monitors the data stored in the members of the ConcurrentData structure. This structure is vital for ensuring safe data access across multiple threads. When disparities between the stored data and in-memory data are detected, Thread 3 takes action, overwriting the data and saving the respective file in the device’s internal memory.

Class Overview

In the process of realizing the RANPW project, I’ve meticulously crafted 15 different classes to lay the foundation for its functionality and modularity. Each of these components plays a specific role in the project’s architecture:

ConcurrentData

This essential structure serves as the backbone for managing concurrent data access across multiple threads. It ensures data integrity and consistency, preventing conflicts and race conditions.

DataSaver

The DataSaver class is responsible for handling data saving and data loading operations, ensuring that changes to critical data are persistently stored in the device’s internal memory.

Ranpw

The Ranpw class serves as the central hub for user interface management. It oversees the creation and initialization of app and game instances, orchestrates their display on the LCD screen, and manages user input via various hardware interfaces.

Kraken

The Kraken class embodies the behavior and lifecycle of the virtual pet, monitoring key metrics such as hunger and life. It simulates the pet’s interactions with the user.

Bag

The Bag class manages the virtual inventory system, allowing users to collect and interact with food items within the application. It enhances gameplay and engagement.

Cronometer

The Cronometer is a specialized application designed to provide users with a versatile stopwatch.

LCatch

LCatch is one of the interactive games featured in RANPW. It provides an engaging experience where users can test their reflexes and coordination. What sets LCatch apart is its incremental speed feature, where the game progressively increases in difficulty as players successfully capture objects.

LockY

LockY is another game that offers users a unique challenge. It leverages hardware components like potentiometers for gameplay.

Pong

In Pong, players use the accelerometer as a unique input method to control the paddle and engage in the timeless challenge of bouncing a ball.

Hell

Unlike other games, Hell only surfaces when the Kraken’s life reaches zero, triggering the Kraken’s respawn process. Distinguished by its lack of a tutorial, Hell immerses players in a realm where they need to discover how to play by themselves.

Termometer

This class allows users to monitor temperature levels in their environment. What sets this component apart is its ability to visualize temperature data through a graph.

Optimization Strategy

Given the scope of this project, ensuring optimal resource utilization became a crucial aspect of development. To achieve this, I delved into various optimization techniques to maximize the efficiency of the system. Several key strategies were implemented:

  • Global Initialization: To minimize memory usage, I opted to initialize certain variables and resources globally in the main function. This approach prevented them from being allocated in the .bss section and instead placed them in the stack, reducing the overall memory footprint.

  • Sensor Initialization: I centralize sensor initialization within a dedicated class, initializing sensors only once and passing their pointers where needed throughout the project. This approach eliminates redundant sensor reinitialization, conserving more memory

  • Scoped Game Initialization: To further optimize memory allocation, I strategically limited the scope of game initialization. Games are initialized only when required, ensuring they occupy memory space only when actively in use.

  • Pointer Management: Ensuring the absence of dangling or unclean pointers was paramount.

How to Install

Binary

All that is necessary is to download the binary available here and then insert it into the internal storage of the microcontroller.

Compile Yourself

To compile it yourself, I recommend following the official embed OS CE wiki instead. In particular, once the development environment has been configured, you can choose to compile it:

Remember that if you add something new to the project you need also to add it to the CMakeList.txt file.