blob: 23210232ca3d9ed0022f24b948ec2a654e56ab37 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
// AVR-Dx NVMCTRL + Mapped EEPROM
// EEPROM is memory-mapped at 0x1400-0x14FF and accessed via NVMCTRL commands.
import type { CPU } from 'avr8js/cpu/cpu';
import type { AVRDxCCP } from './avrdx-ccp';
const CTRLA = 0x0000;
// const CTRLB = 0x0001;
// const STATUS = 0x0002;
// const INTCTRL = 0x0003;
// const INTFLAGS = 0x0004;
// const DATAL = 0x0006;
// const DATAH = 0x0007;
// const ADDR0 = 0x0008;
// const ADDR1 = 0x0009;
// const ADDR2 = 0x000A;
// const ADDR3 = 0x000B;
// CMD values
const CMD_NONE_gc = 0x00;
const CMD_NOOP_gc = 0x01;
// const CMD_FLWR_gc = 0x02;
// const CMD_FLPER_gc = 0x08;
// const CMD_FLMPER2_gc = 0x09;
// const CMD_FLMPER4_gc = 0x0A;
// const CMD_FLMPER8_gc = 0x0B;
// const CMD_FLMPER16_gc = 0x0C;
// const CMD_FLMPER32_gc = 0x0D;
const CMD_EEWR_gc = 0x12;
const CMD_EEERWR_gc = 0x13;
const CMD_EEBER_gc = 0x18;
// const CMD_EEMBER2_gc = 0x19;
// const CMD_EEMBER4_gc = 0x1A;
// const CMD_EEMBER8_gc = 0x1B;
// const CMD_EEMBER16_gc = 0x1C;
// const CMD_EEMBER32_gc = 0x1D;
export class AVRDxNVMCTRL {
readonly eeprom: Uint8Array;
/** Page buffer for EEPROM writes (tracks which bytes have been written) */
private pageBuffer: Uint8Array;
private pageBufferDirty: Uint8Array;
constructor(cpu: CPU, base: number, start: number, private size: number, private ccp: AVRDxCCP, init: undefined | Uint8Array = undefined) {
this.eeprom = new Uint8Array(size);
this.pageBuffer = new Uint8Array(size);
this.pageBufferDirty = new Uint8Array(size);
this.eeprom.fill(0xFF);
if (init) this.loadEeprom(init);
// CTRLA - CCP protected, executes NVM commands
cpu.writeHooks[base + CTRLA] = (value: number) => {
if (this.ccp.isUnlocked()) {
cpu.data[base + CTRLA] = value;
this.executeCommand(value);
}
return true;
};
// Mapped EEPROM read hooks (0x1400-0x14FF)
for (let i = 0; i < size; i++) {
cpu.readHooks[start + i] = () => this.eeprom[i];
// Writes to mapped EEPROM go to the page buffer
cpu.writeHooks[start + i] = (value: number) => {
this.pageBuffer[i] = value;
this.pageBufferDirty[i] = 1;
// Check the current active command
const cmd = cpu.data[base + CTRLA];
if (cmd === CMD_EEERWR_gc) {
// Erase+write: replace byte directly
this.eeprom[i] = value;
this.pageBufferDirty[i] = 0;
} else if (cmd === CMD_EEWR_gc) {
// Write-only: AND with existing data (can only clear bits)
this.eeprom[i] &= value;
this.pageBufferDirty[i] = 0;
}
return true;
};
}
}
loadEeprom(data: Uint8Array) {
this.eeprom.set(data.subarray(0, this.size));
}
private executeCommand(cmd: number) {
switch (cmd) {
case CMD_NONE_gc:
case CMD_NOOP_gc:
this.pageBufferDirty.fill(0);
break;
case CMD_EEWR_gc:
// Write-only mode: subsequent mapped EEPROM writes AND with existing data.
// Actual writes happen in the mapped EEPROM write hooks.
// Don't clear command — it stays active until NONE/NOOP.
break;
case CMD_EEERWR_gc:
// Erase+write mode: subsequent mapped EEPROM writes replace data directly.
// Actual writes happen in the mapped EEPROM write hooks.
// Don't clear command — it stays active until NONE/NOOP.
break;
case CMD_EEBER_gc:
// Erase EEPROM page (the page containing the address in ADDR)
// For simplicity, erase the whole EEPROM
// TODO: figure out page size
this.eeprom.fill(0xFF);
this.pageBufferDirty.fill(0);
break;
default:
// TODO: implement other commands (if needed)
break;
}
}
}
|
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation
Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions.
For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage.
In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.