-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add app format to wiki * Create multi-platform.md * Update multi-platform.md * Update Home.md * Update README.md
- Loading branch information
1 parent
f9b3521
commit c94ff4d
Showing
3 changed files
with
251 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,7 @@ MicroHydra is a simple MicroPython based app launcher with some OS-like features | |
*MicroHydra is currently going through a major overhaul to enable multi-platform support. Many features and APIs will likely undergo significant change by version 2.0.* | ||
please use the "releases" section for stable versions of MicroHydra. | ||
|
||
This code was built with MicroPython v1.23.0 (preview), for a Generic ESP32-S3 controller. | ||
This code was built with MicroPython v1.23, for the ESP32-S3. | ||
|
||
The main function of MicroHydra is to provide an interface to easily switch between MicroPython apps. | ||
And to help lower the barriers to entry for anyone wanting to develop apps for their Cardputer. | ||
|
@@ -36,9 +36,7 @@ Python scripts can be placed in the /apps folder on the flash, or in a /apps fol | |
|
||
Take a look at the [wiki](https://github.com/echo-lalia/Cardputer-MicroHydra/wiki) for some basic guides to get you started with a MicroPython app. | ||
|
||
If you're looking for the compiled firmware, that lives over [here](https://github.com/echo-lalia/microhydra-frozen). | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
echo-lalia
Author
Owner
|
||
|
||
And for a work-in-progress repository of MicroHydra apps, see [here](https://github.com/echo-lalia/MicroHydra-Apps) | ||
And for a repository of community-made MicroHydra apps, see [here](https://github.com/echo-lalia/MicroHydra-Apps). | ||
|
||
<br /><br /><br /> | ||
|
||
|
@@ -67,9 +65,7 @@ Apps are designed to work very simply in this launcher. Any Python file placed i | |
This means that a simple app can be contained as one script, which will be executed when the app is selected from the launcher. | ||
It also means more complicated apps can place a startup file in the apps directory, which imports anything it needs from another folder in the filesystem. | ||
|
||
Some apps for MH can be found [here](https://github.com/echo-lalia/MicroHydra-Apps), but there are many other apps (especially work-in-progress apps) living in other locations, as well. | ||
|
||
*Quick note about apps on the SD card: The apps wont be able to use SPI slot 2 for the display (or anything else) because it will be occupied by the SD card. Thankfully, the display works fine in slot 1.* | ||
Some apps for MH can be found [here](https://github.com/echo-lalia/MicroHydra-Apps), but there are other apps (especially work-in-progress apps) living in other locations, as well. | ||
|
||
<br /><br /><br /> | ||
|
||
|
@@ -78,6 +74,10 @@ Some apps for MH can be found [here](https://github.com/echo-lalia/MicroHydra-Ap | |
|
||
# Installing MicroHydra: | ||
|
||
> NOTE: This guide is for MicroHydra 1.x, and will not work for 2.x due to the new way device-specific source files are dynamically created. | ||
> If you want to test out v2.0, check out the preview binaries in the 'releases' section. | ||
> The full 2.x guides will be coming soon :) | ||
You can install MicroHydra a few different ways. | ||
|
||
- *Install plain .py version on MicroPython:* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
MicroHydra 2.0 brings a major overhaul to the structure of the project, all with the intention of expanding the code to work on multiple different devices, and develop for them all simultaneously. | ||
|
||
This is an overview of how this currently works. | ||
|
||
|
||
<br/> <br/> | ||
|
||
## Main directory structure | ||
|
||
*MicroHydra (base repository)* | ||
│ | ||
├── **src/** | ||
│ \ | ||
│ *This is where the majority of the source code for the program lives* | ||
│ | ||
│ | ||
├── **devices/** | ||
│ \ | ||
│ *This is where the device definitions, and device specific drivers come from* | ||
│ | ||
│ | ||
├── **tools/** | ||
│ \ | ||
│ *`parse_files.py`, and other useful scripts live in here* | ||
│ | ||
│ | ||
└── **MicroHydra/** | ||
\ | ||
*`parse_files.py` creates this directory by combining the source code in `src/`,* | ||
*with the definitions and drivers from `devices/`, for each device.* | ||
|
||
|
||
<br/> <br/> | ||
|
||
## devices/ | ||
|
||
The `devices/` directory contains a `default.yml` file with the following structure: | ||
``` Yaml | ||
# 'constants' contains all the existing hydra constants from device definitions, | ||
# plus the most common value from the devices. | ||
# The values are all strings representing MicroPython code to put in a `const()` declaration | ||
# The keys follow a "_CONST_CASE" naming convention, and always start with "_MH_" | ||
constants: | ||
_MH_CAPS_CASE_KEY_NAME: 'value' | ||
_MH_DISPLAY_BACKLIGHT: '38' | ||
_MH_BATT_ADC: 'None' | ||
|
||
# 'features' contains a list of every single feature that exists in any device definition. | ||
# The entries here follow | ||
features: | ||
- display | ||
- wifi | ||
- keyboard | ||
- any_other_feature | ||
|
||
# This is the MicroPython arch to use when compiling code for the device. | ||
# It is "xtensawin" for any ESP32-S3 based device. | ||
mpy_arch: xtensawin | ||
|
||
# This is the starting point to use when creating a firmware `.bin` file for the device. | ||
# It specifies the name of a directory under `MicroPython/ports/esp32/boards/` | ||
source_board: ESP32_GENERIC_S3 | ||
``` | ||
Then, each device has its own directory containing a `definition.yml` file, along with MicroPython build files and any device-specific drivers. | ||
|
||
*DEVICENAME* | ||
├── definition.yml | ||
├── manifest.py | ||
├── mpconfigboard.cmake | ||
└── *lib/* | ||
└── device_drivers.py | ||
|
||
The `definition.yml` file has the exact same structure as the `default.yml` file, but the values are tailored to that specific device. | ||
Any "constants" that are not in `definition.yml` use the defaults set in `default.yml` instead. | ||
Any "features" that are not in `definition.yml` are assumed to not exist on that device. | ||
|
||
Any additional driver files in this folder are coppied over to the device-specific MicroHydra output folder (after copying the `src` files over) | ||
|
||
|
||
<br/> <br/> | ||
|
||
## Magic Constants | ||
|
||
MicroHydra's 'magic' constants, are device constants that will be automatically replaced with the apropriate device-specific value by `tools/parse_files.py`. | ||
These constants are declared in the device `definition.yml` file, and they can used in any file in `src/`. | ||
|
||
For example, if I write a file `src/lib/example.py`, and include the following line: | ||
``` Py | ||
_MH_DISPLAY_WIDTH = const(1234) | ||
``` | ||
When I run `parse_files.py`, the corrisponding output file for the Cardputer will be created in `MicroHydra/CARDPUTER/lib/example.py`, and the line will now look like this: | ||
``` Py | ||
_MH_DISPLAY_WIDTH = const(240) | ||
``` | ||
|
||
*Side note:* | ||
> Because MicroPython supports 'real' constants, this functionality can be especially useful for MicroHydra. | ||
> When a MicroPython program is run, it must first be compiled into bytecode. At this time, the MicroPython compiler actually replaces the constants with hard-coded values. | ||
> This can slightly increase speed (no need to look-up the values), and can decrease RAM usage (no need to store the value name). | ||
|
||
|
||
|
||
<br/> <br/> <br/> | ||
|
||
## Hydra conditionals | ||
|
||
It's really difficult to account for all the possible differences between devices just by using device constants, and separate driver files. | ||
This is especially true because of the limited memory available to work with on these devices *(assuming you don't have PSRAM)*, so you really don't want to have code you don't need just taking up memory space. | ||
|
||
That's where this final (and most complicated) feature of `tools/parse_files.py` comes in. | ||
|
||
<br/> <br/> | ||
|
||
Hydra conditionals are used to selectively include or exclude blocks of code from `src/` based on device names, included features, and whether the code is 'frozen' or not. | ||
|
||
These statements take the following form: | ||
``` Py | ||
# mh_if {feature}: | ||
my_code() | ||
# mh_end_if | ||
``` | ||
In the above example, if {feature} is in the device-specific `definition.yml` file, then the line `my_code()` will be included in the output code for that device. Otherwise, the entire line is removed. | ||
The `# mh_if...` and `# mh_end_if` lines will be removed regardless of whether or not {feature} matches a feature in the device definition. | ||
|
||
<br/> | ||
|
||
You can also use the "not" keyword: | ||
``` Py | ||
# mh_if not {feature}: | ||
my_code() | ||
# mh_end_if | ||
``` | ||
Which, as expected, will exclude this line of code when {feature} exists on a device. | ||
|
||
<br/> | ||
|
||
If/elif/else statements are also supported: | ||
``` Py | ||
# mh_if {feature}: | ||
feature_code() | ||
# mh_else_if {other_feature}: | ||
other_feature_code() | ||
# mh_else: | ||
no_features_code() | ||
# mh_end_if | ||
``` | ||
|
||
<br/> | ||
|
||
In order to make testing this code directly a bit easier, these conditionals also work on 'commented-out' code. | ||
In this example, the commented out code will be uncommented if the device has no touchscreen: | ||
``` Py | ||
# mh_if touchscreen: | ||
print("this device has a touchscreen!") | ||
# mh_else: | ||
# print("this device has no touchscreen!") | ||
# mh_end_if | ||
``` | ||
|
||
> Note the spacing after the `#`. In order for the commenting/uncommenting to work correctly, this extra space needs to be there. | ||
> This is because Python cares a lot about indentation, and without this space, the `parse_files` script might not correctly guess what the actual indentation was meant to be. | ||
|
||
<br/> <br/> | ||
|
||
Finally, here are some real examples from `src/` to illustrate these features further! | ||
|
||
> From launcher/launcher.py: | ||
``` Py | ||
DISPLAY = display.Display( | ||
# mh_if spi_ram: | ||
# use_tiny_buf=False, | ||
# mh_else: | ||
use_tiny_buf=True, | ||
# mh_end_if | ||
) | ||
``` | ||
``` Py | ||
# add an appname for builtin file browser | ||
app_names.append("Files") | ||
# mh_if frozen: | ||
# app_paths["Files"] = ".frozen/launcher/files" | ||
# mh_else: | ||
app_paths["Files"] = "/launcher/files" | ||
# mh_end_if | ||
``` | ||
|
||
<br/> | ||
|
||
> From launcher/settings.py: | ||
``` Py | ||
# mh_if touchscreen: | ||
def process_touch(keys): | ||
events = kb.get_touch_events() | ||
for event in events: | ||
if hasattr(event, 'direction'): | ||
# is a swipe | ||
keys.append(event.direction) | ||
elif _CONFIRM_MIN_X < event.x < _CONFIRM_MAX_X \ | ||
and _CONFIRM_MIN_Y < event.y < _CONFIRM_MAX_Y: | ||
keys.append("ENT") | ||
# mh_end_if | ||
``` | ||
``` Py | ||
while True: | ||
keys = kb.get_new_keys() | ||
# mh_if touchscreen: | ||
process_touch(keys) | ||
# mh_end_if | ||
``` | ||
|
||
<br/> | ||
|
||
> From lib/display/display.py: | ||
``` Py | ||
def __init__(self, use_tiny_buf=False, **kwargs): | ||
# mh_if TDECK: | ||
# # Enable Peripherals: | ||
# machine.Pin(10, machine.Pin.OUT, value=1) | ||
# mh_end_if | ||
``` | ||
|
||
<br/> <br/> | ||
|
||
*Final note on hydra conditionals:* | ||
> These conditionals can also be nested. However, this is discouraged because it becomes very hard to read (because indentation must be maintained to match the original code). | ||
> It's an option in your toolkit, but please try to find another solution first if it comes to that. |
Why is the link to the compiled firmware not being linked?