-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Add pinmapping functionality. #263
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
Conversation
So this would be the ''string' based indexing version. As a side note I found someone elses GPIO fun with the STM32F here: |
Yes and it has the advantage that it uses no RAM (well until you call the function). I checked the .o file and pinmap.o only uses 4 bytes of RAM to store the function pointer to the user mapping function. We could use the strings to create symbols pretty easily. Somebody just has to decide where they should live and what exactly they should be called. |
Is the idea that pinmap.c would take over some of the board configuration from mpconfigport.h? If so, would it be appropriate to also incorporate board-specific mapping for the SD card detect pin? Given that you included the user switch and LED mapping, I was wondering if there was a specific reason to leave SD detect out. |
No. The idea with pinmap is that it provides a user friendly way of naming GPIO pins. If the user wants to use pin "X2", they call in by name "X2". Or can use "A10", etc. LED and switch are mapped because they are broken out to GPIO header pins. The SD detect pin could also be named (and might be a nice idea, so the user could access it by the name "SDSW"), but you would still need to configure the actual SD detect pin in mpconfigport.h. pinmap is used to name pins, not to configure the low level hardware. |
@dhylands This is very nice indeed, I like that it uses almost 0 RAM and is extensible. Maybe I missed some of the discussion, but what about also providing a dictionary map, as well as the generalised Python function that can do arbitrary mapping? Eg, you call `pin_map("X1", "my pin name").
What exactly do you mean by symbols? Something like pin_map.X1? |
So yeah - it probably makes sense to add the sd-detect pin. I can imagine scenarios where the python code would want to know that the sdcard is present, although it might make sense to provide a function that determines that the card is present, and correctly formatted, etc. @dpgeorge So about the dictionary, you could do a dictionary lookup by just having the function do that. Or did you mean that it should just create an empty dictionary that could have mappings added to, and have the pinmap_map_user_obj do a lookup in said dictionary along with the other methods? I was reluctant to populate a dictionary with the regular mappings, since then it would take up RAM. If I'm reading you correctly, pinmap_map_user_obj would then do something like the following (stopping at the first one that indicates a successful mapping). 1 - Call the (optionally) registered function for a mapping. About the symbols, yeah you could create pin_map.X1 which is essentially a constant, but I didn't want to do that since these would then take up RAM, whereas passing in a string would only allocate ram temporarily, which could then be garbage collected later. Once we can put constants like pin_map.X1 in flash, then I think that would be worth doing. It might also make sense to have the board mapping constants moved to mpconfigport.h since it may very well vary on a per-board basis. I'll also fix the LED/User Switch/SD-Card-Detect to use the constants defined in mpconfigport.h rather than duplicating them. |
I'm a bit behind on the discussion about constants, strings, RAM, flash, etc. But, let me point out the following: gpio("X1") is actually more efficient and uses less memory than gpio(pins.X1). The reason is as follows. In the compiler, all identifiers and all strings found in the script are interned (put in RAM permanently). Running gpio("X1") gets the string "X1" and passes it to the gpio function. The gpio function can then check this against known strings, or parse it to work out which port and pin it refers to. Running gpio(pins.X1) requires looking up pins in the global dictionary, then loading the string X1, then looking up X1 in the pins object, then passing the result (an integer) to gpio. In uPy, you can basically consider all strings (that originate from a script) to belong to one big enumeration. So they are just like using constant symbols. To eliminate RAM usage, we can preload the interned string table with strings like X1, etc. These can live in flash. Regarding the user-populated dictionary, yes, the 5 steps above were my thoughts. I totally agree with your decision not to use RAM for the fixed board mapping array. Re pin_map.X1 being in flash. We can already do this, although it's not obvious at first thought. One would create a new type and give it a custom |
So I created: https://github.com/dhylands/micropython/blob/testattr/unix/testattr.c and in my type I put a .load_attr function. So after building that branch, I can do:
I think the attributes have to be function attributes in order to be useful. Otherwise you can't pass them to the function like so: g = pyb.Gpio(pyb.Gpio.X1) You need to instantiate the object and then you could use g.X1, but that's too late. So I'll dig around a bit and see if I can muddle my way through function attributes. |
Thanks, I get what this is for now. I had been thinking about a way to tweak mpconfigport.h so that a new board could be fully defined within that one file; I was wondering if the new pinmap stuff would affect that at all. To do this I am hoping to clean up the few remaining references to pyboard3 and pyboard4 remaining outside of mpconfigport.h; these references are mostly telling the compiler whether the polarity of the user switch or the sd detect switch is active high or active low. I was thinking that we could define macros like SDSW_ACTIVE_HI and USRSW_ACTIVE_LO within mpconfigport.h, then these more generic directives could replace any remaining references to PYBOARD3/4. I will put together a patch for this if nobody gets to it before me ;-) Mostly I would like to be able to keep changes for my board within mpconfigport.h; my only reason for not contributing my board configuration to the main source tree is that there are so few of these boards in the wild that it won't be useful to anybody else for a while. |
@dpgeorge So I was able to get function attributes to work in a somwhat hacky fashion by commenting out the assertion at the top of fun_native_call and then doing: const mp_obj_type_t test_fun_native_type = { #define fun_native_type test_fun_native_type Then I was able to do dh.Test() So then the question becomes "Is this acceptable"? |
Aha. I think I figured out another way. https://github.com/dhylands/micropython/blob/testattr/unix/testobj.c#L69 I made dh.TestObj be a type If this seems like a reasonable approach, then I'll implement this for the pinmap stuff.
|
@dhylands yes, your second version is correct. Everything is an object (even types). A given object is an instance (perhaps singleton instance) of whatever you put in the Methods of an object come from its type, not from itself. You have created an object ( If you didn't need to create instances of |
@dpgeorge Thanks This is what I'm going to propose for pin mapping then (from the python perspective). All board pins will have predefined mappings. for the PyBoard4: To allocate a GPIO for that, you'd do something like this:
Users can add their own mappings by doing:
and they would then be able to do:
Users would also be able to add a mapper function:
In this case the "MyUserPinName" object is passed through to MyMapper. |
@Neon22 I'd say that the resource usage is the same (between using a meta class and the function attributes). The function example uses a few less flash bytes than the meta object example (0x29d versus 0x2D0 or a difference of 0x33). Both use no RAM at compile time and should cause the same amount of RAM to be consumed at runtime. |
@Neon22 It's good to have docs on this, but at the moment I think it's a bit premature, because things will still change. For example, I want to be able to define an entire uPy module in flash (at the moment it's not possible). This then would be the preferred way to make global, pre-defined entities. |
What should we do about this pull request? We have a big discussion about pin names in issue #265, and perhaps we should sort that out before implementing something?? |
I'll go ahead and close it for now. I was about to do another pull request, but the discussions, I'll make more changes before doing so, and open up a new pull request. I've got the pin data (extracted from the data sheet) in a csv file (this has all of the alternate functions which are available per-pin), as well as the data about which pins are available on which packages. I used pdftk to extract the pages from the datasheet containing the tables, and then used https://github.com/ashima/pdf-table-extract to gets the tables into csv form. So I'm planning on writing a python script which will generate the pin objects, and we can add stuff as needed (like pointers to registers etc) |
This introduces SAMD51 support and re-enables SAMD21 support. Fixes micropython#263
This evolves the API from 2.x (and breaks it). Playback devices are now separate from the samples themselves. This allows for greater playback flexibility. Two sample sources are audioio.RawSample and audioio.WaveFile. They can both be mono or stereo. They can be output to audioio.AudioOut or audiobusio.I2SOut. Internally, the dma tracking has changed from a TC counting block transfers to an interrupt generated by the block event sent to the EVSYS. This reduces the overhead of each DMA transfer so multiple can occure without using up TCs. Fixes micropython#652. Fixes micropython#522. Huge progress on micropython#263
I2SOut. The API is almost the same except the frequency attribute has been renamed to sample_rate so that its less likely to be confused with frequencies within the audio itself. Fixes micropython#263.
This is more or less what I was thinking about for pin mapping functionality.
I only modified the gpio function for now, but if this gets merge, then it can be used in other places as well.