diff --git a/.github/getWorkflowMatrix.py b/.github/getWorkflowMatrix.py index 028996b67..877080b63 100755 --- a/.github/getWorkflowMatrix.py +++ b/.github/getWorkflowMatrix.py @@ -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) @@ -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)))) \ No newline at end of file + print(json.dumps(list(get(args.info)))) diff --git a/.gitmodules b/.gitmodules index 0347f309b..afe3a1712 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 @@ -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 diff --git a/docs/config.yml b/docs/config.yml index 0af12368b..06e505a60 100644 --- a/docs/config.yml +++ b/docs/config.yml @@ -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' \ No newline at end of file +- "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" diff --git a/docs/firmware/osw_os.md b/docs/firmware/flags.md similarity index 72% rename from docs/firmware/osw_os.md rename to docs/firmware/flags.md index 56d1c4523..768368027 100644 --- a/docs/firmware/osw_os.md +++ b/docs/firmware/flags.md @@ -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 @@ -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` | ❌ | ❌ | ✓ | ❌ | ❌ | \ No newline at end of file +| `OSW_FEATURE_LUA` | ❌ | ❌ | ✓ | ❌ | ❌ | diff --git a/docs/firmware/support.md b/docs/firmware/support.md new file mode 100644 index 000000000..89eaf1a0b --- /dev/null +++ b/docs/firmware/support.md @@ -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) | diff --git a/emulator/include/Serial.h b/emulator/include/Serial.h index d4c610140..68d7e768e 100644 --- a/emulator/include/Serial.h +++ b/emulator/include/Serial.h @@ -44,6 +44,7 @@ class Serial_t { int read(); void println(); + void flush(); private: std::list inputBuffer; int bauds = 0; @@ -51,4 +52,4 @@ class Serial_t { bool addBufferNewline = true; }; -extern Serial_t Serial; \ No newline at end of file +extern Serial_t Serial; diff --git a/emulator/src/Emulator.cpp b/emulator/src/Emulator.cpp index 2aec4166e..22305589e 100644 --- a/emulator/src/Emulator.cpp +++ b/emulator/src/Emulator.cpp @@ -452,8 +452,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(); @@ -491,8 +515,7 @@ void OswEmulator::renderGUIFrameEmulator() { // Create the combo-box if (ImGui::BeginCombo(key->label, std::get(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(); @@ -565,4 +588,4 @@ void OswEmulator::renderGUIFrameEmulator() { OswEmulator::CPUState OswEmulator::getCpuState() { return this->cpustate; -} \ No newline at end of file +} diff --git a/emulator/src/IO.cpp b/emulator/src/IO.cpp index 9dac4f491..0dcbd19a5 100644 --- a/emulator/src/IO.cpp +++ b/emulator/src/IO.cpp @@ -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; diff --git a/emulator/src/Serial.cpp b/emulator/src/Serial.cpp index fae25e22d..973cd6b0d 100644 --- a/emulator/src/Serial.cpp +++ b/emulator/src/Serial.cpp @@ -38,6 +38,13 @@ void Serial_t::println() { std::cout << std::endl; } +void Serial_t::flush() { + if(this->bauds < 1) + return; + if(!this->buffered) + std::cout << std::flush; +} + int Serial_t::available() { char c; if(::read(STDIN_FILENO, &c, 1) > 0) { @@ -53,4 +60,4 @@ int Serial_t::read() { char c = this->inputBuffer.front(); this->inputBuffer.pop_front(); return c; -} \ No newline at end of file +} diff --git a/include/OswLogger.h b/include/OswLogger.h index 38221655c..f81ff60ac 100644 --- a/include/OswLogger.h +++ b/include/OswLogger.h @@ -3,7 +3,7 @@ #include #include #include -#include // For Serial.print(ln) +#include #include #include @@ -58,6 +58,7 @@ class OswLogger { template void log(const char* file, const unsigned int line, const severity_t severity, T&& ... message) { std::lock_guard guard(this->m_lock); + OswSerial* serial = OswSerial::getInstance(); this->prefix(file, line, severity); do_in_order([&]() { @@ -67,50 +68,53 @@ class OswLogger { // Iterate over message to find '\n', which trigger new lines... for(auto& c : message) { if (c == '\n') { - Serial.println(); + serial->println(); this->prefix(file, line, severity); } else - Serial.print(c); + serial->putc(c); } } else if constexpr (std::is_same::value or std::is_same::value) { // Iterate over message to find '\n', which trigger new lines... for(auto& c : std::string_view(message)) { if (c == '\n') { - Serial.println(); + serial->println(); this->prefix(file, line, severity); } else - Serial.print(c); + serial->putc(c); } - } else - Serial.print(message); + } else { + serial->print(message); + } } ...); - Serial.println(); + serial->println(); }; void prefix(const char* file, const unsigned int line, const severity_t severity) { + OswSerial* serial = OswSerial::getInstance(); + switch(severity) { case severity_t::D: - Serial.print("D: "); + serial->print("D: "); break; case severity_t::I: - Serial.print("I: "); + serial->print("I: "); break; case severity_t::W: - Serial.print("W: "); + serial->print("W: "); break; case severity_t::E: - Serial.print("E: "); + serial->print("E: "); break; default: throw std::logic_error("Unknown severity level"); } #ifndef NDEBUG - Serial.print(file); - Serial.print("@"); - Serial.print(line); - Serial.print(": "); + serial->print(file); + serial->putc('@'); + serial->print(line); + serial->print(": "); #endif }; }; diff --git a/include/OswSerial.h b/include/OswSerial.h new file mode 100644 index 000000000..c9056ba80 --- /dev/null +++ b/include/OswSerial.h @@ -0,0 +1,92 @@ +#pragma once + +#include +#include +#include OSW_TARGET_PLATFORM_HEADER + +#if OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL == 1 +#include // change this if needed, as this is specifically ESP32s2 +#include +#include +#else +#include +#endif + +/** + * @brief This class is not the fastest (only one byte at a time), but it is the most compatible + * + */ +class OswSerial { + public: + /** + * @brief Start / initialize serial communication (not all platforms may respect the baud rate) + * + * @param baud + */ + void begin(unsigned long baud); + + /** + * @brief Put one byte to the serial port (potentially buffered) + * + * If you only want to print a single character, prefer this method over print() + * + * @param c + */ + void putc(uint8_t c); + + /** + * @brief FLush out the outgoing buffer, if buffered + * + */ + void flush(); + + /** + * @brief Get one byte from the serial port + * + * @param c where to store the byte + * @return true if a byte was read + * @return false if no byte was read + */ + bool getc(uint8_t& c); + + /** + * @brief Print a string to the serial port and flush it + * + * @tparam T + * @param t + */ + template + void print(T t) { +#if OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL == 1 + for(auto& c : String(t)) { + this->putc(c); + } + this->flush(); +#else + Serial.print(t); +#endif + } + + /** + * @brief Print a string to the serial port and flush it + * + * @tparam T + * @param t + */ + template + void println(T t) { + this->print(t); + this->println(); + } + + /** + * @brief Print a newline to the serial port and flush it + * + */ + void println(); + + static OswSerial* getInstance(); + static void resetInstance(); + private: + static OswSerial* instance; +}; diff --git a/include/apps/games/brick_breaker.h b/include/apps/games/brick_breaker.h index 4f74f0b08..71c0cdcbf 100644 --- a/include/apps/games/brick_breaker.h +++ b/include/apps/games/brick_breaker.h @@ -1,5 +1,6 @@ -#ifndef OSW_APP_BRICK_BREAKER_H -#define OSW_APP_BRICK_BREAKER_H +#pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include #include @@ -92,5 +93,4 @@ class OswAppBrickBreaker : public OswApp { void waitingRoom(); }; - #endif diff --git a/include/apps/games/snake_game.h b/include/apps/games/snake_game.h index 43b4cc629..8c9dbf962 100644 --- a/include/apps/games/snake_game.h +++ b/include/apps/games/snake_game.h @@ -1,5 +1,6 @@ -#ifndef OSW_APP_SNAKE_GAME_H -#define OSW_APP_SNAKE_GAME_H +#pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include #include @@ -91,5 +92,4 @@ class OswAppSnakeGame : public OswApp { return deltaSeconds * score > 1; } }; - #endif diff --git a/include/apps/tools/OswAppDistStats.h b/include/apps/tools/OswAppDistStats.h index bec15bbc7..a22678405 100644 --- a/include/apps/tools/OswAppDistStats.h +++ b/include/apps/tools/OswAppDistStats.h @@ -1,6 +1,6 @@ -#ifdef OSW_FEATURE_STATS_STEPS - #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#ifdef OSW_FEATURE_STATS_STEPS #include #include @@ -25,5 +25,4 @@ class OswAppDistStats : public OswApp { OswUI* ui; int32_t cursorPos = 0; // WeekDay position }; - #endif diff --git a/include/apps/tools/OswAppFitnessStats.h b/include/apps/tools/OswAppFitnessStats.h index 2cc4a0be3..f26b66592 100644 --- a/include/apps/tools/OswAppFitnessStats.h +++ b/include/apps/tools/OswAppFitnessStats.h @@ -1,4 +1,6 @@ #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include #include @@ -18,3 +20,4 @@ class OswAppFitnessStats : public OswApp { private: OswUI* ui; }; +#endif diff --git a/include/apps/tools/OswAppKcalStats.h b/include/apps/tools/OswAppKcalStats.h index 2682bed51..2fb3ad6dc 100644 --- a/include/apps/tools/OswAppKcalStats.h +++ b/include/apps/tools/OswAppKcalStats.h @@ -1,6 +1,6 @@ -#ifdef OSW_FEATURE_STATS_STEPS - #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#ifdef OSW_FEATURE_STATS_STEPS #include #include diff --git a/include/apps/tools/OswAppPrintDebug.h b/include/apps/tools/OswAppPrintDebug.h index 44801bf0a..4bef9e2e7 100644 --- a/include/apps/tools/OswAppPrintDebug.h +++ b/include/apps/tools/OswAppPrintDebug.h @@ -1,5 +1,5 @@ -#ifndef NDEBUG #pragma once +#ifndef NDEBUG #include #include diff --git a/include/apps/tools/OswAppStepStats.h b/include/apps/tools/OswAppStepStats.h index 5df8f64ce..3b100266a 100644 --- a/include/apps/tools/OswAppStepStats.h +++ b/include/apps/tools/OswAppStepStats.h @@ -1,6 +1,6 @@ -#ifdef OSW_FEATURE_STATS_STEPS - #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#ifdef OSW_FEATURE_STATS_STEPS #include #include @@ -26,5 +26,4 @@ class OswAppStepStats : public OswApp { int32_t cursorPos=0; OswUI* ui; }; - #endif diff --git a/include/apps/tools/OswAppWaterLevel.h b/include/apps/tools/OswAppWaterLevel.h index c9b19b05a..2fdbdd17e 100644 --- a/include/apps/tools/OswAppWaterLevel.h +++ b/include/apps/tools/OswAppWaterLevel.h @@ -1,4 +1,6 @@ #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include #include @@ -22,3 +24,4 @@ class OswAppWaterLevel : public OswApp { OswUI* ui; int displayMode = 1; }; +#endif diff --git a/include/apps/tools/OswAppWebserver.h b/include/apps/tools/OswAppWebserver.h index a837da066..e900406e7 100644 --- a/include/apps/tools/OswAppWebserver.h +++ b/include/apps/tools/OswAppWebserver.h @@ -1,5 +1,5 @@ -#ifdef OSW_FEATURE_WIFI #pragma once +#ifdef OSW_FEATURE_WIFI #include #include diff --git a/include/apps/watchfaces/OswAppWatchfaceFitness.h b/include/apps/watchfaces/OswAppWatchfaceFitness.h index 4cda87f1b..57ab69ed1 100644 --- a/include/apps/watchfaces/OswAppWatchfaceFitness.h +++ b/include/apps/watchfaces/OswAppWatchfaceFitness.h @@ -1,4 +1,6 @@ #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include #include @@ -25,3 +27,4 @@ class OswAppWatchfaceFitness : public OswAppV2 { void showFitnessTracking(); }; +#endif \ No newline at end of file diff --git a/include/apps/watchfaces/OswAppWatchfaceFitnessAnalog.h b/include/apps/watchfaces/OswAppWatchfaceFitnessAnalog.h index 0613e3067..8209c21b3 100644 --- a/include/apps/watchfaces/OswAppWatchfaceFitnessAnalog.h +++ b/include/apps/watchfaces/OswAppWatchfaceFitnessAnalog.h @@ -2,6 +2,8 @@ #include #include +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 + // if you want a cool background image, enable the following define //#define GIF_BG @@ -43,3 +45,4 @@ class OswAppWatchfaceFitnessAnalog : public OswAppV2 { OswAppGifPlayer* bgGif = nullptr; #endif }; +#endif diff --git a/include/devices/bma400.h b/include/devices/bma400.h index d28c9d274..1f57fe19a 100644 --- a/include/devices/bma400.h +++ b/include/devices/bma400.h @@ -1,7 +1,11 @@ #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_BMA400 == 1 #include #include +#include +#include namespace OswDevices { class BMA400 : public OswTemperatureProvider, public OswAccelerationProvider { @@ -23,14 +27,26 @@ class BMA400 : public OswTemperatureProvider, public OswAccelerationProvider { return 20; }; // This sensor is not sooo good... - virtual uint32_t getStepCount() override; - virtual void resetStepCount() override; virtual float getAccelerationX() override; virtual float getAccelerationY() override; virtual float getAccelerationZ() override; + virtual uint32_t getStepCount() override; + virtual void resetStepCount() override; + virtual OswAccelerationProvider::ActivityMode getActivityMode() override; virtual inline unsigned char getAccelerationProviderPriority() override { return 100; }; // This is a specialized device! - uint8_t getActivityMode(); + + private: + bma400_dev bma = {}; + float accelT = 0.0f; + float accelX = 0.0f; + float accelY = 0.0f; + float accelZ = 0.0f; + uint32_t step_count = 0; + OswAccelerationProvider::ActivityMode activityMode = OswAccelerationProvider::ActivityMode::UNKNOWN; + + void setupTiltToWake(); }; }; +#endif diff --git a/include/devices/bmi270.h b/include/devices/bmi270.h new file mode 100644 index 000000000..a494dfe1a --- /dev/null +++ b/include/devices/bmi270.h @@ -0,0 +1,53 @@ +#pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_BMI270 == 1 + +#include +#include +#include +#include + +namespace OswDevices { +class BMI270 : public OswAccelerationProvider, public OswTemperatureProvider { + public: + BMI270() : OswAccelerationProvider(), OswTemperatureProvider() {}; + virtual ~BMI270() {}; + + virtual void setup() override; + virtual void update() override; + virtual void reset() override {}; + virtual void stop() override {}; + + virtual inline const char* getName() override { + return "BMI270"; + }; + virtual float getAccelerationX() override; + virtual float getAccelerationY() override; + virtual float getAccelerationZ() override; + virtual uint32_t getStepCount() override; + virtual void resetStepCount() override; + virtual OswAccelerationProvider::ActivityMode getActivityMode() override; + virtual inline unsigned char getAccelerationProviderPriority() override { + return 100; + }; // This is a specialized device! + + virtual float getTemperature() override; + virtual inline unsigned char getTemperatureProviderPriority() override { + return 20; + }; // This sensor is not sooo good... + private: + bmi2_dev bmi2 = {}; + float accX = 0; + float accY = 0; + float accZ = 0; + uint32_t step_count = 0; + float temperature = 0; + OswAccelerationProvider::ActivityMode activityMode = OswAccelerationProvider::ActivityMode::UNKNOWN; + + void updateAcceleration(); + void updateSteps(); + void updateTemperature(); + void updateActivityMode(); +}; +}; +#endif \ No newline at end of file diff --git a/include/devices/bmp581.h b/include/devices/bmp581.h new file mode 100644 index 000000000..4ac7f02b7 --- /dev/null +++ b/include/devices/bmp581.h @@ -0,0 +1,41 @@ +#pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_BMP581 == 1 + +#include +#include +#include +#include + +namespace OswDevices { +class BMP581 : public OswPressureProvider, public OswTemperatureProvider { + public: + BMP581() : OswPressureProvider(), OswTemperatureProvider() {}; + virtual ~BMP581() {}; + + virtual void setup() override; + virtual void update() override; + virtual void reset() override {}; + virtual void stop() override {}; + + virtual inline const char* getName() override { + return "BMP581"; + }; + + virtual float getPressure() override; + virtual unsigned char getPressureProviderPriority() override { + return 100; + }; // This is a specialized device! + + virtual float getTemperature() override; + virtual inline unsigned char getTemperatureProviderPriority() override { + return 20; + }; // This sensor is not sooo good... + private: + bmp5_dev bmp5 = {}; + bmp5_osr_odr_press_config osr_odr_press_cfg = {}; + float pressure = 0; + float temperature = 0; +}; +}; +#endif \ No newline at end of file diff --git a/include/devices/ds3231mz.h b/include/devices/ds3231mz.h index f62609522..00f2d63d5 100644 --- a/include/devices/ds3231mz.h +++ b/include/devices/ds3231mz.h @@ -1,4 +1,6 @@ #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_DS3231MZ == 1 #include #include @@ -36,3 +38,4 @@ class DS3231MZ : public OswTemperatureProvider, public OswTimeProvider { uint32_t _utcTime = 0; }; }; +#endif diff --git a/include/devices/interfaces/OswAccelerationProvider.h b/include/devices/interfaces/OswAccelerationProvider.h index b0dddff6a..08e7de2b2 100644 --- a/include/devices/interfaces/OswAccelerationProvider.h +++ b/include/devices/interfaces/OswAccelerationProvider.h @@ -7,12 +7,20 @@ class OswAccelerationProvider : public OswDevice { public: - virtual uint32_t getStepCount() = 0; - virtual void resetStepCount() = 0; + enum class ActivityMode { + UNKNOWN, + STILL, + WALK, + RUN + }; virtual float getAccelerationX() = 0; virtual float getAccelerationY() = 0; virtual float getAccelerationZ() = 0; + virtual uint32_t getStepCount() = 0; + virtual void resetStepCount() = 0; + virtual ActivityMode getActivityMode() = 0; + virtual unsigned char getAccelerationProviderPriority() = 0; static const std::list* getAllAccelerationDevices() { return &allDevices; diff --git a/include/devices/interfaces/OswMagnetometerProvider.h b/include/devices/interfaces/OswMagnetometerProvider.h index 92962d00f..b955dc0d5 100644 --- a/include/devices/interfaces/OswMagnetometerProvider.h +++ b/include/devices/interfaces/OswMagnetometerProvider.h @@ -8,6 +8,11 @@ class OswMagnetometerProvider : public OswDevice { public: virtual int getMagnetometerAzimuth() = 0; + // get field strength in microtesla + virtual int getMagnetometerX() = 0; + virtual int getMagnetometerY() = 0; + virtual int getMagnetometerZ() = 0; + virtual unsigned char getMagnetometerProviderPriority() = 0; static const std::list* getAllMagnetometerDevices() { return &allDevices; diff --git a/include/devices/qmc5883l.h b/include/devices/qmc5883l.h index cbf4186d2..b7748c16c 100644 --- a/include/devices/qmc5883l.h +++ b/include/devices/qmc5883l.h @@ -1,4 +1,6 @@ #pragma once +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_QMC5883L == 1 #include @@ -24,12 +26,13 @@ class QMC5883L : public OswMagnetometerProvider { virtual inline unsigned char getMagnetometerProviderPriority() override { return 100; }; // This is a specialized device! - int getMagnetometerX(); - int getMagnetometerY(); - int getMagnetometerZ(); + virtual int getMagnetometerX() override; + virtual int getMagnetometerY() override; + virtual int getMagnetometerZ() override; byte getMagnetometerBearing(); void setMagnetometerCalibration(int x_min, int x_max, int y_min, int y_max, int z_min, int z_max); private: QMC5883LCompass qmc5883l; }; }; +#endif diff --git a/include/devices/virtual.h b/include/devices/virtual.h index 677af9956..1877442d6 100644 --- a/include/devices/virtual.h +++ b/include/devices/virtual.h @@ -19,7 +19,11 @@ class Virtual : public OswTemperatureProvider, public OswAccelerationProvider, p float accelerationX = 0.0f; float accelerationY = 0.0f; float accelerationZ = -9.81f; + OswAccelerationProvider::ActivityMode activityMode = OswAccelerationProvider::ActivityMode::UNKNOWN; int magnetometerAzimuth = 0; + int magnetometerX = 0; + int magnetometerY = 0; + int magnetometerZ = 0; uint32_t steps = 42; } values; @@ -45,12 +49,6 @@ class Virtual : public OswTemperatureProvider, public OswAccelerationProvider, p return this->priority; }; - virtual inline uint32_t getStepCount() override { - return this->values.steps; - }; - virtual void resetStepCount() override { - this->values.steps = 0; - }; virtual inline float getAccelerationX() override { return this->values.accelerationX; }; @@ -60,9 +58,18 @@ class Virtual : public OswTemperatureProvider, public OswAccelerationProvider, p virtual inline float getAccelerationZ() override { return this->values.accelerationZ; }; + virtual inline uint32_t getStepCount() override { + return this->values.steps; + }; + virtual void resetStepCount() override { + this->values.steps = 0; + }; virtual inline unsigned char getAccelerationProviderPriority() override { return this->priority; }; + virtual OswAccelerationProvider::ActivityMode getActivityMode() override { + return this->values.activityMode; + }; virtual inline float getHumidity() override { return this->values.humidity; @@ -81,6 +88,15 @@ class Virtual : public OswTemperatureProvider, public OswAccelerationProvider, p virtual inline int getMagnetometerAzimuth() override { return this->values.magnetometerAzimuth; }; + virtual int getMagnetometerX() override { + return this->values.magnetometerX; + }; + virtual int getMagnetometerY() override { + return this->values.magnetometerY; + }; + virtual int getMagnetometerZ() override { + return this->values.magnetometerZ; + }; virtual inline unsigned char getMagnetometerProviderPriority() override { return this->priority; }; diff --git a/include/hal/devices.h b/include/hal/devices.h index 31ce47272..8f5b7ecbb 100644 --- a/include/hal/devices.h +++ b/include/hal/devices.h @@ -5,18 +5,12 @@ #include #include #include -#if OSW_PLATFORM_HARDWARE_BMA400 == 1 #include -#endif -#if OSW_PLATFORM_HARDWARE_QMC5883L == 1 #include -#endif -#if OSW_PLATFORM_HARDWARE_BME280 == 1 #include -#endif -#if OSW_PLATFORM_HARDWARE_DS3231MZ == 1 +#include +#include #include -#endif #include #include @@ -25,6 +19,12 @@ class OswHal::Devices { #if OSW_PLATFORM_HARDWARE_BMA400 == 1 OswDevices::BMA400* bma400; #endif +#if OSW_PLATFORM_HARDWARE_BMI270 == 1 + OswDevices::BMI270* bmi270; +#endif +#if OSW_PLATFORM_HARDWARE_BMP581 == 1 + OswDevices::BMP581* bmp581; +#endif #if OSW_PLATFORM_HARDWARE_QMC5883L == 1 OswDevices::QMC5883L* qmc5883l; #endif diff --git a/include/hal/environment.h b/include/hal/environment.h index a4ce5ab90..1167ef0a7 100644 --- a/include/hal/environment.h +++ b/include/hal/environment.h @@ -8,6 +8,7 @@ #include #include #include +#include OSW_TARGET_PLATFORM_HEADER #if OSW_PLATFORM_ENVIRONMENT == 1 class OswHal::Environment { @@ -28,6 +29,9 @@ class OswHal::Environment { #endif #if OSW_PLATFORM_ENVIRONMENT_MAGNETOMETER == 1 + int getMagnetometerX(); + int getMagnetometerY(); + int getMagnetometerZ(); int getMagnetometerAzimuth(); #endif @@ -35,6 +39,7 @@ class OswHal::Environment { float getAccelerationX(); float getAccelerationY(); float getAccelerationZ(); + OswAccelerationProvider::ActivityMode getActivityMode(); // Statistics: Steps uint32_t getStepsToday(); void resetStepCount(); diff --git a/include/osw_config_keys.h b/include/osw_config_keys.h index aa93098c3..9a556dec9 100644 --- a/include/osw_config_keys.h +++ b/include/osw_config_keys.h @@ -57,16 +57,17 @@ extern OswConfigKeyShort settingDisplayBrightness; extern OswConfigKeyBool settingDisplayOverlays; extern OswConfigKeyBool settingDisplayOverlaysForced; extern OswConfigKeyBool settingDisplayDualHourTick; +#if OSW_PLATFORM_BLOCK_SLEEP != 1 extern OswConfigKeyBool raiseToWakeEnabled; extern OswConfigKeyShort raiseToWakeSensitivity; extern OswConfigKeyBool tapToWakeEnabled; extern OswConfigKeyBool lightSleepEnabled; extern OswConfigKeyBool buttonToWakeEnabled; +#endif extern OswConfigKeyDropDown dateFormat; extern OswConfigKeyBool timeFormat; extern OswConfigKeyString timezonePrimary; extern OswConfigKeyString timezoneSecondary; -extern OswConfigKeyShort resetDay; #if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 extern OswConfigKeyShort configHeight; extern OswConfigKeyShort configWeight; @@ -75,6 +76,7 @@ extern OswConfigKeyInt distPerDay; extern OswConfigKeyInt kcalPerDay; extern OswConfigKeyBool stepsHistoryClear; extern OswConfigKeyBool settingDisplayStepsGoal; +extern OswConfigKeyShort resetDay; #endif extern OswConfigKeyDropDown settingDisplayDefaultWatchface; #ifdef OSW_FEATURE_WEATHER diff --git a/include/osw_hal.h b/include/osw_hal.h index a17b34d8a..b92bccd37 100644 --- a/include/osw_hal.h +++ b/include/osw_hal.h @@ -64,7 +64,7 @@ class OswHal { // Setup void setup(bool fromLightSleep); void setupFileSystem(void); - void setupButtons(void); + void setupButtons(); void setupDisplay(); void setupPower(bool fromLightSleep); #if defined(GPS_EDITION) || defined(GPS_EDITION_ROTATED) @@ -284,6 +284,9 @@ class OswHal { void persistWakeUpConfig(OswHal::WakeUpConfig* config, bool toLightSleep); std::optional readAndResetWakeUpConfig(bool fromLightSleep); void resetWakeUpConfig(bool useLightSleep); +#if OSW_PLATFORM_IS_FLOW3R_BADGE == 1 + uint8_t readGpioExtender(uint8_t address = 0x6D); +#endif }; #endif diff --git a/include/osw_pins.h b/include/osw_pins.h index 36d15f183..afad31f61 100644 --- a/include/osw_pins.h +++ b/include/osw_pins.h @@ -2,25 +2,6 @@ // NOTE This file will slowly be migrated into the platform header files. -// pin mapping -#if defined(GPS_EDITION) || defined(GPS_EDITION_ROTATED) -#define TFT_CS 5 -#define TFT_DC 12 -#define TFT_RST 2 -#define TFT_SCK 18 -#define TFT_MOSI 23 -#define TFT_MISO -1 // no data coming back -#define TFT_LED 9 -#else -#define TFT_CS 5 -#define TFT_DC 12 -#define TFT_RST 33 -#define TFT_SCK 18 -#define TFT_MOSI 23 -#define TFT_MISO -1 // no data coming back -#define TFT_LED 9 -#endif - #define SD_CS 4 // SD_MISO 19 // for SCK, MOSI see TFT @@ -30,19 +11,19 @@ #define GPS_FON 26 #define GPS_3D_FIX 36 #define GPS_GEO_FENCE 39 -#define RX1 27 -#define TX1 14 #if defined(GPS_EDITION) #define BTN_1 0 #define BTN_2 13 #define BTN_3 33 -#define VIBRATE 35 +#define GPS_RX1 27 +#define GPS_TX1 14 #elif defined(GPS_EDITION_ROTATED) #define BTN_1 13 #define BTN_2 33 #define BTN_3 0 -#define VIBRATE 35 +#define GPS_RX1 27 +#define GPS_TX1 14 #else #define BTN_1 0 #define BTN_2 13 diff --git a/include/platform/EMULATOR.h b/include/platform/EMULATOR.h index ab88adb61..8188c9f9b 100644 --- a/include/platform/EMULATOR.h +++ b/include/platform/EMULATOR.h @@ -9,10 +9,24 @@ //#define OSW_PLATFORM_HARDWARE_DS3231MZ 0 //#define OSW_PLATFORM_HARDWARE_BMA400 0 +//#define OSW_PLATFORM_HARDWARE_BMI270 0 +//#define OSW_PLATFORM_HARDWARE_BMP581 0 //#define OSW_PLATFORM_HARDWARE_BME280 0 //#define OSW_PLATFORM_HARDWARE_QMC5883L 0 #define OSW_PLATFORM_HARDWARE_VIRTUAL 1 #define OSW_PLATFORM_HARDWARE_ESP32 0 +//#define OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_CS 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_DC 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_RST 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_SCK 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_MOSI 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_LED 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_SPI_NUM 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION 0 +//#define OSW_PLATFORM_HARDWARE_VIBRATE 0 +//#define OSW_PLATFORM_BLOCK_SLEEP 0 // used during the integration of new platforms to prevent the device from going to sleep +//#define OSW_PLATFORM_IS_FLOW3R_BADGE 0 #define OSW_PLATFORM_DEFAULT_CPUFREQ 0 //#define OSW_DEVICE_ESP32_WIFI_LOWPWR 0 @@ -23,3 +37,4 @@ //#define OSW_DEVICE_I2C_SDA 21 #define OSW_DEVICE_TPS2115A_STATPWR 15 #define OSW_DEVICE_ESP32_BATLVL 25 +#define OSW_DEVICE_ESP32_USE_INTTEMP 0 diff --git a/include/platform/FLOW3R_C3CAMP_2023.h b/include/platform/FLOW3R_C3CAMP_2023.h new file mode 100644 index 000000000..bd4b4820a --- /dev/null +++ b/include/platform/FLOW3R_C3CAMP_2023.h @@ -0,0 +1,41 @@ +#pragma once + +#define OSW_PLATFORM_ENVIRONMENT 1 +#define OSW_PLATFORM_ENVIRONMENT_TEMPERATURE 1 +//#define OSW_PLATFORM_ENVIRONMENT_PRESSURE 0 +//#define OSW_PLATFORM_ENVIRONMENT_HUMIDITY 0 +//#define OSW_PLATFORM_ENVIRONMENT_MAGNETOMETER 0 +#define OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER 1 + +//#define OSW_PLATFORM_HARDWARE_DS3231MZ 0 +//#define OSW_PLATFORM_HARDWARE_BMA400 0 +#define OSW_PLATFORM_HARDWARE_BMI270 1 +//#define OSW_PLATFORM_HARDWARE_BMP581 0 +//#define OSW_PLATFORM_HARDWARE_QMC5883L 0 +//#define OSW_PLATFORM_HARDWARE_BME280 0 +//#define OSW_PLATFORM_HARDWARE_VIRTUAL 0 +#define OSW_PLATFORM_HARDWARE_ESP32 1 +#define OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL 1 +#define OSW_PLATFORM_HARDWARE_DISPLAY_CS 40 +#define OSW_PLATFORM_HARDWARE_DISPLAY_DC 38 +// well, the display reset pin is located at MAX7321ATE (U7), pin 5 (P3) +#define OSW_PLATFORM_HARDWARE_DISPLAY_RST -1 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SCK 41 +#define OSW_PLATFORM_HARDWARE_DISPLAY_MOSI 42 +#define OSW_PLATFORM_HARDWARE_DISPLAY_LED 46 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SPI_NUM 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION 2 +//#define OSW_PLATFORM_HARDWARE_VIBRATE 0 +#define OSW_PLATFORM_BLOCK_SLEEP 1 // used during the integration of new platforms to prevent the device from going to sleep +#define OSW_PLATFORM_IS_FLOW3R_BADGE 1 +#define OSW_PLATFORM_DEFAULT_CPUFREQ 240 + +#define OSW_DEVICE_ESP32_WIFI_LOWPWR 0 +//#define OSW_DEVICE_DS3231MZ_RTCINT 32 +//#define OSW_DEVICE_BMA400_INT1 34 +//#define OSW_DEVICE_BMA400_INT2 35 +#define OSW_DEVICE_I2C_SCL 1 +#define OSW_DEVICE_I2C_SDA 2 +//#define OSW_DEVICE_TPS2115A_STATPWR 0 +#define OSW_DEVICE_ESP32_BATLVL 9 +#define OSW_DEVICE_ESP32_USE_INTTEMP 0 diff --git a/include/platform/GPS_EDITION_V3_1.h b/include/platform/GPS_EDITION_V3_1.h index 1e8850767..52a0ce21a 100644 --- a/include/platform/GPS_EDITION_V3_1.h +++ b/include/platform/GPS_EDITION_V3_1.h @@ -1,5 +1,8 @@ #pragma once +// This flag is used for the rotated variant of the PCB +//#define GPS_EDITION_ROTATED 1 + #define OSW_PLATFORM_ENVIRONMENT 1 #define OSW_PLATFORM_ENVIRONMENT_TEMPERATURE 1 #define OSW_PLATFORM_ENVIRONMENT_PRESSURE 1 @@ -9,10 +12,28 @@ #define OSW_PLATFORM_HARDWARE_DS3231MZ 1 #define OSW_PLATFORM_HARDWARE_BMA400 1 +//#define OSW_PLATFORM_HARDWARE_BMI270 0 +//#define OSW_PLATFORM_HARDWARE_BMP581 0 #define OSW_PLATFORM_HARDWARE_BME280 1 #define OSW_PLATFORM_HARDWARE_QMC5883L 1 //#define OSW_PLATFORM_HARDWARE_VIRTUAL 0 #define OSW_PLATFORM_HARDWARE_ESP32 1 +//#define OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_CS 5 +#define OSW_PLATFORM_HARDWARE_DISPLAY_DC 12 +#define OSW_PLATFORM_HARDWARE_DISPLAY_RST 2 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SCK 18 +#define OSW_PLATFORM_HARDWARE_DISPLAY_MOSI 23 +#define OSW_PLATFORM_HARDWARE_DISPLAY_LED 9 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SPI_NUM VSPI +#ifdef GPS_EDITION_ROTATED +#define OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION 1 +#else +#define OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION 0 +#endif +#define OSW_PLATFORM_HARDWARE_VIBRATE 35 +//#define OSW_PLATFORM_BLOCK_SLEEP 0 // used during the integration of new platforms to prevent the device from going to sleep +//#define OSW_PLATFORM_IS_FLOW3R_BADGE 0 #define OSW_PLATFORM_DEFAULT_CPUFREQ 240 #define OSW_DEVICE_ESP32_WIFI_LOWPWR 1 @@ -23,3 +44,4 @@ #define OSW_DEVICE_I2C_SDA 21 #define OSW_DEVICE_TPS2115A_STATPWR 15 #define OSW_DEVICE_ESP32_BATLVL 25 +#define OSW_DEVICE_ESP32_USE_INTTEMP 1 diff --git a/include/platform/LIGHT_EDITION_V3_3.h b/include/platform/LIGHT_EDITION_V3_3.h index c4a095647..5b7b0264c 100644 --- a/include/platform/LIGHT_EDITION_V3_3.h +++ b/include/platform/LIGHT_EDITION_V3_3.h @@ -9,10 +9,24 @@ #define OSW_PLATFORM_HARDWARE_DS3231MZ 1 #define OSW_PLATFORM_HARDWARE_BMA400 1 +//#define OSW_PLATFORM_HARDWARE_BMI270 0 +//#define OSW_PLATFORM_HARDWARE_BMP581 0 //#define OSW_PLATFORM_HARDWARE_QMC5883L 0 //#define OSW_PLATFORM_HARDWARE_BME280 0 //#define OSW_PLATFORM_HARDWARE_VIRTUAL 0 #define OSW_PLATFORM_HARDWARE_ESP32 1 +//#define OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_CS 5 +#define OSW_PLATFORM_HARDWARE_DISPLAY_DC 12 +#define OSW_PLATFORM_HARDWARE_DISPLAY_RST 33 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SCK 18 +#define OSW_PLATFORM_HARDWARE_DISPLAY_MOSI 23 +#define OSW_PLATFORM_HARDWARE_DISPLAY_LED 9 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SPI_NUM VSPI +#define OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION 0 +//#define OSW_PLATFORM_HARDWARE_VIBRATE 0 +//#define OSW_PLATFORM_BLOCK_SLEEP 0 // used during the integration of new platforms to prevent the device from going to sleep +//#define OSW_PLATFORM_IS_FLOW3R_BADGE 0 #define OSW_PLATFORM_DEFAULT_CPUFREQ 240 #define OSW_DEVICE_ESP32_WIFI_LOWPWR 1 @@ -23,3 +37,4 @@ #define OSW_DEVICE_I2C_SDA 21 #define OSW_DEVICE_TPS2115A_STATPWR 15 #define OSW_DEVICE_ESP32_BATLVL 25 +#define OSW_DEVICE_ESP32_USE_INTTEMP 1 diff --git a/include/platform/LIGHT_EDITION_V4_0.h b/include/platform/LIGHT_EDITION_V4_0.h index 3940cc534..28366a0e0 100644 --- a/include/platform/LIGHT_EDITION_V4_0.h +++ b/include/platform/LIGHT_EDITION_V4_0.h @@ -9,10 +9,24 @@ #define OSW_PLATFORM_HARDWARE_DS3231MZ 1 #define OSW_PLATFORM_HARDWARE_BMA400 1 +//#define OSW_PLATFORM_HARDWARE_BMI270 0 +//#define OSW_PLATFORM_HARDWARE_BMP581 0 //#define OSW_PLATFORM_HARDWARE_BME280 0 //#define OSW_PLATFORM_HARDWARE_QMC5883L 0 //#define OSW_PLATFORM_HARDWARE_VIRTUAL 0 #define OSW_PLATFORM_HARDWARE_ESP32 1 +//#define OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_CS 5 +#define OSW_PLATFORM_HARDWARE_DISPLAY_DC 12 +#define OSW_PLATFORM_HARDWARE_DISPLAY_RST 33 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SCK 18 +#define OSW_PLATFORM_HARDWARE_DISPLAY_MOSI 23 +#define OSW_PLATFORM_HARDWARE_DISPLAY_LED 9 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SPI_NUM VSPI +#define OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION 0 +//#define OSW_PLATFORM_HARDWARE_VIBRATE 0 +//#define OSW_PLATFORM_BLOCK_SLEEP 0 // used during the integration of new platforms to prevent the device from going to sleep +//#define OSW_PLATFORM_IS_FLOW3R_BADGE 0 #define OSW_PLATFORM_DEFAULT_CPUFREQ 240 //#define OSW_DEVICE_ESP32_WIFI_LOWPWR 0 @@ -23,3 +37,4 @@ #define OSW_DEVICE_I2C_SDA 21 #define OSW_DEVICE_TPS2115A_STATPWR 15 #define OSW_DEVICE_ESP32_BATLVL 25 +#define OSW_DEVICE_ESP32_USE_INTTEMP 1 diff --git a/include/platform/MINIMAL.h b/include/platform/MINIMAL.h new file mode 100644 index 000000000..153aab22e --- /dev/null +++ b/include/platform/MINIMAL.h @@ -0,0 +1,40 @@ +#pragma once + +//#define OSW_PLATFORM_ENVIRONMENT 0 +//#define OSW_PLATFORM_ENVIRONMENT_TEMPERATURE 0 +//#define OSW_PLATFORM_ENVIRONMENT_PRESSURE 0 +//#define OSW_PLATFORM_ENVIRONMENT_HUMIDITY 0 +//#define OSW_PLATFORM_ENVIRONMENT_MAGNETOMETER 0 +//#define OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER 0 + +//#define OSW_PLATFORM_HARDWARE_DS3231MZ 0 +//#define OSW_PLATFORM_HARDWARE_BMA400 0 +//#define OSW_PLATFORM_HARDWARE_BMI270 0 +//#define OSW_PLATFORM_HARDWARE_BMP581 0 +//#define OSW_PLATFORM_HARDWARE_BME280 0 +//#define OSW_PLATFORM_HARDWARE_QMC5883L 0 +//#define OSW_PLATFORM_HARDWARE_VIRTUAL 0 +//#define OSW_PLATFORM_HARDWARE_ESP32 0 +//#define OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_CS 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_DC 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_RST 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SCK 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_MOSI 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_LED 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_SPI_NUM 0 +//#define OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION 0 +//#define OSW_PLATFORM_HARDWARE_VIBRATE 0 +//#define OSW_PLATFORM_BLOCK_SLEEP 0 // used during the integration of new platforms to prevent the device from going to sleep +//#define OSW_PLATFORM_IS_FLOW3R_BADGE 0 +//#define OSW_PLATFORM_DEFAULT_CPUFREQ 0 + +//#define OSW_DEVICE_ESP32_WIFI_LOWPWR 0 +//#define OSW_DEVICE_DS3231MZ_RTCINT 0 +//#define OSW_DEVICE_BMA400_INT1 0 +//#define OSW_DEVICE_BMA400_INT2 0 +//#define OSW_DEVICE_I2C_SCL 0 +//#define OSW_DEVICE_I2C_SDA 0 +//#define OSW_DEVICE_TPS2115A_STATPWR 0 +//#define OSW_DEVICE_ESP32_BATLVL 0 +//#define OSW_DEVICE_ESP32_USE_INTTEMP 0 diff --git a/include/services/OswServiceManager.h b/include/services/OswServiceManager.h index 9574c73f9..8b3d4359f 100644 --- a/include/services/OswServiceManager.h +++ b/include/services/OswServiceManager.h @@ -25,7 +25,7 @@ class OswServiceManager { #else #define _SERVICE_WIFI 0 #endif - const unsigned workerStackSize = 1024 + (7168 * _SERVICE_WIFI); // If wifi is active, set to same size as core 0 + const unsigned workerStackSize = 2048 + (8192 * _SERVICE_WIFI); // If wifi is active, set to same size as core 0 const unsigned workerStartupDelay = 2000; const unsigned workerLoopDelay = 10; diff --git a/include/services/OswServiceTaskBLECompanion.h b/include/services/OswServiceTaskBLECompanion.h index cfaa7ece9..0fc5e8228 100644 --- a/include/services/OswServiceTaskBLECompanion.h +++ b/include/services/OswServiceTaskBLECompanion.h @@ -2,6 +2,7 @@ #define OSW_SERVICE_COMPANION_H #ifndef OSW_EMULATOR +#if SERVICE_BLE_COMPANION == 1 #include #include #include @@ -44,3 +45,4 @@ class OswServiceTaskBLECompanion : public OswServiceTask { #endif #endif +#endif diff --git a/include/services/OswServiceTaskWiFi.h b/include/services/OswServiceTaskWiFi.h index 0e9015b07..1aa11dc7a 100644 --- a/include/services/OswServiceTaskWiFi.h +++ b/include/services/OswServiceTaskWiFi.h @@ -56,13 +56,6 @@ class OswServiceTaskWiFi : public OswServiceTask { ~OswServiceTaskWiFi() {}; private: - //The ESP32 has some problems broadcasting its SSID while using client & station -#ifdef OSW_FEATURE_WIFI_APST - const bool onlyOneModeSimultaneously = false; -#else - const bool onlyOneModeSimultaneously = true; -#endif - bool m_bootDone = false; // This triggers the async setup inside the loop bool m_enableWiFi = false; bool m_enableClient = false; diff --git a/include/services/OswServiceTasks.h b/include/services/OswServiceTasks.h index d880bfaa2..154298e71 100644 --- a/include/services/OswServiceTasks.h +++ b/include/services/OswServiceTasks.h @@ -1,6 +1,5 @@ #include "osw_service.h" -class OswServiceTaskBLECompanion; class OswServiceTaskExample; class OswServiceTaskMemMonitor; class OswServiceTaskNotifier; @@ -10,6 +9,7 @@ class OswServiceTaskWebserver; #endif namespace OswServiceAllTasks { #if SERVICE_BLE_COMPANION == 1 +class OswServiceTaskBLECompanion; extern OswServiceTaskBLECompanion bleCompanion; #endif // extern OswServiceTaskExample example; diff --git a/lib/BMI270-API b/lib/BMI270-API new file mode 160000 index 000000000..d211d93e2 --- /dev/null +++ b/lib/BMI270-API @@ -0,0 +1 @@ +Subproject commit d211d93e223c57ceff7f488c5dd8381ed04ff271 diff --git a/lib/BMP581-API b/lib/BMP581-API new file mode 160000 index 000000000..c779b44bf --- /dev/null +++ b/lib/BMP581-API @@ -0,0 +1 @@ +Subproject commit c779b44bf3c682d1fc06b5771378361650028223 diff --git a/lib/ESP32-BLE-Keyboard b/lib/ESP32-BLE-Keyboard index f8dd48521..b7aaf9bb7 160000 --- a/lib/ESP32-BLE-Keyboard +++ b/lib/ESP32-BLE-Keyboard @@ -1 +1 @@ -Subproject commit f8dd4852113a722a6b8dc8af987e94cf84d73ad5 +Subproject commit b7aaf9bb711a04216e4417f1e2a6b0ee0eaeaf66 diff --git a/platformio.ini b/platformio.ini index 3486d3ef5..a153b84d0 100755 --- a/platformio.ini +++ b/platformio.ini @@ -11,8 +11,14 @@ [platformio] default_envs = LIGHT_EDITION_V3_3 +# =========================================== +# A note regarding the platform/library versions here: +# Due to potential upstream bugs, we pinned all versions to the latest known working version. +# While this will prevent the use of latest features, it will also prevent randomly breaking builds... +# =========================================== + [env] -platform = espressif32@^6.5.0 +platform = espressif32@6.8.1 ; for USE_ULP: use a special branch and git submodule add https://github.com/boarchuz/HULP.git ; platform_packages = ; framework-arduinoespressif32 @ https://github.com/marcovannoord/arduino-esp32.git#idf-release/v4.2 @@ -22,12 +28,12 @@ framework = arduino board_build.partitions = min_spiffs.csv ; OTA updates (two app slots), but no space for the SPIFFS (as it is currently not used) monitor_filters = esp32_exception_decoder ; Well, it works?! lib_deps = - adafruit/Adafruit Unified Sensor@^1.1.9 - adafruit/Adafruit BusIO@^1.14.1 - makuna/RTC@^2.4.0 - bblanchon/ArduinoJson@^6.21.2 - finitespace/BME280@^3.0.0 ; TODO Use the more popular Adafruit BME280 Library instead (also true for others?)? - mprograms/QMC5883LCompass@^1.1.1 + adafruit/Adafruit Unified Sensor@1.1.14 + adafruit/Adafruit BusIO@1.16.1 + makuna/RTC@2.4.3 + bblanchon/ArduinoJson@6.21.5 + finitespace/BME280@3.0.0 ; TODO Use the more popular Adafruit BME280 Library instead (also true for others?)? + mprograms/QMC5883LCompass@1.2.3 upload_speed = 460800 monitor_speed = 115200 ; Define additional build stage scripts - used to "compile" the html or define additional information @@ -38,6 +44,17 @@ extra_scripts = pre:scripts/build/prebuild_lua.py ; Needed to generate the .cxx file(s), enabled via "OSW_FEATURE_LUA" build flag build_unflags = -std=gnu++11 # The correct flag will be set by the cppflags python script... +# =========================================== +# A note regarding the environments here... +# If you add new ones, checkout `docs/support.md` and update the list there. +# If you wonder what flags are available, check the `docs/flags.md` file. +# =========================================== + +[env:MINIMAL] ; For development only, the absolute minimal operating system +build_flags = + -D OSW_TARGET_PLATFORM_HEADER='"platform/MINIMAL.h"' +build_type = debug + ; Light edition by hardware revisions ; This revision did not change anything on hardware or software level, it just resized the pcb from V3_2 [env:LIGHT_EDITION_V3_3] @@ -48,7 +65,7 @@ build_flags = -D OSW_FEATURE_WIFI build_type = debug -[env:LIGHT_EDITION_V4_0] +[env:EXPERIMENTAL_LIGHT_EDITION_V4_0] build_flags = -D OSW_TARGET_PLATFORM_HEADER='"platform/LIGHT_EDITION_V4_0.h"' -D OSW_FEATURE_STATS_STEPS @@ -58,7 +75,7 @@ build_flags = build_type = debug ; Light edition other stuff -[env:LIGHT_EDITION_DEV_LUA] +[env:EXPERIMENTAL_LIGHT_EDITION_V3_3_LUA] build_flags = -D OSW_TARGET_PLATFORM_HEADER='"platform/LIGHT_EDITION_V3_3.h"' -D OSW_FEATURE_LUA @@ -74,7 +91,7 @@ extra_scripts = build_type = debug ; GPS edition by hardware revisions -[env:GPS_EDITION_V3_1] +[env:EXPERIMENTAL_GPS_EDITION_V3_1] build_flags = -D OSW_TARGET_PLATFORM_HEADER='"platform/GPS_EDITION_V3_1.h"' -D GPS_EDITION @@ -84,12 +101,11 @@ build_flags = -D OSW_FEATURE_STATS_STEPS -D OSW_SERVICE_CONSOLE -D OSW_FEATURE_WIFI - -D OSW_FEATURE_WIFI_APST -D OSW_FEATURE_WIFI_ONBOOT build_type = debug ; GPS edition other stuff -[env:GPS_EDITION_DEV_ROTATED] +[env:EXPERIMENTAL_GPS_EDITION_DEV_ROTATED] build_flags = -D OSW_TARGET_PLATFORM_HEADER='"platform/GPS_EDITION_V3_1.h"' -D PROGMEM_TILES @@ -99,6 +115,15 @@ build_flags = -D OSW_FEATURE_STATS_STEPS -D OSW_SERVICE_CONSOLE -D OSW_FEATURE_WIFI - -D OSW_FEATURE_WIFI_APST + -D OSW_FEATURE_WIFI_ONBOOT +build_type = debug + +[env:3RD_PARTY_FLOW3R_C3CAMP_2023] +board = esp32-s3-devkitc-1 +upload_speed = 921600 ; the usb-c is more stable, allowing faster speeds +build_flags = + -D OSW_TARGET_PLATFORM_HEADER='"platform/FLOW3R_C3CAMP_2023.h"' + -D OSW_SERVICE_CONSOLE + -D OSW_FEATURE_WIFI -D OSW_FEATURE_WIFI_ONBOOT build_type = debug diff --git a/scripts/build/prebuild_assets.py b/scripts/build/prebuild_assets.py index 67b3d7c47..149ff7cc0 100755 --- a/scripts/build/prebuild_assets.py +++ b/scripts/build/prebuild_assets.py @@ -31,9 +31,9 @@ def createAssets(srcPath, assPath, convertAssetToSourceCode, force): # fileStripped = file.removesuffix('.h').removesuffix('.gz') # the above line is only available in python 3.9, so we use the following instead: fileStripped = file - if (split := os.path.splitext(file))[1] == '.h': + if (split := os.path.splitext(fileStripped))[1] == '.h': fileStripped = split[0] - if (split := os.path.splitext(file))[1] == '.gz': + if (split := os.path.splitext(fileStripped))[1] == '.gz': fileStripped = split[0] assFile = os.path.join(subPath, fileStripped) path = os.path.relpath(assFile, assPath) diff --git a/src/OswSerial.cpp b/src/OswSerial.cpp new file mode 100644 index 000000000..5ec8f4169 --- /dev/null +++ b/src/OswSerial.cpp @@ -0,0 +1,80 @@ +#include + +OswSerial* OswSerial::instance = nullptr; + +void OswSerial::begin(unsigned long baud) { +#if OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL == 1 + // CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG would do its magic - but is was not set in ESP-IDF during compile time, so... + // the function bootloader_console_init() would normally set this up, but the compiled one configures another UART + { + // the following line is just a forward to the rom-function + // ld will be instructed to just use a hard-coded addresses + // ...but the ESP-IDF version is too old and does not have this function yet + // esp_rom_output_switch_buffer(ESP_ROM_USB_SERIAL_DEVICE_NUM); + + // this replaces the above function, at least in ESP-IDF v4.3 + { + UartDevice* uart = GetUartDevice(); + uart->buff_uart_no = ESP_ROM_USB_SERIAL_DEVICE_NUM; + } + + // same as before, but not needed for older chips + // esp_rom_output_set_as_console(ESP_ROM_USB_SERIAL_DEVICE_NUM); + + // esp_rom_output_switch_buffer or uart_buff_switch // -> does NOT exist in my old ESP-IDF version + // -> use older variant, which directly accesses the rom-code + } +#else + Serial.begin(115200); +#endif +} + +void OswSerial::putc(uint8_t c) { +#if OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL == 1 + esp_rom_uart_putc(c); +#else + Serial.print((char) c); +#endif +} + +void OswSerial::flush() { +#if OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL == 1 + esp_rom_uart_flush_tx(ESP_ROM_USB_SERIAL_DEVICE_NUM); +#else + Serial.flush(); +#endif +} + +bool OswSerial::getc(uint8_t& c) { +#if OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL == 1 + return esp_rom_uart_rx_one_char(&c) == 0; +#else + if(::Serial.available()) { + c = ::Serial.read(); + return true; + } else { + return false; + } +#endif +} + +void OswSerial::println() { +#if OSW_PLATFORM_HARDWARE_ESP32_USE_JTAG_SERIAL == 1 + this->putc('\n'); + this->flush(); +#else + Serial.println(); +#endif +} + +OswSerial* OswSerial::getInstance() { + if(OswSerial::instance == nullptr) { + OswSerial::instance = new OswSerial(); + } + return OswSerial::instance; +}; + +void OswSerial::resetInstance() { + delete OswSerial::instance; + OswSerial::instance = nullptr; +} diff --git a/src/apps/_experiments/dnatilt.cpp b/src/apps/_experiments/dnatilt.cpp index 787e9cf71..585b141c0 100644 --- a/src/apps/_experiments/dnatilt.cpp +++ b/src/apps/_experiments/dnatilt.cpp @@ -1,4 +1,5 @@ #ifdef OSW_FEATURE_WIFI +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include "./apps/_experiments/dnatilt.h" #include @@ -53,3 +54,4 @@ void OswAppDNATilt::loop() { */ } #endif +#endif diff --git a/src/apps/_experiments/gif_player.cpp b/src/apps/_experiments/gif_player.cpp index 1fb348b0c..cbb222ec1 100644 --- a/src/apps/_experiments/gif_player.cpp +++ b/src/apps/_experiments/gif_player.cpp @@ -87,7 +87,7 @@ void OswAppGifPlayer::setup() { gfx = OswHal::getInstance()->gfx(); // update static gfx handle for the GIFDraw callback gif.begin(LITTLE_ENDIAN_PIXELS); if (gif.open((uint8_t*)GIF_NAME, sizeof(GIF_NAME), GIFDraw)) { - Serial.printf("Successfully opened GIF; Canvas size = %d x %d\n", gif.getCanvasWidth(), gif.getCanvasHeight()); + OSW_LOG_D("Successfully opened GIF; Canvas size = ", gif.getCanvasWidth(), " x ", gif.getCanvasHeight()); gifOpen = true; } OswHal::getInstance()->gfx()->fill(rgb565(0, 0, 0)); diff --git a/src/apps/games/brick_breaker.cpp b/src/apps/games/brick_breaker.cpp index e177c5071..4494ace5b 100644 --- a/src/apps/games/brick_breaker.cpp +++ b/src/apps/games/brick_breaker.cpp @@ -1,3 +1,5 @@ +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include "./apps/games/brick_breaker.h" @@ -385,3 +387,4 @@ void OswAppBrickBreaker::moveBall() { //} } } +#endif \ No newline at end of file diff --git a/src/apps/games/snake_game.cpp b/src/apps/games/snake_game.cpp index 6e03f1856..13706d581 100644 --- a/src/apps/games/snake_game.cpp +++ b/src/apps/games/snake_game.cpp @@ -1,3 +1,5 @@ +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include "./apps/games/snake_game.h" // #define GIF_BG @@ -416,3 +418,4 @@ bool OswAppSnakeGame::touchItself() { } return false; } +#endif \ No newline at end of file diff --git a/src/apps/tools/OswAppBLEMediaCtrl.cpp b/src/apps/tools/OswAppBLEMediaCtrl.cpp index a0f7efdbc..6f0271e7b 100644 --- a/src/apps/tools/OswAppBLEMediaCtrl.cpp +++ b/src/apps/tools/OswAppBLEMediaCtrl.cpp @@ -2,12 +2,16 @@ #ifdef OSW_FEATURE_BLE_MEDIA_CTRL #include "./apps/tools/OswAppBLEMediaCtrl.h" -#include #include #include #include #include +// workaround for compile issues via https://github.com/espressif/arduino-esp32/issues/6388 +#define BLE_42_FEATURE_SUPPORT TRUE +#define BLE_50_FEATURE_SUPPORT TRUE +#include + BleKeyboard* bleKeyboard; void OswAppBLEMediaCtrl::setup() { diff --git a/src/apps/tools/OswAppFitnessStats.cpp b/src/apps/tools/OswAppFitnessStats.cpp index fbd59549e..d44bb58e3 100644 --- a/src/apps/tools/OswAppFitnessStats.cpp +++ b/src/apps/tools/OswAppFitnessStats.cpp @@ -1,3 +1,6 @@ +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 + #include "./apps/tools/OswAppFitnessStats.h" #include "./apps/watchfaces/OswAppWatchfaceDual.h" #include "./apps/watchfaces/OswAppWatchfaceFitness.h" @@ -56,3 +59,4 @@ void OswAppFitnessStats::loop() { } void OswAppFitnessStats::stop() {} +#endif diff --git a/src/apps/tools/OswAppPrintDebug.cpp b/src/apps/tools/OswAppPrintDebug.cpp index b5523f5fe..b8df89962 100644 --- a/src/apps/tools/OswAppPrintDebug.cpp +++ b/src/apps/tools/OswAppPrintDebug.cpp @@ -67,6 +67,17 @@ void OswAppPrintDebug::loop() { printStatus((String(" ") + d->getName()).c_str(), String(d->getMagnetometerAzimuth() + String(" deg")).c_str()); // Idea: Also print azimuth, bearing or calibration #endif +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 + printStatus("Accelerometer", String(String(hal->environment()->getAccelerationX()) + ";" + String(hal->environment()->getAccelerationY()) + ";" + String(hal->environment()->getAccelerationZ()) + " m/s^2").c_str()); + for(auto& d : *OswAccelerationProvider::getAllAccelerationDevices()) + printStatus((String(" ") + d->getName()).c_str(), String(String(hal->environment()->getAccelerationX()) + ";" + String(hal->environment()->getAccelerationY()) + ";" + String(hal->environment()->getAccelerationZ()) + " m/s^2").c_str()); + printStatus("Steps", String(hal->environment()->getStepsToday()).c_str()); + for(auto& d : *OswAccelerationProvider::getAllAccelerationDevices()) + printStatus((String(" ") + d->getName()).c_str(), String(hal->environment()->getStepsToday()).c_str()); + printStatus("Activity", String((int) hal->environment()->getActivityMode()).c_str()); + for(auto& d : *OswAccelerationProvider::getAllAccelerationDevices()) + printStatus((String(" ") + d->getName()).c_str(), String((int) hal->environment()->getActivityMode()).c_str()); +#endif #endif printStatus("UTC Time", String(String(hal->getUTCTime()) + " sec").c_str()); for(auto& d : *OswTimeProvider::getAllTimeDevices()) diff --git a/src/apps/tools/OswAppWaterLevel.cpp b/src/apps/tools/OswAppWaterLevel.cpp index 2d2f3f308..508251c85 100644 --- a/src/apps/tools/OswAppWaterLevel.cpp +++ b/src/apps/tools/OswAppWaterLevel.cpp @@ -1,3 +1,5 @@ +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #include "./apps/tools/OswAppWaterLevel.h" @@ -131,3 +133,4 @@ void OswAppWaterLevel::loop() { } void OswAppWaterLevel::stop() {} +#endif diff --git a/src/apps/tools/OswAppWebserver.cpp b/src/apps/tools/OswAppWebserver.cpp index 530d3d4d5..cc4d39ca9 100644 --- a/src/apps/tools/OswAppWebserver.cpp +++ b/src/apps/tools/OswAppWebserver.cpp @@ -1,7 +1,7 @@ #ifdef OSW_FEATURE_WIFI #include "./apps/tools/OswAppWebserver.h" -#include +#include #include #include #include diff --git a/src/apps/watchfaces/OswAppWatchfaceBinary.cpp b/src/apps/watchfaces/OswAppWatchfaceBinary.cpp index c8e1cae0c..00d894078 100644 --- a/src/apps/watchfaces/OswAppWatchfaceBinary.cpp +++ b/src/apps/watchfaces/OswAppWatchfaceBinary.cpp @@ -5,6 +5,7 @@ #include "apps/watchfaces/OswAppWatchface.h" #include "apps/watchfaces/OswAppWatchfaceBinary.h" +#include OSW_TARGET_PLATFORM_HEADER #define COLOR_SECxOND rgb565(231, 111, 81) #define COLOR_MIxNUTE rgb565(244, 162, 97) @@ -54,6 +55,7 @@ void OswAppWatchfaceBinary::drawWatch() { //cosmetic hal->gfx()->drawLine(width /2 + 40, height / 8 * 1, width /2 + 40, height / 8 * 7, ui->getForegroundColor()); +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 //steps uint32_t steps = hal->environment()->getStepsToday(); hal->gfx()->setTextSize(1); @@ -65,6 +67,7 @@ void OswAppWatchfaceBinary::drawWatch() { hal->gfx()->setTextCursor(width /2 + 48, height / 2 + 32); hal->gfx()->print("0x"); hal->gfx()->print(steps, HEX); +#endif } const char* OswAppWatchfaceBinary::getAppId() { diff --git a/src/apps/watchfaces/OswAppWatchfaceDigital.cpp b/src/apps/watchfaces/OswAppWatchfaceDigital.cpp index 2be8869c3..ca74c6d41 100644 --- a/src/apps/watchfaces/OswAppWatchfaceDigital.cpp +++ b/src/apps/watchfaces/OswAppWatchfaceDigital.cpp @@ -5,6 +5,7 @@ #include "./apps/watchfaces/OswAppWatchface.h" #include "./apps/watchfaces/OswAppWatchfaceDigital.h" +#include OSW_TARGET_PLATFORM_HEADER uint8_t OswAppWatchfaceDigital::dateFormatCache = 42; @@ -133,6 +134,7 @@ const char* OswAppWatchfaceDigital::getAppName() { return LANG_DIGITAL; } +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 void OswAppWatchfaceDigital::drawSteps() { #ifdef OSW_FEATURE_STATS_STEPS uint8_t w = 8; @@ -147,6 +149,7 @@ void OswAppWatchfaceDigital::drawSteps() { hal->gfx()->print(steps); #endif } +#endif void OswAppWatchfaceDigital::digitalWatch(short timeZone,uint8_t fontSize, uint8_t dateCoordY, uint8_t timeCoordY) { diff --git a/src/apps/watchfaces/OswAppWatchfaceFitness.cpp b/src/apps/watchfaces/OswAppWatchfaceFitness.cpp index 016eca90c..d7fe46baf 100644 --- a/src/apps/watchfaces/OswAppWatchfaceFitness.cpp +++ b/src/apps/watchfaces/OswAppWatchfaceFitness.cpp @@ -1,3 +1,6 @@ +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 + #include "apps/watchfaces/OswAppWatchfaceFitness.h" #include "apps/watchfaces/OswAppWatchfaceDigital.h" #include "apps/watchfaces/OswAppWatchface.h" @@ -173,3 +176,4 @@ void OswAppWatchfaceFitness::onButton(Button id, bool up, OswAppV2::ButtonStateN if(OswAppWatchface::onButtonDefaults(*this, id, up, state)) return; // if the button was handled by the defaults, we are done here } +#endif diff --git a/src/apps/watchfaces/OswAppWatchfaceFitnessAnalog.cpp b/src/apps/watchfaces/OswAppWatchfaceFitnessAnalog.cpp index e6083a5bd..63562eff0 100644 --- a/src/apps/watchfaces/OswAppWatchfaceFitnessAnalog.cpp +++ b/src/apps/watchfaces/OswAppWatchfaceFitnessAnalog.cpp @@ -2,6 +2,8 @@ #include "apps/watchfaces/OswAppWatchfaceDigital.h" #include "apps/watchfaces/OswAppWatchface.h" +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 + #ifdef GIF_BG #include "./apps/_experiments/gif_player.h" #endif @@ -196,12 +198,6 @@ void OswAppWatchfaceFitnessAnalog::onLoop() { } void OswAppWatchfaceFitnessAnalog::onDraw() { -#ifndef OSW_EMULATOR - unsigned long old_micros = micros(); -#else - unsigned long old_millis = millis(); -#endif - OswAppV2::onDraw(); #ifdef GIF_BG @@ -236,12 +232,6 @@ void OswAppWatchfaceFitnessAnalog::onDraw() { } this->lastTime = time(nullptr); - -#ifndef OSW_EMULATOR - unsigned long ms_for_onDraw = (micros()-old_micros)/1000; -#else - unsigned long ms_for_onDraw = millis()-old_millis; -#endif } void OswAppWatchfaceFitnessAnalog::onButton(Button id, bool up, OswAppV2::ButtonStateNames state) { @@ -271,3 +261,4 @@ void OswAppWatchfaceFitnessAnalog::onStop() { } #endif } +#endif diff --git a/src/devices/bma400.cpp b/src/devices/bma400.cpp index ff0860837..b987bed58 100644 --- a/src/devices/bma400.cpp +++ b/src/devices/bma400.cpp @@ -1,16 +1,12 @@ #ifndef OSW_EMULATOR +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_BMA400 == 1 #include -#include #include - +#include +#include #include -// #include "BlueDot_BMA400.h" -// #include "bma400_defs.h" -#include "bma400.h" -#include -#include "osw_pins.h" - // Earth's gravity in m/s^2 #define GRAVITY_EARTH (9.80665f) @@ -18,12 +14,6 @@ #define SENSOR_TICK_TO_S (0.0000390625f) #define READ_WRITE_LENGTH UINT8_C(46) -struct bma400_dev bma; -float accelT = 0.0f, accelX = 0.0f, accelY = 0.0f, accelZ = 0.0f; - -static uint8_t dev_addr; -uint8_t act_int; -uint32_t step_count = 0; static float lsb_to_ms2(int16_t accel_data, uint8_t g_range, uint8_t bit_width) { float accel_ms2; @@ -35,43 +25,35 @@ static float lsb_to_ms2(int16_t accel_data, uint8_t g_range, uint8_t bit_width) return accel_ms2; } -void bma400_delay_us(uint32_t period, void* intf_ptr) { +static void bma400_delay_us(uint32_t period, void* intf_ptr) { delayMicroseconds(period); } -void bma400_check_rslt(const char api_name[], int8_t rslt) { - String prefix; - if (rslt != BMA400_OK) { - prefix = api_name; - prefix += ": "; - } - +static void bma400_check_rslt(const char api_name[], int8_t rslt) { switch (rslt) { case BMA400_OK: - // OSW_LOG_I(prefix, "BMA400 OK"); /* Do nothing */ break; case BMA400_E_NULL_PTR: - OSW_LOG_E(prefix, "Error [", rslt, "] : Null pointer"); + OSW_LOG_E(api_name, ": Error [", rslt, "] : Null pointer"); break; case BMA400_E_COM_FAIL: - OSW_LOG_E(prefix, "Error [", rslt, "] : Communication failure"); + OSW_LOG_E(api_name, ": Error [", rslt, "] : Communication failure"); break; case BMA400_E_INVALID_CONFIG: - OSW_LOG_E(prefix, "Error [", rslt, "] : Invalid configuration"); + OSW_LOG_E(api_name, ": Error [", rslt, "] : Invalid configuration"); break; case BMA400_E_DEV_NOT_FOUND: - OSW_LOG_E(prefix, "Error [", rslt, "] : Device not found"); + OSW_LOG_E(api_name, ": Error [", rslt, "] : Device not found"); break; default: - OSW_LOG_E(prefix, "Error [", rslt, "] : Unknown error code"); + OSW_LOG_E(api_name, ": Error [", rslt, "] : Unknown error code"); break; } } -BMA400_INTF_RET_TYPE bma400_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t len, void* intf_ptr) { - uint8_t dev_addr = *(uint8_t*)intf_ptr; - Wire.beginTransmission(dev_addr); +static BMA400_INTF_RET_TYPE bma400_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t len, void* intf_ptr) { + Wire.beginTransmission(*(uint8_t*)intf_ptr); if (!Wire.write(reg_addr)) { return 1; } @@ -80,7 +62,7 @@ BMA400_INTF_RET_TYPE bma400_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32 // if (!) { // return 2; // } - if (!Wire.requestFrom(dev_addr, len)) { + if (!Wire.requestFrom(*(uint8_t*)intf_ptr, len)) { return 3; } for (uint32_t i = 0; i < len; i++) { @@ -95,10 +77,9 @@ BMA400_INTF_RET_TYPE bma400_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32 return 0; } -BMA400_INTF_RET_TYPE bma400_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t len, void* intf_ptr) { - uint8_t dev_addr = *(uint8_t*)intf_ptr; +static BMA400_INTF_RET_TYPE bma400_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t len, void* intf_ptr) { // TODO: catch errors - Wire.beginTransmission(dev_addr); + Wire.beginTransmission(*(uint8_t*)intf_ptr); if (!Wire.write(reg_addr)) { return 1; } @@ -115,37 +96,7 @@ BMA400_INTF_RET_TYPE bma400_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, return 0; } -int8_t bma400_interface_init(struct bma400_dev* bma400, uint8_t intf) { - int8_t rslt = BMA400_OK; - - if (bma400 != NULL) { - // delay(100); - - if (intf == BMA400_I2C_INTF) { - dev_addr = BMA400_I2C_ADDRESS_SDO_LOW; - bma400->read = bma400_i2c_read; - bma400->write = bma400_i2c_write; - bma400->intf = BMA400_I2C_INTF; - } - /* Bus configuration : SPI */ - else if (intf == BMA400_SPI_INTF) { - // not supported on open smartwatch - rslt = BMA400_E_NULL_PTR; - } - - bma400->intf_ptr = &dev_addr; - bma400->delay_us = bma400_delay_us; - bma400->read_write_len = READ_WRITE_LENGTH; - - // delay(200); - } else { - rslt = BMA400_E_NULL_PTR; - } - - return rslt; -} - -void setupTiltToWake() { +void OswDevices::BMA400::setupTiltToWake() { int8_t rslt = 0; // get current state of 0x1F register "load interrupt config part 0" @@ -204,10 +155,11 @@ void setupTiltToWake() { rslt = bma400_set_regs(0x21, ®Set, 1, &bma); } -void IRAM_ATTR isrStep() { +static void IRAM_ATTR isrStep() { OSW_LOG_D("Step"); } -void IRAM_ATTR isrTap() { + +static void IRAM_ATTR isrTap() { // check which interrupt fired // TODO: read INT_STAT0,INT_STAT1,INT_STAT2 @@ -215,10 +167,9 @@ void IRAM_ATTR isrTap() { } void OswDevices::BMA400::resetStepCount() { - int8_t rslt = bma400_soft_reset(&bma); - bma400_check_rslt("bma400_soft_reset", rslt); - step_count = 0; - this->setup(); + uint8_t resetStepCommand = 0xb1; + bma400_set_regs(BMA400_REG_COMMAND, &resetStepCommand, sizeof(resetStepCommand), &bma); + this->step_count = 0; } void OswDevices::BMA400::setup() { @@ -228,11 +179,20 @@ void OswDevices::BMA400::setup() { attachInterrupt(OSW_DEVICE_BMA400_INT2, isrStep, FALLING); int8_t rslt = 0; + static uint8_t device_address = BMA400_I2C_ADDRESS_SDO_LOW; // required for use via pointer struct bma400_sensor_conf accel_setting[3] = {{}}; struct bma400_int_enable int_en[3]; - rslt = bma400_interface_init(&bma, BMA400_I2C_INTF); - bma400_check_rslt("bma400_interface_init", rslt); + // simplified bma400_interface_init function + { + bma.read = bma400_i2c_read; + bma.write = bma400_i2c_write; + bma.intf = BMA400_I2C_INTF; + + bma.intf_ptr = (void*) &device_address; // nullptr is not recognized for default with this library + bma.delay_us = bma400_delay_us; + bma.read_write_len = READ_WRITE_LENGTH; + } rslt = bma400_init(&bma); bma400_check_rslt("bma400_init", rslt); @@ -286,6 +246,7 @@ void OswDevices::BMA400::setup() { } void OswDevices::BMA400::update() { + uint8_t act_int; int8_t rslt = BMA400_OK; struct bma400_sensor_data data; @@ -295,13 +256,29 @@ void OswDevices::BMA400::update() { rslt = bma400_get_accel_data(BMA400_DATA_SENSOR_TIME, &data, &bma); bma400_check_rslt("bma400_get_accel_data", rslt); - /* 12-bit accelerometer at range 2G */ + // 12-bit accelerometer at range 2G accelX = lsb_to_ms2(data.x, 2, 12); accelY = lsb_to_ms2(data.y, 2, 12); accelZ = lsb_to_ms2(data.z, 2, 12); // TODO: add getter accelT = (float)data.sensortime * SENSOR_TICK_TO_S; + + // activity mode + switch(act_int) { + case BMA400_STILL_ACT: + this->activityMode = OswAccelerationProvider::ActivityMode::STILL; + break; + case BMA400_WALK_ACT: + this->activityMode = OswAccelerationProvider::ActivityMode::WALK; + break; + case BMA400_RUN_ACT: + this->activityMode = OswAccelerationProvider::ActivityMode::RUN; + break; + default: + this->activityMode = OswAccelerationProvider::ActivityMode::UNKNOWN; + break; + } } float OswDevices::BMA400::getAccelerationX() { @@ -339,7 +316,9 @@ float OswDevices::BMA400::getTemperature() { uint32_t OswDevices::BMA400::getStepCount() { return step_count; } -uint8_t OswDevices::BMA400::getActivityMode() { - return act_int; + +OswAccelerationProvider::ActivityMode OswDevices::BMA400::getActivityMode() { + return this->activityMode; } #endif +#endif diff --git a/src/devices/bmi270.cpp b/src/devices/bmi270.cpp new file mode 100644 index 000000000..8cccfe003 --- /dev/null +++ b/src/devices/bmi270.cpp @@ -0,0 +1,230 @@ +#ifndef OSW_EMULATOR +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_BMI270 == 1 +#include +#include +#include + +#include + +static int8_t bmi2_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t len, void* intf_ptr) { + if ((reg_data == NULL) || (len == 0) || (len > 32)) { + return -1; + } + uint8_t bytes_received; + + Wire.beginTransmission(BMI2_I2C_PRIM_ADDR); + Wire.write(reg_addr); + if (Wire.endTransmission() == 0) { + bytes_received = Wire.requestFrom(BMI2_I2C_PRIM_ADDR, len); + // Optionally, throw an error if bytes_received != len + for (uint16_t i = 0; i < bytes_received; i++) { + reg_data[i] = Wire.read(); + } + } else { + return -1; + } + + return 0; +} + +static int8_t bmi2_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t len, void* intf_ptr) { + if ((reg_data == NULL) || (len == 0) || (len > 32)) { + return -1; + } + + Wire.beginTransmission(BMI2_I2C_PRIM_ADDR); + Wire.write(reg_addr); + for (uint16_t i = 0; i < len; i++) { + Wire.write(reg_data[i]); + } + if (Wire.endTransmission() != 0) { + return -1; + } + + return 0; +} + +static void bmi2_delay_us(uint32_t period, void* intf_ptr) { + delayMicroseconds(period); +} + +void OswDevices::BMI270::setup() { + int8_t rslt; + { + this->bmi2.chip_id = BMI2_I2C_PRIM_ADDR; + this->bmi2.read = bmi2_i2c_read; + this->bmi2.write = bmi2_i2c_write; + this->bmi2.delay_us = bmi2_delay_us; + this->bmi2.intf = BMI2_I2C_INTF; + this->bmi2.intf_ptr = nullptr; // we are using the default address anyways + this->bmi2.read_write_len = 30; // Bosch mentioned limitations of the "Wire library" + this->bmi2.config_file_ptr = nullptr; // we are not using a config file + + rslt = bmi270_init(&this->bmi2); + if(rslt != BMI2_OK) + throw std::runtime_error("Failed to initialize BMI270!"); + } + + { + struct bmi2_int_pin_config int_pin_cfg; + int_pin_cfg.pin_type = BMI2_INT1; + int_pin_cfg.int_latch = BMI2_INT_NON_LATCH; + int_pin_cfg.pin_cfg[0].lvl = BMI2_INT_ACTIVE_HIGH; + int_pin_cfg.pin_cfg[0].od = BMI2_INT_PUSH_PULL; + int_pin_cfg.pin_cfg[0].output_en = BMI2_INT_OUTPUT_ENABLE; + int_pin_cfg.pin_cfg[0].input_en = BMI2_INT_INPUT_DISABLE; + + struct bmi2_sens_config sens_cfg[2]; + sens_cfg[0].type = BMI2_ACCEL; + sens_cfg[0].cfg.acc.bwp = BMI2_ACC_OSR2_AVG2; + sens_cfg[0].cfg.acc.odr = BMI2_ACC_ODR_100HZ; + sens_cfg[0].cfg.acc.filter_perf = BMI2_PERF_OPT_MODE; + sens_cfg[0].cfg.acc.range = BMI2_ACC_RANGE_4G; + sens_cfg[1].type = BMI2_GYRO; + sens_cfg[1].cfg.gyr.filter_perf = BMI2_PERF_OPT_MODE; + sens_cfg[1].cfg.gyr.bwp = BMI2_GYR_OSR2_MODE; + sens_cfg[1].cfg.gyr.odr = BMI2_GYR_ODR_100HZ; + sens_cfg[1].cfg.gyr.range = BMI2_GYR_RANGE_2000; + sens_cfg[1].cfg.gyr.ois_range = BMI2_GYR_OIS_2000; + + rslt = bmi2_set_int_pin_config(&int_pin_cfg, &this->bmi2); + if (rslt != BMI2_OK) + throw std::runtime_error("Failed configure pins of BMI270!"); + + rslt = bmi2_map_data_int(BMI2_DRDY_INT, BMI2_INT1, &this->bmi2); + if (rslt != BMI2_OK) + throw std::runtime_error("Failed to map data interrupt of BMI270!"); + + rslt = bmi2_set_sensor_config(sens_cfg, 2, &this->bmi2); + if (rslt != BMI2_OK) + throw std::runtime_error("Failed to configure sensors of BMI270!"); + + uint8_t cmndSetFeaturePage = 6; + if(bmi2_set_regs(0x2F, &cmndSetFeaturePage, sizeof(cmndSetFeaturePage), &this->bmi2) < 0) + throw std::runtime_error("Failed to set configuration page of BMI270!"); + + uint8_t cmnd[2] = { 0x00, 0x10 | 0x20 }; // ...; enable counter, enable activity + if(bmi2_set_regs(0x32, cmnd, sizeof(cmnd), &this->bmi2) < 0) + throw std::runtime_error("Failed to configure step counter of BMI270!"); + + uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_GYRO }; + rslt = bmi2_sensor_enable(sens_list, 2, &this->bmi2); + if (rslt != BMI2_OK) + throw std::runtime_error("Failed to enable sensors of BMI270!"); + } + + // We are NOT initializing the IMM150, because there is no hardware with it ;) +} + +void OswDevices::BMI270::update() { + this->updateAcceleration(); + this->updateSteps(); + this->updateTemperature(); + this->updateActivityMode(); +} + +void OswDevices::BMI270::updateAcceleration() { + int8_t rslt; + struct bmi2_sens_data sensor_data; + + rslt = bmi2_get_sensor_data(&sensor_data, &this->bmi2); + if (rslt != BMI2_OK) { + OSW_LOG_E("BMI270 Acceleration read error (SPI error)"); + return; + } + + this->accX = (float) sensor_data.acc.x / 1000; + this->accY = (float) sensor_data.acc.y / 1000; + this->accZ = (float) sensor_data.acc.z / 1000; +} + +void OswDevices::BMI270::updateSteps() { + uint8_t data[2]; + if (bmi2_get_regs(0x1E, data, sizeof(data), &this->bmi2) < 0) { + OSW_LOG_E("BMI270 Steps read error"); + return; + } + + this->step_count = (data[1] << 8) | data[0]; +} + +void OswDevices::BMI270::updateTemperature() { + uint8_t data[2]; + if (bmi2_get_regs(0x22, data, sizeof(data), &this->bmi2) < 0) { + OSW_LOG_E("BMI270 Temperature read error"); + return; + } + + int16_t temp = (data[1] << 8) | data[0]; + + if(temp == 0x8000) { + OSW_LOG_E("BMI270 Temperature read error (value error)"); + return; + } + + this->temperature = temp / 100.0f; +} + +void OswDevices::BMI270::updateActivityMode() { + uint8_t data; + if (bmi2_get_regs(0x20, &data, sizeof(data), &this->bmi2) < 0) { + OSW_LOG_E("BMI270 Activity mode read error"); + return; + } + data = data >> 2; // drop the first two bytes by shifting to the right + data = data & 0x03; // drop the last 6 bytes by masking + + switch(data) { + case 0x00: + this->activityMode = OswAccelerationProvider::ActivityMode::STILL; + break; + case 0x01: + this->activityMode = OswAccelerationProvider::ActivityMode::WALK; + break; + case 0x02: + this->activityMode = OswAccelerationProvider::ActivityMode::RUN; + break; + default: + this->activityMode = OswAccelerationProvider::ActivityMode::UNKNOWN; // also known as 0x03 + break; + } +} + +float OswDevices::BMI270::getAccelerationX() { + return this->accX; +} + +float OswDevices::BMI270::getAccelerationY() { + return this->accY; +} + +float OswDevices::BMI270::getAccelerationZ() { + return this->accZ; +} + +uint32_t OswDevices::BMI270::getStepCount() { + return this->step_count; +} + +OswAccelerationProvider::ActivityMode OswDevices::BMI270::getActivityMode() { + return this->activityMode; +} + +void OswDevices::BMI270::resetStepCount() { + uint8_t cmndSetFeaturePage = 6; + if(bmi2_set_regs(0x2F, &cmndSetFeaturePage, sizeof(cmndSetFeaturePage), &this->bmi2) < 0) + throw std::runtime_error("Failed to set configuration page of BMI270!"); + + uint8_t cmnd[2] = { 0x00, 0x4 | 0x10 | 0x20 }; // ...; reset steps, enable counter, enable activity + if(bmi2_set_regs(0x32, cmnd, sizeof(cmnd), &this->bmi2) < 0) + throw std::runtime_error("Failed to configure step counter of BMI270!"); + + this->step_count = 0; +} + +float OswDevices::BMI270::getTemperature() { + return this->temperature; +} +#endif +#endif \ No newline at end of file diff --git a/src/devices/bmp581.cpp b/src/devices/bmp581.cpp new file mode 100644 index 000000000..e58dee748 --- /dev/null +++ b/src/devices/bmp581.cpp @@ -0,0 +1,111 @@ +#ifndef OSW_EMULATOR +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_BMP581 == 1 +#include +#include +#include + +#include + +static int8_t bmp5_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t len, void* intf_ptr) { + if ((reg_data == NULL) || (len == 0) || (len > 32)) { + return -1; + } + uint8_t bytes_received; + + Wire.beginTransmission(BMP5_I2C_ADDR_PRIM); + Wire.write(reg_addr); + if (Wire.endTransmission() == 0) { + bytes_received = Wire.requestFrom(BMP5_I2C_ADDR_PRIM, len); + // Optionally, throw an error if bytes_received != len + for (uint16_t i = 0; i < bytes_received; i++) { + reg_data[i] = Wire.read(); + } + } else { + return -1; + } + + return 0; +} + +static int8_t bmp5_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t len, void* intf_ptr) { + if ((reg_data == NULL) || (len == 0) || (len > 32)) { + return -1; + } + + Wire.beginTransmission(BMP5_I2C_ADDR_PRIM); + Wire.write(reg_addr); + for (uint16_t i = 0; i < len; i++) { + Wire.write(reg_data[i]); + } + if (Wire.endTransmission() != 0) { + return -1; + } + + return 0; +} + +static void bmp5_delay_us(uint32_t period, void* intf_ptr) { + delayMicroseconds(period); +} + +void OswDevices::BMP581::setup() { + int8_t rslt; + { + this->bmp5.chip_id = BMP5_I2C_ADDR_PRIM; + this->bmp5.read = bmp5_i2c_read; + this->bmp5.write = bmp5_i2c_write; + this->bmp5.delay_us = bmp5_delay_us; + this->bmp5.intf = BMP5_I2C_INTF; + this->bmp5.intf_ptr = nullptr; // we are using the default address anyways + + rslt = bmp5_init(&this->bmp5); + if(rslt != BMP5_OK) + throw std::runtime_error("Failed to initialize BMP581!"); + } + { + rslt = bmp5_set_power_mode(BMP5_POWERMODE_STANDBY, &this->bmp5); + if(rslt != BMP5_OK) + throw std::runtime_error("Failed to reconfigure BMP581 power mode!"); + + struct bmp5_iir_config set_iir_cfg; + rslt = bmp5_get_osr_odr_press_config(&this->osr_odr_press_cfg, &this->bmp5); + + osr_odr_press_cfg.odr = BMP5_ODR_50_HZ; + osr_odr_press_cfg.press_en = BMP5_ENABLE; + osr_odr_press_cfg.osr_t = BMP5_OVERSAMPLING_64X; + osr_odr_press_cfg.osr_p = BMP5_OVERSAMPLING_4X; + rslt = bmp5_set_osr_odr_press_config(&this->osr_odr_press_cfg, &this->bmp5); + + set_iir_cfg.set_iir_t = BMP5_IIR_FILTER_COEFF_1; + set_iir_cfg.set_iir_p = BMP5_IIR_FILTER_COEFF_1; + set_iir_cfg.shdw_set_iir_t = BMP5_ENABLE; + set_iir_cfg.shdw_set_iir_p = BMP5_ENABLE; + rslt = bmp5_set_iir_config(&set_iir_cfg, &this->bmp5); + + rslt = bmp5_set_power_mode(BMP5_POWERMODE_NORMAL, &this->bmp5); + if(rslt != BMP5_OK) + throw std::runtime_error("Failed to reconfigure BMP581 power mode!"); + } + // TODO proper sensor reading configuration +} + +void OswDevices::BMP581::update() { + int8_t rslt; + struct bmp5_sensor_data sensor_data; + + rslt = bmp5_get_sensor_data(&sensor_data, &this->osr_odr_press_cfg, &this->bmp5); + + this->pressure = sensor_data.pressure; + this->temperature = sensor_data.temperature; +} + +float OswDevices::BMP581::getPressure() { + return this->pressure; +} + +float OswDevices::BMP581::getTemperature() { + return this->temperature; +} +#endif +#endif \ No newline at end of file diff --git a/src/devices/ds3231mz.cpp b/src/devices/ds3231mz.cpp index d7fcfd9f8..fab6c3c9b 100644 --- a/src/devices/ds3231mz.cpp +++ b/src/devices/ds3231mz.cpp @@ -1,4 +1,5 @@ -#ifndef OSW_EMULATOR +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_DS3231MZ == 1 #include #include diff --git a/src/devices/esp32.cpp b/src/devices/esp32.cpp index 56b3f812b..a0b593cfe 100644 --- a/src/devices/esp32.cpp +++ b/src/devices/esp32.cpp @@ -31,9 +31,13 @@ uint8_t temprature_sens_read() { void OswDevices::NativeESP32::setup() { // Test temperature for 128 (sensor not available) for 10 times +#if OSW_DEVICE_ESP32_USE_INTTEMP == 1 for(int i = 0; i < 10; i++) if(temprature_sens_read() == 128) this->tempSensorIsBuiltIn = false; +#else + this->tempSensorIsBuiltIn = false; +#endif setenv("TZ", "UTC0", 1); // Force systems clock to correspond to UTC } @@ -108,10 +112,14 @@ time_t OswDevices::NativeESP32::getTimezoneOffset(const time_t& timestamp, const } float OswDevices::NativeESP32::getTemperature() { +#if OSW_DEVICE_ESP32_USE_INTTEMP == 1 const uint8_t temp = temprature_sens_read(); if(!this->tempSensorIsBuiltIn) return 0.0f; return (temp - 32) / 1.8f; +#else + return 0.0f; +#endif } bool OswDevices::NativeESP32::isTemperatureSensorAvailable() { diff --git a/src/devices/qmc5883l.cpp b/src/devices/qmc5883l.cpp index 6f88ed29f..0066e733e 100644 --- a/src/devices/qmc5883l.cpp +++ b/src/devices/qmc5883l.cpp @@ -1,4 +1,5 @@ -#ifndef OSW_EMULATOR +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_HARDWARE_QMC5883L == 1 #include #include diff --git a/src/hal/buttons.cpp b/src/hal/buttons.cpp index b53577dd3..862eb48d4 100644 --- a/src/hal/buttons.cpp +++ b/src/hal/buttons.cpp @@ -5,23 +5,23 @@ #include "osw_pins.h" const char* ButtonNames[BTN_NUMBER] = BTN_NAME_ARRAY; +#if OSW_PLATFORM_IS_FLOW3R_BADGE != 1 static uint8_t buttonPins[BTN_NUMBER] = BTN_PIN_ARRAY; static uint8_t buttonClickStates[BTN_NUMBER] = BTN_STATE_ARRAY; +#endif static int16_t buttonPositionsX[BTN_NUMBER] = BTN_POSX_ARRAY; static int16_t buttonPositionsY[BTN_NUMBER] = BTN_POSY_ARRAY; static bool buttonIsTop[BTN_NUMBER] = BTN_POS_ISTOP_ARRAY; static bool buttonIsLeft[BTN_NUMBER] = BTN_POS_ISLEFT_ARRAY; -void OswHal::setupButtons(void) { - // rtc_gpio_deinit(GPIO_NUM_0); - // rtc_gpio_deinit(GPIO_NUM_10); - // rtc_gpio_deinit(GPIO_NUM_13); +void OswHal::setupButtons() { +#if OSW_PLATFORM_IS_FLOW3R_BADGE != 1 pinMode(BTN_1, INPUT); pinMode(BTN_2, INPUT); pinMode(BTN_3, INPUT); -#if defined(GPS_EDITION) || defined(GPS_EDITION_ROTATED) - - pinMode(VIBRATE, OUTPUT); +#endif +#if OSW_PLATFORM_HARDWARE_VIBRATE != 0 + pinMode(OSW_PLATFORM_HARDWARE_VIBRATE, OUTPUT); #endif // Buttons (Engine) @@ -34,23 +34,34 @@ void OswHal::setupButtons(void) { } } -#if defined(GPS_EDITION) || defined(GPS_EDITION_ROTATED) - +#if OSW_PLATFORM_HARDWARE_VIBRATE != 0 void OswHal::vibrate(long millis) { - digitalWrite(VIBRATE, HIGH); + digitalWrite(OSW_PLATFORM_HARDWARE_VIBRATE, HIGH); OSW_LOG_D("Vibrate for: ", millis); delay(millis); - digitalWrite(VIBRATE, LOW); + digitalWrite(OSW_PLATFORM_HARDWARE_VIBRATE, LOW); } #endif -void OswHal::checkButtons(void) { - // Buttons (Engine) +void OswHal::checkButtons() { +#if OSW_PLATFORM_IS_FLOW3R_BADGE == 1 + uint8_t ur = ~this->readGpioExtender(); + bool r1 = ur & 0b00000001; + bool l1 = ur & 0b10000000; + bool r2 = ur & 0b00100000; + bool l2 = ur & 0b00010000; + _btnIsDown[0] = !digitalRead(0) or !digitalRead(3); + _btnIsDown[1] = l1 or l2; + _btnIsDown[2] = r1 or r2; + if(_btnIsDown[0] or _btnIsDown[1] or _btnIsDown[2]) + this->noteUserInteraction(); // Button pressing counts as user interaction +#else for (uint8_t i = 0; i < BTN_NUMBER; i++) { _btnIsDown[i] = digitalRead(buttonPins[i]) == buttonClickStates[i]; if(_btnIsDown[i]) this->noteUserInteraction(); // Button pressing counts as user interaction } +#endif for (uint8_t i = 0; i < BTN_NUMBER; i++) { _btnGoneUp[i] = _btnLastState[i] == true && _btnIsDown[i] == false; diff --git a/src/hal/devices.cpp b/src/hal/devices.cpp index 81798ab57..c15bae3c6 100644 --- a/src/hal/devices.cpp +++ b/src/hal/devices.cpp @@ -1,3 +1,4 @@ +#include OSW_TARGET_PLATFORM_HEADER #include #include @@ -6,6 +7,12 @@ OswHal::Devices::Devices() { #if OSW_PLATFORM_HARDWARE_BMA400 == 1 this->bma400 = new OswDevices::BMA400(); #endif +#if OSW_PLATFORM_HARDWARE_BMI270 == 1 + this->bmi270 = new OswDevices::BMI270(); +#endif +#if OSW_PLATFORM_HARDWARE_BMP581 == 1 + this->bmp581 = new OswDevices::BMP581(); +#endif #if OSW_PLATFORM_HARDWARE_QMC5883L == 1 this->qmc5883l = new OswDevices::QMC5883L(); #endif @@ -39,6 +46,9 @@ OswHal::Devices::~Devices() { #if OSW_PLATFORM_HARDWARE_QMC5883L == 1 delete this->qmc5883l; #endif +#if OSW_PLATFORM_HARDWARE_BMI270 == 1 + delete this->bmi270; +#endif #if OSW_PLATFORM_HARDWARE_BMA400 == 1 delete this->bma400; #endif diff --git a/src/hal/display.cpp b/src/hal/display.cpp index cf3f4f085..5a834fdb2 100644 --- a/src/hal/display.cpp +++ b/src/hal/display.cpp @@ -1,5 +1,5 @@ -#include #ifndef OSW_EMULATOR +#include #include #include #endif @@ -12,14 +12,24 @@ #include "config_defaults.h" #include "osw_hal.h" #include "osw_pins.h" +#include OSW_TARGET_PLATFORM_HEADER -#ifndef OSW_EMULATOR -Arduino_DataBus* bus = new Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO, VSPI /* spi_num */); -#if defined(GPS_EDITION_ROTATED) -Arduino_GC9A01* tft = new Arduino_GC9A01(bus, TFT_RST, 1 /* rotation */, true /* IPS */); -#else -Arduino_GC9A01* tft = new Arduino_GC9A01(bus, TFT_RST, 0 /* rotation */, true /* IPS */); +#if OSW_PLATFORM_HARDWARE_DISPLAY_RST == 0 +#define OSW_PLATFORM_HARDWARE_DISPLAY_RST -1 #endif +#ifndef OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION +#define OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION -1 +#endif + +#ifndef OSW_EMULATOR +Arduino_DataBus* bus = new Arduino_ESP32SPI( + OSW_PLATFORM_HARDWARE_DISPLAY_DC, + OSW_PLATFORM_HARDWARE_DISPLAY_CS, + OSW_PLATFORM_HARDWARE_DISPLAY_SCK, + OSW_PLATFORM_HARDWARE_DISPLAY_MOSI, + -1, // no data coming back + OSW_PLATFORM_HARDWARE_DISPLAY_SPI_NUM); +Arduino_GC9A01* tft = new Arduino_GC9A01(bus, OSW_PLATFORM_HARDWARE_DISPLAY_RST, OSW_PLATFORM_HARDWARE_DISPLAY_ROTATION, true /* IPS */); #else FakeDisplay* tft = nullptr; #endif @@ -55,12 +65,6 @@ bool OswHal::displayBufferEnabled() { } void OswHal::setupDisplay() { -#ifdef ESP32 - // nasty hack to avoid display flicker - ledcAttachPin(TFT_LED, 1); - ledcSetup(1, 12000, 8); // 12 kHz PWM, 8-bit resolution - ledcWrite(1, 0); -#endif #ifdef OSW_EMULATOR // Always fetch the current instance, just in case the emulator replaced it in the meantime (and as tft is not bound to this objects lifetime) tft = fakeDisplayInstance.get(); @@ -92,11 +96,12 @@ void OswHal::flushCanvas(void) { } void OswHal::displayOff(void) { -#ifdef ESP32 - ledcDetachPin(TFT_LED); +#if OSW_PLATFORM_HARDWARE_DISPLAY_LED != 0 + ledcDetachPin(OSW_PLATFORM_HARDWARE_DISPLAY_LED); + // just pull down the backlight pin + pinMode(OSW_PLATFORM_HARDWARE_DISPLAY_LED, OUTPUT); + digitalWrite(OSW_PLATFORM_HARDWARE_DISPLAY_LED, LOW); #endif - pinMode(TFT_LED, OUTPUT); - digitalWrite(TFT_LED, LOW); tft->displayOff(); _screenOffSince = millis(); } @@ -110,9 +115,13 @@ unsigned long OswHal::screenOffTime() { void OswHal::displayOn() { _screenOnSince = millis(); -#ifdef ESP32 - ledcAttachPin(TFT_LED, 1); +#if OSW_PLATFORM_HARDWARE_DISPLAY_LED != 0 + ledcAttachPin(OSW_PLATFORM_HARDWARE_DISPLAY_LED, 1); ledcSetup(1, 12000, 8); // 12 kHz PWM, 8-bit resolution +#else +#ifndef OSW_EMULATOR // meh, the emulator ignores this for now... +#warning "Display LED pin unconfigured; can't control backlight brightness" +#endif #endif setBrightness(OswConfigAllKeys::settingDisplayBrightness.get(), false); tft->displayOn(); @@ -120,10 +129,8 @@ void OswHal::displayOn() { void OswHal::setBrightness(uint8_t b, bool storeToNVS) { _brightness = b; -#ifdef ESP32 +#if OSW_PLATFORM_HARDWARE_DISPLAY_LED != 0 ledcWrite(1, _brightness); -#else - digitalWrite(TFT_LED, _brightness); #endif if(storeToNVS) { OswConfig::getInstance()->enableWrite(); @@ -175,10 +182,8 @@ uint8_t OswHal::screenBrightness(bool checkHardware) { uint8_t screen_brightness = 0; if(checkHardware) { -#ifdef ESP32 +#if OSW_PLATFORM_HARDWARE_DISPLAY_LED != 0 screen_brightness = ledcRead(1); -#else - screen_brightness = digitalRead(TFT_LED); #endif _brightness = screen_brightness; } diff --git a/src/hal/environment.cpp b/src/hal/environment.cpp index a70c61784..b233e94cb 100644 --- a/src/hal/environment.cpp +++ b/src/hal/environment.cpp @@ -1,3 +1,5 @@ +#include OSW_TARGET_PLATFORM_HEADER +#if OSW_PLATFORM_ENVIRONMENT == 1 #include #ifdef OSW_EMULATOR #include @@ -82,6 +84,12 @@ float OswHal::Environment::getAccelerationZ() { return this->accelSensor->getAccelerationZ(); } +OswAccelerationProvider::ActivityMode OswHal::Environment::getActivityMode() { + if(!this->accelSensor) + throw std::runtime_error("No acceleration provider!"); + return this->accelSensor->getActivityMode(); +} + uint32_t OswHal::Environment::getStepsToday() { if(!this->accelSensor) throw std::runtime_error("No acceleration provider!"); @@ -250,9 +258,28 @@ float OswHal::Environment::getHumidity() { #endif #if OSW_PLATFORM_ENVIRONMENT_MAGNETOMETER == 1 +int OswHal::Environment::getMagnetometerX() { + if(!this->magSensor) + throw std::runtime_error("No magnetometer provider!"); + return this->magSensor->getMagnetometerX(); +} + +int OswHal::Environment::getMagnetometerY() { + if(!this->magSensor) + throw std::runtime_error("No magnetometer provider!"); + return this->magSensor->getMagnetometerY(); +} + +int OswHal::Environment::getMagnetometerZ() { + if(!this->magSensor) + throw std::runtime_error("No magnetometer provider!"); + return this->magSensor->getMagnetometerZ(); +} + int OswHal::Environment::getMagnetometerAzimuth() { if(!this->magSensor) throw std::runtime_error("No magnetometer provider!"); return this->magSensor->getMagnetometerAzimuth(); } #endif +#endif diff --git a/src/hal/gps.cpp b/src/hal/gps.cpp index 82d1c6980..81312a346 100644 --- a/src/hal/gps.cpp +++ b/src/hal/gps.cpp @@ -18,7 +18,7 @@ NMEAGPS* OswHal::gps(void) { void OswHal::setupGps(void) { pinMode(GPS_FON, OUTPUT); digitalWrite(GPS_FON, HIGH); - SerialGPS.begin(9600, SERIAL_8N1, RX1, TX1); + SerialGPS.begin(9600, SERIAL_8N1, GPS_RX1, GPS_TX1); } bool OswHal::hasGPS(void) { return _hasGPS; diff --git a/src/hal/power.cpp b/src/hal/power.cpp index a616ff8ed..6f771a4fa 100644 --- a/src/hal/power.cpp +++ b/src/hal/power.cpp @@ -82,11 +82,19 @@ uint16_t OswHal::getBatteryRawMax() { void OswHal::setupPower(bool fromLightSleep) { if(!fromLightSleep) { +#if OSW_DEVICE_TPS2115A_STATPWR != 0 pinMode(OSW_DEVICE_TPS2115A_STATPWR, INPUT); +#endif +#if OSW_DEVICE_ESP32_BATLVL != 0 pinMode(OSW_DEVICE_ESP32_BATLVL, INPUT); +#endif bool res = powerPreferences.begin("osw-power", false); assert(res && "Could not initialize power preferences!"); +#if OSW_PLATFORM_DEFAULT_CPUFREQ != 0 this->setCPUClock(OSW_PLATFORM_DEFAULT_CPUFREQ); +#else +#warning "OSW_PLATFORM_DEFAULT_CPUFREQ is not set, so CPU frequency won't be configured!" +#endif } esp_sleep_wakeup_cause_t reason = esp_sleep_get_wakeup_cause(); if(reason == ESP_SLEEP_WAKEUP_TIMER) { @@ -128,19 +136,31 @@ void OswHal::updatePowerStatistics(uint16_t currBattery) { } } -bool OswHal::isCharging(void) { +bool OswHal::isCharging() { +#if OSW_DEVICE_TPS2115A_STATPWR != 0 return digitalRead(OSW_DEVICE_TPS2115A_STATPWR); // != 0 means there is V(IN2) in use +#else +#if OSW_PLATFORM_IS_FLOW3R_BADGE == 1 + return ~this->readGpioExtender() & 0b00000100; +#else + return false; +#endif +#endif } /** * Reports the average of numAvg subsequent measurements */ uint16_t OswHal::getBatteryRaw(const uint16_t numAvg) { +#if OSW_DEVICE_ESP32_BATLVL != 0 uint16_t b = 0; for (uint8_t i = 0; i < numAvg; i++) b = b + analogRead(OSW_DEVICE_ESP32_BATLVL); b = b / numAvg; return b > 40 ? b / 2 : b; +#else + return 0; // TODO we should properly report no battery information available +#endif } /** @@ -208,6 +228,11 @@ uint8_t OswHal::getCPUClock() { } void OswHal::doSleep(bool deepSleep) { +#if OSW_PLATFORM_BLOCK_SLEEP == 1 + OSW_LOG_I("Sleeping is blocked by OSW_PLATFORM_BLOCK_SLEEP."); + this->noteUserInteraction(); // reset sleep timer + return; +#else this->stop(!deepSleep); // register user wakeup sources @@ -248,6 +273,7 @@ void OswHal::doSleep(bool deepSleep) { esp_deep_sleep_start(); else esp_light_sleep_start(); +#endif } void OswHal::deepSleep() { @@ -255,6 +281,7 @@ void OswHal::deepSleep() { } void OswHal::lightSleep() { +#if OSW_PLATFORM_BLOCK_SLEEP != 1 if(!OswConfigAllKeys::lightSleepEnabled.get()) { // The light sleep was not enabled, ignore this request and go to deep sleep instead! OSW_LOG_D("Request for light sleep ignored, as only deep sleep is enabled."); @@ -263,6 +290,7 @@ void OswHal::lightSleep() { _isLightSleep = true; doSleep(false); } +#endif } void OswHal::handleWakeupFromLightSleep(void) { diff --git a/src/main.cpp b/src/main.cpp index 32155d6b7..7209d016b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include //time #ifdef OSW_FEATURE_WIFI @@ -75,7 +76,7 @@ #if defined(GPS_EDITION) || defined(GPS_EDITION_ROTATED) #include "./apps/main/map.h" #endif -#include "./services/OswServiceTaskBLECompanion.h" +#include "services/OswServiceTaskBLECompanion.h" #include "services/OswServiceTaskMemMonitor.h" #include "services/OswServiceTasks.h" #ifdef OSW_FEATURE_WIFI @@ -97,7 +98,7 @@ using OswGlobals::main_tutorialApp; #endif void setup() { - Serial.begin(115200); + OswSerial::getInstance()->begin(115200); OSW_LOG_I("Welcome to the OSW-OS! This build is based on commit ", GIT_COMMIT_HASH, " from ", GIT_BRANCH_NAME, ". Compiled at ", __DATE__, " ", __TIME__, " for platform ", PIO_ENV_NAME, "."); @@ -108,7 +109,7 @@ void setup() { try { OswHal::getInstance()->setup(false); } catch(const std::exception& e) { - OSW_LOG_E("CRITICAL ERROR AT BOOTUP: ", + e.what()); + OSW_LOG_E("CRITICAL ERROR AT BOOTUP: ", e.what()); sleep(_MAIN_CRASH_SLEEP); ESP.restart(); } @@ -118,11 +119,13 @@ void setup() { main_mainDrawer.registerAppLazy(LANG_WATCHFACES); main_mainDrawer.registerAppLazy(LANG_WATCHFACES); main_mainDrawer.registerAppLazy(LANG_WATCHFACES); +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 main_mainDrawer.registerAppLazy(LANG_WATCHFACES); + main_mainDrawer.registerAppLazy(LANG_WATCHFACES); +#endif main_mainDrawer.registerAppLazy(LANG_WATCHFACES); main_mainDrawer.registerAppLazy(LANG_WATCHFACES); main_mainDrawer.registerAppLazy(LANG_WATCHFACES); - main_mainDrawer.registerAppLazy(LANG_WATCHFACES); try { main_mainDrawer.startApp(OswConfigAllKeys::settingDisplayDefaultWatchface.get().c_str()); // if this id is invalid, the drawer will fall back to alternatives automatically } catch(const std::runtime_error& e) { @@ -187,10 +190,6 @@ void loop() { sleep(_MAIN_CRASH_SLEEP); ESP.restart(); } - if (delayedAppInit) { - // fix flickering display on latest Arduino_GFX library - ledcWrite(1, OswConfigAllKeys::settingDisplayBrightness.get()); - } if (delayedAppInit) { delayedAppInit = false; @@ -216,6 +215,7 @@ void loop() { #endif // Fitness App +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 #ifdef OSW_FEATURE_STATS_STEPS static OswAppStepStats fitnessStepStats; static OswAppKcalStats fitnessKcalStats; @@ -226,6 +226,7 @@ void loop() { #endif static OswAppFitnessStats fitnessStats; main_mainDrawer.registerApp(LANG_FITNESS, new OswAppV2Compat("osw.fit.fs", "Fitness Statistics", fitnessStats)); +#endif // Tools #if TOOL_CLOCK == 1 @@ -239,7 +240,7 @@ void loop() { #if TOOL_FLASHLIGHT == 1 main_mainDrawer.registerAppLazy(LANG_TOOLS); #endif -#if TOOL_WATERLEVEL == 1 +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 && TOOL_WATERLEVEL == 1 static OswAppWaterLevel toolWaterLevel; main_mainDrawer.registerApp(LANG_TOOLS, new OswAppV2Compat("osw.tool.wl", "Water Level", toolWaterLevel, true, waterlevel_png)); #endif diff --git a/src/osw_config_keys.cpp b/src/osw_config_keys.cpp index 7d0ef86c7..e3c0fedc1 100644 --- a/src/osw_config_keys.cpp +++ b/src/osw_config_keys.cpp @@ -1,4 +1,5 @@ #include "osw_config_keys.h" +#include OSW_TARGET_PLATFORM_HEADER #include #ifndef OSW_EMULATOR @@ -61,11 +62,13 @@ OswConfigKeyDropDown settingDisplayDefaultWatchface("n", "Display", "Default Wat OswAppWatchfaceDigital::APP_ID, OswAppWatchfaceMix::APP_ID, OswAppWatchfaceDual::APP_ID, +#if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 OswAppWatchfaceFitness::APP_ID, + OswAppWatchfaceFitnessAnalog::APP_ID, +#endif OswAppWatchfaceBinary::APP_ID, OswAppWatchfaceMonotimer::APP_ID, - OswAppWatchfaceNumerals::APP_ID, - OswAppWatchfaceFitnessAnalog::APP_ID + OswAppWatchfaceNumerals::APP_ID }, CONFIG_DEFAULT_WATCHFACE_ID); OswConfigKeyBool settingDisplayDualHourTick("h2", "Display", "Display Dual-Time Hour Tick", "Show dual time hour tick", false); #if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 @@ -75,6 +78,7 @@ OswConfigKeyShort oswAppV2ButtonDoublePress("d4", "Display", "Button double pres OswConfigKeyShort oswAppV2ButtonLongPress("d5", "Display", "Button long press time", "Unit: ms", CONFIG_APPV2_LONG_PRESS_TIME); OswConfigKeyShort oswAppV2ButtonVeryLongPress("d6", "Display", "Button very long press time", "Unit: ms", CONFIG_APPV2_VERY_LONG_PRESS_TIME); +#if OSW_PLATFORM_BLOCK_SLEEP != 1 OswConfigKeyBool raiseToWakeEnabled("s5", "Power", "Raise/Tilt to Wake", "Enables Raise to Wake", WAKE_FROM_RAISE); OswConfigKeyShort raiseToWakeSensitivity("s6", "Power", "Raise to Wake Sensitivity", @@ -86,6 +90,7 @@ OswConfigKeyBool tapToWakeEnabled("s8", "Power", "Tap to Wake", WAKE_FROM_TAP); OswConfigKeyBool buttonToWakeEnabled("m", "Power", "Button to Wake", "This will always be used, in case no other trigger is enabled", WAKE_FROM_BTN1); +#endif OswConfigKeyRGB themeBackgroundColor("c1", "Theme & UI", "Background color", nullptr, THEME_BACKROUND_COLOR); OswConfigKeyRGB themeBackgroundDimmedColor("c8", "Theme & UI", "Background color (dimmed)", nullptr, @@ -143,14 +148,16 @@ OswConfigKey* oswConfigKeys[] = { #if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 & OswConfigAllKeys::settingDisplayStepsGoal, #endif +#if OSW_PLATFORM_BLOCK_SLEEP != 1 // energy &OswConfigAllKeys::buttonToWakeEnabled, &OswConfigAllKeys::raiseToWakeEnabled, &OswConfigAllKeys::raiseToWakeSensitivity, &OswConfigAllKeys::tapToWakeEnabled, &OswConfigAllKeys::lightSleepEnabled, +#endif // date + time &OswConfigAllKeys::dateFormat, &OswConfigAllKeys::timezonePrimary, &OswConfigAllKeys::timezoneSecondary, - &OswConfigAllKeys::timeFormat, &OswConfigAllKeys::resetDay, + &OswConfigAllKeys::timeFormat, // colors &OswConfigAllKeys::themeBackgroundColor, &OswConfigAllKeys::themeBackgroundDimmedColor, &OswConfigAllKeys::themeForegroundColor, &OswConfigAllKeys::themeForegroundDimmedColor, @@ -159,9 +166,10 @@ OswConfigKey* oswConfigKeys[] = { #if OSW_PLATFORM_ENVIRONMENT_ACCELEROMETER == 1 // fitness &OswConfigAllKeys::configHeight, &OswConfigAllKeys::configWeight, &OswConfigAllKeys::stepsPerDay, - &OswConfigAllKeys::distPerDay, &OswConfigAllKeys::kcalPerDay, &OswConfigAllKeys::stepsHistoryClear - //weather + &OswConfigAllKeys::distPerDay, &OswConfigAllKeys::kcalPerDay, &OswConfigAllKeys::stepsHistoryClear, + &OswConfigAllKeys::resetDay #ifdef OSW_FEATURE_WEATHER + //weather ,&OswConfigAllKeys::weatherApiKey,&OswConfigAllKeys::weatherLocation1, &OswConfigAllKeys::weatherState1 #endif #endif diff --git a/src/osw_hal.cpp b/src/osw_hal.cpp index b00bd4c4d..7c4a5e205 100644 --- a/src/osw_hal.cpp +++ b/src/osw_hal.cpp @@ -34,7 +34,12 @@ void OswHal::resetInstance() { OswHal::OswHal(FileSystemHal* fs) : fileSystem(fs) { //begin I2c communication #ifndef OSW_EMULATOR - Wire.begin(OSW_DEVICE_I2C_SDA, OSW_DEVICE_I2C_SCL, 100000L); +#if defined(OSW_DEVICE_I2C_SDA) && defined(OSW_DEVICE_I2C_SCL) + bool res = Wire.begin(OSW_DEVICE_I2C_SDA, OSW_DEVICE_I2C_SCL, 100000L); + assert(res); +#else +#warning "I2C pins are not set on this platform, ignoring it then..." +#endif #endif } @@ -91,9 +96,24 @@ void OswHal::stop(bool toLightSleep) { if (!toLightSleep) { this->gfx()->fillBuffer(rgb565(0,0,0)); // This makes the display black this->flushCanvas(); +#if OSW_PLATFORM_ENVIRONMENT == 1 this->_environment.reset(); +#endif this->_devices.reset(); this->timeProvider = nullptr; // He is properly destroyed after devices destruction ↑ } OSW_LOG_D(toLightSleep ? "-> light sleep " : "-> deep sleep "); } + +#if OSW_PLATFORM_IS_FLOW3R_BADGE == 1 +uint8_t OswHal::readGpioExtender(uint8_t address) { + Wire.beginTransmission(address); + Wire.write(0xFF); // we do not want to output anything (who knows if this is a good idea) + uint8_t error = Wire.endTransmission(); + if (error != 0) + OSW_LOG_W("Failed to communicate with GPIO extender chip!"); + uint8_t bytes = 1; // using a variable to prevent compiler warnings.. + Wire.requestFrom(address, bytes); + return Wire.read(); +} +#endif diff --git a/src/services/OswServiceTaskBLECompanion.cpp b/src/services/OswServiceTaskBLECompanion.cpp index 5d99e3973..2e516b2af 100644 --- a/src/services/OswServiceTaskBLECompanion.cpp +++ b/src/services/OswServiceTaskBLECompanion.cpp @@ -1,4 +1,10 @@ #ifndef OSW_EMULATOR + +#if SERVICE_BLE_COMPANION == 1 +#ifdef OSW_FEATURE_WIFI +#error "The RAM on all current OSW models is not big enough to hold both WiFi AND Bluetooth stacks during runtime. This WILL lead to a crash. Please only use one of these features simultaneously!" +#endif + #include "./services/OswServiceTaskBLECompanion.h" #include "osw_hal.h" @@ -11,12 +17,6 @@ #include #include "config_defaults.h" -#ifdef OSW_FEATURE_WIFI -#if SERVICE_BLE_COMPANION == 1 -#error "The RAM on all current OSW models is not big enough to hold both WiFi AND Bluetooth stacks during runtime. This WILL lead to a crash. Please only use one of these features simultaneously!" -#endif -#endif - class NotificationCallback: public BLECharacteristicCallbacks { public: NotificationCallback(OswServiceTaskBLECompanion* comp) { @@ -95,3 +95,4 @@ void OswServiceTaskBLECompanion::stop() { OswServiceTask::stop(); } #endif +#endif diff --git a/src/services/OswServiceTaskConsole.cpp b/src/services/OswServiceTaskConsole.cpp index ead70d75c..a3aabfd96 100644 --- a/src/services/OswServiceTaskConsole.cpp +++ b/src/services/OswServiceTaskConsole.cpp @@ -1,3 +1,4 @@ +#include #include "./services/OswServiceTaskConsole.h" #include "osw_hal.h" @@ -12,8 +13,9 @@ void OswServiceTaskConsole::setup() { void OswServiceTaskConsole::loop() { while(true) { - if(!Serial.available()) break; - char c = Serial.read(); + OswSerial* serial = OswSerial::getInstance(); + char c; + if(!serial->getc((uint8_t&) c)) break; switch (c) { case 10: // LF case 13: // CR @@ -26,19 +28,19 @@ void OswServiceTaskConsole::loop() { if(this->m_inputBuffer.length() > 0) { this->m_inputBuffer.pop_back(); } - Serial.print(c); + serial->print(c); break; case 9: // tab - Serial.println(); // finish the prompt line + serial->println(); // finish the prompt line this->showHelp(); this->showPrompt(); break; default: if(32 <= c and c <= 126) { // printable characters this->m_inputBuffer += c; - Serial.print(c); // echo the entered character back + serial->print(c); // echo the entered character back } else { - Serial.print((char) 0x07); // bell + serial->print((char) 0x07); // bell OSW_LOG_D("Unprocessable character (",(int) c, "): ", c); } } @@ -52,21 +54,23 @@ void OswServiceTaskConsole::newPrompt() { } void OswServiceTaskConsole::showPrompt() { + OswSerial* serial = OswSerial::getInstance(); if (this->m_configuring) { - Serial.print("OSW (configure) > "); + serial->print("OSW (configure) > "); } else { - Serial.print("OSW > "); + serial->print("OSW > "); } if(!this->m_inputBuffer.empty()) { - Serial.print(this->m_inputBuffer.c_str()); + serial->print(this->m_inputBuffer.c_str()); } } void OswServiceTaskConsole::runPrompt() { - Serial.println(); // finish the prompt line + OswSerial* serial = OswSerial::getInstance(); + serial->println(); // finish the prompt line if(this->m_inputBuffer.empty()) return; if(this->m_locked) { - Serial.println("Console is locked! Enter \"unlock\" to unlock."); + serial->println("Console is locked! Enter \"unlock\" to unlock."); if(this->m_inputBuffer == "unlock") { this->m_locked = false; } @@ -83,18 +87,18 @@ void OswServiceTaskConsole::runPrompt() { auto key = this->m_inputBuffer.substr(4); for (auto i = 0; i < oswConfigKeysCount; i++) { if(oswConfigKeys[i]->id == key) { - Serial.println(oswConfigKeys[i]->toString()); + serial->println(oswConfigKeys[i]->toString()); break; } } } else if (this->m_inputBuffer.find("info ") == 0 and this->m_inputBuffer.length() > 5) { auto key = this->m_inputBuffer.substr(5); - Serial.println(OswConfig::getInstance()->getFieldJson(key.c_str())); + serial->println(OswConfig::getInstance()->getFieldJson(key.c_str())); } else if (this->m_inputBuffer == "help") { this->showHelp(); } else if (this->m_inputBuffer == "list") { for (auto i = 0; i < oswConfigKeysCount; i++) { - Serial.println(oswConfigKeys[i]->id); + serial->println(oswConfigKeys[i]->id); } } else if (this->m_inputBuffer.find("reset ") == 0 and this->m_inputBuffer.length() > 7) { auto key = this->m_inputBuffer.substr(7); @@ -105,7 +109,7 @@ void OswServiceTaskConsole::runPrompt() { auto key = this->m_inputBuffer.substr(4); // " " auto space = key.find(" ", 0); if (space == std::string::npos) { - Serial.println("Invalid command."); + serial->println("Invalid command."); return; } auto value = key.substr(space + 1); // "" @@ -123,7 +127,7 @@ void OswServiceTaskConsole::runPrompt() { this->showHelp(); #ifdef OSW_FEATURE_WIFI } else if (this->m_inputBuffer == "hostname") { - Serial.println(OswConfigAllKeys::hostname.get()); + serial->println(OswConfigAllKeys::hostname.get()); #endif } else if (this->m_inputBuffer == "lock") { this->m_locked = true; @@ -133,7 +137,7 @@ void OswServiceTaskConsole::runPrompt() { ESP.restart(); #endif } else if (this->m_inputBuffer == "time") { - Serial.println(OswHal::getInstance()->getUTCTime()); + serial->println(OswHal::getInstance()->getUTCTime()); } else if (this->m_inputBuffer == "wipe") { OswConfig::getInstance()->reset(true); } else { @@ -142,8 +146,8 @@ void OswServiceTaskConsole::runPrompt() { } // show help if the command was not processed if (!processed) { - Serial.println("Unknown command."); - Serial.println(); + serial->println("Unknown command."); + serial->println(); this->showHelp(); this->m_lockCounter++; } @@ -155,29 +159,30 @@ void OswServiceTaskConsole::runPrompt() { } void OswServiceTaskConsole::showHelp() { - Serial.println("Available commands:"); + OswSerial* serial = OswSerial::getInstance(); + serial->println("Available commands:"); // let's try to be civil and show the commands in alphabetical order if (this->m_configuring) { - Serial.println(" clear - reset all keys to default values"); - Serial.println(" exit - leave configuration mode"); - Serial.println(" get - get a value for a key"); - Serial.println(" help - show this help"); - Serial.println(" info - show more information about a key"); - Serial.println(" list - show all keys"); - Serial.println(" reset - reset a key to default value"); - Serial.println(" set - set a value for a key (value is everything until the end of the line)"); + serial->println(" clear - reset all keys to default values"); + serial->println(" exit - leave configuration mode"); + serial->println(" get - get a value for a key"); + serial->println(" help - show this help"); + serial->println(" info - show more information about a key"); + serial->println(" list - show all keys"); + serial->println(" reset - reset a key to default value"); + serial->println(" set - set a value for a key (value is everything until the end of the line)"); } else { - Serial.println(" configure - enter configuration mode"); - Serial.println(" help - show this help"); + serial->println(" configure - enter configuration mode"); + serial->println(" help - show this help"); #ifdef OSW_FEATURE_WIFI - Serial.println(" hostname - show the device hostname"); + serial->println(" hostname - show the device hostname"); #endif - Serial.println(" lock - lock the console"); + serial->println(" lock - lock the console"); #ifndef OSW_EMULATOR - Serial.println(" reboot - warm-start the device forcefully"); + serial->println(" reboot - warm-start the device forcefully"); #endif - Serial.println(" time - show current UTC time"); - Serial.println(" wipe - format NVS partition and reset configuration"); + serial->println(" time - show current UTC time"); + serial->println(" wipe - format NVS partition and reset configuration"); } } diff --git a/src/services/OswServiceTaskWiFi.cpp b/src/services/OswServiceTaskWiFi.cpp index 266d39e62..cd1a54481 100644 --- a/src/services/OswServiceTaskWiFi.cpp +++ b/src/services/OswServiceTaskWiFi.cpp @@ -38,16 +38,9 @@ void OswServiceTaskWiFi::loop() { this->m_connectFailureCount = 0; } else if(!this->m_connectTimeout and WiFi.status() != WL_CONNECTED) { // Wifi is either disconnected or unavailable... - if(this->onlyOneModeSimultaneously and this->m_enableStation) { - // This watch does not support connecting to networks with an active AutoAP. - // It would therefore be not helpful to activate the timeout to try an other - // action, while the AutoAP is active as this will shutdown the AutoAP as the - // timeout expires! - } else { - // -> start timeout - this->m_connectTimeout = time(nullptr); - OSW_LOG_D("[Connection] Timeout activated: 10 seconds"); - } + // -> start timeout + this->m_connectTimeout = time(nullptr); + OSW_LOG_D("[Connection] Timeout activated: 10 seconds"); } // Handling in case of 10 seconds without a successful connect @@ -307,11 +300,8 @@ void OswServiceTaskWiFi::updateWiFiConfig() { } #endif - if(!this->onlyOneModeSimultaneously and this->m_enableWiFi and this->m_enableClient and this->m_enableStation) { - WiFi.mode(WIFI_MODE_APSTA); - OSW_LOG_D("[Mode] Station & client"); - } else if(this->m_enableWiFi and this->m_enableStation) { - //Check this BEFORE the client, so in case of onlyOneModeSimultaneously we prefer the station, when enabled! + // How about "WiFi.mode(WIFI_MODE_APSTA)"? Well, so far every ESP was unable to work with this properly. So we removed it. + if(this->m_enableWiFi and this->m_enableStation) { WiFi.mode(WIFI_MODE_AP); OSW_LOG_D("[Mode] Station"); } else if(this->m_enableWiFi and this->m_enableClient) {