Closed urish closed 3 years ago
Please consider the following draft, I have done a simple test
eeprom.ts
import {CPU} from '../cpu/cpu';
import {avrInterrupt} from '../cpu/interrupt';
import {u8} from '../types';
export interface EEPROMConfig {
EECR: u8;
EEDR: u8;
EEARL: u8;
EEARH: u8;
}
export const eepromConfig: EEPROMConfig = {
EECR: 0x3F,
EEDR: 0x40,
EEARL: 0x41,
EEARH: 0x42,
};
const EERE = 1 << 0;
const EEPE = 1 << 1;
const EEMPE = 1 << 2;
const EERIE = 1 << 3;
const EEPM0 = 1 << 4;
const EEPM1 = 1 << 5;
const PREFIX = 'EEPROM';
export class EEPROM {
constructor(private cpu: CPU, private config: EEPROMConfig) {
this.cpu.data[this.config.EEARH] &= 1;
this.cpu.data[this.config.EEDR] = 0;
this.cpu.data[this.config.EECR] &= 0b00110010;
this.cpu.writeHooks[this.config.EECR] = (eecr, ov) => {
let al = this.cpu.data[this.config.EEARL];
let ah = this.cpu.data[this.config.EEARH];
let addr = (ah<<8) + al;
let eedr = this.cpu.data[this.config.EEDR];
// read
if(eecr & EERE) {
let r = localStorage.getItem(PREFIX + `[${addr}]`);
this.cpu.data[this.config.EEDR] = r;
return true;
}
// write
else if(eecr & EEPE) {
// Erase + Write
if(!(eecr & EEPM0) && !(eecr & EEPM1)) {
localStorage.setItem(PREFIX + `[${addr}]`, eedr);
}
// Erase only
else if((eecr & EEPM0) && !(eecr && EEPM1)) {
localStorage.removeItem(PREFIX + `[${addr}]`);
}
// Write only
else if(!(eecr & EEPM0) && (eecr && EEPM1)) {
let r = localStorage.getItem(PREFIX + `[${addr}]`);
localStorage.setItem(PREFIX + `[${addr}]`, eedr | r);
}
// rev.
else {
}
this.cpu.data[this.config.EECR] &= ~EEPE;
return true;
}
// default handling
return false;
};
}
tick() {
if (this.cpu.interruptsEnabled) {
}
}
}
Thank you so much!
Do you happen to know some AVR assembly as well? It will be great to have test cases in assembly that run can also run on the actual chip and compare the implementation, like we have for TWI or for the timers.
Thanks for your good suggestions.
Most of my time is spent on PC development, and only a small amount of time is spent on chip development, so I am not very familiar with avr assembly and may need time to learn it.
Avr8js is a good project and excellent idea, I am trying to run grbl hex based on it. So the code I wrote directly runs grbl for testing and executes it correctly to achieve my goal.
However, in the process of running grbl, an additional problem arises: maybe there is some implementation of timer1 or timer0 that is not very perfect, because the interrupt function of pwm implemented by timer1 or timer0 in grbl has not been executed, including CTC mode. The way grbl uses timers may be special, but it works correctly on physical chips and proteus8.
For the problem of timer, I am seriously analyzing the chip manual and reading the source code of your relevant part, i try to find the difference between the avr8js timer implemented and physical chip. I also hope to get your help.
Thank you!
Hi @yiivon, thank you for sharing information about your project!
The timers should be pretty accurate, but there is at least one known issue: #41.
It would be best if we could find a simple code example that reproduces the problem, as this would make finding the issue much easier.
Also, how did you set up the timers?
Thanks again @yiivon, I implemented this feature by the simulator inspired by your code, also with tests.
In my implementation, you pass an EEPROMBackend
, which is the object the manages the actual storage for the EEPROM. There's also sample backend which stores everything in memory is provided, called EEPROMMemoryBackend
, and it should be pretty straight forward to implement something that stores the values to localStorage
, like you did above.
Here is an example of EEPROMBackend
that is saved to localStorage, similar to what you did:
https://stackblitz.com/edit/avr8js-eeprom-localstorage?file=eeprom-localstorage-backend.ts
EEPROM allows the AVR program to persist data between runs. The implementation will probably allow the user to specify a callback to read/write/erase data, thus supporting different backends. For instance, the user could use localStorage as a backend for the EEPROM data.
Register description can be found in page 31 / section 8.6 of the datasheet.