diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index acb48669c..f85085c63 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -45,7 +45,8 @@ jobs: 'rp2040:rp2040:generic', 'rp2040:rp2040:rpipicow', 'arduino:mbed_rp2040:pico', - 'SiliconLabs:silabs:nano_matter' + 'SiliconLabs:silabs:nano_matter', + 'WCH:ch32v:CH32V30x_EVT' ] env: @@ -416,6 +417,12 @@ jobs: # arduino-cli board attach -b $BOARD ; cd $GITHUB_WORKSPACE ; fi + if [[ "$BOARD" =~ "WCH:ch32v:" ]]; then + arduino --pref "boardsmanager.additional.urls=https://github.com/openwch/board_manager_files/raw/main/package_ch32v_index.json" --save-prefs ; + arduino --install-boards WCH:ch32v:1.0.4 ; + arduino --board $BOARD --save-prefs ; + cd $GITHUB_WORKSPACE ; + fi - name: Run script run: | @@ -504,3 +511,6 @@ jobs: if [[ "$BOARD" =~ "SiliconLabs:silabs:" ]]; then arduino-cli compile -v -b "$BOARD" $PWD/software/firmware/source/SoftRF ; fi ; + #if [[ "$BOARD" =~ "WCH:ch32v:" ]]; then + # arduino --verify --verbose-build --board $BOARD $PWD/software/firmware/source/SoftRF/SoftRF.ino ; + #fi ; diff --git a/software/firmware/source/SoftRF/Makefile b/software/firmware/source/SoftRF/Makefile index 7cdf9ddd7..c4e0ac573 100644 --- a/software/firmware/source/SoftRF/Makefile +++ b/software/firmware/source/SoftRF/Makefile @@ -141,7 +141,8 @@ PLAT_CPPS := $(PLATFORM_PATH)/ESP8266.cpp \ $(PLATFORM_PATH)/ASR66.cpp \ $(PLATFORM_PATH)/RP2040.cpp \ $(PLATFORM_PATH)/RA4M1.cpp \ - $(PLATFORM_PATH)/EFR32.cpp + $(PLATFORM_PATH)/EFR32.cpp \ + $(PLATFORM_PATH)/CH32.cpp DRV_CPPS := $(DRIVER_PATH)/RF.cpp \ $(DRIVER_PATH)/radio/nordic.cpp \ diff --git a/software/firmware/source/SoftRF/src/platform/CH32.cpp b/software/firmware/source/SoftRF/src/platform/CH32.cpp new file mode 100644 index 000000000..089060984 --- /dev/null +++ b/software/firmware/source/SoftRF/src/platform/CH32.cpp @@ -0,0 +1,592 @@ +/* + * Platform_CH32.cpp + * Copyright (C) 2024 Linar Yusupov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#if defined(ARDUINO_ARCH_CH32) + +#include +#include + +#include "../system/SoC.h" +#include "../driver/RF.h" +#include "../driver/EEPROM.h" +#include "../driver/LED.h" +#include "../driver/OLED.h" +#include "../driver/Baro.h" +#include "../driver/Sound.h" +#include "../driver/Battery.h" +#include "../protocol/data/NMEA.h" +#include "../protocol/data/GDL90.h" +#include "../protocol/data/D1090.h" + +// SX127x pin mapping +lmic_pinmap lmic_pins = { + .nss = SOC_GPIO_PIN_SS, + .txe = LMIC_UNUSED_PIN, + .rxe = LMIC_UNUSED_PIN, + .rst = SOC_GPIO_PIN_RST, + .dio = {LMIC_UNUSED_PIN, LMIC_UNUSED_PIN, LMIC_UNUSED_PIN}, + .busy = LMIC_UNUSED_PIN, + .tcxo = LMIC_UNUSED_PIN, +}; + +#if !defined(EXCLUDE_LED_RING) +// Parameter 1 = number of pixels in strip +// Parameter 2 = Arduino pin number (most are valid) +// Parameter 3 = pixel type flags, add together as needed: +// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) +// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) +// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) +// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) +Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIX_NUM, SOC_GPIO_PIN_LED, + NEO_GRB + NEO_KHZ800); +#endif /* EXCLUDE_LED_RING */ + +#if defined(EXCLUDE_WIFI) +char UDPpacketBuffer[4]; // Dummy definition to satisfy build sequence +#endif /* EXCLUDE_WIFI */ + +static struct rst_info reset_info = { + .reason = REASON_DEFAULT_RST, +}; + +static uint32_t bootCount __attribute__ ((section (".noinit"))); +static bool wdt_is_active = false; + +#if defined(EXCLUDE_EEPROM) +eeprom_t eeprom_block; +settings_t *settings = &eeprom_block.field.settings; +#endif /* EXCLUDE_EEPROM */ + +static void CH32_setup() +{ +#if SOC_GPIO_RADIO_LED_TX != SOC_UNUSED_PIN + pinMode(SOC_GPIO_RADIO_LED_TX, OUTPUT); + digitalWrite(SOC_GPIO_RADIO_LED_TX, ! LED_STATE_ON); +#endif /* SOC_GPIO_RADIO_LED_TX */ +#if SOC_GPIO_RADIO_LED_RX != SOC_UNUSED_PIN + pinMode(SOC_GPIO_RADIO_LED_RX, OUTPUT); + digitalWrite(SOC_GPIO_RADIO_LED_RX, ! LED_STATE_ON); +#endif /* SOC_GPIO_RADIO_LED_RX */ + + Serial.begin(SERIAL_OUT_BR, SERIAL_OUT_BITS); +} + +static void CH32_post_init() +{ + { + Serial.println(); + Serial.println(F("SoftRF Academy Edition Power-on Self Test")); + Serial.println(); + Serial.flush(); + + Serial.println(F("Built-in components:")); + + Serial.print(F("RADIO : ")); + Serial.println(hw_info.rf == RF_IC_SX1276 ? F("PASS") : F("FAIL")); + Serial.print(F("GNSS : ")); + Serial.println(hw_info.gnss != GNSS_MODULE_NONE ? F("PASS") : F("FAIL")); + + Serial.println(); + Serial.println(F("External components:")); + Serial.print(F("BARO : ")); + Serial.println(hw_info.baro != BARO_MODULE_NONE ? F("PASS") : F("N/A")); + Serial.print(F("DISPLAY : ")); + Serial.println(hw_info.display != DISPLAY_NONE ? F("PASS") : F("N/A")); + + Serial.println(); + Serial.println(F("Power-on Self Test is complete.")); + Serial.println(); + Serial.flush(); + } + + Serial.println(F("Data output device(s):")); + + Serial.print(F("NMEA - ")); + switch (settings->nmea_out) + { + case NMEA_UART : Serial.println(F("UART")); break; + case NMEA_USB : Serial.println(F("USB CDC")); break; + case NMEA_OFF : + default : Serial.println(F("NULL")); break; + } + + Serial.print(F("GDL90 - ")); + switch (settings->gdl90) + { + case GDL90_UART : Serial.println(F("UART")); break; + case GDL90_USB : Serial.println(F("USB CDC")); break; + case GDL90_OFF : + default : Serial.println(F("NULL")); break; + } + + Serial.print(F("D1090 - ")); + switch (settings->d1090) + { + case D1090_UART : Serial.println(F("UART")); break; + case D1090_USB : Serial.println(F("USB CDC")); break; + case D1090_OFF : + default : Serial.println(F("NULL")); break; + } + + Serial.println(); + Serial.flush(); + +#if defined(USE_OLED) + OLED_info1(); +#endif /* USE_OLED */ +} + +static uint32_t prev_tx_packets_counter = 0; +static uint32_t prev_rx_packets_counter = 0; +static unsigned long tx_led_time_marker = 0; +static unsigned long rx_led_time_marker = 0; + +#define LED_BLINK_TIME 100 + +static void CH32_loop() +{ +#if SOC_GPIO_RADIO_LED_TX != SOC_UNUSED_PIN + if (digitalRead(SOC_GPIO_RADIO_LED_TX) != LED_STATE_ON) { + if (tx_packets_counter != prev_tx_packets_counter) { + digitalWrite(SOC_GPIO_RADIO_LED_TX, LED_STATE_ON); + prev_tx_packets_counter = tx_packets_counter; + tx_led_time_marker = millis(); + } + } else { + if (millis() - tx_led_time_marker > LED_BLINK_TIME) { + digitalWrite(SOC_GPIO_RADIO_LED_TX, ! LED_STATE_ON); + prev_tx_packets_counter = tx_packets_counter; + } + } +#endif /* SOC_GPIO_RADIO_LED_TX */ + +#if SOC_GPIO_RADIO_LED_RX != SOC_UNUSED_PIN + if (digitalRead(SOC_GPIO_RADIO_LED_RX) != LED_STATE_ON) { + if (rx_packets_counter != prev_rx_packets_counter) { + digitalWrite(SOC_GPIO_RADIO_LED_RX, LED_STATE_ON); + prev_rx_packets_counter = rx_packets_counter; + rx_led_time_marker = millis(); + } + } else { + if (millis() - rx_led_time_marker > LED_BLINK_TIME) { + digitalWrite(SOC_GPIO_RADIO_LED_RX, ! LED_STATE_ON); + prev_rx_packets_counter = rx_packets_counter; + } + } +#endif /* SOC_GPIO_RADIO_LED_RX */ +} + +static void CH32_fini(int reason) +{ + NVIC_SystemReset(); /* TODO */ +} + +static void CH32_reset() +{ + NVIC_SystemReset(); +} + +static uint32_t CH32_getChipId() +{ +#if !defined(SOFTRF_ADDRESS) + uint32_t id = DBGMCU_GetCHIPID(); /* TBD */ + + return DevID_Mapper(id); +#else + return (SOFTRF_ADDRESS & 0xFFFFFFFFU ); +#endif +} + +static void* CH32_getResetInfoPtr() +{ + return (void *) &reset_info; +} + +static String CH32_getResetInfo() +{ + switch (reset_info.reason) + { + default : return F("No reset information available"); + } +} + +static String CH32_getResetReason() +{ + switch (reset_info.reason) + { + case REASON_DEFAULT_RST : return F("DEFAULT"); + case REASON_WDT_RST : return F("WDT"); + case REASON_EXCEPTION_RST : return F("EXCEPTION"); + case REASON_SOFT_WDT_RST : return F("SOFT_WDT"); + case REASON_SOFT_RESTART : return F("SOFT_RESTART"); + case REASON_DEEP_SLEEP_AWAKE : return F("DEEP_SLEEP_AWAKE"); + case REASON_EXT_SYS_RST : return F("EXT_SYS"); + default : return F("NO_MEAN"); + } +} + +extern "C" void * _sbrk (int); + +static uint32_t CH32_getFreeHeap() +{ + char top; + return &top - reinterpret_cast(_sbrk(0)); +} + +static long CH32_random(long howsmall, long howBig) +{ + if(howsmall >= howBig) { + return howsmall; + } + long diff = howBig - howsmall; + + return random(diff) + howsmall; +} + +static void CH32_Sound_test(int var) +{ + if (SOC_GPIO_PIN_BUZZER != SOC_UNUSED_PIN && settings->volume != BUZZER_OFF) { + tone(SOC_GPIO_PIN_BUZZER, 440, 500); delay(500); + tone(SOC_GPIO_PIN_BUZZER, 640, 500); delay(500); + tone(SOC_GPIO_PIN_BUZZER, 840, 500); delay(500); + tone(SOC_GPIO_PIN_BUZZER, 1040, 500); delay(600); + } +} + +static void CH32_Sound_tone(int hz, uint8_t volume) +{ + if (SOC_GPIO_PIN_BUZZER != SOC_UNUSED_PIN && volume != BUZZER_OFF) { + if (hz > 0) { + tone(SOC_GPIO_PIN_BUZZER, hz, ALARM_TONE_MS); + } else { + noTone(SOC_GPIO_PIN_BUZZER); + } + } +} + +static void CH32_WiFi_set_param(int ndx, int value) +{ + /* NONE */ +} + +static void CH32_WiFi_transmit_UDP(int port, byte *buf, size_t size) +{ + /* NONE */ +} + +static bool CH32_EEPROM_begin(size_t size) +{ + return true; +} + +static void CH32_EEPROM_extension(int cmd) +{ + if (cmd == EEPROM_EXT_LOAD) { + if (settings->mode != SOFTRF_MODE_NORMAL +#if !defined(EXCLUDE_TEST_MODE) + && + settings->mode != SOFTRF_MODE_TXRX_TEST +#endif /* EXCLUDE_TEST_MODE */ + ) { + settings->mode = SOFTRF_MODE_NORMAL; + } + + if (settings->nmea_out == NMEA_BLUETOOTH || + settings->nmea_out == NMEA_UDP || + settings->nmea_out == NMEA_TCP ) { + settings->nmea_out = NMEA_UART; + } + if (settings->gdl90 == GDL90_BLUETOOTH || + settings->gdl90 == GDL90_UDP) { + settings->gdl90 = GDL90_UART; + } + if (settings->d1090 == D1090_BLUETOOTH || + settings->d1090 == D1090_UDP) { + settings->d1090 = D1090_UART; + } + + /* AUTO and UK RF bands are deprecated since Release v1.3 */ + if (settings->band == RF_BAND_AUTO || settings->band == RF_BAND_UK) { + settings->band = RF_BAND_EU; + } + } +} + +static void CH32_SPI_begin() +{ + SPI.begin(); +} + +static void CH32_swSer_begin(unsigned long baud) +{ + Serial_GNSS_In.begin(baud); +} + +static void CH32_swSer_enableRx(boolean arg) +{ + /* NONE */ +} + +static byte CH32_Display_setup() +{ + byte rval = DISPLAY_NONE; + +#if defined(USE_OLED) + rval = OLED_setup(); +#endif /* USE_OLED */ + + return rval; +} + +static void CH32_Display_loop() +{ +#if defined(USE_OLED) + OLED_loop(); +#endif /* USE_OLED */ +} + +static void CH32_Display_fini(int reason) +{ +#if defined(USE_OLED) + OLED_fini(reason); +#endif /* USE_OLED */ +} + +static void CH32_Battery_setup() +{ + +} + +static float CH32_Battery_param(uint8_t param) +{ + float rval, voltage; + + switch (param) + { + case BATTERY_PARAM_THRESHOLD: + rval = hw_info.model == SOFTRF_MODEL_ACADEMY ? BATTERY_THRESHOLD_LIPO : + BATTERY_THRESHOLD_NIMHX2; + break; + + case BATTERY_PARAM_CUTOFF: + rval = hw_info.model == SOFTRF_MODEL_ACADEMY ? BATTERY_CUTOFF_LIPO : + BATTERY_CUTOFF_NIMHX2; + break; + + case BATTERY_PARAM_CHARGE: + voltage = Battery_voltage(); + if (voltage < Battery_cutoff()) + return 0; + + if (voltage > 4.2) + return 100; + + if (voltage < 3.6) { + voltage -= 3.3; + return (voltage * 100) / 3; + } + + voltage -= 3.6; + rval = 10 + (voltage * 150 ); + break; + + case BATTERY_PARAM_VOLTAGE: + default: + + { + uint16_t mV = 0; +#if SOC_GPIO_PIN_BATTERY != SOC_UNUSED_PIN + mV = analogRead(SOC_GPIO_PIN_BATTERY); +#endif + rval = mV * SOC_ADC_VOLTAGE_DIV / 1000.0; + } + break; + } + + return rval; +} + +void CH32_GNSS_PPS_Interrupt_handler() { + PPS_TimeMarker = millis(); +} + +static unsigned long CH32_get_PPS_TimeMarker() { + return PPS_TimeMarker; +} + +static bool CH32_Baro_setup() { + return true; +} + +static void CH32_UATSerial_begin(unsigned long baud) +{ + +} + +static void CH32_UATModule_restart() +{ + +} + +static void CH32_WDT_setup() +{ + /* TBD */ +} + +static void CH32_WDT_fini() +{ + /* TBD */ +} + +#if SOC_GPIO_PIN_BUTTON != SOC_UNUSED_PIN +#include +using namespace ace_button; + +AceButton button_1(SOC_GPIO_PIN_BUTTON); + +// The event handler for the button. +void handleEvent(AceButton* button, uint8_t eventType, + uint8_t buttonState) { + + switch (eventType) { + case AceButton::kEventClicked: + case AceButton::kEventReleased: +#if defined(USE_OLED) + if (button == &button_1) { + OLED_Next_Page(); + } +#endif + break; + case AceButton::kEventDoubleClicked: + break; + case AceButton::kEventLongPressed: + if (button == &button_1) { + shutdown(SOFTRF_SHUTDOWN_BUTTON); +// Serial.println(F("This will never be printed.")); + } + break; + } +} + +/* Callbacks for push button interrupt */ +void onPageButtonEvent() { + button_1.check(); +} +#endif /* SOC_GPIO_PIN_BUTTON != SOC_UNUSED_PIN */ + +static void CH32_Button_setup() +{ +#if SOC_GPIO_PIN_BUTTON != SOC_UNUSED_PIN + if (hw_info.model == SOFTRF_MODEL_ACADEMY) { + int button_pin = SOC_GPIO_PIN_BUTTON; + + // Button(s) uses external pull up resistor. + pinMode(button_pin, INPUT); + + button_1.init(button_pin); + + // Configure the ButtonConfig with the event handler, and enable all higher + // level events. + ButtonConfig* PageButtonConfig = button_1.getButtonConfig(); + PageButtonConfig->setEventHandler(handleEvent); + PageButtonConfig->setFeature(ButtonConfig::kFeatureClick); +// PageButtonConfig->setFeature(ButtonConfig::kFeatureDoubleClick); + PageButtonConfig->setFeature(ButtonConfig::kFeatureLongPress); + PageButtonConfig->setFeature(ButtonConfig::kFeatureSuppressAfterClick); +// PageButtonConfig->setFeature(ButtonConfig::kFeatureSuppressAfterDoubleClick); +// PageButtonConfig->setFeature( +// ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); +// PageButtonConfig->setDebounceDelay(15); + PageButtonConfig->setClickDelay(600); +// PageButtonConfig->setDoubleClickDelay(1500); + PageButtonConfig->setLongPressDelay(2000); + +// attachInterrupt(digitalPinToInterrupt(button_pin), onPageButtonEvent, CHANGE ); + } +#endif /* SOC_GPIO_PIN_BUTTON != SOC_UNUSED_PIN */ +} + +static void CH32_Button_loop() +{ +#if SOC_GPIO_PIN_BUTTON != SOC_UNUSED_PIN + if (hw_info.model == SOFTRF_MODEL_ACADEMY) { + button_1.check(); + } +#endif /* SOC_GPIO_PIN_BUTTON != SOC_UNUSED_PIN */ +} + +static void CH32_Button_fini() +{ +#if SOC_GPIO_PIN_BUTTON != SOC_UNUSED_PIN + if (hw_info.model == SOFTRF_MODEL_ACADEMY) { +// detachInterrupt(digitalPinToInterrupt(SOC_GPIO_PIN_BUTTON)); + while (digitalRead(SOC_GPIO_PIN_BUTTON) == LOW); + pinMode(SOC_GPIO_PIN_BUTTON, ANALOG); + } +#endif /* SOC_GPIO_PIN_BUTTON != SOC_UNUSED_PIN */ +} + +const SoC_ops_t CH32_ops = { + SOC_CH32, + "CH32", + CH32_setup, + CH32_post_init, + CH32_loop, + CH32_fini, + CH32_reset, + CH32_getChipId, + CH32_getResetInfoPtr, + CH32_getResetInfo, + CH32_getResetReason, + CH32_getFreeHeap, + CH32_random, + CH32_Sound_test, + CH32_Sound_tone, + NULL, + CH32_WiFi_set_param, + CH32_WiFi_transmit_UDP, + NULL, + NULL, + NULL, + CH32_EEPROM_begin, + CH32_EEPROM_extension, + CH32_SPI_begin, + CH32_swSer_begin, + CH32_swSer_enableRx, + NULL, /* TODO */ + NULL, + NULL, + CH32_Display_setup, + CH32_Display_loop, + CH32_Display_fini, + CH32_Battery_setup, + CH32_Battery_param, + CH32_GNSS_PPS_Interrupt_handler, + CH32_get_PPS_TimeMarker, + CH32_Baro_setup, + CH32_UATSerial_begin, + CH32_UATModule_restart, + CH32_WDT_setup, + CH32_WDT_fini, + CH32_Button_setup, + CH32_Button_loop, + CH32_Button_fini, + NULL +}; + +#endif /* ARDUINO_ARCH_CH32 */ diff --git a/software/firmware/source/SoftRF/src/platform/CH32.h b/software/firmware/source/SoftRF/src/platform/CH32.h new file mode 100644 index 000000000..cc3144141 --- /dev/null +++ b/software/firmware/source/SoftRF/src/platform/CH32.h @@ -0,0 +1,175 @@ +/* + * Platform_CH32.h + * Copyright (C) 2024 Linar Yusupov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#if defined(ARDUINO_ARCH_CH32) + +#ifndef PLATFORM_CH32_H +#define PLATFORM_CH32_H + +#include + +/* Maximum of tracked flying objects is now SoC-specific constant */ +#define MAX_TRACKING_OBJECTS 8 + +#define DEFAULT_SOFTRF_MODEL SOFTRF_MODEL_ACADEMY + +#define isValidFix() isValidGNSSFix() + +#define uni_begin() strip.begin() +#define uni_show() strip.show() +#define uni_setPixelColor(i, c) strip.setPixelColor(i, c) +#define uni_numPixels() strip.numPixels() +#define uni_Color(r,g,b) strip.Color(r,g,b) +#define color_t uint32_t + +#define EEPROM_commit() {} + +#define LED_STATE_ON LOW // State when LED is litted + +#define SerialOutput Serial /* TBD */ + +#define USBSerial Serial /* TBD */ +#define Serial_GNSS_In Serial /* TBD */ +#define Serial_GNSS_Out Serial_GNSS_In +#define UATSerial Serial /* TBD */ + +#define SOC_ADC_VOLTAGE_DIV 2 /* TBD */ + +#ifndef strnlen +#define strnlen(x,y) strlen(x) /* TBD */ +#endif + +enum rst_reason { + REASON_DEFAULT_RST = 0, /* normal startup by power on */ + REASON_WDT_RST = 1, /* hardware watch dog reset */ + REASON_EXCEPTION_RST = 2, /* exception reset, GPIO status won't change */ + REASON_SOFT_WDT_RST = 3, /* software watch dog reset, GPIO status won't change */ + REASON_SOFT_RESTART = 4, /* software restart ,system_restart , GPIO status won't change */ + REASON_DEEP_SLEEP_AWAKE = 5, /* wake up from deep-sleep */ + REASON_EXT_SYS_RST = 6 /* external system reset */ +}; + +struct rst_info { + uint32_t reason; + uint32_t exccause; + uint32_t epc1; + uint32_t epc2; + uint32_t epc3; + uint32_t excvaddr; + uint32_t depc; +}; + +#if defined(CH32V30x) + +/* Peripherals */ +#define SOC_GPIO_PIN_CONS_RX PIN_SERIAL_RX // TBD +#define SOC_GPIO_PIN_CONS_TX PIN_SERIAL_TX // TBD + +#define SOC_GPIO_PIN_GNSS_RX PIN_SERIAL1_RX // TBD +#define SOC_GPIO_PIN_GNSS_TX PIN_SERIAL1_TX // TBD + +#define SOC_GPIO_PIN_STATUS LED_BUILTIN // TBD +#define SOC_GPIO_PIN_BUZZER SOC_UNUSED_PIN + +#define SOC_GPIO_PIN_RX3 SOC_UNUSED_PIN +#define SOC_GPIO_PIN_TX3 SOC_UNUSED_PIN + +/* SPI */ +#define SOC_GPIO_PIN_MOSI PIN_SPI_MOSI // TBD +#define SOC_GPIO_PIN_MISO PIN_SPI_MISO // TBD +#define SOC_GPIO_PIN_SCK PIN_SPI_SCK // TBD +#define SOC_GPIO_PIN_SS SOC_UNUSED_PIN // TBD + +/* NRF905 */ +#define SOC_GPIO_PIN_TXE SOC_UNUSED_PIN +#define SOC_GPIO_PIN_CE SOC_UNUSED_PIN +#define SOC_GPIO_PIN_PWR SOC_UNUSED_PIN + +/* SX1276 */ +#define SOC_GPIO_PIN_RST SOC_UNUSED_PIN // TBD +#define SOC_GPIO_PIN_BUSY SOC_UNUSED_PIN +#define SOC_GPIO_PIN_DIO1 SOC_UNUSED_PIN // TBD + +/* RF antenna switch */ +#define SOC_GPIO_PIN_ANT_RXTX SOC_UNUSED_PIN + +/* I2C */ +#define SOC_GPIO_PIN_SDA PIN_WIRE_SDA // TBD +#define SOC_GPIO_PIN_SCL PIN_WIRE_SCL // TBD + +#define SOC_GPIO_PIN_LED SOC_UNUSED_PIN +#define SOC_GPIO_PIN_GNSS_PPS SOC_UNUSED_PIN /* TBD */ +#define SOC_GPIO_PIN_BATTERY SOC_UNUSED_PIN /* TBD */ +#define SOC_GPIO_PIN_BUTTON SOC_UNUSED_PIN + +#define SOC_GPIO_RADIO_LED_RX SOC_UNUSED_PIN +#define SOC_GPIO_RADIO_LED_TX SOC_UNUSED_PIN + +#else +#error "This CH32 build variant is not supported!" +#endif + +//#define EXCLUDE_EEPROM +#define EXCLUDE_WIFI +#define EXCLUDE_CC13XX +#define EXCLUDE_TEST_MODE +#define EXCLUDE_WATCHOUT_MODE +//#define EXCLUDE_TRAFFIC_FILTER_EXTENSION +//#define EXCLUDE_LK8EX1 + +#define EXCLUDE_GNSS_UBLOX +#define EXCLUDE_GNSS_SONY +//#define EXCLUDE_GNSS_MTK +#define EXCLUDE_GNSS_GOKE +#define EXCLUDE_GNSS_AT65 +#define EXCLUDE_GNSS_UC65 +//#define EXCLUDE_LOG_GNSS_VERSION + +/* Component Cost */ +/* -------------------------------------- */ +#define USE_NMEA_CFG // + kb +#define EXCLUDE_BMP180 // - kb +//#define EXCLUDE_BMP280 // - kb +#define EXCLUDE_BME680 // - kb +#define EXCLUDE_MPL3115A2 // - kb +#define EXCLUDE_NRF905 // - kb +#define EXCLUDE_UATM // - kb +#define EXCLUDE_MAVLINK // - kb +//#define EXCLUDE_EGM96 // - kb +#define EXCLUDE_LED_RING // - kb +#define EXCLUDE_SOUND + +#define USE_OLED // kb +#define EXCLUDE_OLED_049 +//#define EXCLUDE_OLED_BARO_PAGE + +#define USE_TIME_SLOTS +#define USE_OGN_ENCRYPTION + +#if !defined(EXCLUDE_LED_RING) +#include + +extern Adafruit_NeoPixel strip; +#endif /* EXCLUDE_LED_RING */ + +#if defined(USE_OLED) +#define U8X8_OLED_I2C_BUS_TYPE U8X8_SSD1306_128X64_NONAME_HW_I2C +#endif /* USE_OLED */ + +#endif /* PLATFORM_CH32_H */ + +#endif /* ARDUINO_ARCH_CH32 */ diff --git a/software/firmware/source/SoftRF/src/system/SoC.cpp b/software/firmware/source/SoftRF/src/system/SoC.cpp index 0908dfab7..44fa140fc 100644 --- a/software/firmware/source/SoftRF/src/system/SoC.cpp +++ b/software/firmware/source/SoftRF/src/system/SoC.cpp @@ -50,6 +50,8 @@ byte SoC_setup() SoC = &RA4M1_ops; #elif defined(ARDUINO_ARCH_SILABS) SoC = &EFR32_ops; +#elif defined(ARDUINO_ARCH_CH32) + SoC = &CH32_ops; #else #error "This hardware platform is not supported!" #endif diff --git a/software/firmware/source/SoftRF/src/system/SoC.h b/software/firmware/source/SoftRF/src/system/SoC.h index ebf1a9f03..15c940b5e 100644 --- a/software/firmware/source/SoftRF/src/system/SoC.h +++ b/software/firmware/source/SoftRF/src/system/SoC.h @@ -36,6 +36,7 @@ #include "../platform/RP2040.h" #include "../platform/RA4M1.h" #include "../platform/EFR32.h" +#include "../platform/CH32.h" typedef struct SoC_ops_struct { uint8_t id; @@ -112,7 +113,8 @@ enum SOC_ASR66, SOC_RP2040, SOC_RA4M1, - SOC_EFR32 + SOC_EFR32, + SOC_CH32 }; extern const SoC_ops_t *SoC; @@ -158,6 +160,9 @@ extern const SoC_ops_t RA4M1_ops; #if defined(ARDUINO_ARCH_SILABS) extern const SoC_ops_t EFR32_ops; #endif +#if defined(ARDUINO_ARCH_CH32) +extern const SoC_ops_t CH32_ops; +#endif byte SoC_setup(void); void SoC_fini(int); diff --git a/software/firmware/source/libraries/Adafruit_BMP280_Library/Adafruit_BMP280.h b/software/firmware/source/libraries/Adafruit_BMP280_Library/Adafruit_BMP280.h index be9e06873..40f1ed9e3 100644 --- a/software/firmware/source/libraries/Adafruit_BMP280_Library/Adafruit_BMP280.h +++ b/software/firmware/source/libraries/Adafruit_BMP280_Library/Adafruit_BMP280.h @@ -29,7 +29,8 @@ defined(ARDUINO_ARCH_NRF52) || defined(ARDUINO_ARCH_NRF52840) || \ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_AVR) || \ defined(ARDUINO_ARCH_RP2040) || defined(HACKRF_ONE) || \ - defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_ARCH_SILABS)) + defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_ARCH_SILABS) || \ + defined(ARDUINO_ARCH_CH32)) #include #endif diff --git a/software/firmware/source/libraries/nRF905/nRF905.cpp b/software/firmware/source/libraries/nRF905/nRF905.cpp index f7c9529a2..ae788fff9 100644 --- a/software/firmware/source/libraries/nRF905/nRF905.cpp +++ b/software/firmware/source/libraries/nRF905/nRF905.cpp @@ -14,7 +14,7 @@ !defined(HACKRF_ONE) && !defined(ARDUINO_ARCH_SAMD) && \ !defined(ARDUINO_ARCH_ASR650X) && !defined(ARDUINO_ARCH_ASR6601) && \ !defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_RENESAS) && \ - !defined(ARDUINO_ARCH_SILABS) + !defined(ARDUINO_ARCH_SILABS) && !defined(ARDUINO_ARCH_CH32) #include #include @@ -30,6 +30,7 @@ defined(ARDUINO_ARCH_NRF52) || defined(ARDUINO_ARCH_NRF52840) || \ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040) || \ defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_ARCH_SILABS) || \ + defined(ARDUINO_ARCH_CH32) || \ (defined(ARDUINO_ARCH_STM32) && defined(ARDUINO_WisDuo_RAK3172_Evaluation_Board)) #define _BV(bit) (1 << (bit)) #endif /* ENERGIA_ARCH_CC13XX || ENERGIA_ARCH_CC13X2 || ARDUINO_ARCH_NRF52 */ diff --git a/software/firmware/source/libraries/nRF905/nRF905_config.h b/software/firmware/source/libraries/nRF905/nRF905_config.h index 5138ae180..77aeae032 100644 --- a/software/firmware/source/libraries/nRF905/nRF905_config.h +++ b/software/firmware/source/libraries/nRF905/nRF905_config.h @@ -28,7 +28,8 @@ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_AVR) || \ defined(ARDUINO_ARCH_ASR650X) || defined(ARDUINO_ARCH_ASR6601) || \ defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RENESAS) || \ - defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_NRF52840) + defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_CH32) || \ + defined(ARDUINO_ARCH_NRF52840) #define NRF905_INTERRUPTS 0 #else #define NRF905_INTERRUPTS 1 @@ -56,7 +57,8 @@ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_AVR) || \ defined(ARDUINO_ARCH_ASR650X) || defined(ARDUINO_ARCH_ASR6601) || \ defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RENESAS) || \ - defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_NRF52840) + defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_CH32) || \ + defined(ARDUINO_ARCH_NRF52840) #define NRF905_AM_SW 1 #else #define NRF905_AM_SW 0 @@ -74,7 +76,8 @@ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_AVR) || \ defined(ARDUINO_ARCH_ASR650X) || defined(ARDUINO_ARCH_ASR6601) || \ defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RENESAS) || \ - defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_NRF52840) + defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_CH32) || \ + defined(ARDUINO_ARCH_NRF52840) #define NRF905_COLLISION_AVOID 0 #else #define NRF905_COLLISION_AVOID 1 @@ -200,7 +203,8 @@ #define CD 0 // Carrier detect pin (for collision avoidance, if enabled) #elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RP2040) || \ - defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_ARCH_SILABS) + defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_ARCH_SILABS) || \ + defined(ARDUINO_ARCH_CH32) // TBD #define TRX_EN 0 // Enable/standby pin @@ -342,7 +346,8 @@ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_AVR) || \ defined(ARDUINO_ARCH_ASR650X) || defined(ARDUINO_ARCH_ASR6601) || \ defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RENESAS) || \ - defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_NRF52840) + defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_CH32) || \ + defined(ARDUINO_ARCH_NRF52840) #define NRF905_FREQ 868400000UL #else #define NRF905_FREQ 433200000UL @@ -358,7 +363,8 @@ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_AVR) || \ defined(ARDUINO_ARCH_ASR650X) || defined(ARDUINO_ARCH_ASR6601) || \ defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RENESAS) || \ - defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_NRF52840) + defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_CH32) || \ + defined(ARDUINO_ARCH_NRF52840) #define NRF905_BAND NRF905_BAND_868 #else #define NRF905_BAND NRF905_BAND_433 @@ -408,7 +414,8 @@ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_AVR) || \ defined(ARDUINO_ARCH_ASR650X) || defined(ARDUINO_ARCH_ASR6601) || \ defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RENESAS) || \ - defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_NRF52840) + defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_CH32) || \ + defined(ARDUINO_ARCH_NRF52840) #define NRF905_ADDR_SIZE NRF905_ADDR_SIZE_3 //#define NRF905_ADDR_SIZE NRF905_ADDR_SIZE_2 #else @@ -422,7 +429,8 @@ defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_AVR) || \ defined(ARDUINO_ARCH_ASR650X) || defined(ARDUINO_ARCH_ASR6601) || \ defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RENESAS) || \ - defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_NRF52840) + defined(ARDUINO_ARCH_SILABS) || defined(ARDUINO_ARCH_CH32) || \ + defined(ARDUINO_ARCH_NRF52840) #define NRF905_PAYLOAD_SIZE 24 #else #define NRF905_PAYLOAD_SIZE 32 //NRF905_MAX_PAYLOAD