mirror of
https://github.com/HASwitchPlate/openHASP.git
synced 2025-04-20 05:17:20 +00:00
445 lines
10 KiB
C++
445 lines
10 KiB
C++
/* MIT License - Copyright (c) 2020 Francis Van Roie
|
|
For full license information read the LICENSE file in the project folder */
|
|
|
|
#include "hasp_hal.h"
|
|
#include "hasp_conf.h"
|
|
|
|
#if defined(ESP8266)
|
|
#include <Esp.h>
|
|
#include <ESP8266WiFi.h>
|
|
#endif
|
|
|
|
#if defined(ESP32)
|
|
#include <Esp.h>
|
|
#include <WiFi.h>
|
|
#include "esp_system.h"
|
|
#endif
|
|
|
|
#if defined(ARDUINO_ARCH_ESP32)
|
|
#include <rom/rtc.h> // needed to get the ResetInfo
|
|
|
|
// Compatibility function for ESP8266 getRestInfo
|
|
String esp32ResetReason(uint8_t cpuid)
|
|
{
|
|
if(cpuid > 1) {
|
|
return F("Invalid CPU id");
|
|
}
|
|
RESET_REASON reason = rtc_get_reset_reason(cpuid);
|
|
|
|
String resetReason((char *)0);
|
|
resetReason.reserve(128);
|
|
|
|
resetReason += F("CPU");
|
|
resetReason += cpuid;
|
|
resetReason += F(": ");
|
|
|
|
switch(reason) {
|
|
case 1:
|
|
resetReason += F("POWERON");
|
|
break; /**<1, Vbat power on reset*/
|
|
case 3:
|
|
resetReason += F("SW");
|
|
break; /**<3, Software reset digital core*/
|
|
case 4:
|
|
resetReason += F("OWDT");
|
|
break; /**<4, Legacy watch dog reset digital core*/
|
|
case 5:
|
|
resetReason += F("DEEPSLEEP");
|
|
break; /**<5, Deep Sleep reset digital core*/
|
|
case 6:
|
|
resetReason += F("SDIO");
|
|
break; /**<6, Reset by SLC module, reset digital core*/
|
|
case 7:
|
|
resetReason += F("TG0WDT_SYS");
|
|
break; /**<7, Timer Group0 Watch dog reset digital core*/
|
|
case 8:
|
|
resetReason += F("TG1WDT_SYS");
|
|
break; /**<8, Timer Group1 Watch dog reset digital core*/
|
|
case 9:
|
|
resetReason += F("RTCWDT_SYS");
|
|
break; /**<9, RTC Watch dog Reset digital core*/
|
|
case 10:
|
|
resetReason += F("INTRUSION");
|
|
break; /**<10, Instrusion tested to reset CPU*/
|
|
case 11:
|
|
resetReason += F("TGWDT_CPU");
|
|
break; /**<11, Time Group reset CPU*/
|
|
case 12:
|
|
resetReason += F("SW_CPU");
|
|
break; /**<12, Software reset CPU*/
|
|
case 13:
|
|
resetReason += F("RTCWDT_CPU");
|
|
break; /**<13, RTC Watch dog Reset CPU*/
|
|
case 14:
|
|
resetReason += F("EXT_CPU");
|
|
break; /**<14, for APP CPU, reseted by PRO CPU*/
|
|
case 15:
|
|
resetReason += F("RTCWDT_BROWN_OUT");
|
|
break; /**<15, Reset when the vdd voltage is not stable*/
|
|
case 16:
|
|
resetReason += F("RTCWDT_RTC");
|
|
break; /**<16, RTC Watch dog reset digital core and rtc module*/
|
|
default:
|
|
resetReason += F("NO_MEAN");
|
|
return resetReason;
|
|
}
|
|
resetReason += F("_RESET");
|
|
return resetReason;
|
|
}
|
|
#endif
|
|
|
|
void halRestartMcu(void)
|
|
{
|
|
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266)
|
|
ESP.restart();
|
|
#else
|
|
NVIC_SystemReset();
|
|
#endif
|
|
for(;;) {
|
|
} // halt
|
|
}
|
|
|
|
String halGetResetInfo()
|
|
{
|
|
#if defined(ARDUINO_ARCH_ESP32)
|
|
String resetReason((char *)0);
|
|
resetReason.reserve(128);
|
|
|
|
resetReason += String(esp32ResetReason(0));
|
|
resetReason += F(" / ");
|
|
resetReason += String(esp32ResetReason(1));
|
|
return resetReason;
|
|
#elif defined(ARDUINO_ARCH_ESP8266)
|
|
return ESP.getResetInfo();
|
|
#else
|
|
return "";
|
|
#endif
|
|
}
|
|
|
|
String halGetCoreVersion()
|
|
{
|
|
#if defined(ARDUINO_ARCH_ESP32)
|
|
return String(ESP.getSdkVersion());
|
|
#elif defined(ARDUINO_ARCH_ESP8266)
|
|
return String(ESP.getCoreVersion());
|
|
#else
|
|
return String(STM32_CORE_VERSION_MAJOR) + "." + STM32_CORE_VERSION_MINOR + "." + STM32_CORE_VERSION_PATCH;
|
|
#endif
|
|
}
|
|
|
|
String halGetChipModel()
|
|
{
|
|
String model((char *)0);
|
|
model.reserve(128);
|
|
|
|
#if defined(STM32F4xx)
|
|
model = F("STM32");
|
|
#endif
|
|
|
|
#if defined(STM32F4xx)
|
|
model = F("STM32F4xx");
|
|
|
|
#elif defined(ARDUINO_ARCH_ESP8266)
|
|
model = F("ESP8266");
|
|
|
|
#elif defined(ARDUINO_ARCH_ESP32)
|
|
esp_chip_info_t chip_info;
|
|
esp_chip_info(&chip_info);
|
|
|
|
model = chip_info.cores;
|
|
model += F("core ");
|
|
switch(chip_info.model) {
|
|
case CHIP_ESP32:
|
|
model += F("ESP32");
|
|
break;
|
|
#ifdef CHIP_ESP32S2
|
|
case CHIP_ESP32S2:
|
|
model += F("ESP32-S2");
|
|
break;
|
|
#endif
|
|
default:
|
|
model = F("Unknown ESP32");
|
|
}
|
|
model += F(" rev");
|
|
model += chip_info.revision;
|
|
|
|
#else
|
|
model = F("Unknown");
|
|
#endif
|
|
|
|
return model;
|
|
}
|
|
|
|
/*******************************/
|
|
/* Memory Management Functions */
|
|
|
|
#if defined(STM32F4xx)
|
|
#include <malloc.h> // for mallinfo()
|
|
#include <unistd.h> // for sbrk()
|
|
|
|
int freeHighMemory()
|
|
{
|
|
char top;
|
|
#ifdef __arm__
|
|
return &top - reinterpret_cast<char *>(sbrk(0));
|
|
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
|
|
return &top - __brkval;
|
|
#else // __arm__
|
|
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
|
|
#endif // __arm__
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
extern char *fake_heap_end; // current heap start
|
|
extern char *fake_heap_start; // current heap end
|
|
|
|
char* getHeapStart() {
|
|
return fake_heap_start;
|
|
}
|
|
|
|
char* getHeapEnd() {
|
|
return (char*)sbrk(0);
|
|
}
|
|
|
|
char* getHeapLimit() {
|
|
return fake_heap_end;
|
|
}
|
|
|
|
int getMemUsed() { // returns the amount of used memory in bytes
|
|
struct mallinfo mi = mallinfo();
|
|
return mi.uordblks;
|
|
}
|
|
|
|
int getMemFree() { // returns the amount of free memory in bytes
|
|
struct mallinfo mi = mallinfo();
|
|
return mi.fordblks + freeHighMemory();
|
|
} */
|
|
|
|
size_t halGetMaxFreeBlock()
|
|
{
|
|
#if defined(ARDUINO_ARCH_ESP32)
|
|
return ESP.getMaxAllocHeap();
|
|
#elif defined(ARDUINO_ARCH_ESP8266)
|
|
return ESP.getMaxFreeBlockSize();
|
|
#else
|
|
return freeHighMemory();
|
|
#endif
|
|
}
|
|
|
|
size_t halGetFreeHeap(void)
|
|
{
|
|
#if defined(ARDUINO_ARCH_ESP32)
|
|
return ESP.getFreeHeap();
|
|
#elif defined(ARDUINO_ARCH_ESP8266)
|
|
return ESP.getFreeHeap();
|
|
#else
|
|
struct mallinfo chuncks = mallinfo();
|
|
|
|
// fordblks
|
|
// This is the total size of memory occupied by free (not in use) chunks.
|
|
|
|
return chuncks.fordblks + freeHighMemory();
|
|
#endif
|
|
}
|
|
|
|
uint8_t halGetHeapFragmentation()
|
|
{
|
|
#if defined(ARDUINO_ARCH_ESP32)
|
|
return (int8_t)(100.00f - (float)ESP.getMaxAllocHeap() * 100.00f / (float)ESP.getFreeHeap());
|
|
#elif defined(ARDUINO_ARCH_ESP8266)
|
|
return ESP.getHeapFragmentation();
|
|
#else
|
|
return (int8_t)(100.00f - (float)freeHighMemory() * 100.00f / (float)halGetFreeHeap());
|
|
#endif
|
|
}
|
|
|
|
String halGetMacAddress(int start, const char * seperator)
|
|
{
|
|
byte mac[6];
|
|
|
|
#if defined(STM32F4xx)
|
|
uint8_t * mac_p = nullptr;
|
|
#if HASP_USE_ETHERNET > 0
|
|
#if USE_BUILTIN_ETHERNET > 0
|
|
mac_p = Ethernet.MACAddress();
|
|
for(int i = 0; i < 6; i++) mac[i] = *(mac_p + i);
|
|
#else
|
|
Ethernet.macAddress(mac);
|
|
#endif
|
|
#endif
|
|
#else
|
|
WiFi.macAddress(mac);
|
|
#endif
|
|
|
|
String cMac((char *)0);
|
|
cMac.reserve(32);
|
|
|
|
for(int i = start; i < 6; ++i) {
|
|
if(mac[i] < 0x10) cMac += "0";
|
|
cMac += String(mac[i], HEX);
|
|
if(i < 5) cMac += seperator;
|
|
}
|
|
cMac.toUpperCase();
|
|
return cMac;
|
|
}
|
|
|
|
uint16_t halGetCpuFreqMHz()
|
|
{
|
|
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_32)
|
|
return ESP.getCpuFreqMHz();
|
|
#else
|
|
return (F_CPU / 1000 / 1000);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
String halDisplayDriverName()
|
|
{
|
|
#if defined(ILI9341_DRIVER)
|
|
return F("ILI9341");
|
|
#elif defined(ST7735_DRIVER)
|
|
return F("ST7735");
|
|
#elif defined(ILI9163_DRIVER)
|
|
return F("ILI9163");
|
|
#elif defined(S6D02A1_DRIVER)
|
|
return F("S6D02A1");
|
|
#elif defined(ST7796_DRIVER)
|
|
return F("ST7796");
|
|
#elif defined(ILI9486_DRIVER)
|
|
return F("ILI9486");
|
|
#elif defined(ILI9481_DRIVER)
|
|
return F("ILI9481");
|
|
#elif defined(ILI9488_DRIVER)
|
|
return F("ILI9488");
|
|
#elif defined(HX8357D_DRIVER)
|
|
return F("HX8357D");
|
|
#elif defined(EPD_DRIVER)
|
|
return F("EPD");
|
|
#elif defined(ST7789_DRIVER)
|
|
return F("ST7789");
|
|
#elif defined(R61581_DRIVER)
|
|
return F("R61581");
|
|
#elif defined(ST7789_2_DRIVER)
|
|
return F("ST7789_2");
|
|
#elif defined(RM68140_DRIVER)
|
|
return F("RM68140");
|
|
#endif
|
|
return F("Unknown");
|
|
}
|
|
|
|
String halGpioName(uint8_t gpio)
|
|
{
|
|
#if defined(STM32F4xx)
|
|
String ioName;
|
|
uint16_t name = digitalPin[gpio];
|
|
uint8_t num = name % 16;
|
|
switch(name / 16) {
|
|
case PortName::PortA:
|
|
ioName = F("PA");
|
|
break;
|
|
case PortName::PortB:
|
|
ioName = F("PB");
|
|
break;
|
|
#if defined GPIOC_BASE
|
|
case PortName::PortC:
|
|
ioName = F("PC");
|
|
break;
|
|
#endif
|
|
#if defined GPIOD_BASE
|
|
case PortName::PortD:
|
|
ioName = F("PD");
|
|
break;
|
|
#endif
|
|
#if defined GPIOE_BASE
|
|
case PortName::PortE:
|
|
ioName = F("PE");
|
|
break;
|
|
#endif
|
|
#if defined GPIOF_BASE
|
|
case PortName::PortF:
|
|
ioName = F("PF");
|
|
break;
|
|
#endif
|
|
#if defined GPIOG_BASE
|
|
case PortName::PortG:
|
|
ioName = F("PG");
|
|
break;
|
|
#endif
|
|
#if defined GPIOH_BASE
|
|
case PortName::PortH:
|
|
ioName = F("PH");
|
|
break;
|
|
#endif
|
|
#if defined GPIOI_BASE
|
|
case PortName::PortI:
|
|
ioName = F("PI");
|
|
break;
|
|
#endif
|
|
#if defined GPIOJ_BASE
|
|
case PortName::PortJ:
|
|
ioName = F("PJ");
|
|
break;
|
|
#endif
|
|
#if defined GPIOK_BASE
|
|
case PortName::PortK:
|
|
ioName = F("PK");
|
|
break;
|
|
#endif
|
|
#if defined GPIOZ_BASE
|
|
case PortName::PortZ:
|
|
ioName = F("PZ");
|
|
break;
|
|
#endif
|
|
default:
|
|
ioName = F("P?");
|
|
}
|
|
ioName += num;
|
|
ioName += F(" (io");
|
|
ioName += gpio;
|
|
ioName += F(")");
|
|
return ioName;
|
|
#endif
|
|
|
|
// For ESP32 pin labels on boards use the GPIO number
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
return /*String(F("gpio")) +*/ String(gpio);
|
|
#endif
|
|
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
// For ESP8266 the pin labels are not the same as the GPIO number
|
|
// These are for the NodeMCU pin definitions:
|
|
// GPIO Dxx
|
|
switch(gpio) {
|
|
case 16:
|
|
return F("D0");
|
|
case 5:
|
|
return F("D1");
|
|
case 4:
|
|
return F("D2");
|
|
case 0:
|
|
return F("D3");
|
|
case 2:
|
|
return F("D4");
|
|
case 14:
|
|
return F("D5");
|
|
case 12:
|
|
return F("D6");
|
|
case 13:
|
|
return F("D7");
|
|
case 15:
|
|
return F("D8");
|
|
case 3:
|
|
return F("TX");
|
|
case 1:
|
|
return F("RX");
|
|
// case 9:
|
|
// return F("D11");
|
|
// case 10:
|
|
// return F("D12");
|
|
default:
|
|
return F("D?"); // Invalid pin
|
|
}
|
|
#endif
|
|
} |