diff --git a/.gitmodules b/.gitmodules index 7dce60a..f7e01f0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "modules/pico-onewire"] path = modules/pico-onewire url = https://github.com/adamboardman/pico-onewire.git -[submodule "modules/fmt"] - path = modules/fmt - url = https://github.com/fmtlib/fmt.git diff --git a/.vscode/launch.json b/.vscode/launch.json index aa54d5c..c32afb1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,4 +1,4 @@ - { +{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 @@ -11,19 +11,21 @@ "request": "launch", "type": "cortex-debug", "servertype": "openocd", - "gdbPath": "gdb-multiarch", + "gdbPath" : "arm-none-eabi-gdb", "device": "RP2040", + //"showDevDebugOutput": "parsed", "configFiles": [ - "interface/raspberrypi-swd.cfg", + "interface/picoprobe.cfg", "target/rp2040.cfg" ], "svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd", "runToEntryPoint": "main", - // Give restart the same functionality as runToEntryPoint - main - "postRestartCommands": [ - "break main", - "continue" - ] + // Give restart the same functionality as runToMain + //"postRestartCommands": [ + // "break main", + // "continue" + //], + "searchDir": ["${env:HOME}/src/openocd/tcl"], } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 960b66b..5fbeec4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,13 +14,7 @@ "visibility": "hidden" }, }, + "cortex-debug.openocdPath": "${env:HOME}/src/openocd/src/openocd", + "cmake.generator": "Unix Makefiles", "C_Cpp.clang_format_fallbackStyle": "LLVM", - "files.watcherExclude": { - "**/.git/objects/**": true, - "**/.git/subtree-cache/**": true, - "**/node_modules/*/**": true, - "**/.hg/store/**": true, - ".flatpak/**": true, - "_build/**": true - }, } diff --git a/CMakeLists.txt b/CMakeLists.txt index ee8ec1c..067f307 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,22 +1,21 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_C_STANDARD 11) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fno-exceptions") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-volatile -fmodules-ts") # Initialise pico_sdk from installed location # (note this can come from environment, CMake cache etc) -#set(PICO_SDK_PATH "/usr/share/pico-sdk") +set(PICO_SDK_PATH "/usr/share/pico-sdk") # Pull in Raspberry Pi Pico SDK (must be before project) include("cmake/pico_sdk_import.cmake") -project(gbmanager VERSION "1.0.3" LANGUAGES C CXX ASM) +project(gbmanager VERSION "1.0.0" LANGUAGES C CXX ASM) # Initialise the Raspberry Pi Pico SDK pico_sdk_init() add_subdirectory(modules/pico-onewire) -add_subdirectory(modules/fmt) -add_subdirectory(src) +add_subdirectory(src) \ No newline at end of file diff --git a/modules/fmt b/modules/fmt deleted file mode 160000 index b6f4cea..0000000 --- a/modules/fmt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b6f4ceaed0a0a24ccf575fab6c56dd50ccf6f1a9 diff --git a/modules/pico-onewire b/modules/pico-onewire index 6399467..d5af2a1 160000 --- a/modules/pico-onewire +++ b/modules/pico-onewire @@ -1 +1 @@ -Subproject commit 6399467cf7687ecb7f8f4e4923303349e0ecf160 +Subproject commit d5af2a1e1d81c3cb21805e332c8185607ee74b1d diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b9408f4..6e2e75a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,12 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) configure_file(${CMAKE_CURRENT_LIST_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) +#add_compile_options(-fmodules-ts) + set(SOURCES - gbmanager.cpp lcd.cpp relais.cpp + gbmanager.cpp ) # Add executable. Default name is the project name, version 0.1 @@ -14,15 +16,15 @@ pico_set_program_name(${CMAKE_PROJECT_NAME} "gbmanager") pico_set_program_version(${CMAKE_PROJECT_NAME} ${PROJECT_VERSION}) if(CMAKE_BUILD_TYPE STREQUAL "Debug") - pico_enable_stdio_uart(${CMAKE_PROJECT_NAME} 0) - pico_enable_stdio_usb(${CMAKE_PROJECT_NAME} 1) + pico_enable_stdio_uart(${CMAKE_PROJECT_NAME} 1) + pico_enable_stdio_usb(${CMAKE_PROJECT_NAME} 0) else() pico_enable_stdio_uart(${CMAKE_PROJECT_NAME} 0) pico_enable_stdio_usb(${CMAKE_PROJECT_NAME} 0) endif() # Add the standard library to the build -target_link_libraries(${CMAKE_PROJECT_NAME} pico_stdlib pico_one_wire fmt::fmt-header-only) +target_link_libraries(${CMAKE_PROJECT_NAME} pico_stdlib pico_one_wire) # Add any user requested libraries target_link_libraries(${CMAKE_PROJECT_NAME} diff --git a/src/gbmanager.cpp b/src/gbmanager.cpp index 19290e9..5ae7a7d 100644 --- a/src/gbmanager.cpp +++ b/src/gbmanager.cpp @@ -1,13 +1,14 @@ -#include +#include -#include "../modules/fmt/include/fmt/format.h" #include "../modules/pico-onewire/api/one_wire.h" #include "hardware/i2c.h" #include "pico/stdlib.h" #include "config.h" -#include "lcd.h" -#include "relais.h" +//#include "lcd.h" + +import lcd; +import relais; // GPIOs used constexpr uint I2C_SDA_PIN = 26; @@ -31,7 +32,7 @@ using std::string; void buttonPressedCallback(uint gpio, [[maybe_unused]] uint32_t events) { absolute_time_t now = get_absolute_time(); - if (absolute_time_diff_us(lastPressed, now) < 500000) { + if (absolute_time_diff_us(lastPressed, now) < 750000) { return; } else { lastPressed = now; @@ -55,7 +56,7 @@ int main() { stdio_init_all(); // Initialize the LCD - auto myLCD = LCD(i2c1, I2C_SDA_PIN, I2C_SCL_PIN); + auto myLCD = LCD(i2c1, I2C_SDA_PIN, I2C_SCL_PIN, 16, 2); myLCD.clear(); // Initialize the temp sensor @@ -65,9 +66,7 @@ int main() { oneWire.single_device_read_rom(address); // Initialize the relais - // It need the button callback function, since it has to disable the on/off - // button for a short amount of time - Relais relais(RELAIS_PIN, &buttonPressedCallback); + Relais relais(RELAIS_PIN); // Initialize the Buttons gpio_set_irq_enabled_with_callback(BUTTON_1_PIN, GPIO_IRQ_EDGE_FALL, true, @@ -79,19 +78,17 @@ int main() { float temp_act{0}; float temp_diff{0.5}; - string lcdText{}; + std::stringstream lcdText{}; bool isHeating = false; string heatInfo{""}; string systemInfo{""}; - lcdText = fmt::format(" G{}rbox Manager\n (Ver. {})", CUSTOM_CHAR_AE, - PROJECT_VERSION); - myLCD.sendString(lcdText); + lcdText << " G" << CUSTOM_CHAR_AE << "rbox Manager\n (Ver. " + << PROJECT_VERSION << ")"; + myLCD.sendString(lcdText.str()); sleep_ms(3000); while (true) { - uint64_t destTime = time_us_64() + 1000000; - oneWire.convert_temperature(address, true, false); temp_act = oneWire.temperature(address); @@ -108,12 +105,14 @@ int main() { relais.activate(isHeating); - lcdText = fmt::format("ACT: {:05.2f}{}C {}\nTGT: {:05.2f}{}C {}", - temp_act, CUSTOM_CHAR_DEG, heatInfo, temp_tgt, - CUSTOM_CHAR_DEG, systemInfo); - myLCD.setCursor(0, 0); - myLCD.sendString(lcdText); + lcdText.str(""); + lcdText.clear(); + lcdText.precision(4); + lcdText << "ACT: " << temp_act << CUSTOM_CHAR_DEG << "C " << heatInfo + << "\n" + << "TGT: " << temp_tgt << CUSTOM_CHAR_DEG << "C " << systemInfo; - sleep_until((absolute_time_t){destTime}); + myLCD.setCursor(0, 0); + myLCD.sendString(lcdText.str()); } -} +} \ No newline at end of file diff --git a/src/lcd.cpp b/src/lcd.cpp index 52c512e..c8cf230 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -1,6 +1,12 @@ -#include "pico/binary_info.h" +module; -#include "lcd.h" +#include + +#include "hardware/i2c.h" +#include "pico/binary_info.h" +#include "pico/stdlib.h" + +export module lcd; // commands constexpr int LCD_CLEARDISPLAY = 0x01; @@ -29,74 +35,90 @@ constexpr int LCD_8BITMODE = 0x10; constexpr int LCD_BACKLIGHT = 0x08; constexpr int LCD_ENABLE_BIT = 0x04; -LCD::LCD(i2c_inst_t *i2c, const uint gpio_sda, const uint gpio_scl, - const uint8_t i2c_addr, uint8_t num_cols, uint8_t num_lines) - : i2c{i2c}, i2c_addr{i2c_addr}, num_cols{num_cols}, num_lines{num_lines} { - i2c_init(i2c, 400 * 1000); - gpio_set_function(gpio_sda, GPIO_FUNC_I2C); - gpio_set_function(gpio_scl, GPIO_FUNC_I2C); - gpio_pull_up(gpio_sda); - gpio_pull_up(gpio_scl); - // Make the I2C pins available to picotool - bi_decl(bi_2pins_with_func(gpio_sda, gpio_scl, GPIO_FUNC_I2C)); +enum class Mode { COMMAND, CHARACTER }; - sendByte(0x03, Mode::COMMAND); - sendByte(0x03, Mode::COMMAND); - sendByte(0x03, Mode::COMMAND); - sendByte(0x02, Mode::COMMAND); +export class LCD { + public: + LCD(i2c_inst_t *i2c, const uint gpio_sda, const uint gpio_scl, + const uint8_t i2c_addr, const uint8_t num_cols = 16, + const uint8_t num_lines = 2) + : i2c{i2c}, i2c_addr{i2c_addr}, num_cols{num_cols}, num_lines{ + num_lines} { + i2c_init(i2c, 400 * 1000); + gpio_set_function(gpio_sda, GPIO_FUNC_I2C); + gpio_set_function(gpio_scl, GPIO_FUNC_I2C); + gpio_pull_up(gpio_sda); + gpio_pull_up(gpio_scl); + // Make the I2C pins available to picotool + bi_decl(bi_2pins_with_func(gpio_sda, gpio_scl, GPIO_FUNC_I2C)); - sendByte(LCD_ENTRYMODESET | LCD_ENTRYLEFT, Mode::COMMAND); - sendByte(LCD_FUNCTIONSET | LCD_2LINE, Mode::COMMAND); - sendByte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, Mode::COMMAND); - clear(); -} + sendByte(0x03, Mode::COMMAND); + sendByte(0x03, Mode::COMMAND); + sendByte(0x03, Mode::COMMAND); + sendByte(0x02, Mode::COMMAND); -// Go to location on LCD -void LCD::setCursor(int line, int position) { - int val = (line == 0) ? 0x80 + position : 0xC0 + position; - sendByte(val, Mode::COMMAND); - cursor_x = line; - cursor_y = position; -} + sendByte(LCD_ENTRYMODESET | LCD_ENTRYLEFT, Mode::COMMAND); + sendByte(LCD_FUNCTIONSET | LCD_2LINE, Mode::COMMAND); + sendByte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, Mode::COMMAND); + clear(); + } -void LCD::sendChar(char val) { sendByte(val, Mode::CHARACTER); } - -void LCD::sendString(const std::string &str) { - for (const char &c : str) { - if (c == '\n') { - cursor_y++; - setCursor(cursor_y, 0); - } else { - sendChar(c); - cursor_x++; + void sendString(const std::string &str) { + for (const char &c : str) { + if (c == '\n') { + cursor_y++; + setCursor(cursor_y, 0); + } else { + sendChar(c); + cursor_x++; + } } } -} -void LCD::clear() { sendByte(LCD_CLEARDISPLAY, Mode::COMMAND); } + // Go to location on LCD + void setCursor(int line, int position) { + int val = (line == 0) ? 0x80 + position : 0xC0 + position; + sendByte(val, Mode::COMMAND); + cursor_x = line; + cursor_y = position; + } -void LCD::i2cWriteByte(uint8_t val) { - i2c_write_blocking(i2c, i2c_addr, &val, 1, false); -} + void clear() { sendByte(LCD_CLEARDISPLAY, Mode::COMMAND); } -void LCD::toggleEnable(uint8_t val) { - // Toggle enable pin on LCD display - // We cannot do this too quickly or things don't work - constexpr uint64_t DELAY_US = 600; - sleep_us(DELAY_US); - i2cWriteByte(val | LCD_ENABLE_BIT); - sleep_us(DELAY_US); - i2cWriteByte(val & ~LCD_ENABLE_BIT); - sleep_us(DELAY_US); -} + private: + void sendChar(char val) { sendByte(val, Mode::CHARACTER); } -// The display is sent a byte as two separate nibble transfers -void LCD::sendByte(uint8_t val, Mode mode) { - uint8_t high = static_cast(mode) | (val & 0xF0) | LCD_BACKLIGHT; - uint8_t low = static_cast(mode) | ((val << 4) & 0xF0) | LCD_BACKLIGHT; + void i2cWriteByte(uint8_t val) { + i2c_write_blocking(i2c, i2c_addr, &val, 1, false); + } - i2cWriteByte(high); - toggleEnable(high); - i2cWriteByte(low); - toggleEnable(low); -} + void toggleEnable(uint8_t val) { + // Toggle enable pin on LCD display + // We cannot do this too quickly or things don't work + constexpr uint64_t DELAY_US = 600; + sleep_us(DELAY_US); + i2cWriteByte(val | LCD_ENABLE_BIT); + sleep_us(DELAY_US); + i2cWriteByte(val & ~LCD_ENABLE_BIT); + sleep_us(DELAY_US); + } + + // The display is sent a byte as two separate nibble transfers + void sendByte(uint8_t val, Mode mode) { + uint8_t high = static_cast(mode) | (val & 0xF0) | LCD_BACKLIGHT; + uint8_t low = + static_cast(mode) | ((val << 4) & 0xF0) | LCD_BACKLIGHT; + + i2cWriteByte(high); + toggleEnable(high); + i2cWriteByte(low); + toggleEnable(low); + } + + i2c_inst_t *i2c; + uint8_t i2c_addr; + uint8_t num_cols; + uint8_t num_lines; + uint8_t cursor_x{0}; + uint8_t cursor_y{0}; +}; \ No newline at end of file diff --git a/src/relais.cpp b/src/relais.cpp index 980b8f4..39bc970 100644 --- a/src/relais.cpp +++ b/src/relais.cpp @@ -1,35 +1,24 @@ -#include "relais.h" +module; -Relais::Relais(uint gpio, gpio_irq_callback_t callback) - : gpio{gpio}, callback{callback} { - gpio_init(gpio); - gpio_set_dir(gpio, GPIO_OUT); - off(); -} +#include "hardware/gpio.h" +#include "pico/stdlib.h" -void Relais::activate(bool active) { - if (active == lastState) { - return; +export module relais; + +export class Relais { + public: + Relais(uint gpio) : gpio{gpio} { + gpio_init(gpio); + gpio_set_dir(gpio, GPIO_OUT); + off(); } - lastState = active; + void activate(bool active) { gpio_put(gpio, !active); } - gpio_set_irq_enabled_with_callback(BUTTON_1_PIN, GPIO_IRQ_EDGE_FALL, false, - callback); - gpio_set_irq_enabled_with_callback(BUTTON_2_PIN, GPIO_IRQ_EDGE_FALL, false, - callback); - gpio_set_irq_enabled_with_callback(BUTTON_3_PIN, GPIO_IRQ_EDGE_FALL, false, - callback); - gpio_put(gpio, !active); - sleep_ms(100); - gpio_set_irq_enabled_with_callback(BUTTON_1_PIN, GPIO_IRQ_EDGE_FALL, true, - callback); - gpio_set_irq_enabled_with_callback(BUTTON_2_PIN, GPIO_IRQ_EDGE_FALL, true, - callback); - gpio_set_irq_enabled_with_callback(BUTTON_3_PIN, GPIO_IRQ_EDGE_FALL, true, - callback); -} + void on() { activate(true); } -void Relais::on() { activate(true); } + void off() { activate(false); } -void Relais::off() { activate(false); } + private: + uint gpio; +}; \ No newline at end of file diff --git a/src/relais.h b/src/relais.h index d8d4f9e..fcc357e 100644 --- a/src/relais.h +++ b/src/relais.h @@ -4,21 +4,15 @@ #include "hardware/gpio.h" #include "pico/stdlib.h" -extern const uint BUTTON_1_PIN; // declared in gbmanager.cpp -extern const uint BUTTON_2_PIN; // declared in gbmanager.cpp -extern const uint BUTTON_3_PIN; // declared in gbmanager.cpp - class Relais { public: - Relais(uint gpio, gpio_irq_callback_t callback); + Relais(uint gpio); void activate(bool active); void on(); void off(); private: uint gpio; - bool lastState; - gpio_irq_callback_t callback; }; -#endif +#endif \ No newline at end of file