From ee857760e9cae893c3911e154fab8c4db6a51498 Mon Sep 17 00:00:00 2001 From: Geoffrey Hunter Date: Mon, 13 May 2024 20:59:58 +1200 Subject: [PATCH 1/5] Start work on custom baud rates. --- .../PortConfigurationSettings.ts | 32 +++++++++++++++++++ .../PortConfigurationSettingsView.tsx | 22 ++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/model/Settings/PortConfigurationSettings/PortConfigurationSettings.ts b/src/model/Settings/PortConfigurationSettings/PortConfigurationSettings.ts index dccdce6a..5cb6ec68 100644 --- a/src/model/Settings/PortConfigurationSettings/PortConfigurationSettings.ts +++ b/src/model/Settings/PortConfigurationSettings/PortConfigurationSettings.ts @@ -3,6 +3,7 @@ import { makeAutoObservable } from 'mobx'; import { App } from 'src/model/App'; import AppStorage from 'src/model/Storage/AppStorage'; import { createSerializableObjectFromConfig, updateConfigFromSerializable } from 'src/model/Util/SettingsLoader'; +import { z } from 'zod'; export enum PortState { CLOSED, @@ -10,6 +11,10 @@ export enum PortState { OPENED } +export const DEFAULT_BAUD_RATES = [ + 110, 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, +]; + const CONFIG_KEY = ['settings', 'port-configuration-settings']; class Config { @@ -20,6 +25,8 @@ class Config { */ version = 1; + baudRate = 115200; + connectToSerialPortAsSoonAsItIsSelected = true; resumeConnectionToLastSerialPortOnStartup = true; @@ -37,12 +44,37 @@ export default class PortConfiguration { config = new Config(); + baudRateInputValue = this.config.baudRate.toString(); + + baudRateValidation = z.coerce.number().int().min(1).max(115200); + baudRateErrorMsg = ''; + constructor(appStorage: AppStorage) { this.appStorage = appStorage; this._loadConfig(); makeAutoObservable(this); } + setBaudRate = (baudRate: number) => { + this.config.baudRate = baudRate; + this._saveConfig(); + } + + setBaudRateInputValue = (value: string) => { + this.baudRateInputValue = value; + + const parsed = this.baudRateValidation.safeParse(value); + if (parsed.success) { + this.baudRateErrorMsg = ''; + console.log("Setting baud rate to: ", parsed.data); + this.setBaudRate(parsed.data); + } else { + // We want to keep this simple, just show the first + // error message + this.baudRateErrorMsg = parsed.error.errors[0].message; + } + } + setConnectToSerialPortAsSoonAsItIsSelected = (value: boolean) => { this.config.connectToSerialPortAsSoonAsItIsSelected = value; this._saveConfig(); diff --git a/src/view/Settings/PortConfigurationSettings/PortConfigurationSettingsView.tsx b/src/view/Settings/PortConfigurationSettings/PortConfigurationSettingsView.tsx index 7742bdcb..5f8d54e0 100644 --- a/src/view/Settings/PortConfigurationSettings/PortConfigurationSettingsView.tsx +++ b/src/view/Settings/PortConfigurationSettings/PortConfigurationSettingsView.tsx @@ -10,12 +10,14 @@ import { Tooltip, Checkbox, FormControlLabel, + Autocomplete, + TextField, } from '@mui/material'; import { OverridableStringUnion } from '@mui/types'; import { observer } from 'mobx-react-lite'; import { App, PortType } from 'src/model/App'; -import { PortState } from 'src/model/Settings/PortConfigurationSettings/PortConfigurationSettings'; +import { PortState, DEFAULT_BAUD_RATES } from 'src/model/Settings/PortConfigurationSettings/PortConfigurationSettings'; import { StopBits } from 'src/model/Settings/Settings'; import { portStateToButtonProps } from 'src/view/Components/PortStateToButtonProps'; import styles from './PortConfigurationSettingsView.module.css'; @@ -57,6 +59,24 @@ function PortConfigurationView(props: Props) { })} + option.toString())} + renderInput={(params) => } + sx={{ m: 1, width: 160 }} size="small" + onChange={(event: any, newValue: string | null) => { + console.log('onChange() called. newValue: ', newValue); + }} + inputValue={app.settings.portConfiguration.baudRateInputValue} + onInputChange={(event, newInputValue) => { + console.log('newInputValue: ', newInputValue); + app.settings.portConfiguration.setBaudRateInputValue(newInputValue); + }} + /> {/* ====================== NUM. DATA BITS ============================= */} Num. Data Bits From 11629e01ea72fbe2b0e75f810941de28e9a49ea6 Mon Sep 17 00:00:00 2001 From: Geoffrey Hunter Date: Tue, 14 May 2024 16:41:11 +1200 Subject: [PATCH 2/5] Custom baud rate input working. Add circular progress modal. --- CHANGELOG.md | 6 + src/model/App.tsx | 23 +- .../PortConfigurationSettings.ts | 70 +++++- src/model/Settings/Settings.tsx | 61 +----- src/view/AppView.tsx | 204 +++++++++--------- .../PortConfigurationSettingsView.tsx | 120 +++++------ 6 files changed, 255 insertions(+), 229 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de8052d4..46bc9d21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased +### Added + +- Added more recommended baud rate options. +- Added the ability to specify a custom baud rate. +- Added a circular progress modal which is shown when the port is opening. + ## [4.14.0] - 2024-05-12 ### Added diff --git a/src/model/App.tsx b/src/model/App.tsx index 43f6f286..958a4dff 100644 --- a/src/model/App.tsx +++ b/src/model/App.tsx @@ -126,6 +126,8 @@ export class App { SelectionController = SelectionController; + showCircularProgressModal = false; + constructor(testing = false) { this.testing = testing; if (this.testing) { @@ -305,18 +307,21 @@ export class App { } /** - * Opens the selected serial port. + * Opens the selected serial port using settings from the Port Configuration view. * * @param printSuccessMsg If true, a success message will be printed to the snackbar. */ async openPort(printSuccessMsg = true) { if (this.lastSelectedPortType === PortType.REAL) { + // Show the circular progress modal when trying to open the port. If the port opening is going to fail, sometimes it takes + // a few seconds for awaiting open() to complete, so this prevents the user from trying to open the port again while we wait + this.setShowCircularProgressModal(true); try { await this.port?.open({ - baudRate: this.settings.selectedBaudRate, - dataBits: this.settings.selectedNumDataBits, - parity: this.settings.selectedParity as ParityType, - stopBits: this.settings.selectedStopBits, + baudRate: this.settings.portConfiguration.config.baudRate, // This might be custom + dataBits: this.settings.portConfiguration.config.numDataBits, + parity: this.settings.portConfiguration.config.parity as ParityType, + stopBits: this.settings.portConfiguration.config.stopBits, bufferSize: 10000, }); // Default buffer size is only 256 (presumably bytes), which is not enough regularly causes buffer overrun errors } catch (error) { @@ -337,6 +342,8 @@ export class App { console.log(msg); } + this.setShowCircularProgressModal(false); + // An error occurred whilst calling port.open(), so DO NOT continue, port // cannot be considered open return; @@ -345,6 +352,8 @@ export class App { this.snackbar.sendToSnackbar('Serial port opened.', 'success'); } + this.setShowCircularProgressModal(false); + runInAction(() => { this.portState = PortState.OPENED; this.keepReading = true; @@ -899,4 +908,8 @@ export class App { console.log('onRegisterError() called.'); console.error(error.message); } + + setShowCircularProgressModal(show: boolean) { + this.showCircularProgressModal = show; + } } diff --git a/src/model/Settings/PortConfigurationSettings/PortConfigurationSettings.ts b/src/model/Settings/PortConfigurationSettings/PortConfigurationSettings.ts index 5cb6ec68..2d1761ee 100644 --- a/src/model/Settings/PortConfigurationSettings/PortConfigurationSettings.ts +++ b/src/model/Settings/PortConfigurationSettings/PortConfigurationSettings.ts @@ -12,9 +12,25 @@ export enum PortState { } export const DEFAULT_BAUD_RATES = [ - 110, 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, + 110, 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600 ]; +export const NUM_DATA_BITS_OPTIONS = [5, 6, 7, 8]; + +/** + * The string values must match that of the ParityType type provided + * by the Web Serial API. + */ +export enum Parity { + NONE = 'none', + EVEN = 'even', + ODD = 'odd', +}; + +export type StopBits = 1 | 1.5 | 2; + +export const STOP_BIT_OPTIONS: StopBits[] = [1, 2]; + const CONFIG_KEY = ['settings', 'port-configuration-settings']; class Config { @@ -23,10 +39,16 @@ class Config { * This will cause the app to ignore whatever is in local storage and use the defaults, * updating to this new version. */ - version = 1; + version = 2; baudRate = 115200; + numDataBits = 8; + + parity = Parity.NONE; + + stopBits: StopBits = 1; + connectToSerialPortAsSoonAsItIsSelected = true; resumeConnectionToLastSerialPortOnStartup = true; @@ -46,7 +68,12 @@ export default class PortConfiguration { baudRateInputValue = this.config.baudRate.toString(); - baudRateValidation = z.coerce.number().int().min(1).max(115200); + /** + * Set min. baud rate to 1 and max. baud rate to 2,000,000. Most systems won't actually + * support these ranges but let's not limit the user (they don't normally error if an unsupported + * number is provided, it just doesn't work correctly). + */ + baudRateValidation = z.coerce.number().int().min(1).max(2000000); baudRateErrorMsg = ''; constructor(appStorage: AppStorage) { @@ -75,6 +102,24 @@ export default class PortConfiguration { } } + setNumDataBits = (numDataBits: number) => { + if (typeof numDataBits !== 'number') { + throw new Error("numDataBits must be a number"); + } + this.config.numDataBits = numDataBits; + this._saveConfig(); + } + + setParity = (parity: Parity) => { + this.config.parity = parity; + this._saveConfig(); + } + + setStopBits = (stopBits: StopBits) => { + this.config.stopBits = stopBits; + this._saveConfig(); + } + setConnectToSerialPortAsSoonAsItIsSelected = (value: boolean) => { this.config.connectToSerialPortAsSoonAsItIsSelected = value; this._saveConfig(); @@ -111,12 +156,31 @@ export default class PortConfiguration { // At this point we are confident that the deserialized config matches what // this classes config object wants, so we can go ahead and update. updateConfigFromSerializable(deserializedConfig, this.config); + + this.setBaudRateInputValue(this.config.baudRate.toString()); }; _saveConfig = () => { const serializableConfig = createSerializableObjectFromConfig(this.config); this.appStorage.saveConfig(CONFIG_KEY, serializableConfig); }; + + /** + * Computed value which represents the serial port config in short hand, + * e.g. "115200 8n1" + * + * @returns The short hand serial port config for displaying. + */ + get shortSerialConfigName() { + let output = ''; + output += this.config.baudRate.toString(); + output += ' '; + // output += this.selectedNumDataBits.toString(); + // output += this.selectedParity[0]; + // output += this.selectedStopBits.toString(); + output += '8n1'; // TODO: Fix this + return output; + } } diff --git a/src/model/Settings/Settings.tsx b/src/model/Settings/Settings.tsx index 7c853544..d01d97be 100644 --- a/src/model/Settings/Settings.tsx +++ b/src/model/Settings/Settings.tsx @@ -12,7 +12,7 @@ import GeneralSettings from './GeneralSettings/GeneralSettings'; import AppStorage from '../Storage/AppStorage'; import FakePortsController from 'src/model/FakePorts/FakePortsController'; -export type StopBits = 1 | 1.5 | 2; + export enum SettingsCategories { PORT_CONFIGURATION, @@ -40,27 +40,6 @@ export class Settings { generalSettings: GeneralSettings; - selectedPortPath = ''; - - // Commonly-available baud rates as mentioned at https://serialport.io/docs/api-stream/ - baudRates = [ - 110, 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, - ]; - - selectedBaudRate = 115200; - - numDataBitsOptions = [5, 6, 7, 8]; - - selectedNumDataBits = 8; - - parityOptions = ['none', 'even', 'odd']; - - selectedParity = 'none'; - - stopBitOptions: StopBits[] = [1, 2]; - - selectedStopBits: StopBits = 1; - /** * Constructor for the Settings class. * @@ -79,45 +58,13 @@ export class Settings { makeAutoObservable(this); // Make sure this is at the end of the constructor } - /** - * Computed value which represents the serial port config in short hand, - * e.g. "115200 8n1" - * - * @returns The short hand serial port config for displaying. - */ - get shortSerialConfigName() { - let output = ''; - output += this.selectedBaudRate.toString(); - output += ' '; - output += this.selectedNumDataBits.toString(); - output += this.selectedParity[0]; - output += this.selectedStopBits.toString(); - return output; - } - setActiveSettingsCategory(settingsCategory: SettingsCategories) { this.activeSettingsCategory = settingsCategory; } - setSelectedPortPath(selectedPortPath: string) { - this.selectedPortPath = selectedPortPath; - } - - setSelectedBaudRate(baudRate: number) { - this.selectedBaudRate = baudRate; - } - - setSelectedNumDataBits(numDataBits: number) { - this.selectedNumDataBits = numDataBits; - } - - setSelectedParity(parity: string) { - this.selectedParity = parity; - } - - setSelectedStopBits(stopBits: StopBits) { - this.selectedStopBits = stopBits; - } + // setSelectedPortPath(selectedPortPath: string) { + // this.selectedPortPath = selectedPortPath; + // } onKeyDown = (event: React.KeyboardEvent) => { // console.log(event); diff --git a/src/view/AppView.tsx b/src/view/AppView.tsx index ee28ccf1..aaf03c18 100644 --- a/src/view/AppView.tsx +++ b/src/view/AppView.tsx @@ -1,47 +1,43 @@ -import { observer } from 'mobx-react-lite'; +import { observer } from "mobx-react-lite"; -import { - Box, - IconButton, - Tooltip, -} from '@mui/material'; -import { ThemeProvider, createTheme } from '@mui/material/styles'; -import SettingsIcon from '@mui/icons-material/Settings'; -import TimelineIcon from '@mui/icons-material/Timeline'; -import TerminalIcon from '@mui/icons-material/Terminal'; -import SaveAsIcon from '@mui/icons-material/SaveAs'; -import CssBaseline from '@mui/material/CssBaseline'; -import { SnackbarProvider } from 'notistack'; +import { Backdrop, Box, CircularProgress, IconButton, Tooltip } from "@mui/material"; +import { ThemeProvider, createTheme } from "@mui/material/styles"; +import SettingsIcon from "@mui/icons-material/Settings"; +import TimelineIcon from "@mui/icons-material/Timeline"; +import TerminalIcon from "@mui/icons-material/Terminal"; +import SaveAsIcon from "@mui/icons-material/SaveAs"; +import CssBaseline from "@mui/material/CssBaseline"; +import { SnackbarProvider } from "notistack"; // I got the following error here: // error TS2307: Cannot find module 'virtual:pwa-register' or its corresponding type declarations. // even with "vite-plugin-pwa/client" in the types array inside tsconfig.json. So getting typescript // to ignore this import for now. // @ts-ignore:next-line -import { registerSW } from 'virtual:pwa-register'; +import { registerSW } from "virtual:pwa-register"; -import { App, MainPanes } from '../model/App'; -import { PortState } from '../model/Settings/PortConfigurationSettings/PortConfigurationSettings'; -import './App.css'; -import SettingsDialog from './Settings/SettingsView'; -import TerminalView from './Terminals/TerminalsView'; -import GraphView from './Graphing/GraphingView'; -import LogoImage from './logo192.png'; -import styles from './AppView.module.css' -import FakePortDialogView from './FakePorts/FakePortDialogView'; -import { useEffect } from 'react'; -import LoggingView from './Logging/LoggingView'; -import { SelectionController, SelectionInfo } from '../model/SelectionController/SelectionController'; -import 'src/model/WindowTypes'; -import { DataType } from 'src/model/Settings/RxSettings/RxSettings'; +import { App, MainPanes } from "../model/App"; +import { PortState } from "../model/Settings/PortConfigurationSettings/PortConfigurationSettings"; +import "./App.css"; +import SettingsDialog from "./Settings/SettingsView"; +import TerminalView from "./Terminals/TerminalsView"; +import GraphView from "./Graphing/GraphingView"; +import LogoImage from "./logo192.png"; +import styles from "./AppView.module.css"; +import FakePortDialogView from "./FakePorts/FakePortDialogView"; +import { useEffect } from "react"; +import LoggingView from "./Logging/LoggingView"; +import { SelectionController, SelectionInfo } from "../model/SelectionController/SelectionController"; +import "src/model/WindowTypes"; +import { DataType } from "src/model/Settings/RxSettings/RxSettings"; // Create dark theme for MUI const darkTheme = createTheme({ palette: { - mode: 'dark', + mode: "dark", background: { - default: '#202020', - paper: '#202020', + default: "#202020", + paper: "#202020", // paper: deepOrange[900], }, // primary: { @@ -61,31 +57,30 @@ const darkTheme = createTheme({ tooltip: { // Override default font size for all tool-tips, as default is a little // to small - fontSize: '0.8rem', + fontSize: "0.8rem", }, }, }, - MuiButtonBase: { - } + MuiButtonBase: {}, }, }); /** * Maps a port state to the UI elements that should be used to represent it. */ -const portStateToToolbarStatusProperties: { [key in PortState]: any; } = { +const portStateToToolbarStatusProperties: { [key in PortState]: any } = { [PortState.CLOSED]: { - color: 'red', - text: 'Port CLOSED', + color: "red", + text: "Port CLOSED", }, [PortState.CLOSED_BUT_WILL_REOPEN]: { - color: 'orange', - text: 'Port CLOSED (will reopen)', + color: "orange", + text: "Port CLOSED (will reopen)", }, [PortState.OPENED]: { - color: 'green', - text: 'Port OPENED', - } + color: "green", + text: "Port OPENED", + }, }; interface Props { @@ -98,7 +93,6 @@ window.app = app; window.SelectionController = SelectionController; const AppView = observer((props: Props) => { - useEffect(() => { // We need to register the service worker AFTER the app // has rendered, because it we do it before we won't @@ -114,12 +108,12 @@ const AppView = observer((props: Props) => { // @ts-ignore:next-line onRegisterError(error) { app.swOnRegisterError(error); - } - }) + }, + }); const initFn = async () => { await app.onAppUiLoaded(); - } + }; initFn().catch(console.error); @@ -142,9 +136,7 @@ const AppView = observer((props: Props) => { } else if (app.shownMainPane === MainPanes.LOGGING) { mainPaneComponent = ; } else { - throw Error( - `Unsupported main pane. mainPane=${app.shownMainPane}` - ); + throw Error(`Unsupported main pane. mainPane=${app.shownMainPane}`); } // Attach listener to catch key presses over entire app @@ -167,98 +159,101 @@ const AppView = observer((props: Props) => { /* ThemeProvider sets theme for all MUI elements */ -
{ app.handleKeyDown(e); }} tabIndex={-1} style={{ - height: '100%', - display: 'flex', - padding: '10px 10px 10px 0px', // No padding on left - outline: 'none', // Prevent weird white border when selected + height: "100%", + display: "flex", + padding: "10px 10px 10px 0px", // No padding on left + outline: "none", // Prevent weird white border when selected }} > -
- {/* ================== LOGO ==================== */} - NinjaTerm logo. + NinjaTerm logo. {/* SETTINGS BUTTON */} {/* ==================================================== */} - + { app.setShownMainPane(MainPanes.SETTINGS); }} color="primary" - data-testid="settings-button"> + data-testid="settings-button" + > {/* TERMINAL BUTTON */} {/* ==================================================== */} - + { app.setShownMainPane(MainPanes.TERMINAL); }} color="primary" - data-testid="show-terminal-button"> - + data-testid="show-terminal-button" + > + {/* GRAPHING BUTTON */} {/* ==================================================== */} - + { app.setShownMainPane(MainPanes.GRAPHING); }} color="primary" - data-testid="show-graphing-pane-button"> - + data-testid="show-graphing-pane-button" + > + {/* LOGGING BUTTON */} {/* ==================================================== */} - + { app.setShownMainPane(MainPanes.LOGGING); }} color="primary" - data-testid="show-logging-pane-button"> - + data-testid="show-logging-pane-button" + > + -
- {/* MAIN PANE */} {/* =================================================================================== */} {mainPaneComponent} @@ -268,43 +263,41 @@ const AppView = observer((props: Props) => { {/* DATA TYPE */} -
- { app.settings.rxSettings.getDataTypeNameForToolbarDisplay() } -
+
{app.settings.rxSettings.getDataTypeNameForToolbarDisplay()}
{/* LOGGING ON/OFF */} -
- { app.logging.isLogging ? 'Logging ON' : 'Logging OFF'} -
+
{app.logging.isLogging ? "Logging ON" : "Logging OFF"}
{/* GRAPHING ON/OFF */} -
- { app.graphing.graphingEnabled ? 'Graphing ON' : 'Graphing OFF'} -
+
{app.graphing.graphingEnabled ? "Graphing ON" : "Graphing OFF"}
{/* TX/RX ACTIVITY INDICATORS */} {/* Use the key prop here to make React consider this a new element everytime the number of bytes changes. This will re-trigger the flashing animation as desired. Wrap each indicator in another box, so that the keys don't collide (because they might be the same). */} - TX + + TX + - RX + + RX + {/* PORT CONFIG */} {/* Show port configuration in short hand, e.g. "115200 8n1" */} - {app.settings.shortSerialConfigName} + {app.settings.portConfiguration.shortSerialConfigName} {/* PORT STATE */} - {portStateToToolbarStatusProperties[app.portState].text} + {portStateToToolbarStatusProperties[app.portState].text}
@@ -312,8 +305,13 @@ const AppView = observer((props: Props) => { {/* The SnackBar's position in the DOM does not matter, it is not positioned in the doc flow. Anchor to the bottom right as a terminals cursor will typically be in the bottom left */} - + + {/* The backdrop is not in the normal document flow. Shown as modal. Used when we want to indicate to the + user that we are doing something and block them from clicking on anything (e.g. when opening port) */} + theme.zIndex.drawer + 1 }} open={app.showCircularProgressModal}> + +
); diff --git a/src/view/Settings/PortConfigurationSettings/PortConfigurationSettingsView.tsx b/src/view/Settings/PortConfigurationSettings/PortConfigurationSettingsView.tsx index 5f8d54e0..5250b230 100644 --- a/src/view/Settings/PortConfigurationSettings/PortConfigurationSettingsView.tsx +++ b/src/view/Settings/PortConfigurationSettings/PortConfigurationSettingsView.tsx @@ -12,13 +12,14 @@ import { FormControlLabel, Autocomplete, TextField, + Backdrop, + CircularProgress, } from '@mui/material'; import { OverridableStringUnion } from '@mui/types'; import { observer } from 'mobx-react-lite'; import { App, PortType } from 'src/model/App'; -import { PortState, DEFAULT_BAUD_RATES } from 'src/model/Settings/PortConfigurationSettings/PortConfigurationSettings'; -import { StopBits } from 'src/model/Settings/Settings'; +import { PortState, DEFAULT_BAUD_RATES, NUM_DATA_BITS_OPTIONS, Parity, STOP_BIT_OPTIONS, StopBits } from 'src/model/Settings/PortConfigurationSettings/PortConfigurationSettings'; import { portStateToButtonProps } from 'src/view/Components/PortStateToButtonProps'; import styles from './PortConfigurationSettingsView.module.css'; @@ -37,78 +38,70 @@ function PortConfigurationView(props: Props) {
- {/* ====================== BAUD RATE ============================= */} - - Baud Rate - - + {/* ============================================================== */} + {/* BAUD RATE */} + {/* ============================================================== */} + option.toString())} - renderInput={(params) => } - sx={{ m: 1, width: 160 }} size="small" - onChange={(event: any, newValue: string | null) => { - console.log('onChange() called. newValue: ', newValue); - }} - inputValue={app.settings.portConfiguration.baudRateInputValue} - onInputChange={(event, newInputValue) => { - console.log('newInputValue: ', newInputValue); - app.settings.portConfiguration.setBaudRateInputValue(newInputValue); - }} - /> - {/* ====================== NUM. DATA BITS ============================= */} + freeSolo + options={DEFAULT_BAUD_RATES.map((option) => option.toString())} + renderInput={( + params) => + { e.stopPropagation(); }} // Prevents the global keydown event from being triggered + />} + disabled={app.portState !== PortState.CLOSED} + sx={{ m: 1, width: 160 }} size="small" + onChange={(event: any, newValue: string | null) => { + console.log('onChange() called. newValue: ', newValue); + }} + inputValue={app.settings.portConfiguration.baudRateInputValue} + onInputChange={(event, newInputValue) => { + console.log('newInputValue: ', newInputValue); + app.settings.portConfiguration.setBaudRateInputValue(newInputValue); + }} + /> + + {/* ============================================================== */} + {/* NUM. DATA BITS */} + {/* ============================================================== */} Num. Data Bits - {/* ====================== PARITY ============================= */} + {/* ============================================================== */} + {/* PARITY */} + {/* ============================================================== */} Parity - {/* ========================== STOP BITS ============================= */} + {/* ============================================================== */} + {/* STOP BITS */} + {/* ============================================================== */} Stop Bits