0 ? 'mt-4' : ''}>
- {register.modes.length > 1 && (
-
Mode {idx + 1}
- )}
-
- {mode.common && {renderAccess(mode.common)}}
- {mode.read && {renderAccess(mode.read)}}
- {mode.write && {renderAccess(mode.write)}}
-
- {mode.notes && mode.notes.map((note, index) => (
-
{note.ref} {note.text}
- ))}
- {mode.text && mode.text.length > 0 && (
-
-
Notes:
-
{mode.text}
+
0 ? 'mt-4' : ''}>
+
+ {mode.modeName?.length && (
+
{mode.modeName}
+ )}
+
+ {mode.common && {renderAccess(mode.common, register.notes)}}
+ {mode.read && {renderAccess(mode.read, register.notes)}}
+ {mode.write && {renderAccess(mode.write, register.notes)}}
+
+
+ {mode.text && mode.text.length > 0 && (
+
+
Mode Notes:
+
{mode.text}
+
+ )}
- )}
-
))}
+ {register.notes && register.notes.map((note, index) => (
+
{note.ref}: {note.text}
+ ))}
+ {register.text && register.text.length > 0 && (
+
+
Notes:
+
{register.text}
+
+ )}
diff --git a/src/app/scss/_variables.scss b/src/app/scss/_variables.scss
index 93f9444..0635ed1 100644
--- a/src/app/scss/_variables.scss
+++ b/src/app/scss/_variables.scss
@@ -1,5 +1,6 @@
// Pulse 5.3.8
// Bootswatch
+@use 'sass:color';
$theme: "pulse" !default;
@@ -86,7 +87,7 @@ $progress-bar-bg: $primary !default;
$list-group-bg: $gray-900 !default;
$list-group-border-color: transparent !default;
-$list-group-hover-bg: lighten($list-group-bg, 10%) !default;
+$list-group-hover-bg: color.scale($list-group-bg, $lightness:10%) !default;
$list-group-active-color: $white !default;
$list-group-active-bg: $list-group-bg !default;
-$list-group-disabled-color: lighten($list-group-bg, 30%) !default;
+$list-group-disabled-color: color.scale($list-group-bg, $lightness:30%) !default;
diff --git a/src/app/services/register.service.ts b/src/app/services/register.service.ts
index dfa71de..a614138 100644
--- a/src/app/services/register.service.ts
+++ b/src/app/services/register.service.ts
@@ -11,10 +11,10 @@ let registers: Register[] = [];
* @returns A promise that resolves to an array of Register objects.
*/
export async function getRegisters(): Promise
{
- if (registers.length === 0) {
+ // if (registers.length === 0) {
const filePath = path.join(process.cwd(), 'data', 'nextreg.txt');
const fileContent = await fs.readFile(filePath, 'utf8');
registers = await parseNextReg(fileContent);
- }
+ // }
return registers;
}
diff --git a/src/utils/register_parser.ts b/src/utils/register_parser.ts
index da49f35..07d2406 100644
--- a/src/utils/register_parser.ts
+++ b/src/utils/register_parser.ts
@@ -20,11 +20,11 @@ export interface RegisterAccess {
}
export interface RegisterDetail {
+ modeName?: string;
read?: RegisterAccess;
write?: RegisterAccess;
common?: RegisterAccess;
text: string;
- notes: Note[];
}
export interface Register {
@@ -35,6 +35,8 @@ export interface Register {
description: string;
issue_4_only: boolean;
source: string[];
+ text: string;
+ notes: Note[];
}
/**
@@ -91,7 +93,9 @@ export function processRegisterBlock(paragraph: string, registers: Register[]) {
description: description,
modes: [],
issue_4_only: false,
- source: []
+ source: [],
+ text: "",
+ notes: [],
};
// Dispatch to appropriate parser based on hex
diff --git a/src/utils/register_parsers/reg_default.ts b/src/utils/register_parsers/reg_default.ts
index 4ebb55f..938166a 100644
--- a/src/utils/register_parsers/reg_default.ts
+++ b/src/utils/register_parsers/reg_default.ts
@@ -5,11 +5,12 @@ export const parseDescriptionDefault = (reg: Register, description: string) => {
let currentAccess: 'read' | 'write' | 'common' | null = null;
let accessData: RegisterAccess = { operations: [], notes: [] };
// Prepare a new RegisterDetail for this description block
- const detail: RegisterDetail = { read: undefined, write: undefined, common: undefined, text: '', notes: [] };
+ const detail: RegisterDetail = { read: undefined, write: undefined, common: undefined, text: ''};
for (const line of descriptionLines) {
if (line.includes('Issue 4 Only')) reg.issue_4_only = true;
+ const spaces_at_start = line.match(/^(\s*)/)?.[0].length || 0;
const trimmedLine = line.trim();
reg.source.push(line);
@@ -50,7 +51,7 @@ export const parseDescriptionDefault = (reg: Register, description: string) => {
if (currentAccess) {
const bitMatch = trimmedLine.match(/^(bits?|bit)\s+([\d:-]+)\s*=\s*(.*)/);
- const valueMatch = !line.match(/^\s+/) && trimmedLine.match(/^([01\s]+)\s*=\s*(.*)/);
+ // const valueMatch = !line.match(/^\s+/) && trimmedLine.match(/^([01\s]+)\s*=\s*(.*)/);
if (bitMatch) {
let bitDescription = bitMatch[3];
@@ -65,13 +66,15 @@ export const parseDescriptionDefault = (reg: Register, description: string) => {
description: bitDescription,
footnoteRef: footnoteRef,
});
- } else if (valueMatch) {
- accessData.operations.push({
- bits: valueMatch[1].trim().replace(/\s/g, ''),
- description: valueMatch[2].trim(),
- });
+ // } else if (valueMatch) {
+ // console.error("VALUE MATCH",valueMatch);
+ // accessData.operations.push({
+ // bits: valueMatch[1].trim().replace(/\s/g, ''),
+ // description: valueMatch[2].trim(),
+ // });
} else if (trimmedLine.startsWith('*')) {
const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/);
+ console.log("NOTE MATCH",noteMatch);
if (noteMatch) {
accessData.notes.push({
ref: noteMatch[1],
@@ -79,6 +82,12 @@ export const parseDescriptionDefault = (reg: Register, description: string) => {
});
}
} else if (trimmedLine) {
+ if(spaces_at_start == 2) {
+ reg.text += `${line}\n`;
+ continue;
+ }
+ // console.log("LINE",line);
+ console.log(line.match(/^\s+/), line);
if (line.match(/^\s+/) && accessData.operations.length > 0) {
accessData.operations[accessData.operations.length - 1].description += `\n${line}`;
} else {
@@ -92,7 +101,7 @@ export const parseDescriptionDefault = (reg: Register, description: string) => {
if (trimmedLine.startsWith('*')) {
const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/);
if (noteMatch) {
- detail.notes.push({
+ reg.notes.push({
ref: noteMatch[1],
text: noteMatch[2],
});
diff --git a/src/utils/register_parsers/reg_f0.ts b/src/utils/register_parsers/reg_f0.ts
index 1c7a68a..7d2e20b 100644
--- a/src/utils/register_parsers/reg_f0.ts
+++ b/src/utils/register_parsers/reg_f0.ts
@@ -1,101 +1,131 @@
-// Special-case parser for 0xF0 (XDEV CMD): treat headings beginning with '*' inside access blocks
-// as descriptive text instead of notes, so sub-modes become part of the section descriptions.
-import {Register, RegisterAccess, RegisterDetail} from "@/utils/register_parser";
+// Special-case parser for 0xF0 (XDEV CMD): implement multi-mode parsing.
+// Rules:
+// - A line that begins with exactly two spaces (" ") and then a non-* character starts a new mode; the trimmed text is modeName.
+// - Lines with three or more leading spaces (>=3) belong to the current mode.
+// - A line with exactly two spaces followed by '*' is a parent (register-level) note, not a mode note.
+// - Inside access blocks for F0, lines starting with '*' are headings for description (not notes).
+import { Register, RegisterAccess, RegisterDetail } from "@/utils/register_parser";
export const parseDescriptionF0 = (reg: Register, description: string) => {
- const descriptionLines = description.split('\n');
- let currentAccess: 'read' | 'write' | 'common' | null = null;
- let accessData: RegisterAccess = { operations: [], notes: [] };
- const detail: RegisterDetail = { read: undefined, write: undefined, common: undefined, text: '', notes: [] };
+ const descriptionLines = description.split('\n');
+ let currentAccess: 'read' | 'write' | 'common' | null = null;
+ let accessData: RegisterAccess = { operations: [], notes: [] };
+ // Prepare a new RegisterDetail for this description block
+ let detail: RegisterDetail = { read: undefined, write: undefined, common: undefined, text: ''};
+ reg.modes = reg.modes || [];
- for (const line of descriptionLines) {
- if (line.includes('Issue 4 Only')) reg.issue_4_only = true;
+ for (const line of descriptionLines) {
+ reg.source.push(line);
+ const spaces_at_start = line.match(/^(\s*)/)?.[0].length || 0;
+ const trimmedLine = line.trim();
- const trimmedLine = line.trim();
- reg.source.push(line);
-
- if (trimmedLine.startsWith('//')) continue;
-
- if (trimmedLine.startsWith('(R)')) {
- if (currentAccess) detail[currentAccess] = accessData;
- accessData = { operations: [], notes: [] };
- currentAccess = 'read';
- continue;
+ if(spaces_at_start == 2) {
+ if (trimmedLine.startsWith('*')) {
+ console.log("PARENT",trimmedLine);
+ const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/);
+ if (noteMatch) {
+ reg.notes.push({
+ ref: noteMatch[1],
+ text: noteMatch[2],
+ });
}
- if (trimmedLine.startsWith('(W)')) {
- if (currentAccess) detail[currentAccess] = accessData;
- accessData = { operations: [], notes: [] };
- currentAccess = 'write';
- continue;
- }
- if (trimmedLine.startsWith('(R/W')) {
- if (currentAccess) detail[currentAccess] = accessData;
- accessData = { operations: [], notes: [] };
- currentAccess = 'common';
- continue;
- }
- if (line.startsWith(trimmedLine)) {
- if (currentAccess) detail[currentAccess] = accessData;
- accessData = { operations: [], notes: [] };
- currentAccess = null;
- }
-
+ continue;
+ } else {
if (currentAccess) {
- const bitMatch = trimmedLine.match(/^(bits?|bit)\s+([\d:-]+)\s*=\s*(.*)/);
- const valueMatch = !line.match(/^\s+/) && trimmedLine.match(/^([01\s]+)\s*=\s*(.*)/);
-
- if (bitMatch) {
- let bitDescription = bitMatch[3];
- const footnoteMatch = bitDescription.match(/(\*+)$/);
- let footnoteRef: string | undefined = undefined;
- if (footnoteMatch) {
- footnoteRef = footnoteMatch[1];
- bitDescription = bitDescription.substring(0, bitDescription.length - footnoteRef.length).trim();
- }
- accessData.operations.push({
- bits: bitMatch[2],
- description: bitDescription,
- footnoteRef: footnoteRef,
- });
- } else if (valueMatch) {
- accessData.operations.push({
- bits: valueMatch[1].trim().replace(/\s/g, ''),
- description: valueMatch[2].trim(),
- });
- } else if (trimmedLine.startsWith('*')) {
- // SPECIAL: treat star lines as headings in description rather than notes
- const heading = trimmedLine.replace(/^\*+\s*/, '').trim();
- if (!accessData.description) accessData.description = '';
- accessData.description += (accessData.description ? '\n' : '') + heading;
- } else if (trimmedLine) {
- if (line.match(/^\s+/) && accessData.operations.length > 0) {
- accessData.operations[accessData.operations.length - 1].description += `\n${line}`;
- } else {
- if (!accessData.description) {
- accessData.description = '';
- }
- accessData.description += `\n${trimmedLine}`;
- }
- }
- } else {
- if (trimmedLine.startsWith('*')) {
- // Outside access blocks, keep notes as-is but attach to detail now
- const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/);
- if (noteMatch) {
- detail.notes.push({
- ref: noteMatch[1],
- text: noteMatch[2],
- });
- }
- } else if (trimmedLine) {
- detail.text += `${line}\n`;
- }
+ // finalize previous access block into detail
+ detail[currentAccess] = accessData;
}
+ reg.modes.push(detail);
+ detail = {read: undefined, write: undefined, common: undefined, text: ''};
+ detail.modeName = trimmedLine;
+
+ accessData = {operations: [], notes: []};
+ currentAccess = null;
+ continue;
+ }
}
- if (currentAccess) {
+
+ if (line.includes('Issue 4 Only')) reg.issue_4_only = true;
+
+
+ if (trimmedLine.startsWith('//')) continue;
+
+ if (trimmedLine.startsWith('(R)')) {
+ if (currentAccess) {
+ // finalize previous access block into detail
detail[currentAccess] = accessData;
+ }
+ accessData = { operations: [], notes: [] };
+ currentAccess = 'read';
+ continue;
}
- reg.modes = reg.modes || [];
- reg.modes.push(detail);
+ if (trimmedLine.startsWith('(W)')) {
+ if (currentAccess) {
+ detail[currentAccess] = accessData;
+ }
+ accessData = { operations: [], notes: [] };
+ currentAccess = 'write';
+ continue;
+ }
+ if (trimmedLine.startsWith('(R/W')) {
+ if (currentAccess) {
+ detail[currentAccess] = accessData;
+ }
+ accessData = { operations: [], notes: [] };
+ currentAccess = 'common';
+ continue;
+ }
+
+ if (currentAccess) {
+ const bitMatch = trimmedLine.match(/^(bits?|bit)\s+([\d:-]+)\s*=\s*(.*)/);
+ const valueMatch = !line.match(/^\s+/) && trimmedLine.match(/^([01\s]+)\s*=\s*(.*)/);
+
+ if (bitMatch) {
+ let bitDescription = bitMatch[3];
+ const footnoteMatch = bitDescription.match(/(\*+)$/);
+ let footnoteRef: string | undefined = undefined;
+ if (footnoteMatch) {
+ console.log("FOOTNOTE",footnoteMatch);
+ footnoteRef = footnoteMatch[1];
+ bitDescription = bitDescription.substring(0, bitDescription.length - footnoteRef.length).trim();
+ }
+ accessData.operations.push({
+ bits: bitMatch[2],
+ description: bitDescription,
+ footnoteRef: footnoteRef,
+ });
+ } else if (valueMatch) {
+ accessData.operations.push({
+ bits: valueMatch[1].trim().replace(/\s/g, ''),
+ description: valueMatch[2].trim(),
+ });
+ } else if (trimmedLine.startsWith('*') && spaces_at_start > 2) {
+ const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/);
+ if (noteMatch) {
+ reg.notes.push({
+ ref: noteMatch[1],
+ text: noteMatch[2],
+ });
+ }
+ }
+ } else if (trimmedLine) {
+ console.log("LINE", trimmedLine);
+ if (line.match(/^\s+/) && accessData.operations.length > 0) {
+ accessData.operations[accessData.operations.length - 1].description += `\n${line}`;
+ } else {
+ if (!accessData.description) {
+ accessData.description = '';
+ }
+ accessData.description += `\n${trimmedLine}`;
+ }
+ }
+ }
+ if (currentAccess) {
+ detail[currentAccess] = accessData;
+ console.log("FINAL",detail,currentAccess);
+ }
+
+ // Push the parsed detail into modes
+ reg.modes.push(detail);
};