Skip to content

Commit b36e8f5

Browse files
authored
Add files via upload
1 parent 6b871cb commit b36e8f5

File tree

2 files changed

+553
-5
lines changed

2 files changed

+553
-5
lines changed

setup/index.html

Lines changed: 281 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,75 @@ <h3 class="card-title text-lg">Background Image</h3>
9292
</div>
9393
</div>
9494
</div>
95+
96+
<!-- Advanced Settings Collapse Panel -->
97+
<div class="collapse collapse-arrow bg-base-200 border border-base-300">
98+
<input type="checkbox" id="advancedSettingsToggle" />
99+
<div class="collapse-title text-lg font-medium">
100+
🛠️ Advanced Settings
101+
</div>
102+
<div class="collapse-content">
103+
<div class="space-y-4 pt-4">
104+
<!-- AFE Linear Gain -->
105+
<div class="card bg-base-100 border border-base-300">
106+
<div class="card-body py-4">
107+
<h4 class="card-title text-base" id="afeLinearGainTitle">AFE Linear Gain</h4>
108+
<label class="form-control">
109+
<div class="label">
110+
<span class="label-text">Linear gain value (0.1 - 3.0)</span>
111+
<span class="badge badge-primary" id="afeLinearGainValue">1.5</span>
112+
</div>
113+
<input type="range" min="1" max="30" value="15" class="range range-sm"
114+
id="afeLinearGainRange" />
115+
</label>
116+
<button class="btn btn-sm btn-outline mt-2" id="saveAfeLinearGainButton"
117+
disabled>
118+
Save AFE Linear Gain
119+
</button>
120+
</div>
121+
</div>
122+
123+
<!-- AGC Target Level -->
124+
<div class="card bg-base-100 border border-base-300">
125+
<div class="card-body py-4">
126+
<h4 class="card-title text-base" id="agcTargetLevelTitle">AGC Target Level</h4>
127+
<label class="form-control">
128+
<div class="label">
129+
<span class="label-text">Target level (dBFS, 0 - 32)</span>
130+
<span class="badge badge-primary" id="agcTargetLevelValue">1</span>
131+
</div>
132+
<input type="range" min="0" max="32" value="1" class="range range-sm"
133+
id="agcTargetLevelRange" />
134+
</label>
135+
<button class="btn btn-sm btn-outline mt-2" id="saveAgcTargetLevelButton"
136+
disabled>
137+
Save AGC Target Level
138+
</button>
139+
</div>
140+
</div>
141+
142+
<!-- AGC Compression Gain -->
143+
<div class="card bg-base-100 border border-base-300">
144+
<div class="card-body py-4">
145+
<h4 class="card-title text-base" id="agcCompressionGainTitle">AGC Compression
146+
Gain</h4>
147+
<label class="form-control">
148+
<div class="label">
149+
<span class="label-text">Compression gain (dB, 0 - 32)</span>
150+
<span class="badge badge-primary" id="agcCompressionGainValue">15</span>
151+
</div>
152+
<input type="range" min="0" max="32" value="15" class="range range-sm"
153+
id="agcCompressionGainRange" />
154+
</label>
155+
<button class="btn btn-sm btn-outline mt-2" id="saveAgcCompressionGainButton"
156+
disabled>
157+
Save AGC Compression Gain
158+
</button>
159+
</div>
160+
</div>
161+
</div>
162+
</div>
163+
</div>
95164
</div>
96165
</div>
97166
</div>
@@ -125,6 +194,9 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
125194
const SERVER_URL_ID = "cef520a9-bcb5-4fc6-87f7-82804eee2b20";
126195
const BACKGROUND_IMAGE_ID = "d1f3b2c4-5e6f-4a7b-8c9d-0e1f2a3b4c5d";
127196
const RESET_ID = "f0e1d2c3-b4a5-6789-0abc-def123456789";
197+
const AFE_LINEAR_GAIN_ID = "a1b2c3d4-e5f6-4789-0abc-def123456789";
198+
const AGC_TARGET_LEVEL_ID = "b2c3d4e5-f6a7-4890-1bcd-ef2345678901";
199+
const AGC_COMPRESSION_GAIN_ID = "c3d4e5f6-a7b8-4901-2cde-f34567890123";
128200

129201
// global variables
130202
let device = null;
@@ -145,6 +217,7 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
145217
const passInput = document.getElementById('passInput');
146218
const serverUrlInput = document.getElementById('serverUrlInput');
147219
const ssidTitle = document.getElementById('ssidTitle');
220+
const passTitle = document.getElementById('passTitle');
148221
const urlTitle = document.getElementById('urlTitle');
149222
const backgroundImage = document.getElementById('backgroundImage');
150223
const bgPreview = document.getElementById('bgPreview');
@@ -155,6 +228,22 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
155228
const toastMessage = document.getElementById('toastMessage');
156229
const resetNotSupportedModal = document.getElementById('resetNotSupportedModal');
157230

231+
// AFE related DOM elements
232+
const afeLinearGainRange = document.getElementById('afeLinearGainRange');
233+
const afeLinearGainValue = document.getElementById('afeLinearGainValue');
234+
const saveAfeLinearGainButton = document.getElementById('saveAfeLinearGainButton');
235+
const afeLinearGainTitle = document.getElementById('afeLinearGainTitle');
236+
237+
const agcTargetLevelRange = document.getElementById('agcTargetLevelRange');
238+
const agcTargetLevelValue = document.getElementById('agcTargetLevelValue');
239+
const saveAgcTargetLevelButton = document.getElementById('saveAgcTargetLevelButton');
240+
const agcTargetLevelTitle = document.getElementById('agcTargetLevelTitle');
241+
242+
const agcCompressionGainRange = document.getElementById('agcCompressionGainRange');
243+
const agcCompressionGainValue = document.getElementById('agcCompressionGainValue');
244+
const saveAgcCompressionGainButton = document.getElementById('saveAgcCompressionGainButton');
245+
const agcCompressionGainTitle = document.getElementById('agcCompressionGainTitle');
246+
158247
// Track modified fields
159248
const modifiedFields = {
160249
ssid: false,
@@ -174,7 +263,9 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
174263
// Clear field modification mark
175264
function clearFieldModification(fieldName, titleElement) {
176265
modifiedFields[fieldName] = false;
177-
titleElement.textContent = titleElement.textContent.replace(' *', '');
266+
if (titleElement) {
267+
titleElement.textContent = titleElement.textContent.replace(' *', '');
268+
}
178269
updateSaveButtonState();
179270
}
180271

@@ -334,6 +425,11 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
334425
backgroundImage.disabled = false;
335426
clearBgButton.disabled = false;
336427
controlPanel.classList.remove('opacity-50', 'pointer-events-none');
428+
429+
// Enable AFE controls
430+
afeLinearGainRange.disabled = false;
431+
agcTargetLevelRange.disabled = false;
432+
agcCompressionGainRange.disabled = false;
337433
}
338434

339435
// Disable all controls
@@ -347,6 +443,14 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
347443
writeBgButton.disabled = true;
348444
clearBgButton.disabled = true;
349445
controlPanel.classList.add('opacity-50', 'pointer-events-none');
446+
447+
// Disable AFE controls
448+
afeLinearGainRange.disabled = true;
449+
agcTargetLevelRange.disabled = true;
450+
agcCompressionGainRange.disabled = true;
451+
saveAfeLinearGainButton.disabled = true;
452+
saveAgcTargetLevelButton.disabled = true;
453+
saveAgcCompressionGainButton.disabled = true;
350454
}
351455

352456
// Reads Characteristic
@@ -387,8 +491,14 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
387491
await readCharacteristic(PASS_ID, passInput);
388492
await readCharacteristic(SERVER_URL_ID, serverUrlInput);
389493

494+
// Load AFE parameters
495+
await readAfeLinearGain();
496+
await readAgcTargetLevel();
497+
await readAgcCompressionGain();
498+
390499
// Clear all modification marks
391500
clearFieldModification('ssid', ssidTitle);
501+
clearFieldModification('pass', passTitle);
392502
clearFieldModification('url', urlTitle);
393503

394504
showNotification('Success', 'All configuration loaded');
@@ -431,7 +541,7 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
431541

432542
if (modifiedFields.pass) {
433543
await writeCharacteristic(PASS_ID, passInput.value);
434-
clearFieldModification('ssid', ssidTitle);
544+
clearFieldModification('pass', passTitle);
435545
savedCount++;
436546
}
437547

@@ -596,7 +706,7 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
596706
});
597707

598708
passInput.addEventListener('input', () => {
599-
markFieldAsModified('pass', ssidTitle);
709+
markFieldAsModified('pass', passTitle);
600710
});
601711

602712
serverUrlInput.addEventListener('input', () => {
@@ -612,6 +722,173 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
612722
showNotification('Message', 'Background image cleared');
613723
});
614724

725+
// Read AFE Linear Gain (string format f32)
726+
async function readAfeLinearGain() {
727+
if (!isConnected || !service) return false;
728+
try {
729+
const characteristic = await service.getCharacteristic(AFE_LINEAR_GAIN_ID);
730+
const value = await characteristic.readValue();
731+
const decoder = new TextDecoder();
732+
const stringValue = decoder.decode(value);
733+
const gain = parseFloat(stringValue);
734+
if (!isNaN(gain)) {
735+
afeLinearGainRange.value = Math.round(gain * 10);
736+
afeLinearGainValue.textContent = gain.toFixed(1);
737+
// Reset title (remove not supported label)
738+
afeLinearGainTitle.textContent = 'AFE Linear Gain';
739+
saveAfeLinearGainButton.disabled = true;
740+
}
741+
return true;
742+
} catch (error) {
743+
console.error('Failed to read AFE Linear Gain:', error);
744+
// Backward compatibility: disable this control
745+
afeLinearGainRange.disabled = true;
746+
saveAfeLinearGainButton.disabled = true;
747+
afeLinearGainTitle.textContent = 'AFE Linear Gain (Not Supported)';
748+
return false;
749+
}
750+
}
751+
752+
// Read AGC Target Level (i32, 4 bytes little endian)
753+
async function readAgcTargetLevel() {
754+
if (!isConnected || !service) return false;
755+
try {
756+
const characteristic = await service.getCharacteristic(AGC_TARGET_LEVEL_ID);
757+
const value = await characteristic.readValue();
758+
// value is already DataView, use directly
759+
const level = value.getInt32(0, true);
760+
agcTargetLevelRange.value = level;
761+
agcTargetLevelValue.textContent = level;
762+
// Reset title (remove not supported label)
763+
agcTargetLevelTitle.textContent = 'AGC Target Level';
764+
saveAgcTargetLevelButton.disabled = true;
765+
return true;
766+
} catch (error) {
767+
console.error('Failed to read AGC Target Level:', error);
768+
// Backward compatibility: disable this control
769+
agcTargetLevelRange.disabled = true;
770+
saveAgcTargetLevelButton.disabled = true;
771+
agcTargetLevelTitle.textContent = 'AGC Target Level (Not Supported)';
772+
return false;
773+
}
774+
}
775+
776+
// Read AGC Compression Gain (i32, 4 bytes little endian)
777+
async function readAgcCompressionGain() {
778+
if (!isConnected || !service) return false;
779+
try {
780+
const characteristic = await service.getCharacteristic(AGC_COMPRESSION_GAIN_ID);
781+
const value = await characteristic.readValue();
782+
// value is already DataView, use directly
783+
const gain = value.getInt32(0, true);
784+
agcCompressionGainRange.value = gain;
785+
agcCompressionGainValue.textContent = gain;
786+
// Reset title (remove not supported label)
787+
agcCompressionGainTitle.textContent = 'AGC Compression Gain';
788+
saveAgcCompressionGainButton.disabled = true;
789+
return true;
790+
} catch (error) {
791+
console.error('Failed to read AGC Compression Gain:', error);
792+
// Backward compatibility: disable this control
793+
agcCompressionGainRange.disabled = true;
794+
saveAgcCompressionGainButton.disabled = true;
795+
agcCompressionGainTitle.textContent = 'AGC Compression Gain (Not Supported)';
796+
return false;
797+
}
798+
}
799+
800+
// AFE Linear Gain save function
801+
async function saveAfeLinearGain() {
802+
if (!isConnected || !service) {
803+
showNotification('Error', 'Device not connected', true);
804+
return;
805+
}
806+
try {
807+
const gain = parseFloat((afeLinearGainRange.value / 10).toFixed(1));
808+
const characteristic = await service.getCharacteristic(AFE_LINEAR_GAIN_ID);
809+
const encoder = new TextEncoder();
810+
const data = encoder.encode(gain.toString());
811+
await characteristic.writeValue(data);
812+
showNotification('Success', `AFE Linear Gain set to ${gain}`);
813+
clearFieldModification('afeLinearGain', afeLinearGainTitle);
814+
saveAfeLinearGainButton.disabled = true;
815+
} catch (error) {
816+
console.error('Failed to save AFE Linear Gain:', error);
817+
showNotification('Error', 'Failed to save AFE Linear Gain: ' + error.message, true);
818+
}
819+
}
820+
821+
// AGC Target Level save function
822+
async function saveAgcTargetLevel() {
823+
if (!isConnected || !service) {
824+
showNotification('Error', 'Device not connected', true);
825+
return;
826+
}
827+
try {
828+
const level = parseInt(agcTargetLevelRange.value);
829+
const characteristic = await service.getCharacteristic(AGC_TARGET_LEVEL_ID);
830+
const data = new ArrayBuffer(4);
831+
const view = new DataView(data);
832+
view.setInt32(0, level, true);
833+
await characteristic.writeValue(data);
834+
showNotification('Success', `AGC Target Level set to ${level}`);
835+
clearFieldModification('agcTargetLevel', agcTargetLevelTitle);
836+
saveAgcTargetLevelButton.disabled = true;
837+
} catch (error) {
838+
console.error('Failed to save AGC Target Level:', error);
839+
showNotification('Error', 'Failed to save AGC Target Level: ' + error.message, true);
840+
}
841+
}
842+
843+
// AGC Compression Gain save function
844+
async function saveAgcCompressionGain() {
845+
if (!isConnected || !service) {
846+
showNotification('Error', 'Device not connected', true);
847+
return;
848+
}
849+
try {
850+
const gain = parseInt(agcCompressionGainRange.value);
851+
const characteristic = await service.getCharacteristic(AGC_COMPRESSION_GAIN_ID);
852+
const data = new ArrayBuffer(4);
853+
const view = new DataView(data);
854+
view.setInt32(0, gain, true);
855+
await characteristic.writeValue(data);
856+
showNotification('Success', `AGC Compression Gain set to ${gain}`);
857+
clearFieldModification('agcCompressionGain', agcCompressionGainTitle);
858+
saveAgcCompressionGainButton.disabled = true;
859+
} catch (error) {
860+
console.error('Failed to save AGC Compression Gain:', error);
861+
showNotification('Error', 'Failed to save AGC Compression Gain: ' + error.message, true);
862+
}
863+
}
864+
865+
// AFE Linear Gain slider event
866+
afeLinearGainRange.addEventListener('input', () => {
867+
const gain = (afeLinearGainRange.value / 10).toFixed(1);
868+
afeLinearGainValue.textContent = gain;
869+
markFieldAsModified('afeLinearGain', afeLinearGainTitle);
870+
saveAfeLinearGainButton.disabled = false;
871+
});
872+
873+
// AGC Target Level slider event
874+
agcTargetLevelRange.addEventListener('input', () => {
875+
agcTargetLevelValue.textContent = agcTargetLevelRange.value;
876+
markFieldAsModified('agcTargetLevel', agcTargetLevelTitle);
877+
saveAgcTargetLevelButton.disabled = false;
878+
});
879+
880+
// AGC Compression Gain slider event
881+
agcCompressionGainRange.addEventListener('input', () => {
882+
agcCompressionGainValue.textContent = agcCompressionGainRange.value;
883+
markFieldAsModified('agcCompressionGain', agcCompressionGainTitle);
884+
saveAgcCompressionGainButton.disabled = false;
885+
});
886+
887+
// AFE save button events
888+
saveAfeLinearGainButton.addEventListener('click', saveAfeLinearGain);
889+
saveAgcTargetLevelButton.addEventListener('click', saveAgcTargetLevel);
890+
saveAgcCompressionGainButton.addEventListener('click', saveAgcCompressionGain);
891+
615892
if (!navigator.bluetooth) {
616893
showNotification('Error', 'Your browser does not support the Web Bluetooth API. Please use Chrome or Edge', true);
617894
connectButton.disabled = true;
@@ -622,4 +899,4 @@ <h3 class="font-bold text-lg">⚠️ Device Reset Required</h3>
622899
</script>
623900
</body>
624901

625-
</html>
902+
</html>

0 commit comments

Comments
 (0)