First version of app, by GPT5
This commit is contained in:
@@ -18,6 +18,9 @@ export default function Home() {
|
||||
Get started by editing <code>src/app/page.tsx</code>.
|
||||
</li>
|
||||
<li>Save and see your changes instantly.</li>
|
||||
<li>
|
||||
Explore the <a href="/registers">Spectrum Next Registers</a>.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<div className={styles.ctas}>
|
||||
|
||||
45
src/app/registers/RegisterBrowser.tsx
Normal file
45
src/app/registers/RegisterBrowser.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Register } from './types';
|
||||
import { Form, Card, Container, Row, Col } from 'react-bootstrap';
|
||||
|
||||
interface RegisterBrowserProps {
|
||||
registers: Register[];
|
||||
}
|
||||
|
||||
export default function RegisterBrowser({ registers }: RegisterBrowserProps) {
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
|
||||
const filteredRegisters = registers.filter(register =>
|
||||
register.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
register.description.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<Container fluid>
|
||||
<Form.Group className="mb-3">
|
||||
<Form.Control
|
||||
type="text"
|
||||
placeholder="Search registers..."
|
||||
value={searchTerm}
|
||||
onChange={e => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
</Form.Group>
|
||||
<Row>
|
||||
{filteredRegisters.map(register => (
|
||||
<Col key={register.hex_address} xs={12} md={6} lg={4} className="mb-4">
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<strong>{register.name}</strong> ({register.hex_address} / {register.dec_address})
|
||||
</Card.Header>
|
||||
<Card.Body>
|
||||
<pre style={{ whiteSpace: 'pre-wrap' }}>{register.description}</pre>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
87
src/app/registers/page.tsx
Normal file
87
src/app/registers/page.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import { promises as fs } from 'fs';
|
||||
import path from 'path';
|
||||
import RegisterBrowser from './RegisterBrowser';
|
||||
import { Register } from './types';
|
||||
|
||||
async function parseNextReg(fileContent: string): Promise<Register[]> {
|
||||
const registers: Register[] = [];
|
||||
const paragraphs = fileContent.split(/\n\s*\n/);
|
||||
|
||||
for (const paragraph of paragraphs) {
|
||||
if (!paragraph.trim()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const lines = paragraph.trim().split('\n');
|
||||
processRegisterBlock(lines, registers);
|
||||
}
|
||||
|
||||
return registers;
|
||||
}
|
||||
|
||||
function processRegisterBlock(lines: string[], registers: Register[]) {
|
||||
const firstLine = lines[0];
|
||||
const restOfLines = lines.slice(1);
|
||||
|
||||
const multiRegisterMatch = firstLine.match(/([0-9a-fA-F,x]+)\s*\(.*?\)\s*=>\s*(.*)/);
|
||||
|
||||
if (multiRegisterMatch) {
|
||||
const hexAddresses = multiRegisterMatch[1].trim();
|
||||
const decAddresses = multiRegisterMatch[2].trim();
|
||||
const name = multiRegisterMatch[3] ? multiRegisterMatch[3].trim() : '';
|
||||
const description = restOfLines.join('\n').trim();
|
||||
|
||||
const hexList = hexAddresses.split(',').map(h => h.trim());
|
||||
const decList = decAddresses.includes('-') ? decAddresses.split('-') : decAddresses.split(',').map(d => d.trim());
|
||||
|
||||
if (hexList.length > 1) {
|
||||
for (let i = 0; i < hexList.length; i++) {
|
||||
const hexAddr = hexList[i];
|
||||
const decAddr = decList[i] || decAddresses;
|
||||
registers.push({
|
||||
hex_address: hexAddr,
|
||||
dec_address: isNaN(parseInt(decAddr, 10)) ? decAddr : parseInt(decAddr, 10),
|
||||
name: `${name} (${hexAddr})`,
|
||||
description: description,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
registers.push({
|
||||
hex_address: hexAddresses,
|
||||
dec_address: isNaN(parseInt(decAddresses, 10)) ? decAddresses : parseInt(decAddresses, 10),
|
||||
name: name,
|
||||
description: description,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const singleRegisterMatch = lines[0].match(/(0x[0-9a-fA-F]{2})\s+(\d+)\s+=>\s+(.*)/);
|
||||
if(singleRegisterMatch) {
|
||||
const description = lines.slice(1).join('\n').trim();
|
||||
const hexAddr = singleRegisterMatch[1].trim();
|
||||
const decAddr = singleRegisterMatch[2].trim();
|
||||
const name = singleRegisterMatch[3].trim();
|
||||
|
||||
registers.push({
|
||||
hex_address: hexAddr,
|
||||
dec_address: parseInt(decAddr, 10),
|
||||
name: name,
|
||||
description: description,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default async function RegistersPage() {
|
||||
const filePath = path.join(process.cwd(), 'data', 'nextreg_bare.txt');
|
||||
const fileContent = await fs.readFile(filePath, 'utf8');
|
||||
const registers = await parseNextReg(fileContent);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Spectrum Next Registers</h1>
|
||||
<RegisterBrowser registers={registers} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
21
src/app/registers/types.ts
Normal file
21
src/app/registers/types.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export interface BitwiseOperation {
|
||||
bits: string;
|
||||
description: string;
|
||||
value?: string;
|
||||
notes?: string[];
|
||||
}
|
||||
|
||||
export interface RegisterAccess {
|
||||
description?: string;
|
||||
operations: BitwiseOperation[];
|
||||
}
|
||||
|
||||
export interface Register {
|
||||
hex_address: string;
|
||||
dec_address: number | string;
|
||||
name: string;
|
||||
description: string;
|
||||
read?: RegisterAccess;
|
||||
write?: RegisterAccess;
|
||||
notes?: string[];
|
||||
}
|
||||
Reference in New Issue
Block a user