#circuitpython-dev
1 messages Β· Page 45 of 1
Device Under Test
My test jigs are rPIs and they flash and test each board and talk to the board and get data back from the bard during the test, and all of that is sent to the terminal that I am ssh-ing from. So I see the raw serial output
for example...
rPI: wifi connected to UM-C10 (192.168.4.59) in 4.917 secs
rPI: retrying 1
DUT: \x1b]0;\xf0\x9f\x90\x8dWi-Fi: off | code.py | 8.2.3\x1b\\\x1b]0;\xf0\x9f\x90\x8dWi-Fi: No IP | code.py | 8.2.3\x1b\\
rPI: Connecting to UM-C10 on channel 10```
my wifi tests are designed to pass in under 4sec and if over, fail and retry
Ok, so I now know it's a snake, thanks !
when I thought it was colour codes, I was going to see if I could also colour code my own output.
I'm unsure what the preprended \x1b]0; is though
could be color, possible
If it is a color will likely be a magenta
appears to be an escape character of some kind
would probably end up looking like \π\ probably used internally somehow
The \x1b (ESC) sequences are terminalio VT-100 speak
makes sense
oh yeah that's the code for terminal title
I assume that whatever your code is that retrieves the data from serial an passes it down converts high ascii into escape characters
appears to be ansi
it's the code to put the status into the terminal title
makes sense
looks like Mu decided to just remove the whole sequence. at one time in 8.0 beta it was really really messing up almost every line. like every single repl output line had a snake it was a mess.
I think this requires esp_netif_napt_enable(), which isn't available until esp-idf v5.1.
I don't know if this is the right place to ask this question but I'm wanting to create https://learn.adafruit.com/guggenhat-bluetooth-le-wearable-neopixel-marquee-scrolling-led-hat-display nut with circuit python using an nrf52840 or an esp32 s3 feather as the control board if not able to do with circuit python at the moment what board would be best to use with Arduino. Also if unable to be done in Circuit Python how best I ask for the features to be included in future versions of CP?
As someone writing applications for IOT devices, this in and of itself is a dealbreaker driving me to options like micropython (which doesn't have good tooling for BLE, but does in-fact support it). I imagine there anyone else writing applications for IOT devices utilizing bluetooth feels similarly.
I would say that the right place is #help-with-circuitpython ... but I don't have the Discord Skills or Right to move it there.
That guide is from 2014 so CircuitPython did not exist at the time, but I don't see anything not possible in CP.
I found this guide that might help as it display text on a NeoPixel matrix: https://learn.adafruit.com/iot-led-sign
(but this is IOT so using the wifi of the ESP32S2, no Bluetooth)
The secret sauce might be this library to have a framebuffer made of pixel: https://github.com/adafruit/Adafruit_CircuitPython_Pixel_Framebuf
Then for BLE communication you could use the app "Bluefruit connect" https://learn.adafruit.com/bluefruit-le-connect
Now you just need to find some learn guide that use the text transmission of that application... and you need some other learn guide that scroll text on a framebuffer (you could try some MatrixPortal guide, and replace the matrix part with the Neopixel equivalent).
I don't say it is easy (but a lot of things are easy with CP), but my remixing two or three guide, you have piece of code for each part.
The difficulty nowdays is to find the right guide in the learn system, because maybe what you want to do already exist.
Don't forget the feedback you could put on the Guggenhat guide to ask if a CP would be possible, or share your code if you do it.
I suppose the only reason it worked for me is because I used the firmware.zip @RetiredWizard posted above in here which has the updated roots.pem in the build. Thank you for making that build for me. I can live on that build until it gets merged with a stable release.
I really like this approach. Can't see why it shouldn't be permanent.
Not quite sure what this meant to say.
Such a simple and neat feature!
Some more applications for it:
- Have a permanently running app and use REPL as a debugging mode of sorts, where everything is loaded automatically.
- Have a help message (regarding your functions) shown upon entering the repl, clearing the screen or even displaying a new ansi title.
- Show useful board stats upon entering the repl like the temperature or the board ip.
@atomic summit The escape code "\x1b]0;" is "Change icon name and window title" and the title is terminated by "\x1b\". Sometimes just after a first connect, the sequence is incomplete or garbled; we're not sure why and would fix it if we could. And of course when whatever's receiving the sequence isn't a compatible terminal, it might appear garbled like that. And yes, b'\xf0\x9f\x90\x8d' is π in utf-8 encoding. [I see this was discussed to a natural conclusion hours ago but I wrote this so I'm sending it anyway]
Terminals can be weird.
Ansi is very unreliable.
I think spamming it a lot more times around the code would be the only reliable way.
You have no idea how many bugs have I fought with to get terminal size detection going.
Though now I have my own .connected property for passive uart.
And now it's 100% reliable (with the power of spam) and even works over telnet.
Making another dotfiles pr in a bit, disabling dotfiles on boards that don't have native usb
They serve no purpose on boards without usb, other than looking ugly in the web-workflow.
Even if in the future those boards were to be accessed by ftp (which I plan on doing really soon), they do not apply.
A board with usb:
>>> import storage
>>> storage.erase_filesystem()
[17:18:05.090] Disconnected
[17:18:06.092] Warning: Could not open tty device (No such file or directory)
[17:18:06.092] Waiting for tty device..
[17:18:16.105] Connected
Auto-reload is on. Simply save...
ive got some questions about the spi storage in circuitpython
i was running over some numbers in #1143997801274015774 and discovered a major bottleneck
when i was benchmarking erase/program times, i saw pico-sdk does 64kb erase blocks, so erase+program can run at about 80kb/sec
but circuitpython is using 4kb erase blocks, so it gets about 77kb/sec
however, if the blocks had been pre-erased, and your only having to program, it could get 625kb/sec!
i can also kinda see how you might bodge that ontop of fat
first, scan the entire FAT fs, find every used and unused block
second, pre-erase all unused blocks
third, keep a bitmap of pre-erased blocks, and store it somewhere, so you dont have to do 1/2 again
modify the fat block allocation algo, so it will prefer erased blocks
what is your use case for needing fast writes?
just better overall performance when copying things to flash
77 to 625 is a pretty big boost
at a cost of slower startup
those things are usually tradeoffs, making them without a purpose in mind is not a good idea
thats what the bitmap of erased blocks is for, so you dont have to scan on every startup
but a different filesystem, intended for flash, would also work
or a intermediate wear leveling layer
could also just be optional, so not ever board has it
I think the ESP IDF has an intermediate wear leveling layer
I haven't looked because we don't really have a problem with wear
i was thinking of using it more for pre-erase then proper wear leveling
but you kinda get both at the same time
if you just treat the entire flash as a ringbuffer, copy used blocks from tail->head, and erase everything in the middle, then your wear is more even, and things are pre-erased
We're open to folks improving things. We don't have a shortage of ideas, only folks working on them.
yeah
i also realized, i got some wires crossed
the original problem i was trying to solve, was programming a uf2 to an rp2040
so the circuitpython performance doesnt matter in that case
yup, the uf2 code is in rom
It can always be improved π Figuring out what to work on is the hard part
yeah
the MBR code in the broadcom port is also rather fragile
if there is exactly 1 partition, it will create a second for the circuitpython drive
if there is exactly 2 partitions, it will expose the 2nd as MSD
anything else, and it breaks
so you cant multi-boot with pinn/noobs
you cant reserve the fake space on a 32gig card advertising itself as 256gig
its a tricky thing to fix, because i can see it destroying data on an sd card when it goes wrong
so we would need to discuss options first
issues are a better spot to discuss instead of discord since the history gets less and less accessible
good point
we have labels to filter by port too
hmmm, bug report or feature request?
I'd say enhancement since I didn't expect a CP SD card to be used for anything else
The pins were wrong. 37 and 38 are the pin number on the module. Not the GPIO number internal to the chip, which is why I added the other comment.
i think i lack access to add labels myself
I'll add them. Thanks!
Please try this with artifacts from #8345 because it'll detect pin issues that can lead to this error. This example may have a similar problem.
if there is exactly 1 partition, it will create a second for the circuitpython drive
if there is exactly 2 partitions, it will expose the 2nd as MSD
anything else, and it breaks
so you cant multi-boot with pinn/noobs
you cant reserve the fake space on a 32gig card advertising itself as 256gig
pinn/noobs use extended partitions for each OS, so that use-case would require adding extended partition support
and the more general case, of just having unexpected partitions, could be solved w...
https://iosoft.blog/zerowi/
this is a series of blog posts, on how to interface with the wifi on a pi-zero
all of the rpi devices (both broadcom and rp2040) use wifi devices from the same family, so you should be able to adapt this blog to other SDIO based chips
the rp2040 is an exception, because i think the wifi chip needs a unique firmware blob, to re-route things over SPI
Thank you @bergdahl @wtuemura and @hexthat .
Thank you @bergdahl @wtuemura and @hexthat .
It doesn't seems to help for me...
Adafruit CircuitPython 8.2.4-4-g811bd12fa on 2023-08-29; BPI-PicoW-S3 with ESP32S3
>>>
soft reboot
Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
sd card ready
PN532 ready !
i2s ready
waiting for a tag to playΒ·...
<serial broke>
Auto-reload is off.
Running in safe mode! Not running saved code.
You are in safe mode because:
Internal watchdog timer expired.
Press reset to exit sa...
after some minor change (simple refactoring, trying to make my failing code example even more minimal), I managed to get another error:
You are in safe mode because:
CircuitPython core code crashed hard. Whoops!
Hard fault: memory access or instruction error.
Please file an issue with your program at github.com/adafruit/circuitpython/issues.
Press reset to exit safe mode.
Press any key to enter the REPL. Use CTRL-D to reload.
The hard fault will be easier to debug! Please post the minimized code. Thanks!
@slender iron Are there going to be any changes to deal with the safe mode issues on the original Metro S3, or are we basically writing off those 40 boards? Mostly a curiosity. I don't need it for anything.
With my PR it won't safe mode anymore. It just will say the pins are in use. I think Limor's plan is to refund folks if needed though.
I knew her plan. I was curious about yours. Sounds good!
Actually, the code differences don't matter, I now get both error apparently randomly (but more frequently the hard fault) also with the code previously given...
It seems the last time a release was done with 8.2.4, the frozen libs were not updated which is causing problems with boards like the FunHouse because the version that is frozen is not compatible with settings.toml.
This was originally added when we were experiencing some issues with certain boards that used PortalBase. The M4 PortalBase boards (PyPortal MatrixPortal M4) still need this, but esp32-s2 boards have plenty of RAM and don't really need it. In order to make it easier to update,...
Every once in a while, I have a device that consistently at least gets an exception, sometimes safemodes, from a NeoPixel exception. Espressif MCUs, but different board manufacturers.```
File "neopixel.py", line 180, in _transmit
RuntimeError: Input/output error
which port is that?
espressif
from what ive seen, the neopixel is a write-only device
the driver has no way to know if the neopixel is working or not, and it should function the same if the neopixel is missing as when its present or malfunctioning
the error is on neopixel_write which is in the core
I used to get around it with a function that de-inited and re-inited the NeoPixel on exception, but it happens so frequently on those boards, it spends too much time doing that. Now I just move on to a different (identical) board and it's fine.
But I'm not familiar with the RMT peripheral to really know more then that.
Just a quick look a couple previous setup calls don't check for error conditions.
there must be something marginal in the hardware... somewhere ...for most identical boards to work and one not
faulty microcontroller?
marginal in some way maybe, i canβt think of another explanation for only one of otherwise identical units to have the issue
@stuck elbow so if i wanted to add a new class, i would have to do it around here?
STATIC const mp_rom_map_elem_t videocore_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_videocore) },
{ MP_ROM_QSTR(MP_QSTR_Framebuffer), MP_ROM_PTR(&videocore_framebuffer_type) },
};
i'm thinking, there should be 3 objects, for the 3 displays, pre-created with the constructor blocked out
and then another object the user can create instances of...
how would that work exactly?
I have no idea what that code is
I'm not familiar with the videocore module
it looks to be a string=object mapping, for globals in this module, which can then be imported?
yeah
what i need more, is somebody that knows how C modules work in (micro|circuit)python
for example, what is MP_ROM_QSTR(MP_QSTR_videocore) doing?
why can i not find the definition of MP_QSTR_videocore elsewhere in the code?
build-raspberrypi_zero2w/genhdr/qstrdefs.generated.h:QDEF(MP_QSTR_videocore, 175, 9, "videocore")
ah, runtime generation
it's a magical macro for interned strings
git grep is always lying to me
lie to it in return
so, if i want to create my own class type, i would need to duplcate this line:
{ MP_ROM_QSTR(MP_QSTR_Framebuffer), MP_ROM_PTR(&videocore_framebuffer_type) },
and duplicate the struct its refering to in the other file....
root@d235fe3c2fdb:/circuitpython/ports/broadcom# grep test build-raspberrypi_zero/genhdr/qstrdefs.generated.h
QDEF(MP_QSTR_test, 51, 4, "test")
interesting, it seems to have just found that constant in my code
so i just act like it exists, and then it magically exists!
@stuck elbow
.locals_dict = (mp_obj_dict_t *)&videocore_framebuffer_locals_dict,
what are these locals local to?
are they attributes of the resulting Framebuffer class?
>>> videocore.Framebuffer.
deinit height width
>>> videocore.Framebuffer.width
<property>
STATIC const mp_rom_map_elem_t videocore_framebuffer_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&videocore_framebuffer_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&videocore_framebuffer_width_obj) },
{ MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&videocore_framebuffer_height_obj) },
};
STATIC MP_DEFINE_CONST_DICT(videocore_framebuffer_locals_dict, videocore_framebuffer_locals_dict_table);
yeah, attributes of the class at least
libg.a(lib_a-sbrkr.o): in function `_sbrk_r':
hmmm, if i cant malloc() then how should i reserve some memory on the GC-able heap, for this class?
gc_malloc I think. I just got in the door if you're still about I can try to find an example of it
i am still about
m_malloc will do it
how will the object get freed when the python object around it is freed?
STATIC mp_obj_t hvs_sprite_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
sprite_t *sprite = m_malloc(sizeof(sprite_t), true);
return MP_OBJ_FROM_PTR(sprite);
}
const mp_obj_type_t hvs_sprite_type = {
{ &mp_type_type },
.flags = MP_TYPE_FLAG_EXTENDED,
.name = MP_QSTR_Sprite,
.make_new = hvs_sprite_make_new,
};
the basic idea, is that the user code will spawn one instance of this, for each on-screen sprite
and if circuitpython reloads the code and GC's all objects, it should clean up all sprite objects
Can't remember if you want the second m_malloc paramter true or not. If you looked it up and that's correct ignore me.
And it should be freed when the object gets freed. The GC checks for all pointers on the stack including C ones. Some objects have a deinit() python function that will explicity free the memory
>>> import videocore
>>> videocore.Sprite
<class 'Sprite'>
>>> x = videocore.Sprite()
>>> x
and it seems to just hang now, when viewed from the CDC uart
ah, i did see a deinit on the framebuffer
https://github.com/adafruit/circuitpython/blob/main/shared-module/displayio/Bitmap.c
Is a good examples that allocates a buffer and frees it in deinit
i'll copy that if i need something more complex then free
i guess hw uart is next...
Did you figure out the QSTR stuff you asked earlier?
One thing that took me a while to figure out was that a QSTR is just an integer under the hood. Somewhere in the compile files you can see the mapping
yep, found that file already
and ive delt with less magic-y interning before in the nix language
there is just a runtime function, to allocate/lookup a char* in the interned table
and then all maps use the int
hangs the same way over hw uart
no backtrace or anything
next thing, also related to this link
i want to create a bitmap, and store it in an attribute on the sprite
basically:
import videocore
bitmap = something
s = videocore.Sprite()
s.backing_image = bitmap
and then be able to access the image from C
>>> b = displayio.Bitmap(16,16,255)
https://github.com/adafruit/circuitpython/blob/main/shared-module/gifio/OnDiskGif.c
That one I know because the last major thing I contributed did just that
heh
i'll need to find a uSD card then
You are in safe mode because:
CIRCUITPY drive could not be found or created.
guessed the right card on the first try!
import videocore
import gifio
sprite = videocore.Sprite()
gif = gifio.OnDiskGif("/discord-minecraft.gif")
sprite.image = gif
print("Hello World!")
dropped a random gif from my memes folder onto the drive, and it hung
@blissful pollen now what? its hanging on every boot π
If you're stuck that way you can get into safe mode to edit code.py
how do you get into safemode?
if sprite.image is a bitmap too you need to assign it the bitmap from the gif. The docs in the shared-bindings folder should have a decent example
typedef struct {
} sprite_t;
STATIC mp_obj_t hvs_sprite_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
sprite_t *sprite = m_malloc(sizeof(sprite_t), false);
return MP_OBJ_FROM_PTR(sprite);
}
const mp_obj_type_t hvs_sprite_type = {
{ &mp_type_type },
.flags = MP_TYPE_FLAG_EXTENDED,
.name = MP_QSTR_Sprite,
.make_new = hvs_sprite_make_new,
};
sprite.image just doesnt exist
Not sure off the top of my head, I think a couple resets the second after the neopixel lights up.
Hmm yeah I'm not sure on the pi-zero
my setup is also weird
the main circuitpython binary is loaded over the usb-device link
so i can change the C code freely, without having to swap uSD cards
even if its hanging like this
oh, i got a simple hack
just comment out the definition for videocore.Sprite
AttributeError: 'module' object has no attribute 'Sprite'
try and make a sprite now! π
import videocore
import gifio
sprite = videocore.Sprite()
gif = gifio.OnDiskGif("/discord-minecraft.gif")
# sprite.image = gif
print("Hello World!")
and that simple comment, solves the hang
so, i'm clearly missing something in my Sprite class
oh, i didnt populate the locals dict
bindings/videocore/Sprite.c:20:25: error: expected ')' before '(' token
20 | MP_PROPERTY_GETTER(test, (mp_obj_t)&get_test);
| ^~
@blissful pollen the macros make it hard to see what is wrong with this
Do you have test and get_test defined properly?
//| width: int
//| """Width of the gif. (read only)"""
STATIC mp_obj_t gifio_ondiskgif_obj_get_width(mp_obj_t self_in) {
gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return MP_OBJ_NEW_SMALL_INT(common_hal_gifio_ondiskgif_get_width(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_width_obj, gifio_ondiskgif_obj_get_width);
MP_PROPERTY_GETTER(gifio_ondiskgif_width_obj,
(mp_obj_t)&gifio_ondiskgif_get_width_obj);```
As an example
STATIC mp_obj_t get_width_impl(mp_obj_t self_in) {
return MP_ROM_QSTR(MP_QSTR_foobar);
}
MP_DEFINE_CONST_FUN_OBJ_1(get_test, get_width_impl);
MP_PROPERTY_GETTER(test, (mp_obj_t)&get_test);
STATIC const mp_rom_map_elem_t hvs_sprite_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_test), MP_ROM_PTR(&test) },
};
as best as i can tell, its all correct
Yeah I'm not noticing what's off
bindings/videocore/Sprite.c:20:25: error: expected ')' before '(' token
20 | MP_PROPERTY_GETTER(test, (mp_obj_t)&get_test);
| ^~
| )
In file included from bindings/videocore/Sprite.c:3:
bindings/videocore/Sprite.c:23:44: error: 'test' undeclared here (not in a function)
23 | { MP_ROM_QSTR(MP_QSTR_test), MP_ROM_PTR(&test) },
| ^~~~
../../py/obj.h:312:24: note: in definition of macro 'MP_ROM_PTR'
312 | #define MP_ROM_PTR(p) (p)
| ^
i think the 2nd error, is because gcc ignored line 20, due to the 1st error
py/objproperty.h:#define MP_PROPERTY_GETTER(P, G) const mp_obj_property_getter_t P __attribute((section(".property_getter"))) = {.base.type = &mp_type_property, .proxy = {G}}
py/objproperty.h:#define MP_PROPERTY_GETTER(P, G) const mp_obj_property_t P = {.base.type = &mp_type_property, .proxy = {G, MP_ROM_NONE, MP_ROM_NONE}}
the 2 versions are a flash usage thing, so lets focus on the 2nd
const mp_obj_property_t test = {.base.type = &mp_type_property, .proxy = {(mp_obj_t)&get_test, MP_ROM_NONE, MP_ROM_NONE}}
that looks perfectly valid to me
Yeah I still spot what's missing. Sometimes may have to do a clean compile too as some of the macros run before (random idea)
wiped the build dir, no difference
@blissful pollen aha
#include "py/objproperty.h" was missing facepalm
oops! It's late (at least here) so I can see it ha
12:11 am here
still hangs though, so it wasnt the prop list
>>> videocore.Sprite.test
<property>
but the property is at least visible when i dont make a new instance
oh!
i'm calling m_malloc(0, false); ....
Oh yeah
nope
that wasnt it either
>>> s = videocore.Sprite()
sprite is at 0x3c5fa0
>>>
>>> s
a printf confirms it is allocating memory for the sprite when i construct it
how does circuitpython know how to print an unknown class?
Not sure on printing that, never looked into it
looks like you also support animated gifs, nice
is it changing the backing odg.bitmap?
it keeps the same bitmap just re-writes it each frame
yeah, so that will have tearing
the port i'm on has enough ram to just allocate a new bitmap for each frame, and can do vsync flips if you wait for vsync
but i can worry about that once i'm able to actually display anything
I didnt notice any tearing on the small displays but there is barely enough RAM in a RP2040 for one frame let alone two
but i'm on the rpi-zero, with at least 256mb of ram
so maybe make it an argument to the class
odg.next_frame(reallocate=True)
any kind of debug flag i could enable, to see why its just silently hanging?
no difference
oh
i was wondering, how MP_OBJ_FROM_PTR(self->bitmap); turned into something that knows its of the bitmap class
there must be required fields!!
gifio_ondiskgif_t *self = m_new_obj(gifio_ondiskgif_t);
mp_obj_base_t base;
bingo
so circuitpython is casting my sprite to this, expecting to find the base
and its an undefined 32bit width....
π₯
self->base.type = &gifio_ondiskgif_type;
and that is critical
oh yes it is
π
>>> s.test
'foobar'
and the getter works
now to change the code.py back...
AttributeError: can't set attribute 'image'
and then make another property
ok, so i have a mp_obj_t value, which came from the gif.bitmap
how do i assert that it is a bitmap....
displayio_bitmap_t *bitmap = m_new_obj(displayio_bitmap_t);
bitmap->base.type = &displayio_bitmap_type;```
i could check for that exact type?
displayio_bitmap_t *bitmap = mp_arg_validate_type(args[ARG_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_bitmap);
this occurs in many places
TypeError: bitmap must be of type Bitmap, not OnDiskGif
it even gives a nice error, due to forgetting about .bitmap
>>> sprite.image
>>> sprite.image = gif.bitmap
>>> sprite.image
<Bitmap>
yep, progress!
>>> sprite.width
0
>>> sprite.width = 10
>>> sprite.width
10
#define simpleprop(name) \
static mp_obj_t c_getter_##name(mp_obj_t self_in) { sprite_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(self->name); } \
static mp_obj_t c_setter_##name(mp_obj_t self_in, mp_obj_t value) { sprite_t *self = MP_OBJ_TO_PTR(self_in); self->name = mp_obj_get_int(value); return mp_const_none; } \
MP_DEFINE_CONST_FUN_OBJ_1(fun_get_##name, c_getter_##name); \
MP_DEFINE_CONST_FUN_OBJ_2(fun_set_##name, c_setter_##name); \
MP_PROPERTY_GETSET(prop_##name, (mp_obj_t)&fun_get_##name, (mp_obj_t)&fun_set_##name)
#define prop_entry(name) { MP_ROM_QSTR(MP_QSTR_##name), MP_ROM_PTR(&prop_##name) }
simpleprop(width);
STATIC const mp_rom_map_elem_t hvs_sprite_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_test), MP_ROM_PTR(&test_prop) },
{ MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&image_prop) },
prop_entry(width),
};
@blissful pollen behold!!, the power of macros!!
i'm surprised MP_QSTR_##name even worked, lol
>>> import videocore
>>> import gifio
>>> gif = gifio.OnDiskGif("/discord-minecraft.gif")
>>> sprite = videocore.Sprite()
sprite is at 0x3c61e0
>>> sprite.width
0
>>> sprite.height
0
>>> sprite.image = gif.bitmap
>>> sprite.width
313
>>> sprite.height
245
and now the w/h default to the input bitmap, when they started out at 0
Nice, congrats!
>>> sprite.maybe_regen()
regen time
>>> sprite.maybe_regen()
not dirty
>>> sprite.image = gif.bitmap
>>> sprite.maybe_regen()
regen time
>>> sprite.maybe_regen()
not dirty
and dirty tracking works
now, i need to actually generate the display list
https://github.com/librerpi/lk-overlay/blob/master/platform/bcm28xx/hvs/hvs.c#L142C24-L164
void hvs_regen_noscale_noviewport(hvs_layer *l) {
assert(l->dlist_length >= 7);
assert(l->premade_dlist);
uint32_t *d = l->premade_dlist;
// CTL0
d[0] = CONTROL_VALID
| CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ABGR)
| CONTROL_UNITY
| CONTROL_FORMAT(gfx_to_hvs_pixel_format(l->fb->format))
| CONTROL_WORDS(7);
// POS0
d[1] = POS0_X(l->x) | POS0_Y(l->y) | POS0_ALPHA(0xff);
// POS2, input size
d[2] = POS2_H(l->fb->height) | POS2_W(l->fb->width) | (l->alpha_mode << 30);
// POS3, context
d[3] = 0xDEADBEEF;
// PTR0
d[4] = (uint32_t)l->fb->ptr | 0xc0000000;
// context 0
d[5] = 0xDEADBEEF;
// pitch 0
d[6] = l->fb->stride * l->fb->pixelsize;
}
for basic sprites, it just needs 7 entries like this
and thats basically everything i need on the sprite side, for basic stuff
now i need the hvs side...
@blissful pollen now comes the fun part
i want to spawn 3 instances of the HvsChannel class, but not allow the user to create more
i think i can do the 2nd part, by just not having a .make_new
but then the 1st part, i need to create the 3 structs, and MP_ROM_PTR them??
wow, got that all right on the first try!
typedef struct {
mp_obj_base_t base;
uint32_t channel;
} hvs_channel_t;
extern hvs_channel_t hvs_channels[3];
hvs_channel_t hvs_channels[3] = {
[0] = {
.base.type = &hvs_channel_type,
.channel = 0,
},
[1] = {
.base.type = &hvs_channel_type,
.channel = 1,
},
[2] = {
.base.type = &hvs_channel_type,
.channel = 2,
},
};
const mp_obj_type_t hvs_channel_type = {
{ &mp_type_type },
.name = MP_QSTR_HvsChannel,
};
STATIC const mp_rom_map_elem_t videocore_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_videocore) },
{ MP_ROM_QSTR(MP_QSTR_Framebuffer), MP_ROM_PTR(&videocore_framebuffer_type) },
{ MP_ROM_QSTR(MP_QSTR_Sprite), MP_ROM_PTR(&hvs_sprite_type) },
{ MP_ROM_QSTR(MP_QSTR_HvsChannel0), MP_OBJ_FROM_PTR(&hvs_channels[0]) },
};
>>> videocore.HvsChannel1.width
1280
>>> videocore.HvsChannel1.height
1024
>>> videocore.HvsChannel1.enabled
0
mp_obj_new_bool was what i wanted
>>> import videocore
>>> videocore.HvsChannel0.enabled
False
>>> videocore.HvsChannel1.enabled
True
>>> videocore.HvsChannel2.enabled
False
>>> videocore.HvsChannel1.width
1280
>>> videocore.HvsChannel1.height
1024
@blissful pollen hows that look? π
now comes the next fun part...
i need to accept a list of Sprite objects, regen each, and then blast them into the display-list memory
i wrote the rest of that code, ran it, and the screen just goes blank....
the stride, is half the width!!
w: 313, h: 245, stride: 157, bits per value: 16
aha
i forgot to call next_frame() the first time
what i should be seeing
what i'm actually seeing
i changed it from RGB332 to RGB555, and now i'm seeing 4 copies
the problem now, is that i need to understand what the data format is within displayio_bitmap_t
displayio_bitmap_write_pixel() should have answers
d[6] = s->bitmap->stride * 4; helps some
i can now just barely make out the pig, and the whole shape is there
and switching back to 555, i can now see just a single corrupted image, fully in the right shape!
let me try turning on animation, just for the hck of it
other then the colors, its looking amazing
the final code.py
oh, i might as well play with other sprite features, until i figure out color
now performance is horid π
ah, the printf's are to blame
i think its the framebuffer repl, thats always redrawing painfully slow
the initial 2d accel code, tested and working on a pi-zero
it should work on the entire vc4 family, bcm2836/2836/2837, just need to update BCM_PERIPH_BASE_VIRT, or find an existing constant that does the same job
will work on it more tomorrow, but am open to comments
features:
- [x] displaying a bitmap at set coords, with 1:1 scale
- [ ] up/down scaling
- [ ] sprite wide alpha
- [ ] moving the REPL framebuffer into a sprite
- [ ] properly handling colors
example code.py:
`...
if anybody wants to test what ive done while i'm sleeping, its ^
On the road today/tomorrow otherwise I'd be on it! Can't wait to check it out when I get back π
morning
with the newest code.py, its now able to cycle thru all of the gif frames, and it can animate the X/Y coords
OnDiskGif sets the bitmap to RGB565_SWAPPED colorspace so two bytes a pixel I think (though looks like you figured that out)
but now i need to understand how displayio bitmaps handle colors
ah, let me try 565
The examples in the OnDiskGif docs give some hints how it works with displayio
565 is still broken, but it looks better
the dark grey sides of the hole are showing up mostly green
but the brighter bottom sides are showing up dark purple
let me try the other color orders...
There is 565 swapped too
#define HVS_PIXEL_ORDER_RGBA 0
#define HVS_PIXEL_ORDER_BGRA 1
#define HVS_PIXEL_ORDER_ARGB 2
#define HVS_PIXEL_ORDER_ABGR 3
the hardware supports these 4 orders
ARGB and ABGR both look the same
but now i have an idea
from python, how would i generate a bitmap that is 32x32, and solid red?
or would it be faster to just whip up a test image in a gif, lol
actually....
if i just convert this to gif...
Look up the displayio bitmap, it isn't too hard to generate a bitmap
I'm off to work for the day though so probably won't get a chance to check here, though this is more interesting
ValueError: width must be <= 320
ah dang, your gif library has a max width
w: 32, h: 32, stride: 1, bits per value: 1
ah, but creating my own image, breaks things very much
it switched to a 1 bit per pixel format
because i gave Bitmap() diff args
looks like i will need more testing, for each bit-depth, and better docs on the internals
bitmap = displayio.Bitmap(32 * 3, 32 , (1<<16)-1)
bitmaptools.fill_region(bitmap, 0, 0, 32, 32, 31);
bitmaptools.fill_region(bitmap, 32, 0, 64, 32, (63 << 5));
bitmaptools.fill_region(bitmap, 64, 0, 32*3, 32, (31 << 11));
sprite.image = bitmap
HVS_PIXEL_ORDER_ABGR and the above, produces red/green/blue bars
HVS_PIXEL_ORDER_ARGB and the above, produces blue/green/red bars
i should just expose color order, as a param....
Some other test patterns
after some more chat in #general-tech i got things working: https://github.com/adafruit/circuitpython/pull/8349
the root problem, was that gifio was byte-swapping all 16bit ints, to make SPI controllers happy
CircuitPython version
Adafruit CircuitPython 8.2.0 on 2023-07-05; Raspberry Pi Pico with rp2040
and also tried on
Adafruit CircuitPython 8.2.4 on 2023-08-22; Raspberry Pi Pico with rp2040
Code/REPL
lista=[1,2,3,4]
print(lista.reverse())
Behavior
list reverse() returns None
Description
I am expecting to see a reversed list [4,3,2,1] not None
Additional information
None
This is how regular Python works. somelist.reverse() reverses the list in place, modifying the original list, and does not return anything. reversed(somelist) returns a reversed list without modifying the original.
https://github.com/adafruit/circuitpython/pull/8349 adds vc4 sprite support to circuitpython
code.py (in the PR) is the demo code
This requires a change in our fork of esp-idf:
My test platform is https://www.tindie.com/products/makerfabs/matouch-esp32-s3-parallel-tft-with-touch-7/ [800x480 model]
The display is unstable (horizontal tearing) at higher dot clocks, and on my test screen the low refresh rate of ~12Hz is a bit flickery. We think ...
Awesome, jepler! Itβs always a giant leap from black screen to something on the screen, as there are many different ways to make black screens and only limited number of ways to make pixels show up.
Quick question about message translations. I'm putting new/modified strings into circuitypython.pot and assuming that there's some external process that will automagically get the translations into the various .po files. Is there something more I need to do?
@mortal kernel pre-commit will tell you to run "make translate", which updates circuitpython.pot. We use weblate for users to contribute translations, and it also takes care of adding new messages to the individual language .po files, so there's nothing for you to do. https://hosted.weblate.org/projects/circuitpython/main/
Awesome. Thanks for saving me the work of updating the .pot!
@slender iron design question for you. Some dot clock displays require configuration via a SPI bus; some real world designs place that SPI bus on an I2C I/O expander, because it's only used once at startup and the bus speed is unimportant (on the order of a few hundred bits are transacted once when setting up the display) ... and CP will want to do this at boot time outside of a VM for a board with an integrated display, or from circuitpython code if the display is NOT integrated or the user wants to re-initialize the display for any reason. SOOO... should bitbangio.SPI in the core be extended so that anything with a .value property can be used, in addition to a microcontroller.Pin? or would you prefer to see a different approach and if so what?
(this assumes the I/O expander would also have a core implementation I guess)
the espressif lcd devkit and limor's 2nd prototype dotclock tft board are both this way
i had just thrown a random mp_raise_ValueError(translate("too many sprites, unable to pageflip reliably")); into some code i recently wrote
will that be handled automatically?
Ya, that seems right. Very similar to the draft PR from pimoroni
finds it
Ooh I'll look at that this afternoon!
They need native io expander support there too
so I think it's worth doing
the CYW is kinda like that too
the hyperpixel display also needs similar init, i forget which it is
originally, there was just a linux c binary, that bit-banged the whole thing
@buoyant lagoon Ideally you wouldn't add a new sprite class. Instead change the TileGrid implementation to use them under the hood
but more recently, linux was setup to drive it with an {i2c/spi}-gpio driver, so it showed up as a normal device and the driver bit-banged
i'll have to look at what parameters the tilegrid stores, and how i can convert them over
A tilegrid is a superset of a sprite
does tilegrid support scaling?
does it support viewports?
it only supports integer scaling now
is it a int scale factor, or just seperate src and dst w/h?
a tilegrid is a grid of indices into a spritesheet
a 1x1 tilegrid is a sprite
int scale factor
the advantage of making tilegrid use it is that existing code will just work then
could you make one sprite per tile in the grid internally?
what ive been calling viewports, is just fiddling with the starting addr, to render a sub-rect of an image
right, so that's what the index of a tile does
so you can take a 64x64 bitmap
treat it as a grid of 8x8 tiles, each 8x8 pixels
and then just render a single tile from that bitmap
in the little-kernel driver, its just viewport_x and viewport_y, an offset from the top-left of the original image
and then viewport_w and viewport_h, to set how big of a tile it crops out
its on like donkey kong!
then it would accept a sprite sheet where the sprites vary in size
but the index of TileGrid is a far simpler api for users
right now displayio assumes fixed tile sizes
i can see how you might use TileGrid for fixed size sprites
and then maybe a new SpriteSheet for non-fixed sizes in the future?
so you could add videocore.Sprite but also re-implement TileGrid with it
i'll look into the docs, make some demos with TileGrid, and try adapting that...
maybe! tough to know what direction to take displayio
foamyguy has done good work with it
the other question, is about pixel formats, color order, and palettes
the outer API is usually RGB888 and then converted internally
I would like to try and revisit the dma background writes
from what i can see, displayio.Bitmap() acts like a palette with 1 to 65535 colors
To overlap computing pixels with transmitting them?
but a lot of things (gifio) treat it as rgb565
ya, I think of Bitmap of "values" that get mapped to colors
but there is no palette attached to the bitmap
so i have no way of just accepting a bitmap and displaying it
yes, basically add a paremeter that moves the code that waits for the transfer to end to the next call, and use double buffering
sprite.image = gif.bitmap
sprite.color_order = 2
i need to add extra parameters like this
in this case, 2 refers to HVS_PIXEL_ORDER_XRGB
TileGrid is usually what combines a Bitmap with a "pixel_shader". A "pixel_shader" is a Palette or ColorConverter. The converter converts the source colors to the destination colorspace.
ah
Palette uses color converter code internally to map the RGB888 values to the destination color space
but the rpi hw also supports palettes
1bit/2bit/4bit/8bit palettes are allowed
you give it an array of RGBA8888's, for whatever size you chose
right, so by re-implementing tilegrid with hardware, you can have the hw do that conversion for you
I guess you'd reimplement pallete then too
ah, nice
the other thing, is the REPL text console
i suspect its configured in the mmu as uncached ram, and just scrolling it is a major performance bottleneck
how best would i re-direct that to a bitmap/tilegrid, and then access it for inclusion in my sprite list?
it is a tilegrid internally already
so i just need to change it to use cached ram, and get a pointer to it
right now the videocore implements a displayio framebuffer
so it uses all of the displayio code to render the tilegrids into the framebuffer
the instant i run videocore.HvsChannel1.set_sprite_list(), that framebuffer vanishes, and never comes back
https://github.com/adafruit/circuitpython/blob/main/supervisor/shared/display.c#L62 constructs that screen
so i need to access its tilegrid object, and then i can have a videocore.HvsChannel1.show_text_console = True or similar
it's all displayio still
oh, and what about dynamically changing the size of that terminal?
lets say python code decides to put the terminal on the left half, and do gfx on the right half?
the one weird trick the terminal uses is tilegrid's ability to change what index is starts the first row
it can do that already
thats easy enough if you dont want wrapping
just add stride * row_offset to the starting addr
it does wrap to make scrolling easier
ah, i implemented exactly that on the rpi
you could cheat it internally by making the buffer twice as long and saving values to two spots
this was the original little-kernel gfxconsole
on rpi you have plenty of ram
displayio isn't fast for fullscreen updates now anyway
i assume the current displayio terminal is using a ringbuffer for the display, but still has to memcpy() to paint it into the framebuffer?
the tilegrid to framebuffer process is pretty heavy
this is my re-implementation of littlekernel gfxconsole, using 2 sprites to draw the 2 halves of the ringbuffer
so it can scroll with zero copies
it's more than just memcpy because you are doing tile indexing plus color conversion
nice!
it'd be very cool to hw accelerate displayio
this will also allow dual monitor on all pi models
assuming you configure the displays first in config.txt
@buoyant lagoon can it also do that when displaying on an spi display connected to the pi?
and not just mirror, fully independent displays
i cant see any reason why it would interfere with spi displays
that'd be very cool. we don't support dual displays very well yet
for the pi4, dual hdmi will just come up automatically
but i havent fully confirmed how pi4 hvs works
i was being stuborn, and trying to bring the pi4 up from reset with zero blobs π
I mean, can you use all that hardware acceleration with spi displays?
ah, not yet
i would need to figure out how the transposer works
the transposer is basically a mode in the 2d core, where it just writes the fully composited frame back to ram
then you can just dma it out SPI
the 2d hardware natively supports dpi, smi, dsi, hdmi, and vec
dpi is just parallel digital color, like the hyperpixel
smi is undocumented, and is more of an 8080 style bus, where you assert a strobe for each write
vec is the ntsc/pal encoder
for anything else, you would just write it back to ram, and then dma it somewhere custom
lets see...
splash_children looks like my best target
that seems to be an array of tilegrids that make up the screen
oh, one reason to use my custom Sprite class over TileGrid, is caching the displaylist
void hvs_regen_noscale_noviewport(sprite_t *s) {
uint32_t *d = s->dlist;
// CTL0
d[0] = CONTROL_VALID
| CONTROL_PIXEL_ORDER(s->color_order)
| CONTROL_UNITY
| CONTROL_FORMAT(s->pixel_format)
| CONTROL_WORDS(7);
// POS0
d[1] = POS0_X(s->x) | POS0_Y(s->y) | POS0_ALPHA(0xff);
// POS2, input size
d[2] = POS2_H(s->bitmap->height) | POS2_W(s->bitmap->width) | (s->alpha_mode << 30);
// POS3, context
d[3] = 0xDEADBEEF;
// PTR0
d[4] = ((uint32_t)s->bitmap->data) // assumes identity map, should be physical addr
| 0xc0000000; // and tell HVS to do uncached reads
// context 0
d[5] = 0xDEADBEEF;
// pitch 0
d[6] = s->bitmap->stride * 4;
//printf("w: %d, h: %d, stride: %d, bits per value: %d\n", s->bitmap->width, s->bitmap->height, s->bitmap->stride, s->bitmap->bits_per_value);
}
but you have have tree of groups
this is a 7 x 32bit structure, that describes a single sprite
if a sprite hasnt changed, then i dont have to re-generate this structure
and i can just copy it into the displaylist for the next frame
which saves some cpu
so that's what tilegrid should maintain
and group should combine them to produce the displaylist
ah, so the group is basically the same as my videocore.HvsChannel1.set_sprite_list([format1, format2, format3, format4])
is a tilegrid object bound to a single display driver?
I think there is no explicit bond, but the display logic assumes only one display is displaying any object
because there is a linked list internally
and on the rpi, all 3 hvs channels can consume the same format, and infact, share the displaylist ram
but each needs its own copy of the displaylist
basically, there is an uint32_t dlist[4096] in MMIO space
for each 1:1 scaled sprite, you write 7 slots
plus 1 slot to end the list
then you put the starting index into another control reg
a scaled sprite takes up 14 slots
a palette takes an extra 1 slot in the sprite itself, plus N slots to hold the N RGBA8888 colors
I think tilegrid's ensure they are only in one group at a time
so sharing a palette between multiple sprites will reduce the usage
since groups have coordinates and scaling that propagate into the tilegrid
palettes can be shared
and the TileGrid holds a pointer to the palette?
ya, to the pixel_sharder
which is a palette or color converter
tilegrids are ordered by their order in groups
ie z-depth
perfect
the entries in the hw dlist also have to be in z-depth order
it draws them first to last
internally, there is a FIFO that can hold a few scanlines
when that FIFO has room for 1 scanline, the hardware will start parsing the display list, and copying/blending pixels into the FIFO memory
it can draw 4 pixels/clock for unscaled sprites
2 pixels/clock for scaled sprites
and 1 pixel/clock for palette based formats
if it can draw all of the sprites in the scanline within the deadline (normal racing the electron beam stuff), then it can keep up and everything is fine
the FIFO gives it a couple scanlines of wiggle room, so it isnt too fragile
and the 2d core will take turns generating scanlines for up to 3 displays, each in its own FIFO
if no sprite covers a given pixel, then the color is undefined (whatever was already in the fifo), and you get weird effects
but there is an optional background fill, that will pre-write a configurable constant to the whole scanline, at the cost of more clock cycles
there is also hardware dithering support
for context, this was setup to do an r/g/b face from 0% to 100%
but the top 2 bits of green are mis-configured (hw uart conflicts)
in this example, dithering is off, so you can see some hard steps in the darker regions, when the camera isnt over-exposed
this image, then has hardware dithering enabled
but the top 2 bits are still mis-configured, which makes bit0 wiggling far more visible
Do you want to do this on 8.2.x instead?
I think palette has a dither flag too
that or colorconverter
mainly for color eink improvements iirc
huh, interesting
you define the output bit depth
24bit 888
18bit 666
16bit 565
or 15bit 555
and you define a dithering mode
0 = No dithering
1 = Accumulate rounding error horizontally.
2 = As 1, but also apply pseudo-random noise. The noise generator is reset at the start of each frame.
3 = As 2, but the noise generator is free-running. This setting will produce a shimmering effect on static images that may be distracting.
internally, it operates on rgb888, and then it will dither down to the configured depth, as it fills the FIFO with scanlines
https://forums.raspberrypi.com//viewtopic.php?f=41&t=45290&p=363475#p363475
this post explains how to configure dithering in config.txt
but the firmware/config format, only allow configuring it on 1 screen
while the hw lets you configure all 3 screens, with different dithering options
What do you think about adapting Sprite to the TileGrid API and changing the displayio implementation instead? That way existing code would work including the default terminal.
ah, I see
ive RE'd that part of the hardware, so i could expose it in circuitpython easily
but hdmi is already 8bit
most dsi i assume are 8bit?
composite i assume is 8bit, but its analog, hard to tell without a scope and test patterns
so only DPI really needs it
and then youve lost all your gpio
we're just starting to support DPI
Do you have any Adafruit or Espressif dev boards you can reproduce this on? I don't have a BPI. Alternatively, you could try building a debug build and getting a backtrace from the debug uart output.
most of what we support is 565 over spi or 8080
there are 2 ways to do DPI
1: just use the legacy firmware options to setup DPI in config.txt, then it will show up as one of the hvs channels in my code
2: i know how to bringup DPI fully from scratch, so circuitpython could do all of the timing params
the SMI interface on the rpi lets you accelerate 8080 based interfaces
there is also an SMI video mode, but ive not figured it out yet
you configure how many clock cycles long the setup/strobe/hold/pace periods are
then you just load DMA up with a buffer, and point it at SMI, and let it rip!
HDMI is the most interesting part of the pi for me anyway
but nice to know we could accelerate other displays too
ive been struggling with hdmi init on the open firmware
but if your leaning on the closed firmware, its easy to hijack things after init is done
later tonight/tomorrow, i need to go over the tilegrid and group apis, write some example code, and then try throwing a group at my driver
also, how might i allow full rgba8888 or yuv images? the hw supports them
displayio.CIRCUITPYTHON_TERMINAL, ah nice, so thats just exposed to python
https://docs.circuitpython.org/en/latest/shared-bindings/displayio/index.html#displayio.Colorspace.RGB565
oh, and i have my demo backwards!
i'll need to update it then
@buoyant lagoon Do you want to be added to the circuitpythonistas role? I dont' know if we've already offered it, or if you're even interested. But you've been super active lately with CP. The role means you get pinged twice a week about the Monday Community meetings. And your name shows up purple. Let me know if you'd like to be added! No worries if not!
sure, add me
Done!
ive been listening in on those meetings, but somehow missed yesterdays
Next week is Tuesday, FYI.
ah, maybe it was last monday that i missed
@buoyant lagoon The role also lets you speak during the meetings, if you're ever up for participating.
full alpha isn't something we have now. yuv would be another input and output colorspace I imagine
Requesting to add waveshare esp32 s3 pico board.
Would it get propagated to main eventually? If so, yes.
I think I would need to start with branching off 8.2.x to make that change.
but yuv420 is complicated, by the luma plane being at half res, and the chroma plane being in a seperate array
Just a small taste of difficulty. The RP2 places IOPORT and Cortex-M0+ registers above the 2G line in its address map. As it is, memorymap.AddressRange() treats its start argument as signed integer, so it will not accept an address above the 2G line. Digging deeper, unsigned integer argument interpretation and validation isn't implemented in runtime. This problem also affects the NRF53 series.
I do have :
- an esp32-c3 qt py
- a magtag (esp32-s2)
- a circuit playground express (not esp but that would be my test group)
but all of them would require a bit of soldering/desoldering with my current code.
I'm currently trying to get a crashing code that does not need actual hardware connected. I mostly still need to get rid of the nfc pn532. I tried to replace the pn532.read_passive_target() with spamming somewhat similar spi command but it does not crash. So my next step is ...
This requires a change in our fork of esp-idf:
Instead of changing the IDF could we enable CONFIG_SPIRAM_USE_CAPS_ALLOC? I'm not sure how many other modules will start trying to use PSRAM then but maybe that's ok. We don't really need it all for CP.
Just a few minor things. Thanks for getting this going!
Please always include it. In my IDF 5 update above I've always included camera. That ensures that the sdkconfig settings are always available. Later we can omit linking the library.
Want to use this for IDF debug output instead of CP?
Do these displays not auto-refresh by default?
Another thing to check after IDF 5 merge is SPI flash settings since they are on a shared set of pins. The longer the flash reads take, the longer the PSRAM transactions will have to wait. I'm reworking how these settings are done in IDF 5.
oh, on the subject of hdmi audio
you need to encode the audio data into a IEC958 format, which supports up to 8 PCM channels
then configure a DMA block to copy it into a hw fifo
other then the encoding step, that sounds very similar to how i2s and pwm would do audio on most other boards
does circuitpython have any pre-existing framework for managing the dma and ringbuffer, and keeping the buffer topped up with audio data?
Is there an equivalent of the Decimal class?
Trying to port a normal python module over to CP. https://github.com/hrbonz/python-aqi/blob/master/aqi/algos/epa.py#L3
This worked for me https://github.com/jepler/Jepler_CircuitPython_udecimal
The wrinkle is that esp32 requires a cache flush. otherwise a mix of old and new data is displayed.
right, the idf logging is preserved even after the CP console is up.
this was not supposed to be here, it got added back by mistake. will revert.
Instead of changing the IDF could we enable
CONFIG_SPIRAM_USE_CAPS_ALLOC? I'm not sure how many other modules will start trying to use PSRAM then but maybe that's ok. We don't really need it all for CP.
I was reluctant to do this because it looked like a big change (we like to just manage the PSRAM ourselves so we always have a nice big contiguous heap). As far as I understand it, we have to change that if we change this setting. If I'm wrong about that then I'd be happy to change it.
Here is a barely-working GT911 CircuitPython driver for touchscreens, it reads and reports the first touchpoint. Unsure if the init code is required, but seems to work on my unit without it. Might be useful for some of these new dotclock displays. https://gist.github.com/kmatch98/097a34177b68480e511179f9eeb8d909
Protomatter matrix library 1.6.1 (c9c1189) addresses some issues with ESP32-S3. Drive strength compilation issue is fixed, pixel clock is slightly reduced to help w/visual glitches.
The prior release, 1.6.0, if not already in use by CircuitPython, addresses M4 issues. Also a slight pixel clock reduction, and additionally the clock duty cycle is semi-configurable -- perhaps this could be exposed as a named arg in Python, and ignored if not supported by arch. See _PM_setDuty() comments in th...
I'm not sure the "Note" and example code makes sense for circuitpython.org but I figured I'd throw it in and if it doesn't make sense I can pull it out easily enough. Thanks!
CircuitPython version
Adafruit CircuitPython 8.2.4 on 2023-08-22; ESP32-S2-DevKitC-1-N4R2 with ESP32S2
Board ID:espressif_esp32s2_devkitc_1_n4r2
UID:0740D17F678D
Code/REPL
# https://learn.adafruit.com/adafruit-ov5640-camera-breakout/lcd-mirror-demo
from debugfun import breakpoint
import busio
import digitalio
import espcamera
import board
import displayio
from adafruit_st7789 import ST7789
import time
flash = digitalio.DigitalInOut(board.IO45...
Hi, not sure I have ever seen a piece of code on circuitpython.org.
Maybe the best place could be to create a simpletest_code.py next to the board definition in circuitpython repo, as suggested in the first in the weed topic of this week meeting:
https://github.com/adafruit/adafruit-circuitpython-weekly-meeting/blob/main/2023/2023-08-28.md
Now that would be the first time it is ever done, there might be discussion on the best place to put that.
I would also insist on putting a bit of code...
When I was posting this PR, I didn't see the code snippet as example code, I was thinking it was part of a board caution or warning. I had a feeling that some other boards did something similar when there was a minor revision that swapped a pin or two out or for the boards that don't have native USB.
Now that I've thought about it more, and poked around on circuitpython.org, I think those notes/cautions were probably added to the Adafruit product pages. I'm thinking for community provided...
CircuitPython version
Adafruit CircuitPython 8.2.4 on 2023-08-22; Adafruit Feather ESP32-S3 Reverse TFT with ESP32S3
Board ID:adafruit_feather_esp32s3_reverse_tft
Code/REPL
import board
import digitalio
import busio
import asyncio
import binascii
import os
import time
import ssl
import socketpool
import wifi
import adafruit_minimqtt.adafruit_minimqtt as MQTT
from adafruit_httpserver import (
Server,
REQUEST_HANDLED_RESPONSE_SENT,
...
Code for TL021WVC02 480px round display & Adafruit TFT Experiment Rev A https://gist.github.com/jepler/71e9ae8b1e45616fa75988d1139140c1
so is this the "real fix", so that e.g., GPIO 33 is marked as in-use for CONFIG_SPIRAM_MODE_OCT? and the rest is [good] churn? If so, good to go.
I verified that this is a fast-forward pull of tinyusb
frame 6
frame 29
frame 52
frame 12
frame 35
frame 58
frame 18
i modified the C code, to expose the hw frame counter from the 2d core on the rpi
but just the framebuffer (which isnt accelerated yet), adds enough latency to prints, to make it skip over 20 frames, lol
frame 0
frame 4
frame 7
frame 11
frame 14
frame 18
frame 22
frame 25
frame 29
frame 32
frame 36
frame 39
frame 43
frame 46
frame 50
frame 53
frame 57
frame 61
disabling some code in board_init() removed that, and now its better
delta: 3 scanline: 945/1024 overhead: 0.0359802 next: 0.05
delta: 3 scanline: 964/1024 overhead: 0.0360107 next: 0.05
delta: 3 scanline: 936/1024 overhead: 0.0370178 next: 0.05
delta: 3 scanline: 920/1024 overhead: 0.0359802 next: 0.05
delta: 3 scanline: 889/1024 overhead: 0.0370178 next: 0.05
delta: 3 scanline: 855/1024 overhead: 0.0369873 next: 0.05
and with a few more lines of code, it reports where the scanout is within a frame
Resolves #8334 by adding memorymap support to the RP2 port. Also makes these additional changes:
- Changed memorymap hal function prototypes to use size_t rather than uint32_t arguments, allowing prototypes to work with different port word sizes.
- Changes memorymap.AddressRange() start argument from signed to an unsigned int to allow ranges to be specified anywhere in the entire port address map. Added support to the runtime for unsigned int arguments.
- Added wrap-around checking for m...
CI found some breakage. I entirely missed the fact that there are multiple runtimes. Working...
I have the same problem!
Firmware: adafruit-circuitpython-yd_esp32_s3_n16r8-en_GB-8.2.4.bin
Dev board: YD-ESP32-S3 N16R8, 2022-v1.3
After flashing the firmware and connected to it using putty, REPL did not work:
If no one objects, I'd like to pick up this issue.
@tannewt over to you for review. Thanks!
What happens f you leave the height out, but use tile set to 2? Apparently it's an optional parameter.
Sorry for the delay, but requested changes have been completed.
Looked into pin drive strength (i.e., current) support on several (but not all) of the microcontrollers supported by CP and they break down like this:
- Unsupported. Broadcom, cxd56.
- Normal/Stronger. Atmel samd.
- One of four values. Espressif, RP2.
- Standard/High with logic 0/1 specificity. nrf
Any thoughts generalizing all this variation?
@makermelissa on the 9.0 alpha 1.8 build or 8.2.4? I've since switched to the alpha build which works much better. I can go back to 8.2.4 for more testing if needed.
I still get intermittent hard faults on 9.0 alpha but it only when saving code.py. A hard reset usually fixes it and will run indefinitely. I do not get hard faults while the program is running, only happens on file save (using Mu). A good example of the hard fault during save can be seen in the live demo on this weeks [8...
@ouening Are you connected to the port labeled as "USB" on the board? The "COM" isn't gonna show the REPL.
@eightycc Note that the drive strength for PIO was reduced since the previous discussion, to fix a specific use. (I was worried when I saw that, but fortunately it doesn't seem to affect my project too much.) https://github.com/adafruit/circuitpython/pull/7558
So it seems what I was saying in the OP is not the case, and we really need the general drive strength API, as you already started discussing over here: https://github.com/adafruit/circuitpython/issues/1270#issuecomment-1703614207
Even though the nRF## is a suitable workaround, it exhausts pins from the board and undermines the boards built-in capabilities. I hope someone can pick this up! β¨
Hi
Could you explain what you mean by that? What is "it" in your sentence? Does the firmware prevent using pins on the nRF##?
Hi everyone,
I would like to connect a keyboard to a Raspberry Pico (RP2040) with the data+ and data- cables of the USB and check the content of an input string.
From the circuitpython forum I know that recently it has been implemented the usb_host library to use the PIO of the Pico and I tried using my Pico W board with the following script:
import board
import usb_host
import sys
h = usb_host.Port(board.GP0, board.GP1)
while True:
print(sys.stdin.read(1))
H...
Hi Could you explain what you mean by that? What is "it" in your sentence? Does the firmware prevent using pins on the nRF##?
Using an external ble hardware uses pins of the main board, which in most of my projects is not possible, since those pins are already in use. Also, the external hardware takes up space which further complicates the setup.
Furthermore, it makes no sense to work around the above constraints since the pico already has the hardware capability and even Micropython...
Just finished testing thoroughly, everything looks good. Now waitng your review.
I've got @kmatch98's Hack Tablet working with this PR. The bouncing ball demo seems to work fine but the only other thing I've tested so far is the animated Homer Simpson gif which works but is very small on this display :grin:. I'll keep playing and see what I can do, but let me know if there's anything in particular you want tested.
I haven't build CircuitPython in a while. Is there a way to collect the .bin artifacts for the Makerfabs 7" build or the HACKtablet?
I actually had to go digging to find mine.
Is there a way to collect the .bin artifacts for the Makerfabs 7" build or the HACKtablet?
The HACKtablet artifact isn't being built by Jeff's PR yet but I've attached the one I've built. I don't see the Makerfabs artifact, I think you normally find the artifacts by clicking on the "checks" tab on this page and then select "Build CI", the artifacts would be at the very bottom but I only see [adafruit_esp32s3_rgb_tft_experiment](https://github.com/adafruit/circuitpython/suites/15737310922...
Keep in mind that the latest build from main isn't compatible with .mpy files so you need to grab .py versions of any libraries you want to use.
Here's the code I'm using to initialize the display.
import displayio
import framebufferio
import dotclockframebuffer
import board
displayio.release_displays()
fb=dotclockframebuffer.DotClockFramebuffer(**board.TFT,**board.TIMINGS800)
display=framebufferio.FramebufferDisplay(fb)
Oops, sorry, you said .bin artifact...
HACK Tablet firmware.bin.zip
Hi,
I just started with CP9.0.0 and usb_host on my PicoW yesterday and also came across that issue. I fixed it by switching the Pico PIO state-machines for USB D+ and D- and got it running....sort of. Here's the diff:
diff --git a/ports/raspberrypi/common-hal/usb_host/Port.c b/ports/raspberrypi/common-hal/usb_host/Port.c
index 93d19acd6..6b9aeae55 100644
--- a/ports/raspberrypi/common-hal/usb_host/Port.c
+++ b/ports/raspberrypi/common-hal/usb_host/Port.c
@@ -122,8 +122,8 @@ usb_h...
The nRF52840 boards run CircuitPython and have native BLE. They are not an add-on co-processor, so pins do not need to be used up for that.
There's no board definition for the hack tablet in this branch and because of the way the CI works now (tries to build as few boards as possible) you have to go through a few hoops to find the makerfabs one.
I think it'll be: makerfabs_tft7
but basically you go back through the green check marks until you find a build that has your board in it, then go to that link, then click summary, and finally you ...
I've been thinking about this and have some suggestions for how this might be done:
- Use generic language to describe drive strength, for example: STRONGEST/STRONG/WEAK/WEAKEST or HIGHEST/HIGH/LOW/LOWEST. For ports that support only two levels, HIGHEST/HIGH would map to high level and LOW/LOWEST to the low level. For example, 8 mA drive for the RP2 would be DriveStrength.HIGH. Adding a fifth level DEFAULT would set DriveStrength to the reset value for the port. Ports that do not support s...
Thanks jepler and RetiredWizard. I got the makerfabs display working with the binary and the awesome ESP webserial uploader.
Agreed on the difficulty to find GitHub artifacts, I clicked and clicked but didn't know the secret pathway to find what I was looking for.
Special thanks RetiredWizard for the setup instructions for the display, these worked perfectly on the makerfabs binary too.
:
self.param1 = param1
self.param2 = param2
@property
def property1(self):
print(dir(self)) # <-- This is the line that causes the board to c...
CircuitPython version
Adafruit CircuitPython 8.2.4 on 2023-08-22; Adafruit Feather ESP32-S2 TFT with ESP32S2
Board ID:adafruit_feather_esp32s2_tft
UID:487F305FFE63
Code/REPL
class ParentCLass:
def __init__(self, param1: int, param2: int):
self.param1 = param1
self.param2 = param2
@property
def property1(self):
return (self.param1, self.param2)
class ChildClass(ParentCLass):
def __init__(self, param1: i...
Weird. I just tried this on Adafruit CircuitPython 8.2.4 on 2023-08-22; Saola 1 w/Wroom with ESP32S2 and after typing in the class above in REPL paste mode, instantiating SimpleClass in the REPL, and doing dir() if a few ways I get weird results, but no crash:
>>> simple_object = SimpleClass(1, "2")
>>> dir()
['simple_object', 'SimpleClass', '__name__', '__file__']
>>> dir(simple_object)
['__class__', '__init__', '__module__', '__qualname__', '__dict__', 'param1', 'param2', ...
@microdev1 Would you mind doing a merge to resolve the conflicts? Thanks!
Done.
CPython supports so called positional only parameters (PEP 570) with as the name say, cannot be passed using their name.
They are useful when a function e.g. accepts a value that has not special meaning, it is simply a value.
Example:
def some_function(positional_only, /, positional_or_keyword, *, keyword_only):
pass
some_function(1, 2, keyword_only=3)
some_function(1, positional_or_keyword=2, keyword_only=...
Sorry guys, I can't find the modified library any more :(
I experimented with the sensor for an afternoon, decided it was too much work and my student would just have to use an older ST sensor. The board with that code on it then probably went to another student when I ran short on QT Pys. That's one downside of having the source directly on the device I guess.
So, I am back to the L4CD lib and example, with the minor modifications of setting the I2C to 1 MHz. Works only up to 2.2 m. I ma...
Is that FTP from or to (or both) CircuitPython? π
ftp server on CP
client on my thinkpad
I will get a ftp client on CP too, but much later
tbh, I don't see why this couldn't be a built-in module for the big boi boards.
it's not that complicated tbh..
There is is some work already on this in MicroPython: https://github.com/micropython/micropython/pull/8480. We would probably wait for this to be finished and then merge it.
...or use:
context = ssl.create_default_context() context.load_verify_locations()with a CA string or .pem file
...or use:
context = ssl.create_default_context() context.load_verify_locations()with a CA string or .pem file
I'm admittedly not the sharpest python tool in the chest, but I assumed I'd be able to pass a bundle .pem file to load_verify_locations but I get an error about processing CRT (8015)....
PR it?
I will first make it fully in python and then make it in C
Then I will π
It's honestly simplier than telnet
storage.remount? SD?
It just uses the os funcs in it's current form, so it will work with anything mounted
I didn't get as far as to write just yet..
I am doing the LIST command right now
I implemented ACTIVE, and will finish LIST with it.
then I will implement GET with PASV
In the core implementation we should prolly not have as many options as I have here though.
Maybe just PASV or it being should be settable by settings.toml
I was going to ask if that was on CP but then I was like nah no way. That's pretty amazing. π
i saw mention before that the text console is a TileGrid
is it a bitmap being displayed in one, or is it one tile for every single character and then letting displayio draw the fonts?
LIST is done, now onto modesetting and pasv
And I haven't even entered jank mode. It's all decent code thus far.
π
nice
This is probably a duplicate of
There may be two separate problems.
First, dir() is implemented differently in CircuitPython than in desktop Python. In particular, calling dir() on an object actually retrieves all of the object's property values, which can have side effects. When a property getter calls dir() on the object, this creates an unbounded recursion. I did not find this explicitly documented anywhere so it m...
I found that when I increased the amount of 'grace area' in the stack check from 1kB to 2kB I didn't reproduce the problem anymore. There's no particular justification for this value that I could find; it depends how much "additional stuff" can be placed on the stack subsequent to a call to mp_stack_check and I don't think there's any simple way to calculate the maximum such value.
diff --git a/main.c b/main.c
index 94a3feac6b..d0727beb53 100644
--- a/main.c
+++ b/main.c
@@ -1...
load_verify_locations for more than a single certificate?
I'm not sure if it's intended for a bundle (docs could be modified to indicate), just that it's sometimes used to get around a missing cert for a site.
<@&356864093652516868> Reminder - there is no meeting today due to the Labor Day Holiday in the US. Meeting is normal time tomorrow at 2pm EST / 11am PST. See you then!
Hey folks, does anyone here use VS Code when developing with circuitpython? I keep running into an issue where, due to the size of the circuitpython repo (ie all of its submodules), VS Code will often spawn dozens of rg processes whenever I do anything with the editor that could trigger indexing, searching, referencing, etc. It can sometimes get so bad that it completely maxes out my cpu and freezes VS Code.
I'm sure I can fix it by configuring VS Code to ignore certain paths, but thought I'd first check if anyone else here has run into this issue and already has a decent workaround? Thanks!
I've hit the same issue. My workaround is to checkout only the bits pertinent to the port I'm working on by using "make fetch-port-submodules" inside the port directory.
Also I've learned not the run fetch-port-submodules from the terminal inside VS Code as this gets things churning badly. Better to run it in a separate terminal and then open VS Cope when it's done.
@mortal kernel thanks for the input, I'll give that a try! I think that should still work when I'm testing changes to the core circuitpython code (eg in the py directory) since that isn't a submodule.
@mortal kernel Nice! Your suggestion is working quite well, VS Code is much more usable, thanks again!
hello ! I've been working on keyboard with kmk/circuitpython for an esp32s3 and now the only thing I'm missing for going full wireless is the ble workflow. KMKfw is awesome and I'm sure this would be a terrific feature to support espressif chips for building nice bt keybs :)
Any idea if that feature is still being considered for future releases ?
I had another look. Modifying the initialization parameters for the CX gave me about 270 cm maximum in the default mode For long range, it seems the histogram mode is required, and this by necessity requires a bunch of code from the library. Working manually, I don't see a python rewrite happening. The code is way too long (even single files) for the AI code rewriting tools I could find. So, I am back to either compiling the C code and using that or just not using this soft-sensor (reminds me...
Thanks for everything you all are doing. I struggled with this setting up a new Pico W today, trying to talk to the GitHub API. Based on the comments above, I simply downgraded to CircuitPython 8.2.0 and it immediately started working.
I had another look. Modifying the initialization parameters for the CX gave me about 270 cm maximum in the default mode. For long range, it seems the histogram mode is required, and this by necessity requires a bunch of code from the library. Working manually, I don't see a python rewrite happening. The code is way too long (even single files) for the AI code rewriting tools I could find. So, I am back to either compiling the C code and using that or just not using this soft-sensor (reminds...
Hi folks. Based on there being new commits i the 8.2 branch, can I safely assume there's be an 8.2.5 or higher before 9.0 ?
I plan to release an 8.2.x with updated root certificates soon.
Yes, 9.0.0 has quite a ways to go. We'll be doing 8.2.x for a while. See for instance the previous post.
Ok, thanks Dan. I want to commit those FeatherS3 second I2C bus changes into 8.2.x as I did it in main thinking 9.0 was imminent - doh! I should have asked first!
np - if the PR is still open you can change the base
easier to merge from 8.2.x to main so we've been preferring 8.2.x instead of doing a lot of backports
Nah, it was merged already a while ago π¦
I had a combination of different causes that at led to my issue:
- a not so clean solder-point on the D+ cabling => more solder for a more reliable connection
- a very nitpicky USB device (a Micro RP2040 from SBcomponents) => other boards work just fine (that SBcomponents board works just fine with the examples from Pico-PIO-USB - so it's something within circuitpython that behaves different)
- invoking usb_host.Port(...) in boot.py doesn't work => invoking it from code.py does work
Not...
CircuitPython version
Adafruit CircuitPython 9.0.0-alpha.1-25-g000d22f25 on 2023-08-30; VCC-GND YD-ESP32-S3 (N16R8) with ESP32S3
Code/REPL
import wifi
from socketpool import SocketPool
from adafruit_requests import Session
pool = SocketPool(wifi.radio)
_socket = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
_socket2 = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
_socket.bind(("0.0.0.0", 20))
_socket.listen(1)
_socket2.bind(("0.0.0.0", 21))
_socket...
When you say you don't see a python rewrite happening, is that by you, based on how much time you have or anybody? Or more specifically, if I were to dedicate time to it, how long do you think it would take? I frequently port things from c code.
CircuitPython version
Adafruit CircuitPython 8.2.4 on 2023-08-22; micro:bit v2 with nRF52833
Code/REPL
from microbit import *
while True:
display.show("Coucou !")
Behavior
Serial console setup
Auto-reload is off.
Running in safe mode! Not running saved code.
You are in safe mode because:
CircuitPython core code crashed hard. Whoops!
Hard fault: memory access or instruction error.
Please file an issue with your program at github....
Had to tweak the close(). Then it works on raspberrypi, but espressif gets stuck in _socket2.accept() (client times out on connect).
import wifi
from socketpool import SocketPool
pool = SocketPool(wifi.radio)
_socket = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
_socket2 = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
_socket.bind(("0.0.0.0", 20))
_socket.listen(1)
_socket2.bind(("0.0.0.0", 21))
_socket2.listen(1)
a = _socket.accept()
b = _socket2.accept()
a[0].cl...
works in asyncio on both platforms:
<details>
<summary>code.py</summary>
import wifi
from socketpool import SocketPool
async def s1():
_socket = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
_socket.bind(("", 20))
_socket.listen(1)
_socket.settimeout(0)
while True:
try:
a = _socket.accept()
print("s1ok ")
a[0].close()
except OSError:
pass
await asyncio.sleep(0)
async def ...
Hey - I am not using circuitpython but I have the same issue with micropython AND even with plain Arduino Blinky Sketch.
If I am running Micropython it was working perfectly fine for like 2 weeks and then this issue appeared. I factory-resetted the device multiple times and tried re-soldering USB connections and everything. I know it is not the right place but maybe someone can help anyway. Here are some facts:
- Device worked perfectly fine for ~2 weeks
- REPL started to disappear
- a...
@justmobilize the library has 37k lines in total. Not complicated code, but a complicated structure. It's not impossible, sure, but I will certainly not do it :)
I thought it might be a good job for an AI, just parsing all the things and putting it into Python syntax, maybe even simplifying a bit. But it seems the volume is just too much currently.
@MarkJB: I feel like it's a dead end, but here are my changes: https://github.com/veloyage/Adafruit_CircuitPython_VL53L4CD/commit/f3f42bc076...
watch -n0.2 'netstat | grep "board-ip-here"' to monitor all connections and their status.
The second one, as stated above is stuck at SYN_WAIT.
It could just be a oopsie, sending the SYN response to the wrong connection for all I know.
Regarding asyncio, I drafted this:
import asyncio
import wifi
import socketpool
from sys import stdout
conn1 = None
conn2 = None
async def tcpserver1():
s = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
s.bind(("0.0.0.0", 20))...
And now we escale the situation to a safe mode issue..
I made a reproducible safemode with it..
CircuitPython version
Adafruit CircuitPython 9.0.0-alpha.1-25-g000d22f25 on 2023-08-30; VCC-GND YD-ESP32-S3 (N16R8) with ESP32S3
Code/REPL
import wifi
from socketpool import SocketPool
pool = SocketPool(wifi.radio)
_socket = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
_socket.bind(("0.0.0.0", 20))
_socket.bind(("0.0.0.0", 21))
print("Accepting 1")
_socket.listen(5)
a = _socket.accept()
print("Accepting 2")
b = _socket.accept()
print("Accepted...
I just woke up and decided to break esp today.
In ljinux I have seen plenty of dir() weirdness too, from not being able to filter out stuff that .startwith("_") to just random exceptions.
I have put my dir()'s in a try: except: and never seen hardfaults.
I just blamed all the weirdness to the fact i run 20 exec()'s deep.
Didn't think to try on the repl.
Got backtrace:
? 0x420968c6:0x3fceaf60 0x420976a1:0x3fceaf80 0x420992f6:0x3fceafb0 0x4209e32a:0x3fceb020 0x420a1fee:0x3fceb050 0x42093d91:0x3fceb070
0x420968c6: tcp_pcb_num_cal at /home/bill88t/git/circuitpython/ports/espressif/esp-idf/components/lwip/lwip/src/core/tcp.c:1875
0x420976a1: tcp_pcb_num_cal at /home/bill88t/git/circuitpython/ports/espressif/esp-idf/components/lwip/lwip/src/core/tcp.c:1888
(inlined by) tcp_alloc at /home/bill88t/git/circuitpython/ports/espressif/esp-idf/...
Sorry for the stupid question.
I should use tg.bitmap = cam.take(1)
There does seem to be an espressif bug when attempting simultaneous TCP connections. I fully expect sequential connections to work (your 3rd example, and my asyncio example). I wouldn't expect 2 servers on the same port to work (your 1st example).
But PASV doesn't work with sequential connection to the control port, then the data port?
There does seem to be an
espressifbug when attempting simultaneous TCP connections (2 accepts in a row on different ports, without closing either)
I think it would be good to test this with, say, MicroPython on some ESP32xx board to see if it is our issue or is ESP-IDF. Also maybe a quick search of the ESP-iDF issues.
But PASV doesn't work with sequential connection to the control port, then the data port?
PASV tl;dr workflow explanation:
- Open port 21 for control.
- User connects on 21.
- User authenticates.
- User sends the PASV command to start the data socket.
- Server decides on a port to use, and opens it up (
.listen()). - Server sends the RFC defined formatted reply to the client over the control connection.
- Client immediately connects to the ip:port the server sent in step 6...
New discovery!
If the web workflow is disabled, you can do 2 binds.
So in reality you cannot do 3 binds.
import wifi
from socketpool import SocketPool
from sys import exit
try:
wifi.radio.connect("Thinkpood", "REDACTED")
except:
pass
if not wifi.radio.connected:
print("No wifi")
exit(0)
pool = SocketPool(wifi.radio)
_socket = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
_socket.bind(("", 20))
_socket.listen(1)
_socket2 = pool.socket(pool.AF_INET,...
Taking the same code and adding:
_socket3 = pool.socket(pool.AF_INET, pool.SOCK_STREAM)
_socket3.bind(("", 22))
in it, is all that is required to trigger the bug.
.listen() does not affect it.
This gives me some good clues as to where to look.
First,
dir()is implemented differently in CircuitPython than in desktop Python. In particular, callingdir()on an object actually retrieves all of the object's property values, which can have side effects. When a property getter callsdir()on the object, this creates an unbounded recursion. I did not find this explicitly documented anywhere so it may be that we should improve documentation in this area. This difference is inherited from Micropython and we aren't likely to lif...
CircuitPython version
Adafruit CircuitPython 8.2.4 on 2023-08-22; Adafruit ItsyBitsy nRF52840 Express with nRF52840
Code/REPL
This code demonstrates the issue:
import busio
import board
import time
uart_hw = busio.UART(board.TX, board.RX)
while True:
print("Spin Loop")
time.sleep(0.5)
For comparison, this code works OK. The only difference is the use of the `board.UART()` singleton:
```python
import board
import time
uart_hw ...
I did plently of esp debugging.
I only however managed to down as far as lwip_accept in ports/espressif/common-hal/socketpool/Socket.c:272.
With esp_log we can see there, the 2nd/3rd socket not being accepted.
I tried going deeper, but the internal logging of lwip doesn't get printed no matter what I do.
Importing esp_log, is a mess I cannot figure out.
I will have to leave it you you guys from there on out.
(Perhaps C3 can prove itself not being a paperbrick and help with some jt...
If no password is passed via settings.toml, the wifi connection will occur, but the web workflow will not start at all.
This frees up a (as it turns out, very precious) socket.
Ahoy <@&356864093652516868> -- as yesterday was a US holiday, we're having the meeting TODAY in about 70 minutes. Take a moment to add your notes, and then if you can join us in the voice chat. https://docs.google.com/document/d/1P6AwndR-BBldT7jIzLpO72B9nSmnz7VJexO96ttI2O0/edit?usp=sharing
CircuitPython Weekly Meeting for September 5, 2023 Here is the notes document for next TUESDAYβs CircuitPython Weekly meeting due to the Labor Day holiday in the US. It is at the normal time of 11am Pacific / 2pm Eastern here on Discord. Everyone is encouraged to attend! Please add your hug rep...
One tile per character from a bitmap font spritesheet
ahhh, that will be an interesting stress test then
I wonder, maybe it would be even better if I permit wifi conn (and only wifi), on reloads.
Cause now it only runs that stuff on boot.
@crimson ferry Opinion?
assuming a basic 80x24 terminal, thats 1920 characters
and you need 7 words per sprite
which is 13k words, wont fit!
so, to do text console on the broadcom port, i would need to render the text console into a bitmap, but treating the bitmap as a ringbuffer is allowed, and then i can sprite that onto the screen
13k words won't fit where?
the displaylist is only 4096 words long
and you need 7 words for each sprite/tile
so if you had one sprite for each character in the text console, you would run out after ~580 characters
that would kinda negate the benefits of hw accel
so i was thinking, only something with a high tile count, like the text console, would pre-render into a bitmap
and things with a low tile count, can be fully hw accelerated
ive also got another issue
how do i know when the tiles in a tilegrid have changed?
ive not found any hooks yet, and dont know if its timer based?
so ive just modified my test code.py to re-run board.DISPLAY.show() for each update
Without Web Workflow, raspberrypi persists wifi connection across reloads, espressif does not`. MicroPython acknowledges this as a bug https://github.com/micropython/micropython/issues/9505.
With Web Workflow enabled, I think the assumption is: always connected, though robust apps do need to manage the connection since there are ways it can fail that the core does not recover from.
K, imma go make it reconnect on reloads and add that to the docs too.
other core devs probably have more reasoned ideas about this
Well, I am here and I can be pinged. I can also be pinged in the issue directly.
And it's not like I will (or can) merge it on my own.
The only reason it's not connecting upon reload, is because of the delay of starting up allothat
// TODO: Do our own scan so that we can find the channel we want before calling connect.
// Otherwise, connect will do a full slow scan to pick the best AP.
// We can all connect again because it will return early if we're already connected to the
// network. If we are connected to a different network, then it will disconnect before
// attempting to connect to the given network.
Yea, the slow scan, is a slow scan.
Tile indices are changed through the common_hal_displayio_tilegrid_set_tile() function
so i would need to hook that function? but i want some tilegrids to render to a bitmap, while others update the hw accel
I assume you'd reimplement it with your accelerated version of displayio
@RetiredWizard I'd be happy to add the hack tablet as a board as part of this PR!
@tannewt I think I made SPIRAM_USE_CAPS_ALLOC work, please review again! However, I didn't change all sdkconfig files to use it, I figured we could do that when we update idf. Let me know if you concur.
@onyx hinge we can hear you
give me a moment please
If you're using a webbrowser sometimes refreshing the page helps when you can't hear someone
Tuesday meetings are weird π
off by one error but not an error
I'd like to make a few more changes to the pins file (for consideration anyway) and then I'll attach the board files to this PR :grin:
Thanks!
synthio doc bug? https://forums.adafruit.com/viewtopic.php?p=984421#p984421
To show and share a project at 7:30pm Eastern today, view the chat or in discord https://adafru.it/discord and look for the JOIN link to join. For best results, be on a wired network connection and use a headset and microphone.
What if I told you this 96cm wide, five panel, 160x32 Interstate75 powered pixel display can be started for just Β£105 and driven from Python running on a Pi or desktop PC for impressively smoooth demos?
I can read
I'm here too
A test of the most recent version of the Windess IoT Garden Chimes. Uses CircuitPython's synthio module to simulate the chimes using algorithms and empirical models for overtones and note envelopes. Chime characteristics such as scale, tube material, and striker material are specified during instantiation to select the tone of the chimes, includ...
π
I shared the wind chimes with Anne too, such a cool project
This looks amazing, so much potential with such a big display
Very cool @random junco !
taking pictures of matrix panels is hard because of scan lines
quite!
congrats on the new office space @slender iron !
Thank you for hosting @onyx hinge
Thanks all! have a good week!
@tulip sleet @slender iron do you want to take a moment to set a time to talk about 1.20? I am out FRIDAY, I'm busy much of THURSDAY afternoon, so today or tomorrow would be good if it's feasible for you two as well
I'm free later. heading home for lunch now and to deal with a grocery delivery. Free tomorrow too
today is fine; tomw i have someone coming to work on the boiler around 12-2 ET, so may have some interruptions
OK, can we do it at around 16:00 ET / 15:00 CT / 13:00 PT ? I think that's about 80 minutes from now.
i should be able to and will let you know if I'll be late
Hi, I think I remember reading somewhere that the 9.x library bundle is waiting on something specific, is that right?
Also I imagine ESP-IDF v5 isn't going into CircuitPython 9 at this stage? https://github.com/adafruit/circuitpython/pull/6913
For the merger of the micropython 1.20 changes iirc.
1.19 has gone through, causing mpy's version to change, but 1.20 will change it again
so libs won't be built for 9.x till that happens
and retooling mpy-cross to work with the new stuff they're doing.
that is still a wip last I checked
yup, without mpy there won't be any publicly released libraries, so at a minimum have to wait for that to happen.
you can still work on libraries in .py format if that's your goal
Thanks, I see!
Or build them to mpy using mpy-cross matching the CircuitPython version I guess
with all the changes they're doing that would be a moving target as they update mpy-cross.
That's what I thought but it still has 9.0.0 milestone on it and 9.0.0 is in alpha already
alpha for the developers not for users, not even close to user ready and things will very much change before a 9.0 rc
Ah so it could still happen?
If you must do mpy, like I do.. I got a module for that, https://github.com/bill88t/CircuitMPY
You can pass any version via ENV or leave it to autodetect it using the board and download it.
we are not going to make any 9.0.0 releases before the .mpy file format stabilizes, after the MicroPython v1.20 merge. We have made tags, for labeling purposes
Here is the notes document for next Mondayβs CircuitPython Weekly meeting. It is at the normal time of 11am Pacific / 2pm Eastern here on Discord. Everyone is encouraged to attend! Please add your hug reports and status updates even if youβll be attending the meeting - itβs super helpful! If you are unable to attend but would still like to include updates, feel free to include them in the notes and weβll read them off during the meeting. Hope to see you there! <@&356864093652516868> https://docs.google.com/document/d/1M51kkQVUANGjwe9rhnOsSs7U6e_x8YQp_7LXxGnx3Xg/edit?usp=sharing
CircuitPython Weekly Meeting for September 11, 2023 Here is the notes document for next Mondayβs CircuitPython Weekly meeting. It is at the normal time of 11am Pacific / 2pm Eastern here on Discord. Everyone is encouraged to attend! Please add your hug reports and status updates even if youβll...
i usually beta test releases looking for bugs, it's pointless for me to even try with 9.0 alpha builds currently because things will change too much between now and whenever they start merging and folding everything in for 9.0... it kind of hasn't even really started yet. the s3 bucket stuff is still using all 8.x libraries.
After tuning in to the meeting today my understanding of 8.2.x vs. main branch has improved. @tannewt would you like me to rework this pull request for 8.2.x?
because it's all still on 8.x mpy and esp-idf. it's too soon.
OK, I'll leave it for a while! Just saw 9.0.0-alpha appearing and thought that meant it was time to start testing, but sounds like it's not.
Here are the board files I'm using for the Hacktablet...
espressif_esp32s3_devkitc_1_n8r8_hacktablet.zip
Wifi now is auto-connecting on reload.
The web-workflow will not init on a reload, only on boot.
This matches raspberrypi behaviour, treating wifi as always enabled when it's set via settings.toml.
This is not something I can do much with.
I think blocking .bind() on an already bound socket is the only way around this.
Requesting rerun on spontaniously combusting action:
https://github.com/adafruit/circuitpython/actions/runs/6089030421/job/16521012570?pr=8367
back to my desk now
My PR's are in. I am finally done.
btw, now I can do pasv with web-workflow off
If I make a wrapper in ljinux that closes the telnet shell and immediately opens ftpd...
hehe
if then I detect the quit and swap back to telnet..
@tulip sleet ready to chat?
on the phone for a few minutes
Looks like there are compilation issues still.
@jepler Do you want to look at this again?
I'm fine to see the default switched. It should be fine either way.
would be good to put this in, it fixes the script failing part way through https://gist.github.com/jepler/623db67bcdedba822b2e6a29d7136b18
Moved to long term because it wasn't reproducible by the original filer. Leaving it open in case someone else sees it.
Yup, that's the fix. The rest is meant to unify everything to using forbidden pins.
On standard Python, the 2nd bind call is an exception, because a socket can only be bound to one address:
>>> s.bind(("0.0.0.0", 20000))
>>> s.bind(("0.0.0.0", 20001))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
I figured I'd give this a shot as at least from the outside the LYWSD02 seems awfully similar. It displays the same data and it seems to share the same UUID https://github.com/adafruit/Adafruit_CircuitPython_BLE_LYWSD03MMC/blob/8bc79c6fcb72699c159129e8a1b0d27a5eaec9f7/adafruit_ble_lywsd03mmc.py#L66
So I put adafruit_ble_lywsd03mmc.py in my libs directory and copied over the content from ble_lywsd03mmc_simpletest.py to my main.py.
The only thing I changed was change line 19
https://gi...
Jepler, just a few things I remember were issues specific to the S3. Perhaps you have resolved them.
- I got tearing because the ESP-IDF is set to automatically trigger a refresh from some internal timer. I had to turn off the IDFβs auto refresh and created a function where I could allow CP to call for refreshes. This may have been include in v5.0 but I have not verified. That added another issue where typically CP (expecting the display to have its own memory) doesnβt call for a refres...
If I understand correctly, the raspberrypi behavior (wifi connection surviving reload with or without Web Workkflow) will change if MicroPython fixes issue 9505, but this PR would auto-[re]connect wifi on either port if Web Workflow is enabled.
@tulip sleet maybe you found this already but somebody did bluetooth classic for micropython https://github.com/shariltumin/esp32-bluetooth-classic-micropython/blob/main/debug/src/bt_spp_client.c
If I understand correctly, the
raspberrypibehavior (wifi connection surviving reload with or without Web Workkflow) will change if MicroPython fixes issue 9505 (and we merge it), but this PR would auto-[re]connect wifi on either port if Web Workflow is enabled.
@anecdata cyw43 is a persistent object we just never reset.
Our implementation is just not bothering disconnecting it, so it persists.
That's all there is to that.
Our picow wifi stuff is all of our own, not really taking...
I like the first option.
@dhalbert want to do this before 8.2.5?
Can't we do that automatically?
Conclusion: switching the PIO engines for RX and TX (diff from above) solved my issue with CP9.0.0-HEAD and a PicoW.
Just for reference (in case anybody is interested): https://github.com/juergenpabel/circuitpython-picow-escpos/
After tuning in to the meeting today my understanding of 8.2.x vs. main branch has improved. @tannewt would you like me to rework this pull request for 8.2.x?
Only if you want to see it in an 8.x release. Otherwise it's fine on main.
Now that auto-connect can be used with or without web workflow, and wifi.radio.stop_station() has been implemented on raspberrypi, we should consider disconnecting wifi across reload in the non-Auto-Connect case. This would make raspberrypi code behave more like espressif code.
In the Auto-Connect case, the presumption is that wifi should stay up as much as possible, and wifi will now survive reloads. But in the non-Auto-Connect case, it's counterintuitive for...
Hi, apologies and I should have updated this issue here but I do get this regularly:
CircuitPython core code crashed hard. Crikey!
Hard fault: memory access or instruction error
Although I'm only developing the software for the ESP32-S3 at the moment and not using it properly so I assumed that this is a regular occurance and was a known problem being worked on. I also have a lot of python code in at the moment and it's difficult to upload it all but I have no problem with doing that if y...
The adjectives I am not so sure about, in case we have a case of even more choices. But how about 0 for the default or "normal" level, 1, 2, 3, etc., for higher, and -1, -2- 3, etc. for lower? Anything out of range gets set to the max for the board, and you can query. The API could also return the mA value separately, and maybe you could even set it that way. But it has to be a small implementation to fit on the smaller boards.
I am not sure there always is a "default", but maybe there i...
Thanks for the PR! Just a couple questions/suggestions.
Let's not modify py/ at all. Anything we change is something we need to merge when we update. It looks like there is already mp_obj_int_get_uint_checked. (Added in https://github.com/micropython/micropython/commit/176ab99180a95eeac8794828f2f751a696571bb5) You can set the arg type to obj and then check it yourself in shared-bindings.
I'm a little wary of allowing SRAM access where CP is maintaining the heap. Do you need this? I'd prefer to be conservative to start and add areas as we have specific uses.
mp_raise_RuntimeError(translate("Unable to access unaligned IO register"));
Pushing back for these reasons: Overall, memorymap is a "beware, there be dragons here" sort of feature, so I prefer having a comprehensive view of the RP2 memory map and leaving its use to the discretion of the programmer. The other ports (espressif and nrf) that support memorymap do map RAM/SRAM/DRAM. Finally, it's useful to have a view into memory as a poor person's low-level debugger.
Yes, there is already mp_obj_int_get_uint_checked and I'm using it, albeit indirectly. I'll kill MP_ARG_UINT and go with MP_ARG_OBJ as you suggest.
I'll rebase this pull to the 8.2.x branch because that's how I'm already using it! Will GitHub automagically see the rebase or will I need to submit a new pull request?
I like @dhalbert 's idea of using a signed integer to represent drive strength.
The odd port out is still nrf which allows mixing drive strengths depending on logic level. Weird feature, I wonder who uses it and why?
Updating board name because the name here does not match in circuitpython repo.
I'm hitting a problem with the 8.2.x branch. There are several uncommited changes on the branch which is a bit odd. Specifically, I'm encountering a problem building mpy-cross that looks related to "modified content" in tools/huffman. Wondering if anyone can lend me a clue?
I may have borked my forked repository by first forking just main and then several days later adding the 8.2.x branch from the upstream repository?
(.venv) rabeles@ub2004:~/Development/circuitpython-8xx$ make -C mpy-cross
make: Entering directory '/home/rabeles/Development/circuitpython-8xx/mpy-cross'
Use make V=1, make V=2 or set BUILD_VERBOSE similarly in your environment to increase build verbosity.
Traceback (most recent call last):
File "/home/rabeles/Development/circuitpython-8xx/mpy-cross/../py/maketranslationdata.py", line 30, in <module>
import huffman
ModuleNotFoundError: No module named 'huffman'
make: *** [../py/py.mk:274: build/genhdr/compression.generated.h] Error 1
make: Leaving directory '/home/rabeles/Development/circuitpython-8xx/mpy-cross'
(.venv) rabeles@ub2004:~/Development/circuitpython-8xx$ git status
On branch 8.2.x
Your branch is up to date with 'origin/8.2.x'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
(commit or discard the untracked or modified content in submodules)
modified: frozen/circuitpython-pcf85063a (modified content)
modified: frozen/circuitpython_ef_music (modified content)
modified: frozen/circuitpython_picoed (modified content)
modified: frozen/mixgo_cp_lib (modified content)
modified: frozen/pew-pewpew-lcd (modified content)
modified: frozen/pew-pewpew-standalone-10.x (modified content)
modified: lib/quirc (modified content)
modified: ports/espressif/esp-idf (modified content)
modified: ports/raspberrypi/lib/PicoDVI (modified content)
modified: ports/silabs/tools/slc_cli_linux (modified content)
modified: ports/stm/st_driver/stm32f4xx_hal_driver (modified content)
modified: tools/huffman (modified content)
no changes added to commit (use "git add" and/or "git commit -a")
(.venv) rabeles@ub2004:~/Development/circuitpython-8xx$
you have to update the submodules every time to switch branches
I did make fetch-all-submodules after checking out 8.2.x.
if you enter the submodule directory and do git status, it will tell you exactly what's changed
you can do git reset --hard in that directory to force the files to the exact content of the checked out version
it will delete any changes that are not commited
No joy with hard medicine. Think I'll kill my forked repo on GitHub and fork it again.
you don't need to fork it, just clone it again to a new directory
CircuitPython version
Adafruit CircuitPython 8.2.4 on 2023-08-22; Adafruit QT Py ESP32-S3 no psram with ESP32S3
Code/REPL
import os
import supervisor
import wifi
print(f"Connected={wifi.radio.connected} IP={wifi.radio.ipv4_address}")
if os.getenv("WIFI_SSID") and not wifi.radio.connected:
print(f"Connecting...")
wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
print(f"Connected={wifi.radio.connected} IP={wifi.radio.ipv...
Thanks, I got it!
This also matches rgbmatrix (https://docs.circuitpython.org/en/latest/shared-bindings/rgbmatrix/index.html#rgbmatrix.RGBMatrix.refresh) and will need to be explicit if and when we add double buffering.
this only affects folks who are accessing the raw framebuffer and does not affect displayio usage.
Yes, almost anytime there's contention for the access to the SPI bus the display will shift and tear, but, it self heals. we're hoping IDF 5 will improve things, and will fine tune then.
I didn't encounter the problem you're mentioning with the lack of automatic refresh. the "relax_on_idle" flag does need to be set to false to get automatic refresh, but that seemed to be all that was necessary.
@dhalbert want to do this before 8.2.5?
I think so, but maybe not expose the argument (yet).
The odd port out is still nrf which allows mixing drive strengths depending on logic level. Weird feature, I wonder who uses it and why?
We could just ignore the mixed drive-strength possibility on nRF. We don't have to expose every single feature.
Umm. This is a scenation I not only tested, but also works on my boards..
Simplifying to:
import wifi
import supervisor
from time import sleep
wifi.radio.enabled = 0
sleep(3)
supervisor.reload()
Does not produce any hardfaults..
And the example code needs fixing:
import os
import supervisor
import wifi
from time import sleep
print(f"Connected={wifi.radio.connected} IP={wifi.radio.ipv4_address}")
if os.getenv("CIRCUITPY_WIFI_SSID") and not wifi.radio...
Oh wait, that is on 8.2.4.
Yea, that was something the code did never account for and I just run into it.
Shall I create a minimal "backport" just doing the fix?
Probably not necessary, it's a bit if an edge case.
Can I go ahead and implement the bind lock?
If a bind goes thorough, set the lock at true.
If the lock is true, raise OSError(22) on another bind.
@tannewt CI is green now. I'd like to leave the refresh argument, because it matches rgbmatrix, will be helpful if/when we add double buffering, and doesn't affect displayio use (displayio calls the equivalent internally).
this is failing because of use of β (em-dash) in the russian translation. I have changed these manually back to ASCII dashes.
@gfghjjk Thank you for working on the Russian translation.
Please note that due to technical limitations, it's not OK to use characters like β (em dash) in the Russian translation. Instead, use the ASCII equivalent - (called dash or hyphen)
The reason is that, for every translation where it's possible, we want to have a simple way to reduce the Unicode value of every character to a single byte. For the russian translation, this is done by letting 0-127 be the ASCII equivalent, and value...
This is something Adafruit is getting interested in at the moment too: Ladyada has shown a prototype dot clock LCD board with the esp32-s3 which uses PCA9554 as an I/O expander including for buttons and for a low-speed SPI bus.
For early testing it was OK for us to just bit bang the SPI bus from Python code but we'll want something better.
This makes me think that it's important to generalize the I/O expander. For now I think it's probably OK to hard code the I2C bus, chip type(s) and a...
Are these invalid_params_if checking for internal errors or for errors in Python code? If the latter, they should also use an approprate function from argcheck.
Instead, use mp_arg_validate_int_range
Is there something rp2040-specific about this code? If not, it should be placed in $(TOPDIR)/shared-bindings and similarly for the implementation, it should go in $(TOPDIR)/shared-module.
We usually prefer only to silence warnings in code that comes from submodules (like files from pico-sdk). In files that we add to the core, the warnings should be addressed, so that it's not necessary to list the file here.
Here's an example of how introducing a "protocol" will help. Instead of having a separate preprocessor ifdef for each possible kind of IO expander, it would become a call like return mp_proto_get(obj, MP_QSTR_Pin) != NULL. This protocol would be implemented by microcontroller.Pin, as well as the cyw43 pin, the tca9555 pin, and the PCA9554.
The protocol structure would have a number of function pointers, for getting & setting value, direction, & pull.
Then the common_hal_digitalio_digi...
@ouening Are you connected to the port labeled as "USB" on the board? The "COM" isn't gonna show the REPL.
Yes, when I connected to the 'USB' port, it works! Thank you!
the only artifact is mpy-cross?
@StreakingJerry @casinho are you also connecting to the port labeled "USB" on the board, as discussed above?
Hi @jepler
This is something Adafruit is getting interested in at the moment too: Ladyada has shown a prototype dot clock LCD board with the esp32-s3 which uses PCA9554 as an I/O expander including for buttons and for a low-speed SPI bus.
Oh, that is exciting to hear!
For early testing it was OK for us to just bit bang the SPI bus from Python code but we'll want something better.
This makes me think that it's important to generalize the I/O expander. For now I think it's ...
Ah, thanks. I put it there to be minimally invasive since I cannot verify its correctness for chips other than RP2040. Happy to move it.
Ah yes. What should I update that to. I assumed all CircuitPython code would be copyright Adafruit?
We don't have to expose every single feature.
Indeed, memorymap is there to diddle the true esoterica. I'm still curious as to why the nRF designers would have added it to begin with?
It's for internal errors I believe, checking that the pin number on the pin object is valid for the number of IO expanders being used (which should be unlikely to occur given the number of pins is hardcoded). None of the functions in argcheck look to be suitable.
Yes, I can see how changing to your proposed protocol here would be much better
The adjectives I am not so sure about, in case we have a case of even more choices. But how about 0 for the default or "normal" level, 1, 2, 3, etc., for higher, and -1, -2- 3, etc. for lower? Anything out of range gets set to the max or min for the board, and you can query. The API could also return the mA value separately, and maybe you could even set it that way. But it has to be a small implementation to fit on the smaller boards.
I'd rather standardize on fewer choices that are po...
How does this work on ESP? This shared supervisor code shouldn't need port-specific defines.
Is it possible that I have a faulty board?
I doubt it. These errors are usually a software problem.
If it isn't then I'll try and get something that is repeatable and upload the code here.
A small, reproducible code snippet is always best for debugging.
Is there more information about the problem that I can do with CircuitPython to get it to output more details?
You can build a version of CircuitPython that will output the ESP-IDF logging over UART and it'll include a bac...
Nope, it should be your copyright. It should reflect who wrote the non-trivial code.
Thanks for merging. A quick question I created pull in main branch but noticed the bulid has been generated for only circuitpython 9.x.x. no build for 8.x.x. and 7.x.x. So to make them available on circuitpython download page do I have to create a pull request on branch 8.2.x and 7.3.x.
Would these IO expander implementations be made available to user code? If they have a Python dictionary, then you could do a lookup in the dictionary instead of having a new protocol. That's how you'd do it if you were using a Python object.
I'd rather standardize on fewer choices that are portable. LOWEST and HIGHEST are the first two obvious choices. One for fast signalling and one for driving LEDs and such. We'd default to HIGHEST.
If LOWEST and HIGHEST are the only names being used, then I'd prefer just LOW and HIGH.
I suggested signed integers to avoid LOW, LOWER, LOWEST kind of naming, which can be head-scratching, since it's not all that quantitative. So for instance -100 and 100 are definitely "lowest" and "highes...
We'd default to HIGHEST.
Not sure that HIGHEST is the best choice for the default. Consider the RP2 which has an IOVDD_MAX of 50mA. It's easy to exceed this driving just a few LEDs at 12mA which would underpower QSPI and break XIP.
Thanks for getting the CI green. Just a couple other minor things.
// (but it's OK if this is a no-op due to the heap being initialized in port_init())
This should be reverted now.
If we had the space, I'd suggest also including DigitalInOut.drive_strengths, which would return a tuple of port-specific available drive strengths, in mA. Then the code can choose. Setting DigitalInOut.drive_strength would then have to either set a valid drive strength exactly, or (alternatively, a more forgiving API) would set the nearest one (or floor or ceil).
I have added this board to main branch but noticed only circuitpython 9.x.x build is available And also no direct download and installation option on page. Userd have to find that build from s3.
This board is comparatively new and manufacturer tergets beginner audience. So trying to make new users journey as smooth as possible.
To make this board available for circuitpython 8.2.x trying to backport it.
thanks.
Ya, you can cherry pick the commit onto 8.2.x and it will be in the next release. We're not planning on any more 7.x releases so no need to add it there. Next time, you can PR to 8.2.x and we'll merge it into main periodically.
Not sure that HIGHEST is the best choice for the default. Consider the RP2 which has an IOVDD_MAX of 50mA. It's easy to exceed this driving just a few LEDs at 12mA which would underpower QSPI and break XIP.
People shouldn't be using drive strength to limit LED current. It doesn't work that way, e.g. setting 4mA drive strength doesn't actually limit the current to 4mA, you just get a voltage drop which may or may not limit current by much, depending what you're driving.
So you could ...
When you take a look at the HackTablet board files......
I've reduced and tested the DEFAULT_RESERVED_PSRAM setting as follows:
// a 800x480 16BPP framebuffer + some breathing room
#define DEFAULT_RESERVED_PSRAM (800 * 800 * 2)
the only artifact is mpy-cross?
No idea man. Actions sus.
How does this work on ESP? This shared supervisor code shouldn't need port-specific defines.
@tannewt This PR exists to just make raspberrypi act the same way as espressif.
The espressifwifi connection is not preserved upon reload, however theraspberrypi` one is, since the object is persistent. With this change, both will close their wifi connection on reload.
Running some experiments to pin current on RP2 (Adafruit Feather RP2040) I'm seeing some strangeness in the programmed values in PADS_BANK0. Here's a dump after I've programmed D5, D6, D9-D12 (GPIO7-GPIO12) for output and driven them high:
Pad 0: 92
Pad 1: 92
Pad 2: 92
Pad 3: 92
Pad 4: 72
Pad 5: 72
Pad 6: 72
Pad 7: 92
Pad 8: b2
Pad 9: 92
Pad 10: 92
Pad 11: 92
Pad 12: 92
Pad 13: 92
Pad 14: 92
Pad 15: da
Pad 16: 70616430
Pad 17: 3
Pad 18: 0
Pad 19: 3
Pad 20: 0
Pad ...
- Fixes #8299
Use the new repo https://github.com/adafruit/certificates as a submodule instead of https://github.com/adafruit/nina-fw. This new repo provides a revised roots.pem that fixes the problems introduced in 8.2.2 when the nina-fw cert bundle was updated.
- The new cert repo has a manual test for a large number of URLs, as does https://github.com/arduino/nina-fw. The URL list includes a number of URLs used by Adafruit code, including from the Learn Guide repo.
- https://git...
@tulip sleet If I have the Metro M7, with 8MB of QSPI flash, running CircuitPython, about how much flash memory is left over for me to do things with?
The RP2040 with 16MB flash had about half left. Is "half" correct, or is it a static amount?
have to look, but you can just see how large CIRCUITPY is by asking the host OS to tell you
Oh ok
I haven't gotten that far yet, so I figured I would ask.
I can verify it later. Or leave it out.
i can plug one in and see
That also works
about 6.2MB
Thank you
official size is 6MB
I said "around 6"
I have added this board to circuitpython 9.x.x.
also created backporting Pull request have been submitted for circuitpython 8.2.x.
On merge you can download .bin and .uf2 from this page.
you are welcome.