diff --git a/src/index.html b/src/index.html
index 34db84a..c0283a3 100644
--- a/src/index.html
+++ b/src/index.html
@@ -70,13 +70,13 @@
@@ -238,11 +249,11 @@
diff --git a/src/js/configure.js b/src/js/configure.js
index c8d6f26..09af949 100644
--- a/src/js/configure.js
+++ b/src/js/configure.js
@@ -185,7 +185,8 @@ export class Configure {
)
}
- static download = async (deviceType, radioType, config, firmwareUrl, options) => {
+ static download = async (deviceType, rxAsTxType, radioType, config, firmwareUrl, options) => {
+ if (rxAsTxType !== undefined) firmwareUrl = firmwareUrl.replace('_RX', '_TX')
if (config.platform === 'stm32') {
const entry = await this.#fetch_file(firmwareUrl, 0, (bin) => this.#configureSTM32(bin, deviceType, radioType, options))
return [entry]
@@ -201,14 +202,15 @@ export class Configure {
// get layout from version specific folder OR fall back to global folder
const hardwareLayoutFile = await this.#fetch_file(`${folder}/hardware/${deviceType}/${config.layout_file}`, 0)
.catch(() => this.#fetch_file(`firmware/hardware/${deviceType}/${config.layout_file}`, 0))
- if (config.overlay === undefined) {
- hardwareLayoutData = hardwareLayoutFile.data
- } else {
- hardwareLayoutData = this.#bstrToUi8(JSON.stringify({
- ...JSON.parse(this.#ui8ToBstr(hardwareLayoutFile.data)),
+ let layout = JSON.parse(this.#ui8ToBstr(hardwareLayoutFile.data))
+ if (config.overlay !== undefined) {
+ layout = {
+ ...layout,
...config.overlay
- }))
+ }
}
+ if (rxAsTxType === 'external') layout['serial_rx'] = layout['serial_tx']
+ hardwareLayoutData = this.#bstrToUi8(JSON.stringify(layout))
}
if (config.platform.startsWith('esp32')) {
diff --git a/src/js/index.js b/src/js/index.js
index 979e03e..ed7cc93 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -35,6 +35,7 @@ let binary = null
let term = null
let stlink = null
let uploadURL = null
+let expertMode = false
document.addEventListener('DOMContentLoaded', initialise, false)
@@ -238,6 +239,8 @@ const compareSemanticVersionsRC = (a, b) => {
}
async function initialise () {
+ expertMode = new URLSearchParams(location.search).has("expert")
+ console.log("Expert mode: %s", expertMode)
checkProxy()
setInterval(() => { checkProxy() }, 30000)
term = new Terminal()
@@ -396,6 +399,8 @@ typeSelect.onchange = () => {
models.push(hardware[v][t][m].product_name)
}
}
+ if (t.startsWith('rx_')) setDisplay('.rx-as-tx', expertMode)
+ else setDisplay('.rx-as-tx', false)
autocomplete(modelSelect, models, true)
}
@@ -406,6 +411,12 @@ modelSelect.onchange = () => {
if (hardware[v][t][m].product_name === modelSelect.value) {
vendorSelect.value = v
typeSelect.value = t
+ if (t.startsWith('rx_')) {
+ setDisplay('.rx-as-tx', expertMode)
+ }
+ else {
+ setDisplay('.rx-as-tx', false)
+ }
selectedModel = hardware[v][t][m]
typeSelect.disabled = false
deviceNext.disabled = false
@@ -418,6 +429,33 @@ modelSelect.onchange = () => {
modelSelect.value = ''
}
+_('rx-as-tx').onchange = (e) => {
+ if (e.target.checked) {
+ for (const v in hardware) {
+ for (const t in hardware[v]) {
+ for (const m in hardware[v][t]) {
+ if (hardware[v][t][m].product_name === modelSelect.value) {
+ if (hardware[v][t][m].platform === 'esp8285') {
+ setDisplay('.rx-as-tx-connection', false)
+ _('connection').value = 'internal'
+ } else {
+ setDisplay('.rx-as-tx-connection', true)
+ _('connection').value = 'internal'
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ setDisplay('.rx-as-tx-connection', false)
+ }
+}
+
+function adjustedType() {
+ return _('rx-as-tx').checked ? typeSelect.value.replace('rx_', 'tx_') : typeSelect.value
+}
+
deviceNext.onclick = (e) => {
e.preventDefault()
setDisplay('.tx_2400', false)
@@ -438,7 +476,7 @@ deviceNext.onclick = (e) => {
if (features) features.forEach(f => setDisplay(`.feature-${f}`))
_('fcclbt').value = 'FCC'
- setDisplay(`.${typeSelect.value}`)
+ setDisplay(`.${adjustedType()}`)
setDisplay(`.${selectedModel.platform}`)
_('uart').disabled = true
@@ -446,7 +484,13 @@ deviceNext.onclick = (e) => {
_('etx').disabled = true
_('wifi').disabled = true
_('stlink').disabled = true
- selectedModel.upload_methods.forEach((k) => { if (_(k)) _(k).disabled = false })
+ if (_('rx-as-tx').checked) {
+ _('uart').disabled = false
+ _('wifi').disabled = false
+ }
+ else {
+ selectedModel.upload_methods.forEach((k) => { if (_(k)) _(k).disabled = false })
+ }
setDisplay('#step-device', false)
setClass('#step-2', 'active')
@@ -484,7 +528,7 @@ const getSettings = async (deviceType) => {
options['wifi-password'] = _('wifi-password').value
}
}
- if (deviceType === 'RX') {
+ if (deviceType === 'RX' && !_('rx-as-tx').checked) {
options['rcvr-uart-baud'] = +_('rcvr-uart-baud').value
options['rcvr-invert-tx'] = _('rcvr-invert-tx').checked
options['lock-on-first-connection'] = _('lock-on-first-connection').checked
@@ -542,7 +586,8 @@ const connectUART = async (e) => {
})
setDisplay(connectButton, false)
- binary = await Configure.download(deviceType, radioType, config, firmwareUrl, options)
+ const txType = _('rx-as-tx').checked ? _('connection').value : undefined
+ binary = await Configure.download(deviceType, txType, radioType, config, firmwareUrl, options)
const method = methodSelect.value
@@ -580,7 +625,8 @@ const generateFirmware = async () => {
const deviceType = typeSelect.value.startsWith('tx_') ? 'TX' : 'RX'
const radioType = typeSelect.value.endsWith('_900') ? 'sx127x' : (typeSelect.value.endsWith('_2400') ? 'sx128x' : 'lr1121')
const { config, firmwareUrl, options } = await getSettings(deviceType)
- const firmwareFiles = await Configure.download(deviceType, radioType, config, firmwareUrl, options)
+ const txType = _('rx-as-tx').checked ? _('connection').value : undefined
+ const firmwareFiles = await Configure.download(deviceType, txType, radioType, config, firmwareUrl, options)
return [
firmwareFiles,
{ config, firmwareUrl, options }