Closed ilikecake closed 2 years ago
numpy isnt available for circuitpython microcontroller boards, ideally the library would not require it - however you can write the library to support as long as it fails nicely. 480 bytes extra is fine. you can see how we do it for RGB TFT displays here https://github.com/adafruit/Adafruit_CircuitPython_RGB_Display/blob/main/adafruit_rgb_display/rgb.py :)
You could look at using ulab
, which is like a mini-numpy
, and has a very similar API.
https://circuitpython.readthedocs.io/en/latest/shared-bindings/ulab/index.html
You may be able to use the same code just by altering the imports.
Thanks for the responses. It looks like ulab does not have the functions I use that do the magic conversion:
I can look at making a modification to the code to check for numpy and fail back to the old functions if numpy is not present. Can you give any pointers on the right way to do this? Looking at the code, it looks like I would need to:
Modify adafruit_framebuf.py to add in a new format similar to MHMSB, but using numpy array functions. This would involve adding a check to the framebuffer.py file for numpy.
Modify adafruit_sharpmemorydisplay.py to check for numpy and switch to the different framebuffer format and functions if it is present.
This is doable, but seems like a rather large change to your code, and I don't know if that would be okay.
For reference, below is a modified sharpdisplay class. I started out with your code and modified it to work with numpy the way I outlined in the previous thread. This class is not dependent on the FrameBuffer class, and only displays PIL images. This code should illustrate what I am trying to do, but it is not really compatible with your libraries as-is.
can you shove the numpy part just into the PIL/image generation part? if PIL is there, you can assume numpy is too (unless im not understanding something)
Sorry for the slow response, your reply sent me down a bit of a rabbit hole. There are two interrelated issues here:
Both of these issues involve manipulation of (relatively) large arrays, so I initially used numpy for both. However, issue 1 involves iterating over a matrix of all the pixels in the display (240*400=96000), while issue 2 only involves iterating over the height of the display (240). I figured I would try separating the two solutions and figure out how fast the screen can update with no changes to the framebuffer format.
TLDR: I can get a frame time of .1s (~10fps) (frame generation using numpy, array formatting using python native array manipulation). However, I am unsure of the memory usage implications of this.
For all three methods below, I generate a frame in PIL and convert it to a bytearray using numpy. In the code snippets below, DisplayBuffer starts off as the standard framebuffer format, and ends as the final packet to be sent to the display.
#Convert a PIL image to the adafruit framebuffer format
DisplayBuffer = np.packbits(np.asarray(img), axis=1).flatten().tolist()
HeaderBytes = bytearray([0x00,0x00])
addressToSend = self._displayheight+1
for x in range(((self._displaywidth // 8) * self._displayheight), 0, -1*(self._displaywidth // 8)):
HeaderBytes[1] = reverse_bit(addressToSend)
DisplayBuffer[x:x] = HeaderBytes
addressToSend = addressToSend - 1
HeaderBytes[1] = reverse_bit(addressToSend)
DisplayBuffer[0:0] = HeaderBytes
#Convert a PIL image to the adafruit framebuffer format
DisplayBuffer = np.packbits(np.asarray(img), axis=1).flatten().tolist()
pc_index = len(self._HeaderVals_ada)-1 #start at the top of the list, count down.
for x in range(((self._displaywidth // 8) * self._displayheight), 0, -1*(self._displaywidth // 8)):
DisplayBuffer[x:x] = self._HeaderVals_ada[pc_index]
pc_index = pc_index - 1
DisplayBuffer[0:0] = self._HeaderVals_ada[pc_index]
#Import image and convert
self.buffer = np.packbits(np.asarray(img), axis=1)
DisplayBuffer = np.append(np.hstack((self._HeaderVals, self.buffer)),self._TailVals).tolist() #Note: append also flattens the matrix
To my surprise, numpy does not really seem to give any benefits for the array formatting. Given that, I could modify only the sharpmemorydisplay.py file to address both of these issues.
However, I am wary of the implications on memory usage. Methods 1 and 2 above both insert the headers into the framebuffer before sending it. Since the framebuffer persists between frames, this probably means that the length of the framebuffer will grow by ~480bytes every time a frame is sent. Is there a way to reset the framebuffer length, or at least bound it somehow?
Hi All,
I was having issues with performance using this display on a Raspberry Pi. The details of my issue can be found here. It basically boiled down to two issues with the code:
I was able to fix both of these issues and significantly speed up the device. (frame generation time went from ~6s per frame to .011s) I would like to submit this code back to the repo so that others can use it, but I am not sure of the implications of how this would affect the code running on other devices. I am looking for help/guidance on how this code can be implemented in a way that does not break things for other devices.
Given freedom to change any of the code, the best way to implement this would probably be
Does this make sense? I worry that this is too big of a change and it would affect other devices too much to be allowable.