From 389c2a4e40d8685578eaae55fdbb2617ebb28c15 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Tue, 31 Aug 2021 22:15:25 +0200 Subject: [PATCH] Add stm32f7 --- platformio.ini | 25 +++++++ src/dev/device.h | 5 +- src/dev/stm32f4/stm32f4.h | 2 +- src/dev/stm32f7/stm32f7.cpp | 140 ++++++++++++++++++++++++++++++++++++ src/dev/stm32f7/stm32f7.h | 67 +++++++++++++++++ src/drv/tft/tft_driver.h | 3 + src/hal/hasp_hal.cpp | 2 +- src/hasp/hasp_dispatch.cpp | 116 ++++++++++++++++++------------ src/sys/gpio/hasp_gpio.cpp | 8 +-- src/sys/gpio/hasp_gpio.h | 4 +- src/sys/svc/hasp_http.cpp | 6 +- 11 files changed, 319 insertions(+), 59 deletions(-) create mode 100644 src/dev/stm32f7/stm32f7.cpp create mode 100644 src/dev/stm32f7/stm32f7.h diff --git a/platformio.ini b/platformio.ini index fcaa6212..617ab08a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -255,3 +255,28 @@ lib_deps = ; sstaub/Ticker @ ^3.2.0 stm32duino/STM32duino LwIP @ ^2.1.2 ;https://github.com/stm32duino/LwIP.git + +[stm32f7] +framework = arduino +platform = ststm32 +build_flags= +; -I include/stm32f4 + -D MQTT_MAX_PACKET_SIZE=2048 ; longer PubSubClient messages + -D HASP_CONSOLE_BUFFER=220 ; maximum length of a console/telnet command + -D IRAM_ATTR= ; No IRAM_ATTR available on STM32 + -D ICACHE_RAM_ATTR= + -D STM32 + -D ARDUINOJSON_DECODE_UNICODE=1 ; for utf-8 symbols + -D ARDUINOJSON_ENABLE_PROGMEM=1 ; for PROGMEM arguments + -D STREAMUTILS_USE_EEPROM_UPDATE=1 ; update cell only when changed +; -- lvgl build options ----------------------------- + -D LV_MEM_SIZE=20480U ; 20kB lvgl memory + -D HASP_USE_SYSLOG=0 ; Needs UDP + -D HASP_USE_SPIFFS=0 + -D HASP_USE_LITTLEFS=0 + -D HASP_USE_CONFIG=1 ; Native application, not library + +lib_deps = + ; sstaub/Ticker @ ^3.2.0 + stm32duino/STM32duino LwIP @ ^2.1.2 + ;https://github.com/stm32duino/LwIP.git diff --git a/src/dev/device.h b/src/dev/device.h index 708c7981..10f541f8 100644 --- a/src/dev/device.h +++ b/src/dev/device.h @@ -136,6 +136,9 @@ class BaseDevice { #elif defined(STM32F4) // #warning Building for STM32F4xx Devices #include "stm32f4/stm32f4.h" +#elif defined(STM32F7) +#warning Building for STM32F7xx Devices +#include "stm32f7/stm32f7.h" #elif defined(WINDOWS) // #warning Building for Win32 Devices #include "win32/hasp_win32.h" @@ -144,7 +147,7 @@ class BaseDevice { #include "posix/hasp_posix.h" #else -// #warning Building for Generic Devices +#warning Building for Generic Devices using dev::BaseDevice; extern dev::BaseDevice haspDevice; #endif diff --git a/src/dev/stm32f4/stm32f4.h b/src/dev/stm32f4/stm32f4.h index 0dc65f45..0c58aaf1 100644 --- a/src/dev/stm32f4/stm32f4.h +++ b/src/dev/stm32f4/stm32f4.h @@ -30,7 +30,7 @@ class Stm32f4Device : public BaseDevice { void set_hostname(const char*); const char* get_core_version(); const char* get_chip_model(); - const char* get_chip_hardware_id(); + const char* get_hardware_id(); void set_backlight_pin(uint8_t pin) override; void set_backlight_level(uint8_t val) override; diff --git a/src/dev/stm32f7/stm32f7.cpp b/src/dev/stm32f7/stm32f7.cpp new file mode 100644 index 00000000..97294c79 --- /dev/null +++ b/src/dev/stm32f7/stm32f7.cpp @@ -0,0 +1,140 @@ +/* MIT License - Copyright (c) 2019-2021 Francis Van Roie + For full license information read the LICENSE file in the project folder */ + +#if defined(STM32F7xx) + +#include "Arduino.h" + +#include "stm32f7.h" + +#include "hasp_conf.h" +#include "hasp_debug.h" + +#define BACKLIGHT_CHANNEL 0 + +namespace dev { + +void Stm32f7Device::reboot() +{ + // ESP.restart(); +} + +void Stm32f7Device::show_info() +{ + LOG_VERBOSE(TAG_DEV, F("Processor : STM32F4xx")); + // LOG_VERBOSE(TAG_DEV, F("CPU freq. : %i MHz"), get_cpu_frequency()); + // LOG_VERBOSE(TAG_DEV, F("Voltage : %2.2f V"), ESP.getVcc() / 918.0); // 918 empirically determined +} + +const char* Stm32f7Device::get_hostname() +{ + return _hostname.c_str(); +} + +void Stm32f7Device::set_hostname(const char* hostname) +{ + _hostname = hostname; +} + +const char* Stm32f7Device::get_core_version() +{ + // return ESP.getCoreVersion().c_str(); +} + +const char* Stm32f7Device::get_hardware_id() +{ + // https://stm32duinoforum.com/forum/viewtopic_f_29_t_2909_start_10.html + // Serial.println("UID [HEX] : "+String(*(uint32_t*)(UID_BASE), HEX)+" "+String(*(uint32_t*)(UID_BASE+0x04), + // HEX)+" "+String(*(uint32_t*)(UID_BASE+0x08), HEX)); + return _hardware_id.c_str(); +} + +void Stm32f7Device::set_backlight_pin(uint8_t pin) +{ + _backlight_pin = pin; + /* Setup Backlight Control Pin */ + if(pin >= 0) { + LOG_VERBOSE(TAG_GUI, F("Backlight : Pin %d"), pin); + pinMode(_backlight_pin, OUTPUT); + update_backlight(); + } +} + +const char* Stm32f7Device::get_chip_model() +{ +#if defined(STM32F407ZG) + return "STM32F407ZG"; +#elif defined(STM32F407ZE) + return "STM32F407ZE"; +#elif defined(STM32F407VE) + return "STM32F407VE"; +#elif defined(STM32F407VG) + return "STM32F407VG"; +#elif defined(STM32F4xx) || defined(ARDUINO_ARCH_STM32F4) + return "STM32F4"; +#else + return "Unknown STM32"; +#endif +} + +void Stm32f7Device::set_backlight_level(uint8_t level) +{ + _backlight_level = level; + update_backlight(); +} + +uint8_t Stm32f7Device::get_backlight_level() +{ + return _backlight_level; +} + +void Stm32f7Device::set_backlight_power(bool power) +{ + _backlight_power = power; + update_backlight(); +} + +bool Stm32f7Device::get_backlight_power() +{ + return _backlight_power != 0; +} + +void Stm32f7Device::update_backlight() +{ + if(_backlight_pin == -1) return; + + // analogWrite(_backlight_pin, _backlight_power ? map(_backlight_level, 0, 255, 0, 1023) : 0); +} + +size_t Stm32f7Device::get_free_max_block() +{ + // return ESP.getMaxFreeBlockSize(); +} + +size_t Stm32f7Device::get_free_heap(void) +{ + // return ESP.getFreeHeap(); +} + +uint8_t Stm32f7Device::get_heap_fragmentation() +{ + // return ESP.getHeapFragmentation(); +} + +uint16_t Stm32f7Device::get_cpu_frequency() +{ + // return ESP.getCpuFreqMHz(); +} + +bool Stm32f7Device::is_system_pin(uint8_t pin) +{ + // if((pin >= 6) && (pin <= 11)) return true; // integrated SPI flash + // if((pin >= 12) && (pin <= 14)) return true; // HSPI + return false; +} + +} // namespace dev + +dev::Stm32f7Device haspDevice; + +#endif // STM32F4xx \ No newline at end of file diff --git a/src/dev/stm32f7/stm32f7.h b/src/dev/stm32f7/stm32f7.h new file mode 100644 index 00000000..ebe7f11c --- /dev/null +++ b/src/dev/stm32f7/stm32f7.h @@ -0,0 +1,67 @@ +/* MIT License - Copyright (c) 2019-2021 Francis Van Roie + For full license information read the LICENSE file in the project folder */ + +#ifndef HASP_DEVICE_STM32F4_H +#define HASP_DEVICE_STM32F4_H + +#include "hasp_conf.h" +#include "dev/device.h" + +#if defined(STM32F7xx) + +namespace dev { + +class Stm32f7Device : public BaseDevice { + + public: + Stm32f7Device() + { + _hostname = MQTT_NODENAME; + _backlight_power = 1; + _backlight_invert = 0; + _backlight_level = 255; + _backlight_pin = TFT_BCKL; + } + + void reboot() override; + void show_info() override; + + const char* get_hostname(); + void set_hostname(const char*); + const char* get_core_version(); + const char* get_chip_model(); + const char* get_hardware_id(); + + void set_backlight_pin(uint8_t pin) override; + void set_backlight_level(uint8_t val) override; + uint8_t get_backlight_level() override; + void set_backlight_power(bool power) override; + bool get_backlight_power() override; + + size_t get_free_max_block() override; + size_t get_free_heap() override; + uint8_t get_heap_fragmentation() override; + uint16_t get_cpu_frequency() override; + + bool is_system_pin(uint8_t pin) override; + + private: + std::string _hostname; + std::string _hardware_id; + + uint8_t _backlight_pin; + uint8_t _backlight_level; + uint8_t _backlight_power; + uint8_t _backlight_invert; + + void update_backlight(); +}; + +} // namespace dev + +using dev::Stm32f7Device; +extern dev::Stm32f7Device haspDevice; + +#endif // STM32F7xx + +#endif // HASP_DEVICE_STM32F4_H \ No newline at end of file diff --git a/src/drv/tft/tft_driver.h b/src/drv/tft/tft_driver.h index 79b383d3..9a29d188 100644 --- a/src/drv/tft/tft_driver.h +++ b/src/drv/tft/tft_driver.h @@ -45,6 +45,9 @@ class BaseTft { #elif defined(STM32F4) // #warning Building for STM32F4xx Tfts #include "tft_driver_tftespi.h" +#elif defined(STM32F7) +#warning Building for STM32F7xx Tfts +#include "tft_driver_tftespi.h" #elif defined(WINDOWS) || defined(POSIX) // #warning Building for SDL2 #include "tft_driver_sdl2.h" diff --git a/src/hal/hasp_hal.cpp b/src/hal/hasp_hal.cpp index 28e41d43..92ebc5be 100644 --- a/src/hal/hasp_hal.cpp +++ b/src/hal/hasp_hal.cpp @@ -258,7 +258,7 @@ String halGetMacAddress(int start, const char* seperator) { byte mac[6]; -#if defined(STM32F4xx) +#if defined(STM32F4xx) || defined(STM32F7xx) || defined(STM32H7xx) uint8_t* mac_p = nullptr; #if HASP_USE_ETHERNET > 0 #if USE_BUILTIN_ETHERNET > 0 diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp index 1b60abf3..17aeb18e 100644 --- a/src/hasp/hasp_dispatch.cpp +++ b/src/hasp/hasp_dispatch.cpp @@ -1,6 +1,8 @@ /* MIT License - Copyright (c) 2019-2021 Francis Van Roie For full license information read the LICENSE file in the project folder */ +#include + //#include "ArduinoLog.h" #include "hasplib.h" @@ -648,6 +650,72 @@ void dispatch_parse_jsonl(const char*, const char* payload, uint8_t source) #endif } +void dispatch_exec(const char*, const char* payload, uint8_t source) +{ +#if ARDUINO + if(!HASP_FS.exists(payload)) { + LOG_WARNING(TAG_MSGR, F(D_FILE_NOT_FOUND ": %s"), payload); + return; + } + + LOG_TRACE(TAG_MSGR, F(D_FILE_LOADING), payload); + + File cmdfile = HASP_FS.open(payload, "r"); + if(!cmdfile) { + LOG_ERROR(TAG_MSGR, F(D_FILE_LOAD_FAILED), payload); + return; + } + + // char buffer[512]; // use stack + String buffer((char*)0); // use heap + buffer.reserve(256); + + ReadBufferingStream bufferedFile{cmdfile, 256}; + cmdfile.seek(0); + + while(bufferedFile.available()) { + size_t index = 0; + buffer = ""; + // while(index < sizeof(buffer) - 1) { + while(index < MQTT_MAX_PACKET_SIZE) { + int c = bufferedFile.read(); + if(c < 0 || c == '\n' || c == '\r') { // CR or LF + break; + } + // buffer[index] = (char)c; + buffer += (char)c; + index++; + } + // buffer[index] = 0; // terminate string + // if(index > 0 && buffer[0] != '#') dispatch_text_line(buffer.c_str(), TAG_FILE); // # for comments + if(index > 0 && buffer.charAt(0) != '#') dispatch_text_line(buffer.c_str(), TAG_FILE); // # for comments + } + + cmdfile.close(); + LOG_INFO(TAG_MSGR, F(D_FILE_LOADED), payload); +#else + char path[strlen(payload) + 4]; + path[0] = '.'; + path[1] = '\0'; + strcat(path, payload); + path[1] = '\\'; + + LOG_TRACE(TAG_HASP, F("Loading %s from disk..."), path); + std::ifstream f(path); // taking file as inputstream + if(f) { + std::string line; + while(std::getline(f, line)) { + LOG_VERBOSE(TAG_HASP, line.c_str()); + if(!line.empty() && line[0] != '#') dispatch_text_line(line.c_str(), TAG_FILE); // # for comments + } + } else { + LOG_ERROR(TAG_MSGR, F(D_FILE_LOAD_FAILED), payload); + } + f.close(); + LOG_INFO(TAG_HASP, F("Loaded %s from disk"), path); +#endif +} + void dispatch_current_page() { char topic[8]; @@ -1071,7 +1139,7 @@ bool dispatch_factory_reset() #if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0 formated = HASP_FS.format(); - if (formated) filesystemSetupFiles(); + if(formated) filesystemSetupFiles(); #endif #if HASP_USE_EEPROM > 0 @@ -1161,52 +1229,6 @@ void dispatch_service(const char*, const char* payload, uint8_t source) #endif } -void dispatch_exec(const char*, const char* payload, uint8_t source) -{ -#if ARDUINO - if(!HASP_FS.exists(payload)) { - LOG_WARNING(TAG_MSGR, F(D_FILE_NOT_FOUND ": %s"), payload); - return; - } - - LOG_TRACE(TAG_MSGR, F(D_FILE_LOADING), payload); - - File cmdfile = HASP_FS.open(payload, "r"); - if(!cmdfile) { - LOG_ERROR(TAG_MSGR, F(D_FILE_LOAD_FAILED), payload); - return; - } - - // char buffer[512]; // use stack - String buffer((char*)0); // use heap - buffer.reserve(256); - - ReadBufferingStream bufferedFile{cmdfile, 256}; - cmdfile.seek(0); - - while(bufferedFile.available()) { - size_t index = 0; - buffer = ""; - // while(index < sizeof(buffer) - 1) { - while(index < MQTT_MAX_PACKET_SIZE) { - int c = bufferedFile.read(); - if(c < 0 || c == '\n' || c == '\r') { // CR or LF - break; - } - // buffer[index] = (char)c; - buffer += (char)c; - index++; - } - // buffer[index] = 0; // terminate string - // if(index > 0 && buffer[0] != '#') dispatch_text_line(buffer.c_str(), TAG_FILE); // # for comments - if(index > 0 && buffer.charAt(0) != '#') dispatch_text_line(buffer.c_str(), TAG_FILE); // # for comments - } - - cmdfile.close(); - LOG_INFO(TAG_MSGR, F(D_FILE_LOADED), payload); -#endif -} - /******************************************* Commands builder *******************************************/ static void dispatch_add_command(const char* p_cmdstr, void (*func)(const char*, const char*, uint8_t)) diff --git a/src/sys/gpio/hasp_gpio.cpp b/src/sys/gpio/hasp_gpio.cpp index 7561aa9e..2d540322 100644 --- a/src/sys/gpio/hasp_gpio.cpp +++ b/src/sys/gpio/hasp_gpio.cpp @@ -268,7 +268,7 @@ static void gpio_setup_pin(uint8_t index) #endif break; - case hasp_gpio_type_t::DAC: + case hasp_gpio_type_t::HASP_DAC: #if defined(ARDUINO_ARCH_ESP32) gpio_num_t pin; if(dac_pad_get_io_num(DAC_CHANNEL_1, &pin) == ESP_OK) @@ -548,7 +548,7 @@ static bool gpio_set_output_value(hasp_gpio_config_t* gpio, bool power, uint16_t case hasp_gpio_type_t::PWM: return gpio_set_analog_value(gpio); - case hasp_gpio_type_t::DAC: + case hasp_gpio_type_t::HASP_DAC: return gpio_set_dac_value(gpio); case hasp_gpio_type_t::SERIAL_DIMMER: @@ -580,7 +580,7 @@ static void gpio_set_normalized_value(hasp_gpio_config_t* gpio, hasp_update_valu break; case hasp_gpio_type_t::LED... hasp_gpio_type_t::LED_W: - case hasp_gpio_type_t::DAC: + case hasp_gpio_type_t::HASP_DAC: case hasp_gpio_type_t::PWM: case hasp_gpio_type_t::SERIAL_DIMMER: case hasp_gpio_type_t::SERIAL_DIMMER_AU: @@ -872,7 +872,7 @@ void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonA relay.add(gpioConfig[i].pin); break; - case hasp_gpio_type_t::DAC: + case hasp_gpio_type_t::HASP_DAC: case hasp_gpio_type_t::LED: // Don't include the moodlight case hasp_gpio_type_t::SERIAL_DIMMER: case hasp_gpio_type_t::SERIAL_DIMMER_AU: diff --git a/src/sys/gpio/hasp_gpio.h b/src/sys/gpio/hasp_gpio.h index 9003a9d8..e7a886b0 100644 --- a/src/sys/gpio/hasp_gpio.h +++ b/src/sys/gpio/hasp_gpio.h @@ -88,7 +88,7 @@ enum hasp_gpio_type_t { SHUTTER_CLOSE = 0x1B, BACKLIGHT = 0x20, PWM = 0x21, - DAC = 0x22, + HASP_DAC = 0x22, SERIAL_DIMMER = 0x30, SERIAL_DIMMER_EU = 0x31, SERIAL_DIMMER_AU = 0x32, @@ -136,7 +136,7 @@ enum hasp_gpio_type_t { BUTTON_TOGGLE_BOTH = 0xF3, TOUCH = 0xF4, - ADC = 0xF9, + HASP_ADC = 0xF9, COUNTER_RISE = 0xFA, // User Counters COUNTER_FALL = 0xFB, diff --git a/src/sys/svc/hasp_http.cpp b/src/sys/svc/hasp_http.cpp index 49fe6d1c..6c07e3a1 100644 --- a/src/sys/svc/hasp_http.cpp +++ b/src/sys/svc/hasp_http.cpp @@ -1583,7 +1583,7 @@ void webHandleGpioConfig() case hasp_gpio_type_t::PWM: httpMessage += F(D_GPIO_PWM); break; - case hasp_gpio_type_t::DAC: + case hasp_gpio_type_t::HASP_DAC: httpMessage += F(D_GPIO_DAC); break; @@ -1701,8 +1701,8 @@ void webHandleGpioOutput() selected = (conf.type == hasp_gpio_type_t::SHUTTER_RELAY); httpMessage += getOption(hasp_gpio_type_t::SHUTTER_RELAY, F("Shutter Relay"), selected); - selected = (conf.type == hasp_gpio_type_t::DAC); - httpMessage += getOption(hasp_gpio_type_t::DAC, F(D_GPIO_DAC), selected); + selected = (conf.type == hasp_gpio_type_t::HASP_DAC); + httpMessage += getOption(hasp_gpio_type_t::HASP_DAC, F(D_GPIO_DAC), selected); // selected = (conf.type == hasp_gpio_type_t::SERIAL_DIMMER); // httpMessage += getOption(hasp_gpio_type_t::SERIAL_DIMMER, F(D_GPIO_SERIAL_DIMMER), selected);