diff --git a/boards/muzi-base.json b/boards/muzi-base.json new file mode 100644 index 000000000..5f65c0dc8 --- /dev/null +++ b/boards/muzi-base.json @@ -0,0 +1,56 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v6.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_NRF52840_MUZI_BASE -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [["0x239A", "0xcafe"]], + "mcu": "nrf52840", + "variant": "muzi-base", + "variants_dir": "variants", + "bsp": { + "name": "adafruit" + }, + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "6.1.1", + "sd_fwid": "0x00B6" + }, + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": ["bluetooth"], + "debug": { + "jlink_device": "nRF52840_xxAA", + "onboard_tools": ["jlink"], + "svd_path": "nrf52840.svd", + "openocd_target": "nrf52840-mdk-rs" + }, + "frameworks": ["arduino"], + "name": "Muzi Base", + "url": "https://muzi.works/", + "vendor": "MuziWorks", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": [ + "jlink", + "nrfjprog", + "nrfutil", + "blackmagic", + "cmsis-dap", + "mbed", + "stlink" + ], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + } +} diff --git a/src/Power.cpp b/src/Power.cpp index 75fd32202..0ac89670f 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -278,6 +278,11 @@ class AnalogBatteryLevel : public HasBatteryLevel break; } } +#if defined(BATTERY_CHARGING_INV) + // bit of trickery to show 99% up until the charge finishes + if (!digitalRead(BATTERY_CHARGING_INV) && battery_SOC > 99) + battery_SOC = 99; +#endif return clamp((int)(battery_SOC), 0, 100); } @@ -455,6 +460,8 @@ class AnalogBatteryLevel : public HasBatteryLevel } // if it's not HIGH - check the battery #endif +#elif defined(MUZI_BASE) + return NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk; #endif return getBattVoltage() > chargingVolt; } @@ -470,6 +477,8 @@ class AnalogBatteryLevel : public HasBatteryLevel #endif #ifdef EXT_CHRG_DETECT return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value; +#elif defined(BATTERY_CHARGING_INV) + return !digitalRead(BATTERY_CHARGING_INV); #else #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(DISABLE_INA_CHARGING_DETECTION) if (hasINA()) { @@ -702,7 +711,16 @@ bool Power::setup() }, CHANGE); #endif - +#ifdef BATTERY_CHARGING_INV + attachInterrupt( + BATTERY_CHARGING_INV, + []() { + power->setIntervalFromNow(0); + runASAP = true; + BaseType_t higherWake = 0; + }, + CHANGE); +#endif enabled = found; low_voltage_counter = 0; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 167728ad3..bcf49286e 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -547,6 +547,11 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) case ICM20948_ADDR: // same as BMX160_ADDR case ICM20948_ADDR_ALT: // same as MPU6050_ADDR registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); +#ifdef HAS_ICM20948 + type = ICM20948; + logFoundDevice("ICM20948", (uint8_t)addr.address); + break; +#endif if (registerValue == 0xEA) { type = ICM20948; logFoundDevice("ICM20948", (uint8_t)addr.address); diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index 692f3c2d2..1122f0a51 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -112,7 +112,11 @@ RTCSetResult readFromRTC() #elif defined(RX8130CE_RTC) if (rtc_found.address == RX8130CE_RTC) { uint32_t now = millis(); +#ifdef MUZI_BASE + ArtronShop_RX8130CE rtc(&Wire1); +#else ArtronShop_RX8130CE rtc(&Wire); +#endif tm t; if (rtc.getTime(&t)) { tv.tv_sec = gm_mktime(&t); @@ -245,7 +249,11 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd } #elif defined(RX8130CE_RTC) if (rtc_found.address == RX8130CE_RTC) { +#ifdef MUZI_BASE + ArtronShop_RX8130CE rtc(&Wire1); +#else ArtronShop_RX8130CE rtc(&Wire); +#endif tm *t = gmtime(&tv->tv_sec); if (rtc.setTime(*t)) { LOG_DEBUG("RX8130CE setDateTime %02d-%02d-%02d %02d:%02d:%02d (%ld)", t->tm_year + 1900, t->tm_mon + 1, diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 86599d5b3..dc9806156 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -435,6 +435,14 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) PMU->enablePowerOutput(XPOWERS_ALDO2); #endif +#if defined(MUZI_BASE) + dispdev->init(); + dispdev->setBrightness(brightness); + dispdev->flipScreenVertically(); + dispdev->resetDisplay(); + digitalWrite(SCREEN_12V_ENABLE, HIGH); + delay(100); +#endif #if !ARCH_PORTDUINO dispdev->displayOn(); #endif @@ -484,6 +492,10 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) #endif dispdev->displayOff(); + +#ifdef SCREEN_12V_ENABLE + digitalWrite(SCREEN_12V_ENABLE, LOW); +#endif #ifdef USE_ST7789 SPI1.end(); #if defined(ARCH_ESP32) @@ -534,7 +546,7 @@ void Screen::setup() static_cast(dispdev)->setDetected(model); #endif -#ifdef USE_SH1107_128_64 +#if defined(USE_SH1107_128_64) || defined(USE_SH1107) static_cast(dispdev)->setSubtype(7); #endif @@ -542,6 +554,9 @@ void Screen::setup() // Apply custom RGB color (e.g. Heltec T114/T190) static_cast(dispdev)->setRGB(TFT_MESH); #endif +#if defined(MUZI_BASE) + dispdev->delayPoweron = true; +#endif // === Initialize display and UI system === ui->init(); diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 74b8d7c5d..375bc2805 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -249,6 +249,8 @@ class Screen : public concurrency::OSThread bool isOverlayBannerShowing(); + bool isScreenOn() { return screenOn; } + // Stores the last 4 of our hardware ID, to make finding the device for pairing easier // FIXME: Needs refactoring and getMacAddr needs to be moved to a utility class char ourId[5]; diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index bb3fc6dca..ff76baaa1 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -734,6 +734,9 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) config.display.screen_on_secs = 30; config.display.wake_on_tap_or_motion = true; #endif +#ifdef COMPASS_ORIENTATION + config.display.compass_orientation = COMPASS_ORIENTATION; +#endif #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI if (WiFiOTA::isUpdated()) { WiFiOTA::recoverConfig(&config.network); diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp index d04daf594..719e342b1 100644 --- a/src/modules/SerialModule.cpp +++ b/src/modules/SerialModule.cpp @@ -64,7 +64,8 @@ SerialModule *serialModule; SerialModuleRadio *serialModuleRadio; #if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \ - defined(ELECROW_ThinkNode_M5) || defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE) || defined(ELECROW_ThinkNode_M3) + defined(ELECROW_ThinkNode_M5) || defined(HELTEC_MESH_SOLAR) || defined(T_ECHO_LITE) || defined(ELECROW_ThinkNode_M3) || \ + defined(MUZI_BASE) SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") { api_type = TYPE_SERIAL; @@ -204,7 +205,7 @@ int32_t SerialModule::runOnce() Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); } #elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \ - !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) + !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && !defined(MUZI_BASE) if (moduleConfig.serial.rxd && moduleConfig.serial.txd) { #ifdef ARCH_RP2040 Serial2.setFIFOSize(RX_BUFFER); @@ -261,7 +262,7 @@ int32_t SerialModule::runOnce() } #if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \ - !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) + !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && !defined(MUZI_BASE) else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) { processWXSerial(); @@ -537,7 +538,7 @@ void SerialModule::processWXSerial() { #if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \ !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && \ - !defined(ARCH_STM32WL) + !defined(ARCH_STM32WL) && !defined(MUZI_BASE) static unsigned int lastAveraged = 0; static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded. static double dir_sum_sin = 0; diff --git a/src/motion/ICM20948Sensor.cpp b/src/motion/ICM20948Sensor.cpp index 10918eb7d..9455eafe0 100755 --- a/src/motion/ICM20948Sensor.cpp +++ b/src/motion/ICM20948Sensor.cpp @@ -47,6 +47,21 @@ int32_t ICM20948Sensor::runOnce() int32_t ICM20948Sensor::runOnce() { #if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN +#if defined(MUZI_BASE) // temporarily gated to single device due to feature freeze + if (screen && !screen->isScreenOn() && !config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) { + if (!isAsleep) { + LOG_DEBUG("sleeping IMU"); + sensor->sleep(true); + isAsleep = true; + } + return MOTION_SENSOR_CHECK_INTERVAL_MS; + } + if (isAsleep) { + sensor->sleep(false); + isAsleep = false; + } +#endif + float magX = 0, magY = 0, magZ = 0; if (sensor->dataReady()) { sensor->getAGMT(); @@ -156,6 +171,8 @@ int32_t ICM20948Sensor::runOnce() void ICM20948Sensor::calibrate(uint16_t forSeconds) { #if !defined(MESHTASTIC_EXCLUDE_SCREEN) && HAS_SCREEN + LOG_DEBUG("Old calibration data: highestX = %f, lowestX = %f, highestY = %f, lowestY = %f, highestZ = %f, lowestZ = %f", + highestX, lowestX, highestY, lowestY, highestZ, lowestZ); LOG_DEBUG("BMX160 calibration started for %is", forSeconds); if (sensor->dataReady()) { sensor->getAGMT(); diff --git a/src/motion/ICM20948Sensor.h b/src/motion/ICM20948Sensor.h index 27ce4f451..a9b7b69d0 100755 --- a/src/motion/ICM20948Sensor.h +++ b/src/motion/ICM20948Sensor.h @@ -82,7 +82,13 @@ class ICM20948Sensor : public MotionSensor private: ICM20948Singleton *sensor = nullptr; bool showingScreen = false; +#ifdef MUZI_BASE + bool isAsleep = false; + float highestX = 449.000000, lowestX = -140.000000, highestY = 422.000000, lowestY = -232.000000, highestZ = 749.000000, + lowestZ = 98.000000; +#else float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0; +#endif public: explicit ICM20948Sensor(ScanI2C::FoundDevice foundDevice); diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index dc3930d64..1568e1790 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -108,6 +108,8 @@ #define HW_VENDOR meshtastic_HardwareModel_SEEED_WIO_TRACKER_L1 #elif defined(HELTEC_MESH_SOLAR) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_MESH_SOLAR +#elif defined(MUZI_BASE) +#define HW_VENDOR meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN #else #define HW_VENDOR meshtastic_HardwareModel_NRF52_UNKNOWN #endif diff --git a/variants/nrf52840/muzi_base/platformio.ini b/variants/nrf52840/muzi_base/platformio.ini new file mode 100644 index 000000000..49393f4e0 --- /dev/null +++ b/variants/nrf52840/muzi_base/platformio.ini @@ -0,0 +1,15 @@ +[env:muzi-base] +extends = nrf52840_base +board = muzi-base +build_flags = ${nrf52840_base.build_flags} + -I variants/nrf52840/muzi_base + -D MUZI_BASE + -D CONFIG_NFCT_PINS_AS_GPIOS=1 + -L "${platformio.libdeps_dir}/${this.__env__}/bsec2/src/cortex-m4/fpv4-sp-d16-hard" + +build_src_filter = ${nrf52840_base.build_src_filter} +<../variants/nrf52840/muzi_base> +lib_deps = + ${nrf52840_base.lib_deps} + artronshop/ArtronShop_RX8130CE@1.0.0 + + diff --git a/variants/nrf52840/muzi_base/rfswitch.h b/variants/nrf52840/muzi_base/rfswitch.h new file mode 100644 index 000000000..589f24767 --- /dev/null +++ b/variants/nrf52840/muzi_base/rfswitch.h @@ -0,0 +1,11 @@ +#include "RadioLib.h" + +static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; + +static const Module::RfSwitchMode_t rfswitch_table[] = { + // mode DIO5 DIO6 + {LR11x0::MODE_STBY, {LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW}}, + {LR11x0::MODE_TX, {LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH}}, + {LR11x0::MODE_TX_HF, {LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW}}, + {LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE, +}; diff --git a/variants/nrf52840/muzi_base/variant.cpp b/variants/nrf52840/muzi_base/variant.cpp new file mode 100644 index 000000000..da01de974 --- /dev/null +++ b/variants/nrf52840/muzi_base/variant.cpp @@ -0,0 +1,83 @@ +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + // P0 + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + + // P1 + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, +}; + +void initVariant() +{ + // Initialize the digital pins as inputs or outputs + pinMode(PIN_LED1, OUTPUT); + digitalWrite(PIN_LED1, HIGH); + + pinMode(PIN_LED2, OUTPUT); + digitalWrite(PIN_LED2, HIGH); + + // Initialize LoRa pins + pinMode(SX126X_RESET, OUTPUT); + digitalWrite(SX126X_RESET, HIGH); + + pinMode(SX126X_CS, OUTPUT); + digitalWrite(SX126X_CS, HIGH); + + pinMode(GPS_EN_GPIO, OUTPUT); + digitalWrite(GPS_EN_GPIO, HIGH); // GPS on initially + + pinMode(SCREEN_12V_ENABLE, OUTPUT); + digitalWrite(SCREEN_12V_ENABLE, LOW); // + + pinMode(BATTERY_CHARGING_INV, INPUT); +} diff --git a/variants/nrf52840/muzi_base/variant.h b/variants/nrf52840/muzi_base/variant.h new file mode 100644 index 000000000..d3e315f8b --- /dev/null +++ b/variants/nrf52840/muzi_base/variant.h @@ -0,0 +1,192 @@ +#pragma once + +#ifndef _VARIANT_MUZI_BASE_ +#define _VARIANT_MUZI_BASE_ + +/** Master clock frequency */ +#define VARIANT_MCK (64000000ul) + +#define USE_LFXO // Board uses 32khz crystal for LF + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "WVariant.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Number of pins defined in PinDescription array +#define PINS_COUNT (48) +#define NUM_DIGITAL_PINS (48) +#define NUM_ANALOG_INPUTS (6) +#define NUM_ANALOG_OUTPUTS (0) + +// Define I2C Peripherals +#define WIRE_INTERFACES_COUNT 2 + +// this is the OLED bus +#define PIN_WIRE_SDA (0 + 24) // P0.24 +#define PIN_WIRE_SCL (0 + 25) // P0.25 + +// IMU bus +#define PIN_WIRE1_SDA (0 + 04) // P0.04 +#define PIN_WIRE1_SCL (0 + 06) // P0.06 + +#define COMPASS_ORIENTATION meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270 +#define HAS_ICM20948 // forces the i2c address to be seen as this sensor + +#define HAS_RTC 1 +#define RX8130CE_RTC 0x32 + +// LEDs +#define PIN_LED1 (32 + 3) // P1.03, Green +#define PIN_LED2 (32 + 4) // P1.04, Blue + +#define LED_BUILTIN -1 // PIN_LED1 +#define LED_BLUE PIN_LED2 +#define LED_STATE_ON 0 // State when LED is lit + +// Buttons +#define HAS_TRACKBALL 1 +#define TB_UP (0 + 21) +#define TB_DOWN (0 + 17) +#define TB_LEFT (32 + 05) +#define TB_RIGHT (0 + 16) +#define TB_PRESS (0 + 10) +#define TB_DIRECTION FALLING + +#define CANCEL_BUTTON_PIN (0 + 15) // P0.15 +#define CANCEL_BUTTON_ACTIVE_LOW true +#define CANCEL_BUTTON_ACTIVE_PULLUP false + +// Switch +#define SWITCH_MODE1 (32 + 9) // P1.09, Top Position +#define SWITCH_MODE2 (0 + 12) // P0.12, Middle Position +#define PIN_GPS_SWITCH SWITCH_MODE2 + +/* + * SPI Interfaces + */ + +#define SPI_INTERFACES_COUNT 1 + +// For LORA, spi 0 +#define PIN_SPI_MISO (32 + 15) // P1.15 +#define PIN_SPI_MOSI (32 + 14) // P1.14 +#define PIN_SPI_SCK (32 + 13) // P1.13 + +#define LORA_SCK PIN_SPI_SCK +#define LORA_MISO PIN_SPI_MISO +#define LORA_MOSI PIN_SPI_MOSI +#define LORA_CS (32 + 12) // P1.12 + +#define USE_SX1262 +#define SX126X_CS LORA_CS +#define SX126X_DIO1 (32 + 6) // P1.06 +#define SX126X_BUSY (32 + 11) // P1.11 +#define SX126X_RESET (32 + 10) // P1.10 +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 3.3 + +#define USE_LR1121 +#define LR1121_IRQ_PIN (32 + 8) // P1.08 +#define LR1121_NRESET_PIN (32 + 10) // P1.10 +#define LR1121_BUSY_PIN (32 + 11) // P1.11 +#define LR1121_SPI_NSS_PIN LORA_CS +#define LR1121_SPI_SCK_PIN LORA_SCK +#define LR1121_SPI_MOSI_PIN LORA_MOSI +#define LR1121_SPI_MISO_PIN LORA_MISO +#define LR11X0_DIO3_TCXO_VOLTAGE 3.0 +#define LR11X0_DIO_AS_RF_SWITCH + +// GPS +#define GPS_RX_PIN (0 + 19) // P0.19 +#define GPS_TX_PIN (0 + 20) // P0.20 +#define GPS_EN_GPIO (32 + 1) // P1.01 + +#define PIN_SERIAL1_RX GPS_TX_PIN +#define PIN_SERIAL1_TX GPS_RX_PIN + +#define PIN_BUZZER (0 + 22) // P0.22 + +// Battery monitoring +#define BATTERY_PIN (0 + 31) // P0.31 + +// #define CHARGER_FAULT (0 + 27) // P0.27 +#define BATTERY_CHARGING_INV (32 + 02) // P1.02 +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define BATTERY_SENSE_RESOLUTION 4096.0 +#define ADC_MULTIPLIER 1.537 + +#define OCV_ARRAY 4050, 4010, 3990, 3930, 3870, 3820, 3740, 3630, 3550, 3450, 3100 + +// Display - I2C display +#define HAS_SCREEN 1 +#define SCREEN_12V_ENABLE (0 + 23) // P0.23 +#define USE_SH1107 + +#define USERPREFS_OEM_TEXT "muzi_works_logo" +#define USERPREFS_OEM_FONT_SIZE 0 +#define USERPREFS_OEM_IMAGE_WIDTH 88 // 11 bytes wide +#define USERPREFS_OEM_IMAGE_HEIGHT 47 // 517 bytes total +#define USERPREFS_OEM_IMAGE_DATA \ + { \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, \ + 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0xF7, 0x0F, 0xFF, 0x00, 0xF0, 0xFF, 0x0F, 0xC0, 0xFF, 0x07, 0x78, 0xFF, 0x9F, 0xFF, 0x01, 0xF0, 0xFF, 0x0F, 0xC0, \ + 0xFF, 0x03, 0x78, 0x3F, 0xFE, 0xF3, 0x01, 0xF0, 0xFF, 0x0F, 0x00, 0xE0, 0x03, 0x78, 0x1F, 0xFC, 0xC0, 0x03, 0xF0, \ + 0xFF, 0x0F, 0x00, 0xE0, 0x01, 0x78, 0x0F, 0xF8, 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0xF0, 0x00, 0x78, 0x0F, 0x78, \ + 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0x70, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0x78, 0x00, \ + 0x78, 0x07, 0x70, 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0x3C, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xF0, 0xFF, 0x0F, \ + 0x00, 0x1C, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xF0, 0xFF, 0x0F, 0x00, 0x1E, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, \ + 0xE0, 0xFF, 0x0F, 0x00, 0x0F, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xE0, 0xFF, 0x07, 0x80, 0x07, 0x00, 0x78, 0x07, \ + 0x70, 0x80, 0x03, 0xC0, 0xFF, 0x07, 0x80, 0x07, 0x00, 0x78, 0x07, 0x70, 0x80, 0x03, 0xC0, 0xFF, 0x03, 0xC0, 0xFF, \ + 0x07, 0x78, 0x07, 0x70, 0x80, 0x03, 0x00, 0xFF, 0x01, 0xE0, 0xFF, 0x07, 0x78, 0x07, 0x70, 0x80, 0x03, 0x00, 0x7C, \ + 0x00, 0xF0, 0xFF, 0x07, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xE3, 0xE7, 0xC7, 0x1F, 0xF8, 0x0F, 0xF0, 0xE7, 0xE3, 0x07, 0x7C, 0xC7, 0xE7, \ + 0xC3, 0x0F, 0xE0, 0x07, 0xE0, 0xC7, 0xE1, 0x03, 0x70, 0xC7, 0xC3, 0xE3, 0x87, 0xC1, 0x07, 0xC0, 0xC7, 0xF8, 0xE3, \ + 0x71, 0xC7, 0xC3, 0xE3, 0xE3, 0xC7, 0xC7, 0xC7, 0x47, 0xF8, 0xF3, 0x7F, 0x8F, 0xC3, 0xF1, 0xE3, 0x8F, 0xC7, 0x8F, \ + 0x27, 0xFC, 0xE3, 0x7F, 0x8F, 0x81, 0xF1, 0xF1, 0x8F, 0xC7, 0xCF, 0x07, 0xFE, 0x03, 0x7E, 0x8F, 0x99, 0xF1, 0xF1, \ + 0x8F, 0x07, 0xC0, 0x07, 0xFF, 0x07, 0x78, 0x9F, 0x99, 0xF9, 0xF1, 0x8F, 0x07, 0xE0, 0x07, 0xFE, 0x3F, 0x70, 0x1F, \ + 0x18, 0xF8, 0xF3, 0x8F, 0x07, 0xF0, 0x27, 0xFC, 0xFF, 0x71, 0x3F, 0x18, 0xF8, 0xE3, 0xC7, 0xC7, 0xF1, 0x47, 0xF8, \ + 0xF3, 0x63, 0x3F, 0x3C, 0xFC, 0xC3, 0xC3, 0xC7, 0xE3, 0xC7, 0xF0, 0xE1, 0x71, 0x3F, 0x3C, 0xFC, 0x07, 0xE0, 0xC7, \ + 0xC7, 0xC7, 0xE1, 0x03, 0x70, 0x7F, 0x7E, 0xFE, 0x0F, 0xF0, 0xC7, 0x87, 0xC7, 0xC3, 0x07, 0x78, 0xFF, 0xFF, 0xFF, \ + 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0x7F \ + } + +// QSPI Pins +#define PIN_QSPI_SCK (0 + 3) +#define PIN_QSPI_CS (0 + 26) +#define PIN_QSPI_IO0 (0 + 30) +#define PIN_QSPI_IO1 (0 + 29) +#define PIN_QSPI_IO2 (0 + 28) +#define PIN_QSPI_IO3 (0 + 2) + +// On-board QSPI Flash +#define EXTERNAL_FLASH_DEVICES W25Q32JVSS +#define EXTERNAL_FLASH_USE_QSPI + +// NFC is disabled via CONFIG_NFCT_PINS_AS_GPIOS=1 build flag +// This configures P0.09 and P0.10 as regular GPIO pins instead of NFC pins + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ +#ifdef __cplusplus +#endif + +#endif // _VARIANT_MUZI_BASE_ \ No newline at end of file