Skip to content

Commit

Permalink
Tutorial, Icons, better rendering & more (#358)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonmicro committed Jul 9, 2023
2 parents 4cd799a + 04cfef4 commit 2b998dc
Show file tree
Hide file tree
Showing 158 changed files with 3,056 additions and 1,279 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/test-EMULATOR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ jobs:
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
lfs: 'true'
- name: Update packages
run: sudo apt-get update && sudo apt-get upgrade -y
run: sudo apt-get update
- name: Install packages
run: sudo apt-get -y install gcc g++ cmake libsdl2-dev libsdl2-image-dev
run: sudo apt-get -y install gcc g++ cmake libsdl2-dev libsdl2-image-dev python3 python3-pip
- name: Install python packages
run: pip3 install --user -r scripts/requirements.txt
- name: Create build directory
run: mkdir build
- name: CMake ${{ matrix.build-configuration }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-FEATURE.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
lfs: 'true'
- id: get-flag
run: |
echo "feature=$(python3 .github/getWorkflowMatrix.py all_flags)" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -56,6 +57,7 @@ jobs:
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
lfs: 'true'
- name: Cache pip
uses: actions/cache@v3
with:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-OS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
lfs: 'true'
- uses: dorny/paths-filter@v2.11.1
id: filter
with:
Expand Down Expand Up @@ -49,6 +50,7 @@ jobs:
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
lfs: 'true'
- name: Cache pip
uses: actions/cache@v3
with:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-OSW.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
lfs: 'true'
- uses: dorny/paths-filter@v2.11.1
id: filter
with:
Expand Down Expand Up @@ -62,6 +63,7 @@ jobs:
uses: nschloe/action-cached-lfs-checkout@v1.2.1
with:
submodules: recursive
lfs: 'true'
- name: Cache pip
uses: actions/cache@v3
with:
Expand Down
19 changes: 18 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required (VERSION 3.10)
cmake_minimum_required (VERSION 3.12)
project (OSW-OS-Emulator)

set(CMAKE_CXX_STANDARD 20)
Expand Down Expand Up @@ -60,13 +60,27 @@ target_link_libraries(ImGUI LINK_PUBLIC
${SDL2IMAGE_LIBRARIES}
)

# OSW custom prebuild-scripts
find_package(Python3 REQUIRED COMPONENTS Interpreter)
file(GLOB_RECURSE INCLUDE_OSW_ASSETS ./include/assets/img/** ./include/assets/www/**)
add_custom_target(
osw_script_prebuild_assets ALL
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/build/prebuild_assets.py --output-asset-path ${CMAKE_CURRENT_SOURCE_DIR}/include/assets
BYPRODUCTS ${INCLUDE_OSW_ASSETS}
COMMENT "Generating OSW assets..."
)

# Emulator
file(GLOB_RECURSE SOURCES_OSW ./src/*.cpp)
file(GLOB_RECURSE SOURCES_OSW_EMULATOR ./emulator/src/*.cpp)
add_executable(emulator.run
${SOURCES_OSW}
${SOURCES_OSW_EMULATOR}
)
add_dependencies(emulator.run
osw_script_prebuild_assets
)
target_include_directories(emulator.run PUBLIC
./emulator/include
./include
Expand Down Expand Up @@ -99,8 +113,11 @@ target_compile_definitions(emulator.run PUBLIC
$<$<CONFIG:Release>:
NDEBUG=1
>
# Uncomment the following line to use a different locale (only for the emulator, for the whole OS use the config variable!)
# LOCALE="locales/en-US.h"
# Comment these as you wish...
OSW_FEATURE_STATS_STEPS
OSW_APPS_EXAMPLES=1
GAME_SNAKE=1
GAME_BRICK_BREAKER=1
TOOL_FLASHLIGHT=1
Expand Down
12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
# How to contribute to Open-smartwatch

In case the `develop` branch is ahead of the `master` branch and the `develop` branch is stabile enough, we periodically merge it into the `master`.
In case the `develop` branch is ahead of the `master` branch and the `develop` branch is stable enough, we periodically merge it into the `master`.

In order to contribute new or updated documentation, you must first create a GitHub account and fork the original repository to your own account. You can make changes, save them in your repository and then create a pull request against this repository.

Unless you are opening a pull request which only makes small corrections (for instance correcting a typo), you are more likely to get traction for your changes if you open an issue first to discuss the proposed changes.

**IMPORTANT** If you want to create a pull request, please work based on the `develop` branch - so we don't have to rebase it...
**IMPORTANT** If you want to create a pull request, please work based on the most recent `develop` branch - so we don't have to rebase it...

If you are reading this page, you are possibly interested in contributing to our project 😄 . We have an active (and friendly) developer group and would love to get your help! Some common ways you can support us are:

* Testing the code
* Filing issues on GitHub, if you see a problem (or adding detail to existing issues that effect you)
* Reporting issues on GitHub, if you see a problem (or adding detail to existing issues that also affect you)
* Fixing issues 😁
* Adding new features
* Reviewing existing pull requests and possibly also contributing to them.
* Translation. Always a good idea...
* Reviewing existing pull requests and possibly also contributing to them
* Translations are always a good idea...

## How to make a good bug report

Submit according to the bug report form. Attach the debug log if necessary. [Read more here!](https://open-smartwatch.github.io/howto/contribute/#how-to-open-an-issue)

## Submitting patches

Please also see our [wiki](https://open-smartwatch.github.io/howto/contribute/) article for that.
Please also see our [wiki](https://open-smartwatch.github.io/howto/contribute/) article for that.
5 changes: 4 additions & 1 deletion docs/firmware/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ If you have cloned the repo without the recurse option, run `git submodule updat

!!! note "Tip"
After changing or updating/pulling a branch, run the command again to also update dependencies:
`git submodule update`
```bash
git pull
git submodule update --init --recursive
```

Then, open the directory with Visual Studio Code.

Expand Down
7 changes: 5 additions & 2 deletions docs/firmware/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ Check the driver insertion.
You did not clone the repository with the `--recursive-submodules` flag.

!!! note "Tip"
After changing the branch, follow the command :
`git submodule update`
After changing or updating/pulling a branch, run the command again to also update dependencies:
```bash
git pull
git submodule update --init --recursive
```

## Failed to connect to ESP32: Timed out waiting for packet header

Expand Down
10 changes: 6 additions & 4 deletions emulator/include/Emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <variant>
#include <list>
#include <map>
#include <hal/buttons.h>
#include <osw_pins.h> // for button definitions

#include "Jzon.h"

Expand Down Expand Up @@ -46,8 +48,8 @@ class OswEmulator {
void run();
void exit();

void setButton(unsigned id, bool state);
bool getButton(unsigned id);
void setButton(Button id, bool state);
bool getButton(Button id);
uint8_t getBatteryRaw();
bool isCharging();

Expand All @@ -67,8 +69,8 @@ class OswEmulator {
SDL_Surface* mainSurface = nullptr; // Only used in headless mode
SDL_Renderer* mainRenderer = nullptr;
std::atomic_bool running = true;
std::array<std::atomic_bool, 3> buttons; // TODO This length should come from the platform itself!
std::array<bool, 3> buttonCheckboxes = { false, false, false }; // These are just state caches of the buttons for their respective checkboxes!
std::array<std::atomic_bool, BTN_NUMBER> buttons;
std::array<bool, BTN_NUMBER> buttonCheckboxes; // These are just state caches of the buttons for their respective checkboxes!
bool buttonResetAfterMultiPress = true;
uint8_t batRaw = 0;
bool charging = true;
Expand Down
55 changes: 30 additions & 25 deletions emulator/src/Emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ static void shutdownEmulatorByInterruptSignal(int s) {
}

OswEmulator::OswEmulator(bool headless, std::string configPath, std::string imguiPath): isHeadless(headless) {
// Initialize variables
for(size_t i = 0; i < BTN_NUMBER; i++)
this->buttonCheckboxes[i] = false;

// Load emulator config
this->configPath = configPath;
this->imguiPath = imguiPath;
Expand Down Expand Up @@ -256,13 +260,13 @@ void OswEmulator::run() {

// Present the fake-display texture as an ImGUI window
if(!this->isHeadless) {
ImGui::Begin("Display");
ImGui::Begin(LANG_IMGUI_DISPLAY "###display");
// Using ImGui::BeginChild() to set the size of the inner window properly
ImGui::BeginChild("##FakeDisplayTexture", ImVec2(fakeDisplayInstance->width, fakeDisplayInstance->height));
if(fakeDisplayInstance->isEnabled())
ImGui::Image((void*) fakeDisplayInstance->getTexture(), ImVec2(fakeDisplayInstance->width, fakeDisplayInstance->height));
else
ImGui::Text("Display is not active.");
ImGui::Text(LANG_IMGUI_DISPLAY_NOPE);
ImGui::EndChild();
ImGui::End();
}
Expand Down Expand Up @@ -358,12 +362,12 @@ void OswEmulator::requestSleep(RequestSleepState state) {
this->requestedSleepState = state;
}

void OswEmulator::setButton(unsigned id, bool state) {
void OswEmulator::setButton(Button id, bool state) {
this->buttonCheckboxes.at(id) = state;
this->buttons.at(id) = state;
};

bool OswEmulator::getButton(unsigned id) {
bool OswEmulator::getButton(Button id) {
return this->buttons.at(id);
};

Expand Down Expand Up @@ -397,48 +401,49 @@ void OswEmulator::addGUIHelp(const char* msg) {

void OswEmulator::renderGUIFrameEmulator() {
// Emulator control
ImGui::Begin("Emulator");
ImGui::Text("CPU: %s", this->cpustate == CPUState::active ? "Active" : (this->cpustate == CPUState::light ? "Light Sleep" : "Deep Sleep"));
ImGui::Begin(LANG_IMGUI_EMULATOR "###emulator");
ImGui::Text("CPU: %s", this->cpustate == CPUState::active ? LANG_EMULATOR_CPU_ACTIVE : (this->cpustate == CPUState::light ? LANG_EMULATOR_CPU_LIGHT_SLEEP : LANG_EMULATOR_CPU_DEEP_SLEEP));
ImGui::PlotLines("FPS Emulator", (float*) this->frameCountsEmulator.data() + 1, this->frameCountsEmulator.size() - 1);
ImGui::PlotLines("FPS OSW-UI", (float*) this->frameCountsOsw.data() + 1, this->frameCountsOsw.size() - 1);
ImGui::PlotLines("loop()", (float*) this->timesLoop.data(), this->timesLoop.size());
ImGui::Separator();
ImGui::Checkbox("Keep-Awake", &this->autoWakeUp);
this->addGUIHelp("This will always wakeup the watch for the next frame.");
ImGui::Checkbox(LANG_EMULATOR_WAKELOCK, &this->autoWakeUp);
this->addGUIHelp(LANG_EMULATOR_WAKELOCK_HELP);
if(this->cpustate == CPUState::active) { // If false, the ui instance could be unavailable
ImGui::Checkbox("FPS Limiter", &OswUI::getInstance()->mEnableTargetFPS);
this->addGUIHelp("This will limit the FPS to the target FPS set in the OswUI class.");
ImGui::Checkbox(LANG_EMULATOR_FPSLIMIT, &OswUI::getInstance()->mEnableTargetFPS);
this->addGUIHelp(LANG_EMULATOR_FPSLIMIT_HELP);
}
if(!this->autoWakeUp and this->cpustate != CPUState::active and ImGui::Button("Wake Up"))
this->manualWakeUp = true;
ImGui::End();

// Button Control
ImGui::Begin("Buttons");
if(ImGui::Button("Button PWR")) {
ImGui::Begin(LANG_IMGUI_BUTTONS "###buttons");
if(ImGui::Button(LANG_EMULATOR_BTN " PWR")) {
this->enterSleep(true);
this->manualWakeUp = true;
}
this->addGUIHelp("This button will interrupt the power to the CPU and reset the OS (as from deep sleep).");
this->addGUIHelp(LANG_EMULATOR_BTN_PWR_HELP);
for(size_t buttonId = 0; buttonId < this->buttons.size(); ++buttonId) {
ImGui::Button(("Button " + std::to_string(buttonId + 1)).c_str());
// Due to this checkbox-alignment they are always one frame behind the button state (but this is not a problem)
ImGui::Checkbox(("##btn" + std::to_string(buttonId + 1)).c_str(), &this->buttonCheckboxes.at(buttonId)); // "##" as prefix hides the label, but still allows for unique ids
ImGui::SameLine();
ImGui::Button((std::string(LANG_EMULATOR_BTN " ") + ButtonNames[buttonId]).c_str());
if(ImGui::IsItemActivated() or ImGui::IsItemDeactivated()) // Only use the button to control the button state, if it changed during the last frame
this->buttonCheckboxes.at(buttonId) = ImGui::IsItemActive();
if(ImGui::IsItemDeactivated() and this->buttonResetAfterMultiPress) {
for(size_t bId = 0; bId < this->buttonCheckboxes.size(); ++bId)
if(this->buttonCheckboxes.at(bId))
this->setButton(bId, false);
this->setButton((Button) bId, false);
}
ImGui::SameLine();
ImGui::Checkbox(("##btn" + std::to_string(buttonId + 1)).c_str(), &this->buttonCheckboxes.at(buttonId)); // "##" as prefix hides the label, but still allows for unique ids
this->setButton(buttonId, this->buttonCheckboxes.at(buttonId));
this->setButton((Button) buttonId, this->buttonCheckboxes.at(buttonId));
}
ImGui::Checkbox("Release after multi-press", &this->buttonResetAfterMultiPress);
this->addGUIHelp("Whenever you press-and-hold any butten(s) by activating their checkbox(es) and then click-and-release any button normally, all other held buttons will also be released.");
ImGui::Checkbox(LANG_EMULATOR_MBTN, &this->buttonResetAfterMultiPress);
this->addGUIHelp(LANG_EMULATOR_MBTN_HELP);
ImGui::End();

// Virtual Sensors
ImGui::Begin("Virtual Sensors");
ImGui::Begin(LANG_IMGUI_VIRTUAL_SENSORS "###virtual_sensors");
if(OswHal::getInstance()->devices() and OswHal::getInstance()->devices()->virtualDevice) {
ImGui::InputFloat("Temperature", &OswHal::getInstance()->devices()->virtualDevice->values.temperature, 1, 10);
ImGui::InputFloat("Pressure", &OswHal::getInstance()->devices()->virtualDevice->values.pressure, 1, 10);
Expand All @@ -449,10 +454,10 @@ void OswEmulator::renderGUIFrameEmulator() {
ImGui::InputInt("Magnetometer Azimuth", &OswHal::getInstance()->devices()->virtualDevice->values.magnetometerAzimuth, 1, 10);
ImGui::InputInt("Steps", (int*) &OswHal::getInstance()->devices()->virtualDevice->values.steps, 1, 10); // Warning - negative values will cause an underflow... ImGui has no conventient way of limiting the input range...
} else
ImGui::Text("The virtual sensors are only available, while the virtual device is active.");
ImGui::Text(LANG_IMGUI_VIRTUAL_SENSORS_NOPE);
ImGui::End();

ImGui::Begin("Configuration");
ImGui::Begin(LANG_IMGUI_CONFIGURATION "###configuration");
if(this->configValuesCache.size()) {
for(auto& [label, keyIds] : this->configSectionsToIdCache) {
if(ImGui::CollapsingHeader(label.c_str()))
Expand Down Expand Up @@ -515,7 +520,7 @@ void OswEmulator::renderGUIFrameEmulator() {
}
}

ImGui::Button("Save");
ImGui::Button(LANG_SAVE);
if(ImGui::IsItemActive()) {
OswConfig::getInstance()->enableWrite();
for(size_t keyId = 0; keyId < oswConfigKeysCount; ++keyId) {
Expand Down Expand Up @@ -553,7 +558,7 @@ void OswEmulator::renderGUIFrameEmulator() {
OswConfig::getInstance()->notifyChange();
}
} else
ImGui::Text("The configuration is not initialized yet.");
ImGui::Text(LANG_IMGUI_CONFIGURATION_NOPE);
ImGui::End();
}

Expand Down
7 changes: 4 additions & 3 deletions emulator/src/IO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "Emulator.hpp"
#include OSW_TARGET_PLATFORM_HEADER
#include "hal/buttons.h"
#include "osw_pins.h" // Used for BTN_*

void pinMode(int pin, int mode) {
Expand All @@ -24,13 +25,13 @@ uint8_t digitalRead(int pin) {
const uint8_t buttonClickStates[] = BTN_STATE_ARRAY;
switch (pin) {
case BTN_1:
return ((OswEmulator::instance->getButton(0) ? LOW : HIGH) == buttonClickStates[0]) ? LOW : HIGH;
return ((OswEmulator::instance->getButton(Button::BUTTON_SELECT) ? LOW : HIGH) == buttonClickStates[Button::BUTTON_SELECT]) ? LOW : HIGH;
break;
case BTN_2:
return ((OswEmulator::instance->getButton(1) ? LOW : HIGH) == buttonClickStates[1]) ? LOW : HIGH;
return ((OswEmulator::instance->getButton(Button::BUTTON_UP) ? LOW : HIGH) == buttonClickStates[Button::BUTTON_UP]) ? LOW : HIGH;
break;
case BTN_3:
return ((OswEmulator::instance->getButton(2) ? LOW : HIGH) == buttonClickStates[2]) ? LOW : HIGH;
return ((OswEmulator::instance->getButton(Button::BUTTON_DOWN) ? LOW : HIGH) == buttonClickStates[Button::BUTTON_DOWN]) ? LOW : HIGH;
break;
case OSW_DEVICE_TPS2115A_STATPWR:
return OswEmulator::instance->isCharging() ? 1 : 0;
Expand Down
2 changes: 2 additions & 0 deletions emulator/src/Preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ bool Preferences::begin(const char* name, bool readOnly) {
// Init "NVS"
nvs_flash_init();
this->name = std::string(name);
if(this->name.length() > 15)
return false; // Name too long (max 15 chars, as specified for nvs_open())
// Init Jzon tree by loading (existing) file
this->path = std::filesystem::path(preferencesFolderName) / (this->name + ".json");
if(std::filesystem::exists(this->path)) {
Expand Down
3 changes: 1 addition & 2 deletions emulator/src/tests/OswAppAlarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ class TestAlarm {

// Helpers
static OswAppAlarm createAlarm() {
std::shared_ptr<OswAppSwitcher> mockSwitcher = std::make_shared<OswAppSwitcher>(BUTTON_1, SHORT_PRESS, false, false, nullptr);
OswAppAlarm alarm{mockSwitcher.get()};
OswAppAlarm alarm;
return alarm;
}

Expand Down
3 changes: 1 addition & 2 deletions emulator/src/tests/OswAppTimer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ class TestTimer {

// Helpers
static OswAppTimer createTimer() {
std::shared_ptr<OswAppSwitcher> mockSwitcher = std::make_shared<OswAppSwitcher>(BUTTON_1, SHORT_PRESS, false, false, nullptr);
OswAppTimer timer{mockSwitcher.get()};
OswAppTimer timer;
return timer;
}

Expand Down
1 change: 1 addition & 0 deletions img/icons/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.xcf
Loading

0 comments on commit 2b998dc

Please sign in to comment.