Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Progress Feedback / Widget #369

Draft
wants to merge 47 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
52a509f
Added initial support for Flow3r-Badge from c3camp
simonmicro Aug 17, 2023
a84a30a
Compile error fixes
simonmicro Aug 17, 2023
5381cb8
Moved vibration pin into platform header
simonmicro Aug 17, 2023
b9b4505
Fixed emulator build
simonmicro Aug 17, 2023
b818e98
Other platforms build fixes
simonmicro Aug 17, 2023
a9e63f0
Added platform-specific sleep blocker
simonmicro Aug 17, 2023
c585cec
Fix crashes due to stack corruptions
simonmicro Aug 17, 2023
f80fef0
Implemented basic button support
simonmicro Aug 17, 2023
a862736
Added right button middle
simonmicro Aug 18, 2023
c8aead2
Added proper power detection
simonmicro Aug 18, 2023
4d0f5f7
Whoopsie
simonmicro Aug 18, 2023
54b97b2
Added minimal-platform (into workflows), so new devices can be integr…
simonmicro Aug 18, 2023
be3c5b1
Exposed raw magnetometer values
simonmicro Aug 19, 2023
2989e2e
Added accelerometer values to debug view
simonmicro Aug 19, 2023
57edd0f
Cleanup BMA400 code
simonmicro Aug 19, 2023
b444afd
Do not compile BLE companion if not used
simonmicro Aug 19, 2023
a105128
Added basic BMI270 support
simonmicro Aug 19, 2023
cf5c9f9
Fixed step counter and activity detection
simonmicro Aug 20, 2023
fb6c4a8
Fixed multiple emulator compile problems
simonmicro Aug 20, 2023
d1ee8fa
Re-added submodule
simonmicro Sep 5, 2023
b223285
Fixed virtual sensor interface
simonmicro Sep 10, 2023
6c4f5a2
Display current state; not emulator-state
simonmicro Sep 10, 2023
25c94cc
Added BMP581 api support
simonmicro Oct 5, 2023
df4e836
Added basic BMP581 code (untested as FLOW3R platform uses another int…
simonmicro Apr 6, 2024
a505f85
Added platform-support docs
simonmicro Aug 11, 2024
b88d2f8
Fixed minimal (non-acceleration-sensor) build
simonmicro Aug 11, 2024
77f24a1
Fixed double define compile warning
simonmicro Aug 11, 2024
da9d1e6
Fixed broken CI script
simonmicro Aug 11, 2024
b33a5f5
Fixed compile warning (unused variable)
simonmicro Aug 11, 2024
ac57345
Fixed bug, which always regenerated gz-compressed assets
simonmicro Aug 11, 2024
4d6f9a5
Fixed compilation bug with ESP32-BLE-Keyboard
simonmicro Aug 11, 2024
39c05de
Removed (not working) APSTA wifi mode
simonmicro Sep 13, 2023
4f431d8
Fixed broken min/max implementations
simonmicro Sep 21, 2023
c72910e
Fixed OswUi native progress bar
simonmicro Sep 21, 2023
7e66444
First draft for progress widget / feedback
simonmicro Sep 21, 2023
d094ac2
Added ability to pass-trough arguments to the unit-test-framework dir…
simonmicro Sep 21, 2023
823f4fd
Added test listing back to ui tests
simonmicro Sep 22, 2023
907f74b
No-race condition upon waiting for CPU start
simonmicro Sep 22, 2023
4792fab
Use non-headless if available
simonmicro Sep 22, 2023
6c24932
Do not compare nullptr-text
simonmicro Sep 22, 2023
efa8532
Also expire wakeup configs with wifi active
simonmicro Sep 22, 2023
eb64289
Fixed invalid texture error due to not destroyed display texture
simonmicro Sep 22, 2023
645b347
Print emulator crash message
simonmicro Sep 22, 2023
b61fe97
Added emulator app fixture for switching
simonmicro Sep 22, 2023
43d5c18
Added small test for progress widget
simonmicro Sep 22, 2023
3568f29
Fixed arc regression
simonmicro Aug 11, 2024
eae8c52
Fixed multiple progress widget alignment problems
simonmicro Aug 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/getWorkflowMatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def get(info: GettableInfo):
returnArray.add(line.split('=')[1].strip())
break
elif info == GettableInfo.FLAGS:
with open('docs/firmware/osw_os.md') as f:
with open('docs/firmware/flags.md') as f:
for line in f:
# this parses a row with the format: "| `flag` | description | requirements |"
match = re.match(r'^\| `(.+)`\s+\| .+ \| (.+) \|$', line)
Expand Down Expand Up @@ -76,4 +76,4 @@ def get(info: GettableInfo):
ap.add_argument('info', type=GettableInfo)
args = ap.parse_args()

print(json.dumps(list(get(args.info))))
print(json.dumps(list(get(args.info))))
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
path = lib/LUA
url = https://github.com/lua/lua.git
branch = v5.3
[submodule "lib/BMI270-API"]
path = lib/BMI270-API
url = https://github.com/Open-Smartwatch/BMI270-Sensor-API.git
[submodule "emulator/lib/ArduinoJson"]
path = emulator/lib/ArduinoJson
url = https://github.com/bblanchon/ArduinoJson.git
Expand All @@ -42,3 +45,6 @@
[submodule "emulator/lib/ImGUI_TestEngine"]
path = emulator/lib/ImGUI_TestEngine
url = https://github.com/ocornut/imgui_test_engine.git
[submodule "lib/BMP581-API"]
path = lib/BMP581-API
url = https://github.com/boschsensortec/BMP5-Sensor-API.git
19 changes: 10 additions & 9 deletions docs/config.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# This file is similar to the mkdocs.nav configuration option, but it will be mounted under mkdocs.nav.Firmware only!

- 'OSW-OS':
- firmware/getting_started.md
- firmware/osw_os.md
- firmware/troubleshooting.md
- 'Applications':
- 'Watchfaces': 'firmware/apps/watchfaces.md'
- 'Tools': 'firmware/apps/tools.md'
- 'Games': 'firmware/apps/games.md'
- 'OSW Weather': 'firmware/apps/OswWeather.md'
- "OSW-OS":
- firmware/getting_started.md
- firmware/flags.md
- firmware/troubleshooting.md
- firmware/support.md
- "Applications":
- "Watchfaces": "firmware/apps/watchfaces.md"
- "Tools": "firmware/apps/tools.md"
- "Games": "firmware/apps/games.md"
- "OSW Weather": "firmware/apps/OswWeather.md"
23 changes: 12 additions & 11 deletions docs/firmware/osw_os.md → docs/firmware/flags.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# Feature Flags
The table below list all currently available features of the OSW-OS. These features can be manually enabled (or disabled) by modifying the `platformio.ini` and adding (or removing) their `-D`-Define lines.

| Flag | Description | Requirements |
| ------------------------- | ------------------------------------------------------------------- | ---------------------------------- |
| `OSW_FEATURE_STATS_STEPS` | Enable step history (displayed on the watchfaces) | - |
| `OSW_FEATURE_WIFI` | Enable all wifi related functions (services, webinterface) | - |
| `OSW_FEATURE_WIFI_APST` | Allow the watch to enable wifi client and station simultaneously | `OSW_FEATURE_WIFI` |
| `OSW_FEATURE_WIFI_ONBOOT` | Allow the user to enable the wifi on boot | `OSW_FEATURE_WIFI` |
| `OSW_FEATURE_LUA` | Enable LUA scripting support for apps | `LUA_C89_NUMBERS` |
| `DEBUG=1` | Enables debug logging to the console & additional utilities | - |
| `GPS_EDITION` | Configure the build for use with GPS (including apps, api, sensors) | `PROGMEM_TILES`, `BOARD_HAS_PSRAM` |
| `GPS_EDITION_ROTATED` | Replacement for `GPS_EDITION` to work with flipped boards | - |
| Flag | Description | Requirements |
| ---------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------- |
| `OSW_FEATURE_STATS_STEPS` | Enable step history (displayed on the watchfaces) | - |
| `OSW_FEATURE_WIFI` | Enable all wifi related functions (services, webinterface) | - |
| `OSW_FEATURE_WIFI_ONBOOT` | Allow the user to enable the wifi on boot | `OSW_FEATURE_WIFI` |
| `OSW_FEATURE_BLE_MEDIA_CTRL` | Enables media control via BLE | - |
| `OSW_FEATURE_LUA` | Enable LUA scripting support for apps | `LUA_C89_NUMBERS` |
| `SERVICE_BLE_COMPANION=1` | Enables the BLE Companion Service (unstable, requires custom smartphone application) | - |
| `DEBUG=1` | Enables debug logging to the console & additional utilities | - |
| `GPS_EDITION` | Configure the build for use with GPS (including apps, api, sensors) | `PROGMEM_TILES`, `BOARD_HAS_PSRAM` |
| `GPS_EDITION_ROTATED` | Replacement for `GPS_EDITION` to work with flipped boards | - |

## Example Flags

Expand Down Expand Up @@ -42,4 +43,4 @@ The table below lists which features are available in which version of the OS by
| `OSW_FEATURE_WIFI` | ✓ | ✓ | ❌ | ✓ | ✓ |
| `OSW_FEATURE_WIFI_APST` | ❌ | ❌ | ❌ | ✓ | ✓ |
| `OSW_FEATURE_WIFI_ONBOOT` | ✓ | ❌ | ❌ | ✓ | ✓ |
| `OSW_FEATURE_LUA` | ❌ | ❌ | ✓ | ❌ | ❌ |
| `OSW_FEATURE_LUA` | ❌ | ❌ | ✓ | ❌ | ❌ |
19 changes: 19 additions & 0 deletions docs/firmware/support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Hardware Support
Over time, the operating system gained additional hardware support for non open-smartwatch environments. This page lists the supported hardware and how to use it (as well as unwanted features, so called "bugs"). You can also find all these configurations inside the `platformio.ini` file.

## Official Hardware
...based on hardware schematics released by the OSW team and tested frequently.

| Hardware | Status | Reference |
| -------------------------------------- | ------------ | --------------------------------------------------------- |
| `LIGHT_EDITION_V3_3` | Maintained | See "Hardware"-Documentation section |
| `EXPERIMENTAL_LIGHT_EDITION_V4_0` | Experimental | See "Hardware"-Documentation section |
| `EXPERIMENTAL_LIGHT_EDITION_V3_3_LUA` | Experimental | Same as `LIGHT_EDITION_V3_3`, but with LUA-script-support |
| `EXPERIMENTAL_GPS_EDITION_V3_1` | Experimental | See "Hardware"-Documentation section |
| `EXPERIMENTAL_GPS_EDITION_DEV_ROTATED` | Experimental | See "Hardware"-Documentation section |

## 3rd Party Hardware

| Hardware | Status | Reference | Known Issues |
| ------------------------------ | ------------ | --------------------------------- | ----------------------------------------------------------------------- |
| `3RD_PARTY_FLOW3R_C3CAMP_2023` | Experimental | [website](https://flow3r.garden/) | [PR368](https://github.com/Open-Smartwatch/open-smartwatch-os/pull/368) |
14 changes: 12 additions & 2 deletions emulator/include/Arduino.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
#pragma once

#include "DataTypes.h"
#include "Defines.h"

unsigned long millis();
long random(int howbig);
long random(int howsmall, int howbig);
void delay(long millis);
int32_t min(int32_t a, int32_t b);
int32_t max(int32_t a, int32_t b);

// Following are just forwards to the their std-equivalents, specific implementations will confuse the compiler (and cause e.g. std::min != min != what-it-should-be problems)
template<typename T>
inline T min(T a, T b) {
return std::min(a, b);
}
template<typename T>
inline T max(T a, T b) {
return std::max(a, b);
}
8 changes: 0 additions & 8 deletions emulator/src/Arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,4 @@ long random(int howsmall, int howbig) {

void delay(long millis) {
std::this_thread::sleep_for(std::chrono::milliseconds(millis));
}

int32_t min(int32_t a, int32_t b) {
return a < b ? a : b;
}

int32_t max(int32_t a, int32_t b) {
return a > b ? a : b;
}
34 changes: 29 additions & 5 deletions emulator/src/Emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ OswEmulator::~OswEmulator() {
}

// Close window and renderer
fakeDisplayInstance.reset(); // drop the display and its texture
SDL_DestroyRenderer(this->mainRenderer);
int w = 0, h = 0;
if(!this->isHeadless) {
Expand Down Expand Up @@ -165,10 +166,10 @@ void OswEmulator::run() {
this->bootReason = BootReason::byTimer;
else
this->bootReason = BootReason::undefined; // Should never happen...
this->cpustate = CPUState::active;
setup();
this->cpustate = CPUState::active; // update state AFTER boot, so developers can await it
this->manualWakeUp = false;
this->selfWakeUpAtTimestamp = 0;
setup();

/**
* At the first startup - prepare the key value cache dynamically
Expand Down Expand Up @@ -452,8 +453,32 @@ void OswEmulator::renderGUIFrameEmulator() {
ImGui::InputFloat("Acceleration X", &OswHal::getInstance()->devices()->virtualDevice->values.accelerationX, 0.1f, 10);
ImGui::InputFloat("Acceleration Y", &OswHal::getInstance()->devices()->virtualDevice->values.accelerationY, 0.1f, 10);
ImGui::InputFloat("Acceleration Z", &OswHal::getInstance()->devices()->virtualDevice->values.accelerationZ, 0.1f, 10);
ImGui::InputInt("Magnetometer X", &OswHal::getInstance()->devices()->virtualDevice->values.magnetometerX, 0.1f, 10);
ImGui::InputInt("Magnetometer Y", &OswHal::getInstance()->devices()->virtualDevice->values.magnetometerY, 0.1f, 10);
ImGui::InputInt("Magnetometer Z", &OswHal::getInstance()->devices()->virtualDevice->values.magnetometerZ, 0.1f, 10);
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 convenient way of limiting the input range...
// get string to display selected value
const char* str = "unknown";
OswAccelerationProvider::ActivityMode& activityMode = OswHal::getInstance()->devices()->virtualDevice->values.activityMode; // take reference, for easier access
if(activityMode == OswAccelerationProvider::ActivityMode::STILL)
str = "still";
else if(activityMode == OswAccelerationProvider::ActivityMode::WALK)
str = "walk";
else if(activityMode == OswAccelerationProvider::ActivityMode::RUN)
str = "run";
// display activity mode
if (ImGui::BeginCombo("Activity", str)) {
if(ImGui::Selectable("still", activityMode == OswAccelerationProvider::ActivityMode::STILL))
OswHal::getInstance()->devices()->virtualDevice->values.activityMode = OswAccelerationProvider::ActivityMode::STILL;
else if(ImGui::Selectable("walk", activityMode == OswAccelerationProvider::ActivityMode::WALK))
OswHal::getInstance()->devices()->virtualDevice->values.activityMode = OswAccelerationProvider::ActivityMode::WALK;
else if(ImGui::Selectable("run", activityMode == OswAccelerationProvider::ActivityMode::RUN))
OswHal::getInstance()->devices()->virtualDevice->values.activityMode = OswAccelerationProvider::ActivityMode::RUN;
else if(ImGui::Selectable("unknown", activityMode == OswAccelerationProvider::ActivityMode::UNKNOWN))
OswHal::getInstance()->devices()->virtualDevice->values.activityMode = OswAccelerationProvider::ActivityMode::UNKNOWN;
ImGui::EndCombo();
}
} else
ImGui::Text(LANG_IMGUI_VIRTUAL_SENSORS_NOPE);
ImGui::End();
Expand Down Expand Up @@ -491,8 +516,7 @@ void OswEmulator::renderGUIFrameEmulator() {
// Create the combo-box
if (ImGui::BeginCombo(key->label, std::get<std::string>(this->configValuesCache[keyId]).c_str())) {
for (size_t i = 0; i < options.size(); i++) {
bool isSelected = currentOption == i;
if (ImGui::Selectable(options[i].c_str(), &isSelected))
if (ImGui::Selectable(options[i].c_str(), currentOption == i))
this->configValuesCache[keyId] = options[i];
}
ImGui::EndCombo();
Expand Down Expand Up @@ -565,4 +589,4 @@ void OswEmulator::renderGUIFrameEmulator() {

OswEmulator::CPUState OswEmulator::getCpuState() {
return this->cpustate;
}
}
3 changes: 0 additions & 3 deletions emulator/src/IO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ uint8_t digitalRead(int pin) {
case OSW_DEVICE_TPS2115A_STATPWR:
return OswEmulator::instance->isCharging() ? 1 : 0;
break;
case TFT_LED:
return 255; // The emulator has always full brightness for now...
break;
default:
OSW_EMULATOR_THIS_IS_NOT_IMPLEMENTED;
return LOW;
Expand Down
17 changes: 12 additions & 5 deletions emulator/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,23 @@ int main(int argc, char** argv) {
const std::string argUiTests = "ui_tests";
const std::string argHeadless = "headless";
const std::string argSoftwareRenderer = "software_renderer";
a.add(argRunUnitTests, '\0', "run the unit test framework");
a.add(argRunUnitTests, '\0', "run the unit test framework (if you have any arguments for it (use it with --help to learn more), just pass them AS THE LAST ONES)");
a.add(argListAllTests, '\0', "list all unit and UI tests, one per line");
a.add(argUiTests, '\0', "run emulator with UI tests window");
a.add(argHeadless, '\0', "do not open a window; also implies --software_renderer"); // Warning: This parameter name is also used in the unit-tests!
a.add(argSoftwareRenderer, '\0', "use software-rendering only");
a.parse_check(argc, argv);
bool cmdParsed = a.parse(argc, argv);
if(!cmdParsed) {
if(a.exist(argRunUnitTests) or a.exist(argUiTests)) {
// unable to fully parse command line, but I'll ignore that and pass the arguments to the test framework...
} else {
a.parse_check(argc, argv); // this will not only re-parse, but also bail out
}
}

// Initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
printf("error initializing SDL: %s\n", SDL_GetError());
std::cerr << "Error initializing SDL: " << SDL_GetError() << std::endl;

// Run the unit tests or the emulator
int returnval = EXIT_SUCCESS;
Expand All @@ -60,7 +67,7 @@ int main(int argc, char** argv) {
UiTests_main(UiTests_Mode::List);
} else if (a.exist(argUiTests)) {
// Run the emulator together with the testing engine
returnval = UiTests_main();
returnval = UiTests_main(UiTests_Mode::Run);
} else {
// Create and run the emulator
std::unique_ptr<OswEmulator> oswEmu = std::make_unique<OswEmulator>(a.exist(argSoftwareRenderer) or a.exist(argHeadless), a.exist(argHeadless));
Expand All @@ -73,4 +80,4 @@ int main(int argc, char** argv) {
SDL_Quit();

return returnval;
}
}
2 changes: 1 addition & 1 deletion emulator/src/tests/uiTests/UiTests_main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,4 @@ int UiTests_main(UiTests_Mode mode = UiTests_Mode::Run) {
SDL_Quit();

return 0;
}
}
60 changes: 60 additions & 0 deletions emulator/src/tests/unitTests/emulator/OswAppV2Fixture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <memory>
#include <thread>
#include <optional>
#include <functional>

#include "utest.h"
#include "../fixtures/CaptureSerialFixture.hpp"
#include "../fixtures/PreferencesFixture.hpp"
#include "../fixtures/EmulatorFixture.hpp"
#include "../fixtures/OswAppV2Fixture.hpp"

#include "apps/examples/OswAppExampleV2.h"
#include "apps/watchfaces/OswAppWatchfaceMonotimer.h"
#include "apps/watchfaces/OswAppWatchfaceBinary.h"

#include <osw_hal.h>
#include <osw_ui.h>

extern int emulatorMainArgc;
extern char** emulatorMainArgv;

/// switch though some apps and make sure it worked (without crashing)
UTEST(OswAppV2Fixture, app_switching) {
EMULATOR_FIXTURE_HEADLESS_VARIABLE;

CaptureSerialFixture capture;
PreferencesFixture prefsFixture;
EmulatorFixture runEmu(headless);

OswAppV2* original = OswUI::getInstance()->getRootApplication();
{
OswAppExampleV2 app;
OswAppV2Fixture appFixture(app);
for(int i = 0; i < 10; ++i) {
EXPECT_TRUE(OswUI::getInstance()->getRootApplication() == &appFixture.getApp()); // nobody should have changed the root application
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
ASSERT_TRUE(OswUI::getInstance()->getRootApplication() == original); // should have reverted changed the root application

{
OswAppWatchfaceMonotimer app;
OswAppV2Fixture appFixture(app);
for(int i = 0; i < 10; ++i) {
EXPECT_TRUE(OswUI::getInstance()->getRootApplication() == &appFixture.getApp());
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
ASSERT_TRUE(OswUI::getInstance()->getRootApplication() == original);

{
OswAppWatchfaceBinary app;
OswAppV2Fixture appFixture(app);
for(int i = 0; i < 10; ++i) {
EXPECT_TRUE(OswUI::getInstance()->getRootApplication() == &appFixture.getApp());
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
ASSERT_TRUE(OswUI::getInstance()->getRootApplication() == original);
}
Loading
Loading