diff --git a/README.md b/README.md
index f6f8b53..d25c12b 100644
--- a/README.md
+++ b/README.md
@@ -101,7 +101,7 @@ Once the node is up and running you can start to explore and customize the sourc
- User modifiable code is clearly marked in the source code.
- Supports two different LMIC libraries: MCCI LoRaWAN LMIC library and IBM LMIC framework.
- Support for many popular (LoRa) development boards.
-- Cross-platform, tested on STM32, SAMD21, ESP32, ESP8266, RP2040, MKL26Z64VFT4, ATmega32u4 and ATmega328 boards.
+- Cross-platform, tested on STM32, SAMD21, ESP32, ESP32S3, ESP8266, RP2040, MKL26Z64VFT4, ATmega32u4 and ATmega328 boards.
- Hardware dependencies are handled in separate Board Support Files (BSF).
- Built-in 'wait for serial port ready' with adjustable timeout and countdown visible on display. *Useful when using the serial monitor with boards with MCU with integrated USB support.*
- Abstraction of the serial port so code can print to `serial` without needing to know if it must print to `Serial` or `SerialUSB`.
@@ -155,6 +155,7 @@ The following LoRa development boards have onboard LoRa support. Most have onboa
| TTGO LoRa32 V2.1.6 | ESP32 | no | yes | no | yes | ttgo_lora32_v21 |
| TTGO T-Beam
*versions v0.5, v0.6 and v0.7* | ESP32 | no | yes | yes | no | ttgo_tbeam |
| TTGO T-Beam
*versions v1.0 and v1.1* | ESP32 | no | yes | no | no | ttgo_tbeam_v1 |
+| unPhone9 | ESP32S3 | no | yes | yes | yes | unphone9 |
_\*1_: DIO1 must be manually wired to GPIO6.
_\*2_: For versions 1.0, 1.1 and 1.2 DIO1 must be manually wired to GPIO5 (version 1.3 is already wired on the PCB).
@@ -574,6 +575,7 @@ default_envs =
; ttgo_lora32_v21 ; TTGO LoRa32 v2.1.6
; ttgo_t_beam ; TTGO T-Beam v0.5, v0.6, v0.7
; ttgo_t_beam_v1 ; TTGO T-Beam v1.0, v1.1
+ ; unphone9 ; unPhone9
; Development boards that require an external SPI LoRa module:
diff --git a/platformio.ini b/platformio.ini
index 3988725..14cffed 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -47,6 +47,7 @@ default_envs =
; ttgo_lora32_v21 ; TTGO LoRa32 v2.1.6
; ttgo_t_beam ; TTGO T-Beam v0.5, v0.6, v0.7
; ttgo_t_beam_v1 ; TTGO T-Beam v1.0, v1.1
+ ; unphone9 ; unPhone9
; Development boards that require an external SPI LoRa module:
@@ -879,4 +880,28 @@ build_flags =
; -D USE_DISPLAY ; Requires external I2C OLED display
-; end of file
\ No newline at end of file
+[env:unphone9]
+; unPhone with RFM95W LoRa (ESP32S3).
+; HX8357 display.
+platform =
+ https://github.com/platformio/platform-espressif32
+board = unphone9
+framework = arduino
+monitor_speed = ${common.monitor_speed}
+lib_deps =
+ ${common.lib_deps}
+ ${mcci_lmic.lib_deps}
+build_flags =
+ ${common.build_flags}
+ ${mcci_lmic.build_flags}
+ ${esp32.build_flags}
+ -D BSFILE=\"boards/bsf_unphone9.h\"
+ -D MONITOR_SPEED=${common.monitor_speed}
+ -D _GNU_SOURCE
+ -D LMIC_PRINTF_TO=Serial
+ -D USE_SERIAL
+ -D USE_LED
+ ; -D USE_DISPLAY ; HX8357 TFT LCD (not implemented yet)
+
+
+; end of file
diff --git a/src/boards/bsf_unphone9.h b/src/boards/bsf_unphone9.h
new file mode 100644
index 0000000..bf3882e
--- /dev/null
+++ b/src/boards/bsf_unphone9.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ *
+ * File: bsf_unphone9.h
+ *
+ * Function: Board Support File for unPhone9 RFM95W LoRa.
+ *
+ * Copyright: Copyright (c) 2022 Hamish Cunningham
+ *
+ * License: MIT License. See accompanying LICENSE file.
+ *
+ * Author: Hamish Cunningham
+ *
+ * Description: This is an ESP32S3 board with onboard USB (provided by the MCU).
+ * It supports automatic firmware upload and serial over USB.
+ * Onboard display via HX8357
+ *
+ * CONNECTIONS AND PIN DEFINITIONS:
+ *
+ * Indentifiers between parentheses are defined in the board's
+ * Board Support Package (BSP) which is part of the Arduino core.
+ *
+ * Leds GPIO
+ * ---- ----
+ * LED <――――――――――> 13 (LED_BUILTIN) active-low
+ *
+ * I2C [display] GPIO
+ * --- ----
+ * SDA <――――――――――> 3 (SDA)
+ * SCL <――――――――――> 4 (SCL)
+ *
+ * SPI/LoRa GPIO
+ * --- ----
+ * MOSI <――――――――――> 40 (MOSI)
+ * MISO <――――――――――> 41 (MISO)
+ * SCK <――――――――――> 39 (SCK)
+ * NSS <――――――――――> 44 (unPhone::LORA_CS)
+ * RST <――――――――――> 42 (unPhone::LORA_RESET)
+ * DIO0 <――――――――――> 10 (unPhone::LMIC_DIO0)
+ * DIO1 <――――――――――> 11 (unPhone::LMIC_DIO1)
+ *
+ * Docs: https://unphone.net
+ * https://iot.unphone.net
+ * https://gitlab.com/hamishcunningham/unphone
+ * https://gitlab.com/hamishcunningham/unPhoneLibrary
+ *
+ * Identifiers: LMIC-node
+ * board-id: unphone9_lora
+ * PlatformIO
+ * board: unphone9
+ * platform: espressif32
+ * Arduino
+ * board: ARDUINO_UNPHONE9
+ * architecture: ARDUINO_ARCH_ESP32
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#ifndef BSF_UNPHONE9_LORA_H_
+#define BSF_UNPHONE9_LORA_H_
+
+#include "LMIC-node.h"
+
+#define DEVICEID_DEFAULT "unphone9" // Default deviceid value
+
+// Wait for Serial
+// Can be useful for boards with MCU with integrated USB support.
+#define WAITFOR_SERIAL_SECONDS_DEFAULT 10 // -1 waits indefinitely
+
+// LMIC Clock Error
+// This is only needed for slower 8-bit MCUs (e.g. 8MHz ATmega328 and ATmega32u4).
+// Value is defined in parts per million (of MAX_CLOCK_ERROR).
+// #ifndef LMIC_CLOCK_ERROR_PPM
+// #define LMIC_CLOCK_ERROR_PPM 0
+// #endif
+
+// Pin mappings for LoRa tranceiver
+// Pin mapping
+const lmic_pinmap lmic_pins = {
+ .nss = 44,
+ .rxtx = LMIC_UNUSED_PIN,
+ .rst = 42,
+ .dio = { /*dio0*/ 10, /*dio1*/ 11, /*dio2*/ LMIC_UNUSED_PIN },
+#ifdef MCCI_LMIC
+ .rxtx_rx_active = 0,
+ .rssi_cal = 8, // TODO in unphone library code is 0; 8 works here though...
+ .spi_freq = 8000000 /* 8 MHz */
+#endif
+};
+
+#ifdef USE_SERIAL
+# define serial Serial
+// Serial_& serial = Serial; (creates compile errors)
+#endif
+
+#ifdef USE_LED
+ EasyLed led(LED_BUILTIN, EasyLed::ActiveLevel::Low);
+#endif
+
+#ifdef USE_DISPLAY
+ // TODO HX8357
+
+ // Create U8x8 instance for SSD1306 OLED display (no reset) using hardware I2C.
+ U8X8_SSD1306_128X64_NONAME_HW_I2C display(/*rst*/ U8X8_PIN_NONE, /*scl*/ SCL, /*sda*/ SDA);
+#endif
+
+
+bool boardInit(InitType initType)
+{
+ // This function is used to perform board specific initializations.
+ // Required as part of standard template.
+
+ // InitType::Hardware Must be called at start of setup() before anything else.
+ // InitType::PostInitSerial Must be called after initSerial() before other initializations.
+
+ bool success = true;
+ switch (initType)
+ {
+ case InitType::Hardware:
+ // Note: Serial port and display are not yet initialized and cannot be used use here.
+ // No actions required for this board.
+ break;
+
+ case InitType::PostInitSerial:
+ // Note: If enabled Serial port and display are already initialized here.
+ // No actions required for this board.
+ break;
+ }
+ return success;
+}
+
+
+#endif // BSF_UNPHONE9_LORA_H_