Graphics.getPixel(x,y) on ILI9341 Module for ILI9341 LCD CONTROLLER #585
Replies: 9 comments
-
Posted at 2014-10-23 by DrAzzy The module doesn't buffer the screen (it wouldn't fit in memory) - so it has to ask the display for the color of a pixel. But no code to do that is present in the module. See the module - it has fillRect and setPixel (which I figure must be called in turn by other methods of Graphics), but no getPixel. http://www.espruino.com/modules/ILI9341.js setColor and getColor don't involve any communication with the display. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-23 by @gfwilliams As @drazzy says, all drawing is done by Espruino (hence getColor) but is written direct to the screen. As far as I know that module set up so it doesn't even need the MISO input. You could definitely add it though - shouldn't be too painful. It sounds like you might want to make your own version that reads whole blocks anyway. I'm not sure what you're trying to do, but if you want to save stuff for later use I'd consider creating an ArrayBuffer graphics and rendering it on Espruino in the first place. It'll be a lot faster. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-23 by JumJum Some time ago I played around the ILI9341 and added a lot of functions.
To read colors of a rect would be very timeconsuming. Translating the RGB-Array to a color used for ILI9341 takes a lot of time. Some lines in assembler speeded it up, but its still slow. I don't have a tutorial for that, could only send sources, if somebody is interested. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-23 by @allObjects exactly what I expected, but the ILI9341 controller chip has the memory and the ability to return information from it. When inspecting the return object from var lcd = require("ILI9341").connect() (just typing lcd in command pane), I see iSetPixel and iFillRect functions listed... and yes, I would have seen also something like iGetPixel (and/or what I would like even more: iGetRect). I though wonder where all the other methods are that I can use with lcd object... looked at the modules code, and see the Graphics.createCallback(...). So I inspect global Graphics (Singleton) object, and get single function with [native code] back... so I conclude that there is something hybrid/tricky in the interpreter which is invisible/uninspectable from the outside..., which then let's the lcd object (as the returned object from Graphics.createCallback()) understand all the Graphics methods... last but not least also the getWidth() and getHeight(), which return just the LCD_WIDTH and LCD_HEIGHT constants passed to Graphics.createCallback() method in the first place. I guess that the literally passed 16 in that very same method tells the chip to use 16 bit color input mode... (glancing over http://www.newhavendisplay.com/app_notes/ILI9341.pdf). Regarding creating my own version (or an extension) is the way to go for reading whole blocks. Regarding what I'm trying to do is save and restore the areas overridden by the (about) 20x20 px calibration marks after using them in the calibration module - one at the time, or some (simple) drop down menu. For (re)calibration I need save-and-restore only when I have drawn the screen already. If I (re)calibrate before the app draws the screen, I do not need it. Also, I think, I may not need re-calibration after all, because the touch detection accuracy is sufficient for what I want to do in the application: +-15..20 px when using the finger tip, +-5..10px with stylo, or in terms of drawn button sizes: 30..40 px minimal and 10..20 px, respective. For a simple drop down menu, I need of course to save and restore a larger area. The idea of an memory rendered element is not flying, because the area to backup and restore is changing along the application and a redrawing becomes practically impossible... and if made possible, the extra memory (to keep states) and hold the code to support that would become a problem as well - and with that the speed would not be faster either, because drawing just a section - a display section unrelated to the application section - is impossible, and therefore, the whole display would have to be redrawn (think of a PacMan game board state after some time after the start of the game...). No matter what, save and restore would have to stream to a processor-external storage - SD card or (serial) RAM chip (does not need persistence), (default) Espruino's (48K) memory is just too small after all... 'We' really need the option of a board with a chip with larger/largest memory... because I feel the cpu power of the chip and amount of memory are not balanced: memory is not at par with what amount of JavaScript application code can be crunched - a VM w/ garbage collection needs by definition just way more memory than a native straight forward programming with C-like language as Arduino and most of the other micro controllers (may be you have some good news there) - yes, price is an item... but any other additional chip to alleviate the issue adds cost AND hassle beyond what the larger chip costs, especially when you want to do some serious projects with it, an not just educational pet/bricollage/t(h)inkering projects (no insult here). Look at the bare BASIC Stamp... and its price... I would rather make learners use JavaScript than BASIC (or C) - Web technologies are omnipresent, after all (would like to say: 'before' all). Btw, what is the lot size you (have to) order from a manufacturer? I know that 'socketing' pulls it right away 'out of the socks' price-wise - if even possible, and hand-soldering for an average dude like me is not really an option... (the times where I needed only my bare eyes to actually see and do things the size the processor legs are have passed a while ago...). I messed around with various Arduino's, but when I came across Espruino, the 5-times price was not a question at all, because of JavaScript and the processing power (and of course, what you made out of the idea of combining a powerful micro controller and JavaScript... you see the 'softy' in me...). Also: Espruino - not any Arduino - got me really going again with my micro controller t(h)inkering projects after my initial playing around with ubicom.com / Parallax 's SX a while ago. @jumjum, thank you for the code snippet. It will get me going... ;-) ...btw, what is setRect() function looing like and doing? |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-23 by @gfwilliams Ahh - you haven't included setRect in that - but it might be in another forum post :) You should also be able to use a larger 'setRect', and then a bigger array for zzz, and then you can load in a whole load of pixels at once. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-23 by JumJum I have a ILI9341_extended module, including a tiny window implementation.
To get it running, you need attached module and the assembler part loaded using the name ILIcalc. Please see http://www.espruino.com/Assembler for more information.Attachments: |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-23 by @allObjects @jumjum, parsed through your posts - which not necessarily expose ILI9341 relationship in title... nice 'Goldgrube'. The examples - and the provided extension - give me the opportunity to stand on giant's shoulders. Especially intriguing is the windowing aspect... last but not least to make sure a 'display' does not get messed up (...and did you have scrolling in mind?). |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-23 by JumJum There are some items which sound like scrolling,in ILI9341-commands, but I did not get them running. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-25 by @allObjects I ventured into the ILI9341 datasheet and - of course - some coding. First I did an analysis of the existing module... I hope I got the comments right.. I added also getPixel(), getRect()angle, setRect() - for saving and restoring on overlay, and a helper method to convert from 3 byte 6 bit <<2 pixel data from reading a pixel w/ getPixel() to writing using setPixel()*. Code - ready to be loaded into the editor, a shot and a clip are attached to the post. The attached clip shows you the behavior:
Most difficult part in getRect() and setRect() for save and restore (or copy) of an area was the different pixel format: it is read with 3 6bit bytes and a left shift of <<2 (White is 252,252,252). Writing back requires two Uint8 that cover 5 bits read, 6 bits green (straddling the bytes), and 5 bits blue. After a while I got the hang of it. You can use the color values to set the color and then call setPixel with no color argument... but that's super strolly...
The method .pixToInt(px) in line 126 helps to get this a bit easier (and is borrowed from getRect() method (line 133) - a slow version of ILICalc in assembler from @jumjum ;), figured that out in hindsight. Initially I just read all the bytes in one swoosh by creating and sending a 0x00 initialized Uint8Array --- and wasted lots of memory... 4 or more bytes per pixel... and could read only 10x10 before running out of memory. Also, I kept the read format until restoring and did above mentioned conversion from 3 to 2 bytes when restoring: Another tie up of additional 50% memory. So I came up with the one px at a time (which works quite well - form me - but could be optimized by some bulking algorithm), and do the conversion right when reading.. Now, only the bare minimum on memory is used. This seems to work for my purposes. But I'm looking int adding some serial RAM (flash is an option too, but sucks in power... on the other hand it's on the board...) I was also thinking of using the controller's 'porches' outside of the visual area - if there is memory left; but I did not go into detail thoughts yet). The approach of reading just a pixel and do the conversion turned out not much slower than reading and keeping all data memory efficiently, but the write is now a very quick one:
I hoped to get more out of it when making it a module and using minification: Speed was insignificant faster... 12% (last but not least removed the inline/infunction comments), but memory looks great:
I had also some difficulties with reading from the controller via SPI, because for each byte to read, a byte has to be sent (?) with SPI.send(). Unfortunately, SPI.send() is not supporting the object {data:data, count#} parameter as the write does... and the SPI.write - which supports it - does not return anything... So my suggestion is that the send() should support the object parameter option... the count would have made it really easy: repeatedly sending 0x00 (send is always a 0x00) Small changes to the existing module are possible: when defining the rectangle (column and page address), the rectangle can have an extend of 0: no need to add 1. And as said, the spi.send could use the object parameter option... (and a native map.reduce function...). @jumjum, I did not venture into assembler yet... Attachments: |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-22 by @allObjects
I tried to use the .getPixel(x,y) to save areas of the display to later restore...
Reading from any location I always get 0 - even for locations I just set, and can actually see the just set pixel.
I know that the boards are connected properly (Espruino outputs and inputs to breakout board inputs and outputs). I also know that the boards communicate properly because can write and read from the board (for example, .setColor() and .getColor() work). I use the breakout board from http://www.adafruit.com/products/1770
Why do I get just 0 back with .getPixel()?
PS: 'looked around' and found some low level reading... about Highly optimized ILI9341 (320x240 TFT color display) at http://forum.pjrc.com/threads/26305 I'm sure this would all hide behind the Graphics.readPixel(x,y) JavaScript implementation. Since a single pixel is usually not of real use, the read of a rectangle and related (re-)write into and from, for example, a uInt16 like buffer (streaming in to and out of an SD card for larger areas), is the desired function. To make it w/ 16 bits, two colors have to be expanded/collapsed by a bit to make that happen, and from what I can read from the controller's datasheet, it may even be supported by the controller...). I'm not ready yet to take on such hardware close calls... but it could happen sooner with some help from any Mr or Mrs Geek G. Shoehorn.... ;-)
Beta Was this translation helpful? Give feedback.
All reactions