Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simpler API? Request for comments #87

Open
urish opened this issue Mar 5, 2021 · 13 comments
Open

Simpler API? Request for comments #87

urish opened this issue Mar 5, 2021 · 13 comments
Labels
question Further information is requested

Comments

@urish
Copy link
Contributor

urish commented Mar 5, 2021

As part of the discussion in #67, I started working on creating a simpler API for using the simulator.

For instance, creating an ATmega328p simulation, will look something like:

import { createAVR, ATmega328p } from 'avr8js';

const { cpu } = createAVR(ATmega328p);

// Microcontroller loop
while (...) {
  avrInstruction(cpu);
  cpu.tick();
}

The idea is that createAVR() will return an object that contains the CPU and all the peripherals:

{
  cpu: CPU;
  timers: AVRTimer[];
  clock: AVRClock[];
  eeprom: AVREEPROM;
  spi: AVRSPI;
  usart: AVRUSART[];
  twi: AVRTWI;
  gpio: { [key: string]: AVRIOPort };
};

e.g. if you need accept to GPIO port B and the first hardware USART peripheral you could do something like:

const { cpu, gpio, usart } = createAVR(ATmega328p);

gpio.B.addListener(() => {
  // listener code
});

usart[0].onLineTransmit = () => {
  // listener code
};

I've created a prototype in the simpler-api branch, and would love to hear your thoughts - especially from people who worked with the current API in the past, e.g. @gfeun, @elliottkember, @ricardojlrufino, @SebastianZug, @tawjaw, @yiivon.

Should we keep the API the way it is? Do you like the proposed API better? What can we improve?

@urish urish added the question Further information is requested label Mar 5, 2021
@tawjaw
Copy link

tawjaw commented Mar 5, 2021

This looks great! I think many people would like to use this library as an Arduino board simulation more than AVR simulation.

This library was extremely educational for me on AVR architecture and helped me understand every little detail of the basic Arduino boards that I've been using for a while but only worked with as a "black box".

However I don't think everyone would like to go through that learning phase to use the library. For example the difference between Uno and Mega board.

So this would probably attracts bigger audience and makes it easy to simulate existing boards.

I've been playing around with some high level way to implement connections and electronics with AVR8js

const uno = new Uno();
const led = new Led();
const resistor = new Resistor(0.2);

const wire1 = new Wire();
wire1.left = uno.digital[3];
wire1.right = led.cathode;

// etc ...

uno.run();

Although so far everything I've played with has been using High, Low only. And just updating all the wires and components recursively whenever AVR pin gets updated.

I would like to make it more realistic and include circuit simulation with this.

So it would actually make a difference if you use a resistor with the LED or not.

Would this be an interest for this new API? And the development roadmap of AVR8js?

Or do you see it as a separate project that would at some point integrate Pico simulation maybe.

@urish
Copy link
Contributor Author

urish commented Mar 6, 2021

Thanks for the detailed feedback!

Yes, something like you suggest seems to be out of the scope of AVR8js, as it goes into digital (and maybe also analog?) simulation, and is not AVR specific.

with the new API, I guess the implementation of UNO would look something along the lines of:

class Uno {
  constructor() {
    const { cpu, gpio }  = createAVR(ATmega328p);
    this.cpu = cpu;
    this.digital = {
      0: new DigitalPin(gpio.D, 0),
      1: new DigitalPin(gpio.D, 1),
       ...
      13: new DigitalPin(gpio.B, 5),
    }
  }

  run() {
    while (...) {
      avrInstruction(cpu);
      cpu.tick();
    }

    requestAnimationFrame(() => this.run());
  } 
}

WDYT?

@tawjaw
Copy link

tawjaw commented Mar 6, 2021

I like this.

So all the parts of AVR are being initialized with the CPU object even if you're not importing them from createAVR?

How would you rerun the simulation?
Call createAVR again?

@urish
Copy link
Contributor Author

urish commented Mar 6, 2021

Yes, exactly. I figured out that in most cases, people would probably want the default configuration for the chip. But the API can let you initialize things differently, at least the way it's prototyped now. The ATmega328p is a configuration object with all the peripherals. So let's say you don't want the SPI for some reason, you could do something like:

createAVR({
  ...ATmega328p,
  spi: [],
})

and that would create zero SPI peripherals.

Regarding resetting the simulation - yes. There's a reset() method on the CPU, but the not for all the peripherals. So it's best just to recreate everything whenever you restart the simulation

@tawjaw
Copy link

tawjaw commented Mar 7, 2021

I like this a lot. I was going to ask what if someone doesn't want all the components.. I didn't think of using it this way.

Would it be possible to use EEPROM with local storage using this API?

@urish
Copy link
Contributor Author

urish commented Mar 7, 2021

Would it be possible to use EEPROM with local storage using this API?

I addressed this by letting you specify a different EEPROM backend, so given this localstorage backend implementation you could do something like:

createAVR(ATmega328p, { 
  eepromBackend: new EEPROMLocalStorageBackend()
});

What else?

@tawjaw
Copy link

tawjaw commented Mar 7, 2021

how about interrupt pins configuration per chip?
I think this is an issue right now with AVR8js in general? #82 #70

@urish
Copy link
Contributor Author

urish commented Mar 7, 2021

Indeed! there's a pull-request, mostly working. I have to sit down for half a day and finish it.

Does it affect in any way the new API?

@tawjaw
Copy link

tawjaw commented Mar 8, 2021

I may be wrong but wouldn't it have different configuration for external interrupts per chip?

On the Uno it's pin 2 and 3.

On the mega it's 2, 3, 18, 19, 20, 21.

The ATMega4809 on the Nano Every has all digital pins usable for interrupts.

How would this be set with the new API after the pull-request is merged

@SebastianZug
Copy link

I guess it is not necessary to integrate a broad bunch of microcontrollers but the new API is a great idea. A real unique selling point would be the integration of a gdb interface. With this, in addition to the continuous execution of a program, one could then also step through the code and explain certain processes.

@urish
Copy link
Contributor Author

urish commented Mar 8, 2021

I may be wrong but wouldn't it have different configuration for external interrupts per chip?

That's correct. The idea is to have this configuration as part of the GPIO port configuration, e.g.:

export const portDConfig: AVRPortConfig = {
  PIN: 0x29,
  DDR: 0x2a,
  PORT: 0x2b,

  // Interrupt settings
  pinChange: PCINT2,
  externalInterrupts: [null, null, INT0, INT1],
};

(taken from here, part of #82)

so normally that'd be hidden inside the ATmega328p object (and in the future possibly ATmega2560 for the MEGA, and ATmega4809 for the Nano Every, so users won't really have to worry about configuring it themselves.

Also, thanks for all the feedback so far, that's really helpful!

I guess it is not necessary to integrate a broad bunch of microcontrollers but the new API is a great idea. A real unique selling point would be the integration of a gdb interface. With this, in addition to the continuous execution of a program, one could then also step through the code and explain certain processes.

Agreed. Have you seen the experimental GDB support in Wokwi?

@ricardojlrufino
Copy link

I'm having to do something similar in my application.
image

An example is the digitalWrite function
image

And tried to implement the devices through drivers (Controllers)
While I wait for you to release the current drivers (=])
image

After I complete the tests, I'll share with you to see if you can use any ideas.

@Green-hcq
Copy link

I'm having to do something similar in my application. image

An example is the digitalWrite function image

And tried to implement the devices through drivers (Controllers) While I wait for you to release the current drivers (=]) image

After I complete the tests, I'll share with you to see if you can use any ideas.

I'm having to do something similar in my application. image

An example is the digitalWrite function image

And tried to implement the devices through drivers (Controllers) While I wait for you to release the current drivers (=]) image

After I complete the tests, I'll share with you to see if you can use any ideas.

Hello, can I borrow your code? I have encountered some issues that require calling Digitalwrite and Analogwrite. I would like to receive some inspiration and guidance from your code. Can you share a copy with me?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants