davidgfnet / wifi_display

E-ink wireless display
244 stars 36 forks source link

hooking up to a raspberry #9

Closed VanLaser closed 7 years ago

VanLaser commented 7 years ago

Hello, great work!

(this more of a question/advice than an "issue", but I don't know where else to ask, so feel free to close it, delete it etc.)

I intend to hook up the same display (waveshare e-paper 4.3 inch) to a Raspberry PI Zero. My problem/concern is image transfer speed to the display.

If using the UART communication, do you know if it's possible to setup the display to use a higher UART rate (e.g. 460800, as you used)? I read about how to set this on the Raspberry part. Do I need to flash a custom firmware on the STM? (I guess I can try to see if it accepts setting this speed as a normal command first) Or, do you recommend taking the longer route (custom FW and SPI communication)? In this case (since I'm not much of a "hardware" guy) what would be the simplest way to hookup the PI with the display? Or, what would be a "simple" and fast way to hookup the two? I'm also thinking if it would be possible to only modify the FW on the STM in order to add new commands to its API, keeping the UART communication interface, but making it "more powerful" so to speak (i.e. adding some algorithm to make the image transfer, compressed etc., faster).

Thanks for any details

P.S. I think what I'm after is some version of the custom firmware that still uses the default UART communication, so that I won't have to tinker with the electronics, and only further modify the FW to accept custom (i.e. more efficient/compressed) display commands from the PI.

davidgfnet commented 7 years ago

Hey The chinese firmware has a very limited command set, I don't know whether you can draw arbitrary stuff easily, since it takes lines, rectangles and so forth. I'd definelty recommend you to write a very minimal software FW for the STM32, something that just takes whatever you send via UART/SPI to the screen, and place all the "meat" in the raspberry. It will be probably faster and you will never have to flash it again, since any updates will come from the raspi side. As you can see there's 4 power pins (to turn stuff on) and 6 pins to drive data. I'd write some very very basic firmware that allows turn on/off, write some bits into the GPIO or similar, etc. Also in that case use a fast bus, like SPI at a high clock rate or maybe UART at 1mbps too. Otherwise the bus will be your bottleneck

davidgfnet commented 7 years ago

Sorry there's 6+8 bits for the display, 8 for the data port + 6 for clocks and enables. It should be easy to have some basic commands like "output this and clock this gpio", most of the time you are just drawing a row for instance.

VanLaser commented 7 years ago

Thanks for answering! :)

So - based on your work (and advice), I think I'll try to implement some custom commands that would pack as much "pixel writing information" as possible (maybe even 1pixel per 1bit, black on white, and then compressed) in the messages sent through the UART from raspberry to the STM32, either to update a certain specified region, or the whole screen, or some lines etc. I read about setting the UART at higher speeds, and happily it also seems to be possible on the raspberry :)

Since my electronics tinkering "fu" is quite limited, I'll ask for confirmation: apart from connecting in order to flash the STM32, can I continue to use the default white big connector and UART, without any other soldering, with the new, custom FW on the STM32? I mean, you did some "fu" there by altering the board, and I don't know exactly how the PCB wiring goes. Also, I don't know yet which of the two UARTs on the STM32 is the one wired to the default connector. I still have to study your code, I looked into it, but I'm not yet familiar with the architecture etc.

davidgfnet commented 7 years ago

Hey! Yeah it should be straightforward to do as you say: Write a simple FW for the STM32 that uses the UART0 (the one that's connected to the white connector) and takes stuff in and draws. You can use it up to 1mbps at least (check the STM32 manual but I think you can run the micro at 72Mhz and generate a quite fast UART clock, just start with a slow uart to make sure you don't have transmission errors due to noise, then you can start using high uart speeds. In fact you can make that something programmable in your protocol, start at 115200 bps and add a command to change the UART speed). And yeah, you'll need to connect your program to the SWDIO connector (to program the STM32) and that's it, no more soldering. I did use solder to use SPI, also to allow the board to be gated for low power. You won't need any modifications to the board, and you can use the SRAM/NAND (which I didn't to save power and desoldered them). Feel free to reach me by email if you think some questions are not interesting for people to read here.

VanLaser commented 7 years ago

Thanks again! I just managed today to configure openocd so that I can connect to the STM32, through the SWDIO connector, from the same Raspberry Zero, and things seems to go ok (I can 'reset halt', 'reset run' or dump an image from the STM32). It will probably take me some time to digest the info from the programming manuals (UART, DMA etc.) and understand your code; but after that I'll probably shoot you some questions. I'll close this (non-)"issue", much appreciated once again.

davidgfnet commented 7 years ago

@VanLaser Sure no problem. Note that I use compressed images, apart from that it should be pretty straightforward I believe to come up with somethin that works. Good luck!

VanLaser commented 7 years ago

I was reading the last few days about how the e-paper display mechanism works (waveform tables and all that) and I think I "got it", except for the following. My use case is somewhat different than yours (or X-Ryl669s) in that I (also) intend to use the screen in some sort of "terminal emulator" text mode, in which I'm trying to refresh the display without closing it. Is this possible? I know that I'll have to use the 'old_pic' information to derive the right waveform offset for the 'new_pic' pixel display (I'm trying to avoid clearing the screen to white between two image draw operations) but what I didn't find in any example is - is it mandatory to power on, draw, then power off the screen (einkd_PowerOn(); einkd_refresh_compressed(scratch); einkd_PowerOff();) or is the code allowed to draw multiple times while the display is kept on power (taking into account the previous picture when drawing the new one)?

Also, is it right that you used a "short" waveform table, but there are other, longer ones, optimized for long image display without power? Thanks!

davidgfnet commented 7 years ago

It is not necessary to power it off, although that saves power and also guarantees that you get a hard reset of the state of the screen. I haven't tried to update it twice without powering off though, so maybe you find bugs in my code (I dunno whether you need to do something funny to start a new frame, I guess not). It should be doable, if you intend to use it for a black/white terminal, since the refresh is kinda slow and you will only refresh a very tiny space of the screen. If you wanna leave the pixels the way they are just feed zeros and nothing will happen (that's the short table you mention). Still, remember that eink is not perfect so even if you calculate the delta between two images and draw that delta, you won't get the same image you intend, mainly because positive deltas are stronger than negative ones. Meaning darkening a pixel and then whiteining it the same amount won't result in the same color. You probably need something smarter than just rendering images and creating deltas, but that's a starting point :)

VanLaser commented 7 years ago

Thanks for answering! :) I'm not even sure if I intend to calculate a delta and draw it; maybe I will draw the entire image again (I have to scan it, anyway).

But, from reading the meaning of the waveform tables, the 4 rows, for example such as this: BW waveform table have precisely the role of changing the pixel value, from an initial state, black or white (coded in the row number in the table), to a desired state (black or white), so all 4 combinations start->end (w->w, w->b, b->w, b->b) should be supported. I mean, reading the old pixel value, than re-drawing all screen according to the right row in the table, column after column, should 'move' all pixels in that number of frames from their initial values to their desired values. I hope I understand this stuff ...

davidgfnet commented 7 years ago

In my particular use case I clear the screen (white, like 16 times) and then darken it using that table. If you are going in either direction you would need a different table, if the delta is 0, send a bunch of zeros, if it's positive, a bunch of 0x1, if it's negative 0x2 or something like that. Also you can skip rows that are unmodified, notice that after each row gets drawn we flip some CLKs for some shift registers. That advances the line counter or something internally. So if you are to update a bunch of rows, say 20, it should be significantly faster. You can also redraw a subset of rows as well if you want.

VanLaser commented 7 years ago

Another question (and sorry to bother) - can you tell me anything about the WAKE_UP and the RESET pins, which are also available on the white serial connector? I.e. are they also pins directly connected to the STM32? If so, wouldn't be possible to re-define RX, TX, WAKE_UP and RESET, by some sort of rerouting, in order to use them for SPI instead? And if not, at least some idea of how can I put them to use (I don't even know how to reset the STM32, for example, from the Raspberry, when not using the SWDIO interface, so maybe one of these pins could be used). I know they are used with the current firmware, but I don't know if they go to the STM32 or directly to the e-paper screen.

davidgfnet commented 7 years ago

Check the wires and the manual yourself. I think Reset might be wired to the reset pin (which is pulled up by default in STM32 devices). Wakeup might be wired to wakeup pin (I recall it's PA0), but you can check yourself.

sam1006 commented 7 years ago

Hey @VanLaser I am also working on the similar project as you are, but I am using Arduino instead of raspberry pi.... I want to know that did you get any success in developing basic firmware for the display with the partial update?

sam1006 commented 7 years ago

@VanLaser Or we can work together? I am unable to get your email from your account.

VanLaser commented 7 years ago

@sam1006 I didn't get to that part yet - I decided to start from 'the other side' (Linux) and implement a custom terminal emulator that uses local keyboard as input and the serial-connected e-paper device as output (for now, I'm getting my head wrapped around stuff like 'tty', 'pty' and 'libvterm'). You could start from X-Ryl669's fork, since he already uses the UART instead of the SPI.

P.S. If you add an email to your github.com account, I'll send you an email.

sam1006 commented 7 years ago

@VanLaser sorry for late response, I am trying to understand and modify the firmware of X-RyI669. I will let you know If I get any success. I have added an email in my GitHub account.