@Rayman said:
Btw also think seeing that what is taken over here is the hardware version of i2c.
But one can also activate the soft i2c. That relies on a Pins module, but looks like @ersmith has implemented that in his pyb modules. So, if didn’t need pull-ups, looks like that is almost out of the box ready.
If you look at machine_pin.c in my native P2 variant you'll see the new "machine" way to do things which supports machine.Pin objects. This should be compatible with the SOFT I2C stuff. Or at least it was back in 1.13. This should be able to work with optional internal pull ups configured on the pin (implemented using P2 drive modes). You'll also probably need some of what is in modmachine.c/h related to Pin functionality.
@rogloh Ok, think have machine.Pin working. Slight distraction from working on I2C...
Had to change your gpio.c around to use riscvp2 way.
Seems could use compiler directives to have both ways there though...
Here's the thing you need to add to modmachine.c to make it work:
I'm not really liking this machine.I2C() way of doing things...
Seems like it slows things down a lot with this self stuff, also they add in variable length arguments to the functions for no apparent reason...
There's a read_mem() function which looks reasonable, just the self thing.
Then, there's the exposed function:
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
// create the buffer to store data into
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
// do the transfer
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
args[ARG_addrsize].u_int, (uint8_t *)vstr.buf, vstr.len);
if (ret < 0) {
mp_raise_OSError(-ret);
}
return mp_obj_new_bytes_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
That seems to do a lot of work to turn the variable length arguments into fixed length arguments.
But, maybe this is all very fast and serves some purpose that I don't get...
@Rayman said:
That seems to do a lot of work to turn the variable length arguments into fixed length arguments.
But, maybe this is all very fast and serves some purpose that I don't get...
Yeah I know what you mean. In general I don't typically question the actual MP implementation or these conventions and treated most of it as a black box. Without knowing their design reasons up front and the evolution of this project over time, it's not going to be simple to figure it all out unless you dig quite deep. I don't think Python's execution efficiency was necessarily their top priority everywhere - perhaps flexibility/portability/expandability could have outweighed that here. But unnecessary bloating is not good either for sizing the application to suit small micros.
@Tubular If you do talk to the Micropython guys, you might mention that the I2C.scan() that we are doing here, based on the @JonnyMac way, with grid is much better than what they have and easy to implement...
Yeah lets find out what they were thinking. I know they spent a fair bit of effort trying to make things same-ish across the ports, perhaps that was the main driver. Sometimes the backstory is contained in the github discussion of the change request where it changed.
Think see how it works now, looking at STM32 example.
Seems we use the locals_dict from micropython version of machine_i2c.c and then use the MP_DEFINE_CONST_OBJ_TYPE to implement our own version of make_new, print, and transfer.
The transfer() does all the actual work.
Only drawback is that seems stuck using their version of scan(). Unless, we replace it with our code.
Probably not supposed to do that, but might anyway. Or, perhaps call ours scan2() or something...
just started actual testing of I2C with LIS3DH accelerometer. But, seems we are missing the "time" module and not sure why...
Guessing this is something we need to implement in the port?
Ok, think I'd be close to saying i2c is working if only had time to slow things down.
But, this code appears to work... Modified to change how I2C is invoked and with time stuff commented out.
Also, can't reboot the lis3dh with out a time delay after..
Suppose can add some delay into p2 module and use that instead...
@Rayman said:
just started actual testing of I2C with LIS3DH accelerometer. But, seems we are missing the "time" module and not sure why...
Guessing this is something we need to implement in the port?
The "time" module stuff is a built in feature of MP so in theory it's mostly present when included but it looks like they've changed the way it's implemented in the lower level. Seems you now need a port specific modtime.c file to be present in the port folder and some additional settings in the mpconfigport.h file (like below for STM32) as well as the mp_hal_ticks_us function related to getting ticks in microseconds etc. It should be possible for the 64 bit P2 counter to be used to report microseconds since boot up for ticks however without an actual RTC you won't be able to implement a proper calendar time.
There should already be some other code available from Eric's RISC-V and my native P2 machine port variant for the other time delay API stuff in that module too you could utilize if you are putting together a proper modtime.c and updated mphalport.c file for this later MP version's requirements.
@rogloh thanks. definitely need to figure that out. For now, added a waitus() to p2 module and can verify that i2c is working with lis3dh at least. I2c seems a bit fragile at the moment though so definitely needs more testing. But, big win for now for sure.
i think @ersmith put something into flex-c to support linux time by adding a current datetime diff to the 64 bit cnt while using p2load to load a program, not sure if this may help here
Ok, LIS3DH accelerometer code works just about as is now. Just the I2C() invocation is changed, think ...
One think I'm noticing now is that there's no way to quit a program like this...
started it with: execfile("test_lis3dh.py")
Some places say CTRL-something should exit, but nothing works...
@Rayman said:
One think I'm noticing now is that there's no way to quit a program like this...
started it with: execfile("test_lis3dh.py")
Some places say CTRL-something should exit, but nothing works...
I'd imagine that the program either needs to exit or needs to take input so you can press ^C or ^D etc to quit/restart MP. Unless there is interrupt driven serial IO or the IO is non-blocking polled and buffered automatically in the middle of MP's normal processing loop running the executed program there'd be no way to abort by looking for a ^C character in the middle of the program that is not itself already waiting on input.
If you look in micropython/shared/runtime/pyexec.c you'll see the REPL processing loop code which does look for special characters like ^C & ^D etc to interrupt execution. But when you invoke the execfile statement other things happen, so you'd have to track that particular sequence down to see how it processes any input data. It seems to call parse_compile_execute with different flags in different situations and the mp_hal_set_interrupt_char routine is called to specify the "interrupt" character in different cases. You'd probably have to search down wherever this special character is being detected and see if it is part of the processing loop when execfile is invoked.
but, there might be something that I don't understand...
Had to rename the driver "icm20948.py" to "micropython_icm20948.py". This seems strange...
Maybe if it's in a properly named folder wouldn't have to?
Also seems need to create a "micropython_icm20948" folder and put "i2c_helpers.py" in it.
Also, had to change the printout for some reason. This code seems to be using some format that isn't supported for some reason here:
Openamp for MP does seem useful if it gives us a framework for other firmware to be loaded onto other COGs. The ancillary endpoint API stuff that comes along with it could be good too as it provides an in-built path for messaging between MicroPython and the other spawned COGs allowing control and data to be passed between a COG and MP. The COG side could potentially see this as a buffered mailbox. Additionally being able to optionally load binaries from a filesystem into COGs looks especially useful and is more dynamic and capable than requiring them all statically built into the entire executable image itself.
@Rayman said:
Might be able to put it in Propeller2.h, but is not really a P2 thing, don't think. I'm open to suggestions...
Here is the related check-in they did for this recently: https://github.com/micropython/micropython/commit/decf8e6a8bb940d5829ca3296790631fcece7b21
I think it would be best to try to follow the same approach for consistency. By #defining STATIC to avoid the change is sort of working around the problem. They used a convenient "git ls-files | egrep .. | xargs sed ..." script command to change a large number of files which should save time. You might just want to apply it to the P2 port specific folder files instead of everything, by running it within the P2 port folder.
Comments
If you look at machine_pin.c in my native P2 variant you'll see the new "machine" way to do things which supports machine.Pin objects. This should be compatible with the SOFT I2C stuff. Or at least it was back in 1.13. This should be able to work with optional internal pull ups configured on the pin (implemented using P2 drive modes). You'll also probably need some of what is in modmachine.c/h related to Pin functionality.
@rogloh Ok, think have machine.Pin working. Slight distraction from working on I2C...
Had to change your gpio.c around to use riscvp2 way.
Seems could use compiler directives to have both ways there though...
Here's the thing you need to add to modmachine.c to make it work:
I'm not really liking this machine.I2C() way of doing things...
Seems like it slows things down a lot with this self stuff, also they add in variable length arguments to the functions for no apparent reason...
There's a read_mem() function which looks reasonable, just the self thing.
Then, there's the exposed function:
That seems to do a lot of work to turn the variable length arguments into fixed length arguments.
But, maybe this is all very fast and serves some purpose that I don't get...
Yeah I know what you mean. In general I don't typically question the actual MP implementation or these conventions and treated most of it as a black box. Without knowing their design reasons up front and the evolution of this project over time, it's not going to be simple to figure it all out unless you dig quite deep. I don't think Python's execution efficiency was necessarily their top priority everywhere - perhaps flexibility/portability/expandability could have outweighed that here. But unnecessary bloating is not good either for sizing the application to suit small micros.
@Tubular If you do talk to the Micropython guys, you might mention that the I2C.scan() that we are doing here, based on the @JonnyMac way, with grid is much better than what they have and easy to implement...
Yeah lets find out what they were thinking. I know they spent a fair bit of effort trying to make things same-ish across the ports, perhaps that was the main driver. Sometimes the backstory is contained in the github discussion of the change request where it changed.
Ray (and everyone) - if you haven't already seen it check out this curated MP collection that mcauser keeps updating
https://awesome-micropython.com/
Think see how it works now, looking at STM32 example.
Seems we use the locals_dict from micropython version of machine_i2c.c and then use the MP_DEFINE_CONST_OBJ_TYPE to implement our own version of make_new, print, and transfer.
The transfer() does all the actual work.
Only drawback is that seems stuck using their version of scan(). Unless, we replace it with our code.
Probably not supposed to do that, but might anyway. Or, perhaps call ours scan2() or something...
Yep if possible do the scan2 or scanjm or whatever, so we can show side by side on same system and espound the benefits
just started actual testing of I2C with LIS3DH accelerometer. But, seems we are missing the "time" module and not sure why...
Guessing this is something we need to implement in the port?
Ok, think I'd be close to saying i2c is working if only had time to slow things down.
But, this code appears to work... Modified to change how I2C is invoked and with time stuff commented out.
Also, can't reboot the lis3dh with out a time delay after..
Suppose can add some delay into p2 module and use that instead...
The "time" module stuff is a built in feature of MP so in theory it's mostly present when included but it looks like they've changed the way it's implemented in the lower level. Seems you now need a port specific modtime.c file to be present in the port folder and some additional settings in the mpconfigport.h file (like below for STM32) as well as the mp_hal_ticks_us function related to getting ticks in microseconds etc. It should be possible for the 64 bit P2 counter to be used to report microseconds since boot up for ticks however without an actual RTC you won't be able to implement a proper calendar time.
There should already be some other code available from Eric's RISC-V and my native P2 machine port variant for the other time delay API stuff in that module too you could utilize if you are putting together a proper modtime.c and updated mphalport.c file for this later MP version's requirements.
@rogloh thanks. definitely need to figure that out. For now, added a waitus() to p2 module and can verify that i2c is working with lis3dh at least. I2c seems a bit fragile at the moment though so definitely needs more testing. But, big win for now for sure.
i think @ersmith put something into flex-c to support linux time by adding a current datetime diff to the 64 bit cnt while using p2load to load a program, not sure if this may help here
So, seems need to do something like this in mpconfigport:
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES)
Ok, got time, but not under machine...
Ok, LIS3DH accelerometer code works just about as is now. Just the I2C() invocation is changed, think ...
One think I'm noticing now is that there's no way to quit a program like this...
started it with:
execfile("test_lis3dh.py")
Some places say CTRL-something should exit, but nothing works...
I'd imagine that the program either needs to exit or needs to take input so you can press ^C or ^D etc to quit/restart MP. Unless there is interrupt driven serial IO or the IO is non-blocking polled and buffered automatically in the middle of MP's normal processing loop running the executed program there'd be no way to abort by looking for a ^C character in the middle of the program that is not itself already waiting on input.
If you look in micropython/shared/runtime/pyexec.c you'll see the REPL processing loop code which does look for special characters like ^C & ^D etc to interrupt execution. But when you invoke the execfile statement other things happen, so you'd have to track that particular sequence down to see how it processes any input data. It seems to call parse_compile_execute with different flags in different situations and the mp_hal_set_interrupt_char routine is called to specify the "interrupt" character in different cases. You'd probably have to search down wherever this special character is being detected and see if it is part of the processing loop when execfile is invoked.
This code for 9DOF sensor ICM-20948 seems to be working over I2C:
https://github.com/jposada202020/MicroPython_ICM20948
but, there might be something that I don't understand...
Had to rename the driver "icm20948.py" to "micropython_icm20948.py". This seems strange...
Maybe if it's in a properly named folder wouldn't have to?
Also seems need to create a "micropython_icm20948" folder and put "i2c_helpers.py" in it.
Also, had to change the printout for some reason. This code seems to be using some format that isn't supported for some reason here:
Just noticed the ² and ° symbols don't seem to work with the VGA driver... Wonder if it's worth or possible to fix that...
Just made these binaries with different options enabled or not. I've been uploading these with FlexProp GUI.
Also posted the source code to bottom of page here:
https://www.rayslogic.com/Propeller2/upy/micropython.html
Looks like they just released MP 1.23 including the dynamic usb and openamp support
Interesting… openamp looks to be similar to something I know openmp, but for microcontrollers I guess
Not sure the asymmetric part makes sense with P2 though…
Openamp for MP does seem useful if it gives us a framework for other firmware to be loaded onto other COGs. The ancillary endpoint API stuff that comes along with it could be good too as it provides an in-built path for messaging between MicroPython and the other spawned COGs allowing control and data to be passed between a COG and MP. The COG side could potentially see this as a buffered mailbox. Additionally being able to optionally load binaries from a filesystem into COGs looks especially useful and is more dynamic and capable than requiring them all statically built into the entire executable image itself.
UPDATE: here's the link to their API for openamp
https://docs.micropython.org/en/latest/library/openamp.html
Got 1.23 to compile. Just had to add this to basically all the port files:
#define STATIC static
Isn't there some common header that's already included by everything that you can add that to?
Might be able to put it in Propeller2.h, but is not really a P2 thing, don't think. I'm open to suggestions...
Maybe Propeller2.h makes sense after all.
These are the files:
Here is the related check-in they did for this recently:
https://github.com/micropython/micropython/commit/decf8e6a8bb940d5829ca3296790631fcece7b21
I think it would be best to try to follow the same approach for consistency. By #defining STATIC to avoid the change is sort of working around the problem. They used a convenient "git ls-files | egrep .. | xargs sed ..." script command to change a large number of files which should save time. You might just want to apply it to the P2 port specific folder files instead of everything, by running it within the P2 port folder.