Skip to content

Commit 6c486b3

Browse files
feat: Major UI/UX improvements and data parsing fixes
## Web Interface Enhancements ### UI Layout Redesign - Implemented responsive two-column layout with left column for visuals (connection/grid/chart) and right column for controls (terminal/commands) - Added CSS Grid layout with auto-sizing right column to match grid width - Improved responsive breakpoint at 900px with proper column stacking order - Reduced padding and spacing for more compact, efficient layout ### Grid Visualization Improvements - Fixed grid orientation to match Mac app by reversing capacitance array before grid update - Implemented golden gradient visualization (rgba(0,0,0,0) to #dca32f) for better visual feedback - Added corner position exclusion from gradient calculation for more accurate scaling - Improved grid cell styling with rounded corners and better typography ### Performance Optimizations - Added auto-clearing logs (max 1000 entries, emergency clear at 2000) to prevent browser lockup - Implemented adaptive timeout system for JCP stream (30s when touch detected, 15s default) - Temporarily disabled chart updates and excessive logging for better performance - Added null checks in updateConnectionStatus to prevent DOM errors ### Data Parsing Fixes - Fixed pressure data parsing to match Mac app byte indices and big-endian Float32 format - Added fallback to little-endian parsing if big-endian values are corrupted - Improved capacitive data processing with better validation and error handling - Enhanced packet framing with dual magic bytes and CRC-16 support ### Error Handling - Added comprehensive error handling for corrupted float values and invalid data - Implemented sanity checks for packet length, buffer size, and data alignment - Added adaptive timeout mechanism to handle high data rates during touchpad use ## Technical Details - Reverted byte order changes that caused invalid cell values - Added array reversal only at grid update stage to maintain data integrity - Enhanced packet fragmentation handling with increased timeouts - Improved CSS responsive design with better mobile experience ## Files Modified - web_interface/script.js: Core data processing and UI logic - web_interface/index.html: HTML structure for two-column layout - web_interface/styles.css: Responsive CSS Grid layout and styling - central_uart/prj.conf: Configuration updates - central_uart/src/main.c: Firmware updates
1 parent c651af6 commit 6c486b3

5 files changed

Lines changed: 1524 additions & 225 deletions

File tree

central_uart/prj.conf

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ CONFIG_RTT_CONSOLE=y
1818
# Enable USB CDC ACM for screen communication
1919
CONFIG_USB_DEVICE_STACK=y
2020
CONFIG_USB_CDC_ACM=y
21-
CONFIG_USB_CDC_ACM_RINGBUF_SIZE=1024
21+
CONFIG_USB_CDC_ACM_RINGBUF_SIZE=4096
2222
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=y
2323
CONFIG_USB_DEVICE_PRODUCT="MouthPad^USB"
2424
CONFIG_USB_DEVICE_MANUFACTURER="Augmental.Tech"
@@ -32,6 +32,11 @@ CONFIG_BT_CENTRAL=y
3232
CONFIG_BT_SMP=y
3333
CONFIG_BT_GATT_CLIENT=y
3434

35+
# Enable larger MTU for BLE NUS
36+
CONFIG_BT_L2CAP_TX_MTU=247
37+
CONFIG_BT_BUF_ACL_RX_SIZE=247
38+
CONFIG_BT_BUF_ACL_TX_SIZE=247
39+
3540
# Enable the BLE modules from NCS
3641
CONFIG_BT_NUS_CLIENT=y
3742
CONFIG_BT_SCAN=y

central_uart/src/main.c

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,25 @@ static K_FIFO_DEFINE(fifo_uart_rx_data);
6767
static struct bt_conn *default_conn;
6868
static struct bt_nus_client nus_client;
6969

70+
// Calculate CRC-16 (CCITT) for data integrity checking
71+
static uint16_t calculate_crc16(const uint8_t *data, uint16_t len)
72+
{
73+
uint16_t crc = 0xFFFF; // Initial value
74+
75+
for (uint16_t i = 0; i < len; i++) {
76+
crc ^= (uint16_t)data[i] << 8;
77+
for (int j = 0; j < 8; j++) {
78+
if (crc & 0x8000) {
79+
crc = (crc << 1) ^ 0x1021; // CCITT polynomial
80+
} else {
81+
crc = crc << 1;
82+
}
83+
}
84+
}
85+
86+
return crc & 0xFFFF;
87+
}
88+
7089
static void ble_data_sent(struct bt_nus_client *nus, uint8_t err,
7190
const uint8_t *const data, uint16_t len)
7291
{
@@ -152,12 +171,30 @@ static uint8_t ble_data_received(struct bt_nus_client *nus,
152171
printk("*** PACKET STRUCTURE: Type=0x%02x, Length=%d ***\n", data[0], len);
153172
}
154173

155-
// Send data directly to USB CDC
156-
printk("*** FORWARDING %d BYTES TO CDC ***\n", len);
174+
// Send data directly to USB CDC with robust packet framing
175+
// New format: [0xAA][0x55][LEN_H][LEN_L][DATA...][CRC_H][CRC_L]
176+
printk("*** FORWARDING %d BYTES TO CDC WITH NEW FRAMING ***\n", len);
177+
178+
// Calculate CRC-16 for the payload
179+
uint16_t crc = calculate_crc16(data, len);
180+
181+
// Send dual start markers
182+
uart_poll_out(uart, 0xAA); // First start marker
183+
uart_poll_out(uart, 0x55); // Second start marker
184+
185+
// Send packet length (2 bytes, big-endian)
186+
uart_poll_out(uart, (len >> 8) & 0xFF); // High byte
187+
uart_poll_out(uart, len & 0xFF); // Low byte
188+
189+
// Send packet data
157190
for (uint16_t i = 0; i < len; i++) {
158191
uart_poll_out(uart, data[i]);
159192
}
160193

194+
// Send CRC (2 bytes, big-endian)
195+
uart_poll_out(uart, (crc >> 8) & 0xFF); // CRC high byte
196+
uart_poll_out(uart, crc & 0xFF); // CRC low byte
197+
161198
return BT_GATT_ITER_CONTINUE;
162199
}
163200

@@ -453,8 +490,11 @@ static void gatt_discover(struct bt_conn *conn)
453490
static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
454491
{
455492
if (!err) {
456-
LOG_INF("MTU exchange done");
493+
uint16_t mtu = bt_gatt_get_mtu(conn);
494+
printk("*** MTU EXCHANGE SUCCESSFUL: MTU = %d bytes ***\n", mtu);
495+
LOG_INF("MTU exchange done, MTU: %d", mtu);
457496
} else {
497+
printk("*** MTU EXCHANGE FAILED: error = %d ***\n", err);
458498
LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err);
459499
}
460500
}
@@ -487,6 +527,7 @@ static void connected(struct bt_conn *conn, uint8_t conn_err)
487527
static struct bt_gatt_exchange_params exchange_params;
488528

489529
exchange_params.func = exchange_func;
530+
// Request maximum MTU (247 bytes) to handle bigger packets
490531
err = bt_gatt_exchange_mtu(conn, &exchange_params);
491532
if (err) {
492533
LOG_WRN("MTU exchange failed (err %d)", err);

web_interface/index.html

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,84 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>MouthPad Controller</title>
6+
<title>MouthPad^USB</title>
77
<link rel="stylesheet" href="styles.css">
88
</head>
99
<body>
1010
<div class="container">
1111
<!-- Header -->
12-
<header class="header">
13-
<h1>MouthPad^ Controller</h1>
12+
<!-- <header class="header">
13+
<h1>MouthPad^USB</h1>
1414
<div class="connection-status" id="connectionStatus">
1515
<span class="status-indicator" id="statusIndicator"></span>
1616
<span class="status-text" id="statusText">Not Connected</span>
1717
</div>
18-
</header>
18+
</header> -->
1919

20-
<!-- Connection Panel -->
21-
<div class="connection-panel">
22-
<button id="connectBtn" class="btn btn-primary">Connect to Serial Port</button>
23-
<button id="disconnectBtn" class="btn btn-secondary" disabled>Disconnect</button>
24-
<select id="portSelect" class="port-select">
25-
<option value="">Select Port...</option>
26-
</select>
27-
</div>
28-
29-
<!-- Command Panel -->
30-
<div class="command-panel">
31-
<div class="command-buttons">
32-
<button class="btn btn-command" data-command="jcp">Start JCP Stream</button>
33-
<button class="btn btn-command" data-command="imu">Start IMU Stream</button>
34-
<button class="btn btn-command" data-command="click">Start Click Stream</button>
35-
<button class="btn btn-command" data-command="pwr">Start PWR Stream</button>
36-
</div>
37-
<div class="custom-command">
38-
<input type="text" id="customCommand" placeholder="Enter custom command..." class="command-input">
39-
<button id="sendCustomBtn" class="btn btn-primary">Send</button>
40-
</div>
41-
</div>
20+
<!-- Two Column Layout -->
21+
<div class="two-column-layout">
22+
<!-- Left Column: Connection, Grid & Chart -->
23+
<div class="left-column">
24+
<!-- Connection Panel -->
25+
<div class="connection-panel">
26+
<button id="connectBtn" class="btn btn-primary">Connect Serial</button>
27+
<button id="disconnectBtn" class="btn btn-secondary" disabled>Disconnect</button>
28+
<span style="flex: 1;"></span>
29+
<span class="status-indicator" id="statusIndicator"></span>
30+
</div>
4231

43-
<!-- Main Content -->
44-
<div class="main-content">
45-
<!-- Grid Display -->
46-
<div class="grid-container">
47-
<h3>Touchpad Grid (8x6)</h3>
48-
<div class="grid" id="pressureGrid">
49-
<!-- Grid cells will be generated by JavaScript -->
32+
<!-- Grid Display -->
33+
<div class="grid-container">
34+
<div class="grid" id="touchpadGrid">
35+
<!-- Grid cells will be generated by JavaScript -->
36+
</div>
37+
<!-- <div class="grid-info">
38+
<span>Min: <span id="minPressure">0</span></span>
39+
<span>Max: <span id="maxPressure">0</span></span>
40+
<span>Active: <span id="activeCells">0</span></span>
41+
</div> -->
5042
</div>
51-
<div class="grid-info">
52-
<span>Min: <span id="minPressure">0</span></span>
53-
<span>Max: <span id="maxPressure">0</span></span>
54-
<span>Active: <span id="activeCells">0</span></span>
43+
44+
<!-- Pressure Chart -->
45+
<div class="chart-container">
46+
<div class="chart-wrapper">
47+
<canvas id="pressureChart" width="280" height="200"></canvas>
48+
</div>
49+
<!-- <div class="chart-info">
50+
<span>Current: <span id="currentPressure">0</span> hPa</span>
51+
<span>Avg: <span id="avgPressure">0</span> hPa</span>
52+
<span>Peak: <span id="peakPressure">0</span> hPa</span>
53+
</div> -->
5554
</div>
5655
</div>
5756

58-
<!-- Terminal Log -->
59-
<div class="terminal-container">
60-
<h3>Data Log</h3>
61-
<div class="terminal" id="terminal">
62-
<div class="terminal-line">MouthPad Controller Ready...</div>
57+
<!-- Right Column: Terminal & Commands -->
58+
<div class="right-column">
59+
<!-- Command Panel -->
60+
<div class="command-panel">
61+
<!-- <div class="command-buttons">
62+
<button class="btn btn-command" data-command="jcp">StartStream jcp</button>
63+
<button class="btn btn-command" data-command="imu">StartStream imu</button>
64+
<button class="btn btn-command" data-command="click">StartStream click</button>
65+
<button class="btn btn-command" data-command="pwr">StartStream pwr</button>
66+
</div> -->
67+
<div class="custom-command">
68+
<input type="text" id="customCommand" placeholder="Enter custom command..." class="command-input">
69+
<button id="sendCustomBtn" class="btn btn-primary">Send</button>
70+
</div>
6371
</div>
64-
<div class="terminal-controls">
65-
<button id="clearLogBtn" class="btn btn-secondary">Clear Log</button>
66-
<button id="exportLogBtn" class="btn btn-secondary">Export Log</button>
72+
73+
<!-- Terminal Log -->
74+
<div class="terminal-container">
75+
<div class="terminal" id="terminal">
76+
<div class="terminal-line">MouthPad Controller Ready...</div>
77+
</div>
78+
<div class="terminal-controls">
79+
<button id="clearLogBtn" class="btn btn-secondary">Clear Log</button>
80+
<button id="exportLogBtn" class="btn btn-secondary">Export Log</button>
81+
<span style="flex: 1;"></span>
82+
<button class="btn btn-command" data-command="jcp">StartStream jcp</button>
83+
</div>
6784
</div>
6885
</div>
6986
</div>

0 commit comments

Comments
 (0)