Epsilon Graphing Calculator OS

repository·master·Indexed 22 days ago

https://github.com/numworks/epsilon

A high-performance operating system for high school mathematics featuring eleven built-in applications. It is structured into five layers: Ion (Hardware Abstraction), Kandinsky (Graphics Engine), Escher (GUI Toolkit), Poincaré (Mathematics Engine), and Apps. Epsilon supports multiple platforms including physical NumWorks hardware, native simulators (Windows, macOS, Linux), and web-based simulation via Emscripten. It also provides the External App Development Kit (EADK) for creating independent .nwa applications in C, C++, and Rust.

Tokens
26.5K
Snippets
43
Records
163
Agent score
83%

What's inside Epsilon

  1. Overview of liba

    master
    liba is a minimal, adhoc implementation of a subset of the standard C library (libc). It is designed to provide essential types and functions without the overhead or licensing complexities of a full-scale libc implementation. It does not aim for full standard compliance but provides the necessary entities required by the project.
  2. Getting started with Epsilon

    master

    Epsilon is a high-performance graphing calculator operating system containing eleven apps for high school mathematics. To begin using or developing with Epsilon, you can:

    1. Try it in the browser: Use the online simulator to experience the OS without installation.
    2. Read the core documentation: The main documentation provides the foundation for understanding the project.
    3. Develop for the platform: Depending on your goal, you can build custom firmware or create external apps.
  3. Overview of HIDAPI capabilities and back-ends

    master

    HIDAPI is a multi-platform library for interfacing with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and Mac OS X. It can be used as a shared library (.so or .dll) or embedded directly into an application by adding a single header and a single source file per platform.

    Supported Back-ends

    • Windows: Uses hid.dll.
    • Linux/hidraw: Uses the kernel's hidraw driver. Supports both USB and Bluetooth. Note that keyboards, mice, and certain blacklisted devices may not have hidraw nodes. Kernels prior to 2.6.39 may have limitations on feature reports.
    • Linux/libusb: Uses libusb-1.0. Does not support Bluetooth.
    • FreeBSD: Uses libusb-1.0.
    • Mac OS X: Uses IOHidManager.
  4. What is Poincare?

    master

    Poincare is the algebraic computation engine for Epsilon. It is responsible for processing text-based mathematical expressions (e.g., 1+2*3) by converting them into an internal tree structure. Once in this tree format, expressions can undergo several operations:

    • Parsing: Converting raw text into a structured format using a custom lexer and parser.
    • Simplification: Applying algebraic rules to reduce expressions to their simplest form.
    • Approximation: Calculating numerical approximations of expressions.
    • Pretty printing: Laying out expressions in 2D to match textbook-style formatting.
  5. Explore the Sample C app for Epsilon

    master

    The sample_c application serves as a demonstration of how to build and run C applications on a NumWorks calculator using Epsilon. The app showcases several core capabilities:

    • Text Rendering: Displays content from a file (e.g., src/input.txt).
    • Graphics: Renders colorful rectangles on the screen.
    • Input Handling: Implements a square pointer that responds to user input via the calculator's arrow keys.
  6. What is Ion and how does it work?

    master

    Ion is a hardware abstraction library used throughout Epsilon. Instead of interacting with hardware registers directly, Epsilon code calls Ion functions (e.g., serialNumber(), LED::setColor(), Display::pushRect()).

    This abstraction allows the same Epsilon logic to run on multiple platforms by providing different implementations of the same Ion functions. For example, Display::pushRect() can be implemented to drive a physical LCD panel on a calculator or to render content in a web browser via Emscripten.

  7. What is ION and how is it used?

    master

    ION is the hardware abstraction layer (HAL) for the Epsilon project. Its primary responsibility is managing I/O operations.

    ION provides a consistent set of headers that abstract hardware-specific details. These headers are implemented for different targets, including physical devices and simulators, allowing higher-level code to remain portable across different hardware environments. Additionally, ION is responsible for initializing the boot environment.

  8. What is a Tree in Poincare?

    master

    A Tree is the central data structure in Poincare. It represents an arbitrary, editable tree stored as a contiguous chunk of memory, making it efficient to move, copy, and compare.

    Memory Layout

    Every Tree starts with a Node followed by its children in memory. The structure is composed of two types of blocks:

    • TypeBlock: The first block in a Node, containing a Type enum value that identifies what the tree represents.
    • ValueBlock: All subsequent blocks. These can represent the number of children for n-ary nodes or contain specific values (e.g., numbers are represented as leaves where the value is stored inside the node).

    Key Characteristics

    • Iteration: Trees can only be iterated forward. You cannot access a parent or a previous sibling directly; you must walk down from a known root using parentOfDescendant.
    • Pointers: Because trees have variable sizes, they are manipulated via Tree * pointers. Use const Tree * to indicate read-only access.
    • Feature Sets: Some nodes are controlled by feature macros (e.g., POINCARE_MATRIX). If a feature is disabled, tree->isFoo() will return false and related switch cases will be dropped at compile time.
  9. Use switch and C-style code for Tree structures

    master

    To optimize performance and avoid heavy v-tables, Poincare avoids heavy use of virtuality on the Tree structure. Instead of overriding methods in subclasses, use switch statements on the tree type within static methods or modules.

    // Static method of Simplification module. Tree is a final class.
    bool Simplify(Tree* t) {
      switch (t->type()) {
        case Type::Add:
          return SimplifyAdd(t);
        // ...
      }
    }
  10. Writing code for bare metal environments

    master

    Epsilon is embedded firmware, which differs from standard OS-based programming in several ways:

    • No Virtual Memory: The firmware must know the exact memory layout in advance (stack location, heap, global variables, read-only variables, and code location).
    • No Standard 'main' Function: On Cortex-M devices, the CPU jumps to the address at 0x00000000 (the start of flash memory) after a reset. Execution begins exactly where the firmware is mapped.
    • Linker Scripts: Epsilon uses scripted embedded linkers to enforce precise memory layouts. The linker script can be found at ion/src/device/userland/flash/userland_shared.ld.
    • System Initialization: Since there is no OS to handle startup, tasks like initializing global variables to zero must be handled manually. This is implemented in ion/src/device/shared/boot/rt0.cpp.
  11. How the expression metric is used for simplification

    master

    The simplification process uses a metric to determine the 'best' form of an expression. A metric is a function $m: E \longrightarrow \mathbb{R_{\geq 0}}$ that assigns a score representing the 'size' or 'complexity' of an expression.

    During advanced reduction, the algorithm aims to minimize this metric. At each leaf of the search tree, the metric is called to compare the current expression against the best (lowest metric) expression found so far.

    Key Metric Behaviors:

    • Size counting: A basic metric counts the number of nodes in an expression.
    • Multiplicative coefficients: To encourage reducing the contents of specific functions (like Abs, arg, im, root, or ln), the metric increases the cost of their children using a coefficient.
    • Beautification awareness: The metric can ignore costs for nodes that are expected to be cleaned up by the beautification step (e.g., ignoring the cost of multiplication in -1 * A because it will be beautified to -A).
    • Null metric: A null metric indicates an expression is ideal and cannot be reduced further (e.g., $2 + \pi$). This is implemented via CannotBeReducedFurther in metric.h.