ryansuchocki / microscheme

A Scheme subset for Atmel microcontrollers.
http://ryansuchocki.github.io/microscheme/
MIT License
300 stars 20 forks source link

Supporting more models #13

Open ryansuchocki opened 9 years ago

ryansuchocki commented 9 years ago

The process for adding new models was previously quite complicated, and involved editing obscure pieces of code.

I have relocated the model-specific data to a well-structured store in 'models.c'. The pin-mapping vectors remain in 'stdlib.ms'. There is now a single primitive (@if-model "modelname" ...) for model-specific microscheme code, rather than a primitive (@if-model-modelname ...) for each model.

As a result, the process for supporting a new model is much simpler. One must add a new entry to the models[] array in 'models.c', and an (@if-model "modelname") block in 'stdlib.ms', containing pin mapping vectors.

I will soon write a guide on exactly how these data should be derived, but the existing models provide a fairly good indication...

rekado commented 8 years ago

I'd like to add new models, so I checked to see how the values for ports and pins are derived. The variables arduino-ports and arduino-pins are to be read as a zipped list of pairs. A pin is defined by the address of the register containing it (given in arduino-ports), the bit of the register (given as n=2^m in arduino-pins), and a number, i.e. the index into both arduino-ports and arduino-pins.

For example, in the model "UNO", the first pin is located in the register with address #x29 and bit 0 (because 2^0 = 1, the first value in arduino-pins). The summary datasheet for the Atmega328 tells us in section "Register Summary" that 0x29 is the address for "PIND"; the zeroth bit would be "PIND0".

If this explanation is correct, I wonder if it wouldn't be better to represent pins and ports as simple lists (or vectors or alists) of pairs rather than two separate vectors, e.g.

(define pins
  `((#x2C . 0)
     (#x2C . 1)
     ...))

It would also be quite convenient if we could refer to pins by name, e.g. (pin 'e 7). I do not own an Arduino and I've always just played with plain micro controllers, so I don't use absolute pin numbers but work with port and pin register names/aliases (PORTD, PINA2, etc).

Would you be willing to discuss a patch along these lines?

ryansuchocki commented 8 years ago

Hi. We've used 2 vectors of numbers, rather than any other structure, simply because it uses the least memory, with no difference to the user.

For example, the existing representation uses 220 bytes for the 'mega' mappings. A vector of pairs would use 326...

I think supporting raw chips, and pin access by port letter is an excellent idea. The primitive (digital-state ...) allows access to ports by address and pin mask, so this might be a neat way of doing it:

(define 2^ (vector 1 2 4 8 16 32 64 128))

(define (raw-pin port pin)
    (digital-state port (vector-ref 2^ pin)))

(@if-model "328p"
    (define PORTB #x23)
    (define PORTC #x26)
    (define PORTD #x29))

Now we can access, for example, (raw-pin PORTC 7). Adding (set-raw-pin ...) and (set-raw-ddr ...) should be easy...