Wyświetlacze do minikomputerów to ciągle jest nie do końca rozwiązany problem. Wyświetlacze z interfejsami HDMI czy MIPI DSI to znacznie ograniczona oferta i nie zawsze są dobrej jakości. Dlatego zainteresowałem się modułami NanoPI Fire które są wyposażone w całkiem pożądne procesory Samsung-a i posiadają wyprowadzone złącze RGB, czyli najprostszy interfejs LCD. Takich wyświetlaczy jest najwięcej i są najtańsze.
Ale do rzeczy, opiszę tutaj jak podłączyłem dwa wyświetlacze firmy Winstar o całkiem przyjemnym obrazie i pojemnościowym ekranem dotykowym: 5'':WF50BTIAGDNGY i 7'': WF70GTIAGDNG0. Wyświetlacze można kupić w Polsce w cenie 128 i 220zł.

Problem #1
Dla NanoPI Fire, producent przewidział kilka modeli wyświetlaczy, jednak są dość drogie (>300zł) i jakość też jest słaba (mam http://wiki.friendlyarm.com/wiki/images/d/d8/CMOS-camera-nanopi2.png ). Złącze na module jest 45-pinowe do taśmy FPC. Wyświetlacze z interfejsami RGB występują zwykle w dwóch odmianach: 40-pinowej i 50-pinowej. Czyli potrzebny będzie adapter krosujący sygnały z 45 złącza NanoPI na układ wyświetlacza.
Problem #2
Zasilanie. Tu jest znacznie ciekawiej. Wyświetlacze potrzebują kilku napięć i to podanych w odpowiedniej kolejności. Ten 5'' ze złączem 40-pinowym posiada wbudowany zasilacz do wszystkich tych napięć (widać go na taśmie). Z zewnątrz podajemy tylko 3.3V i zasilanie diod backlight-u. Wyświetlacze z taśmą 50-pinową wymagają podania tych napięć z zewnątrz. Tych napięć jest aż pięć + backlight.
Problem #3
Oprogramowanie NanoPI Fire ma taki ich mechanizm rozpoznawania LCD na podstawie wymyślonego protokołu po 1Wire. Ich wyświetlacze są rozpoznawana i działają bez problemu. Potrzebny jest mechanizm rozpoznawania typu wyświetlacza bo każdy ma inny zestaw parametrów.
Na początek hardware. Postanowiłem sprawdzić czy da się zrobić tanią przejściówkę, to znaczy oszczędzić złącze i taśmę od przejściówki do NanoPI. Wykonałem druki a następnie przy pomocy wiertła diamentowego do glazury i dobrej wiertarki stołowej, zeszlifowałem laminat nad złączem krawędziowym do ok 0.3-0.4 mm. Trzeb uważać bo taki laminat jest łamliwy. Tak zeszlifowany laminat wchodzi w złącze FPC. Można taką płytkę zrobić na laminacie 0.3mm czy zrobić "flex" ale cena przy małej ilości jest kosmiczna.

Na przejściówce do wyświetlacza 5'' jest tylko zasilacz 3.3V (z Nano mamy 5V) i przetwornica step-up dającą 19.5V dla backlight-u na MCP1661.
W przypadku wyświetlacza 7'', generacją napięć zajmuje się specjalny do tego celu TPS65105
Schematy:
Software - UBOOT:
NonoPI Fire bazuje na UBOOT-cie. To i dobrze. Trzeba zrobić kompilację i w dość sprawny sposób uaktualniać UBOOT bo zmian wykonuje się sporo (np. po SCP,SSH).
Każdy LCD ma zestaw parametrów czasowych. Każdy inne. Parametry te opisywane są w dokumentacji:
- zegar w MHz
- horyzontalnie czas trwania imp. synchronizacji (w cyklach zegara)
- horyzontalnie czas trwania rozbiegu przed danymi : back-porch (blanking) (w cyklach zegara)
- horyzontalnie czas trwania wygaszania po danych : front-porch (w cyklach zegara)
- wertykalnie czas trwania imp. synchronizacji (w liniach)
- wertykalnie czas trwania rozbiegu przed danymi : back-porch (blanking) (w liniach)
- wertykalnie czas trwania wygaszania po danych : front-porch (w liniach)
- polaryzacja impulsów synchronizacji.
W pliku "board/s54418/nanopi2/lcds.c" znajdują się definicje parametrów dla wspieranych wyświetlaczy. W pliku "board/s54418/nanopi2/board.c" następuje detekcja wyświetlacza, funkcja "bd_lcd_init" - nadpisujemy zmienną "myid":
Następnie w pliku "lcds.c" odszukujemy definicję parametrów dla indeksu 3: tablica "nanopi2_lcd_config" i tam jest przypisanie:
Szukamy struktury "wvga_s70" i modyfikujemy ją w zależności od parametrów naszego wyświetlacza:
dla WF50BTIAGDNGY ja wykombinowałem:
Dla WF70GTIAGDNG0
Parametry "width", "height" są oczywiste. Parametry "p_width" i "p_height" są bez znaczenie (nie ma żadnych odwołań), "freq" ustawiamy jakoś sensownie np. 63Hz bo to może się jeszcze zmienić co wyjaśnię. Znaczenie: "h_fp" - front-porch, "h_bp" - back-porch, "h_sw" - sync-width, podobnie dla v. Co robi "v_fpe" i "v_bpe" nie wiem, wszędzie jest 1 (enable?). Niby proste a jednak. parametry dla v należy dobierać jak najkrótsze czyli wartości bliskie minimum z DS. Długie wartości powodowały brzydki rozbłysk ekranu po wyjściu z UBOOT-a a przed kernelem. Wydawało by się, że back-porch jest krytyczne bo DS podaje bez marginesu ale tak nie jest. Krytyczne okazało się coś zupełnie innego.
Otóż, na końcu jest jeszcze jeden parametr:
Jest to wskaźnik na funkcje której zadaniem jest ustawienie "strength" pinów. Są tam 3 grupy: CLK, RGB i HS,VS,DE. Wszystkie glitch-e i paskudne zachowania obrazu zależą od tych wartości. Siła pinu jest od 0 do 3. Tutaj jedynie metoda prób i błędów, jeśli coś dzieje się w środku obrazu, np przejście z białego na czarne daje duszki pikselowe, to jest to relacja pomiędzy pinami RGB a CLK, jeśli coś dzieje się na końcu czyli na krawędzi to grzebiemy przy HS,VS,DE. Jeśli już będzie nam się to dobrze zachowywało dla jednego obrazu, to np. terminal tekstowy pokaże że coś drży i zaczynamy dostrajanie od nowa.
Ja ustaliłem:
UBOOT ma łatwy sposób na podstawienie logo, po prostu plik "logo.bmp" w katalogu "/boot". Wrzuciłem tam obraz kontrolny i tak regulowałem aby wszystko było wyświetlane idealnie, obraz ma być bez żadnych drgań czy pikselków w niewłaściwych miejscach:
(trzeba przerobić na BMP).
Software - KERNEL:
UBOOT detektuje LCD i jego nazwę przekazuje do kernela jako parametr "lcd=", jeśli wybraliśmy "3" to odpowiada to nazwie LCD "S70" i na takiej podstawie drajwer kernela wybierze parametry.
Niestety, drajwer UBOOT-a nie jest spójny z drajwerem kernela i wszystkie zmiany musimy powtórzyć ręcznie. Plik: "linux-3.4.y/arch/arm/plat-s5p4418/nanopi2/lcds.c". Wyszukujemy parametry dla wyświetlacza "S70", kopiujemy z UBOOT-a i dodajemy odpowiednio funkcje dla "siły" pinów. Po tym, okazało się że jeszcze trochę regulacji właśnie w "sile" pinów było konieczne, bo choć obraz kontrolny był idealny to np. LXDE już pokazało pewne problemy. Też obraz konsoli w trybie tekstowym lekko drżał i kilka iteracji dla każdego wyświetlacza było koniecznych. Potem, to co poprawiłem w kernelu przeniosłem do UBOOT-a.
Uwaga co do częstotliwości. Jeśli specyfikacja podaje jaki min/max ma być zegar, to liczy się go tak:
Fclk = freq*(width+h_fp+h_bp+h_sw)*(height+v_fp+v_bp+v_sw)
Czyli jest to częstotliwość uwzględniająca wszystkie takty. Trzeba przeliczyć i sprawdzić czy to co jest w parametrze "freg" daje odpowiednią częstotliwość CLK.
Efekt:
To z czym nie było problemu to dotyk. Po prostu działa. Wymagał jedynie kalibracji w X11, w LXDE jest do tego narzędzie ale można też ręcznie.
Chciałem zrobić on/off korzystając z pinu GPIOB25 do backlight, ale nie zauważyłem, że 3.3V to za mało dla MCP1661. Też widzę że układ płytek jest nieco niefortunny i trzeb będzie to inaczej przemyśleć, w końcu to pierwszy prototyp.
Ale do rzeczy, opiszę tutaj jak podłączyłem dwa wyświetlacze firmy Winstar o całkiem przyjemnym obrazie i pojemnościowym ekranem dotykowym: 5'':WF50BTIAGDNGY i 7'': WF70GTIAGDNG0. Wyświetlacze można kupić w Polsce w cenie 128 i 220zł.


Problem #1
Dla NanoPI Fire, producent przewidział kilka modeli wyświetlaczy, jednak są dość drogie (>300zł) i jakość też jest słaba (mam http://wiki.friendlyarm.com/wiki/images/d/d8/CMOS-camera-nanopi2.png ). Złącze na module jest 45-pinowe do taśmy FPC. Wyświetlacze z interfejsami RGB występują zwykle w dwóch odmianach: 40-pinowej i 50-pinowej. Czyli potrzebny będzie adapter krosujący sygnały z 45 złącza NanoPI na układ wyświetlacza.
Problem #2
Zasilanie. Tu jest znacznie ciekawiej. Wyświetlacze potrzebują kilku napięć i to podanych w odpowiedniej kolejności. Ten 5'' ze złączem 40-pinowym posiada wbudowany zasilacz do wszystkich tych napięć (widać go na taśmie). Z zewnątrz podajemy tylko 3.3V i zasilanie diod backlight-u. Wyświetlacze z taśmą 50-pinową wymagają podania tych napięć z zewnątrz. Tych napięć jest aż pięć + backlight.
Problem #3
Oprogramowanie NanoPI Fire ma taki ich mechanizm rozpoznawania LCD na podstawie wymyślonego protokołu po 1Wire. Ich wyświetlacze są rozpoznawana i działają bez problemu. Potrzebny jest mechanizm rozpoznawania typu wyświetlacza bo każdy ma inny zestaw parametrów.
Na początek hardware. Postanowiłem sprawdzić czy da się zrobić tanią przejściówkę, to znaczy oszczędzić złącze i taśmę od przejściówki do NanoPI. Wykonałem druki a następnie przy pomocy wiertła diamentowego do glazury i dobrej wiertarki stołowej, zeszlifowałem laminat nad złączem krawędziowym do ok 0.3-0.4 mm. Trzeb uważać bo taki laminat jest łamliwy. Tak zeszlifowany laminat wchodzi w złącze FPC. Można taką płytkę zrobić na laminacie 0.3mm czy zrobić "flex" ale cena przy małej ilości jest kosmiczna.


Na przejściówce do wyświetlacza 5'' jest tylko zasilacz 3.3V (z Nano mamy 5V) i przetwornica step-up dającą 19.5V dla backlight-u na MCP1661.
W przypadku wyświetlacza 7'', generacją napięć zajmuje się specjalny do tego celu TPS65105

Schematy:
Software - UBOOT:
NonoPI Fire bazuje na UBOOT-cie. To i dobrze. Trzeba zrobić kompilację i w dość sprawny sposób uaktualniać UBOOT bo zmian wykonuje się sporo (np. po SCP,SSH).
Każdy LCD ma zestaw parametrów czasowych. Każdy inne. Parametry te opisywane są w dokumentacji:
- zegar w MHz
- horyzontalnie czas trwania imp. synchronizacji (w cyklach zegara)
- horyzontalnie czas trwania rozbiegu przed danymi : back-porch (blanking) (w cyklach zegara)
- horyzontalnie czas trwania wygaszania po danych : front-porch (w cyklach zegara)
- wertykalnie czas trwania imp. synchronizacji (w liniach)
- wertykalnie czas trwania rozbiegu przed danymi : back-porch (blanking) (w liniach)
- wertykalnie czas trwania wygaszania po danych : front-porch (w liniach)
- polaryzacja impulsów synchronizacji.
W pliku "board/s54418/nanopi2/lcds.c" znajdują się definicje parametrów dla wspieranych wyświetlaczy. W pliku "board/s54418/nanopi2/board.c" następuje detekcja wyświetlacza, funkcja "bd_lcd_init" - nadpisujemy zmienną "myid":
Code: c
Następnie w pliku "lcds.c" odszukujemy definicję parametrów dla indeksu 3: tablica "nanopi2_lcd_config" i tam jest przypisanie:
Code: c
Szukamy struktury "wvga_s70" i modyfikujemy ją w zależności od parametrów naszego wyświetlacza:
dla WF50BTIAGDNGY ja wykombinowałem:
Code: c
Dla WF70GTIAGDNG0
Code: c
Parametry "width", "height" są oczywiste. Parametry "p_width" i "p_height" są bez znaczenie (nie ma żadnych odwołań), "freq" ustawiamy jakoś sensownie np. 63Hz bo to może się jeszcze zmienić co wyjaśnię. Znaczenie: "h_fp" - front-porch, "h_bp" - back-porch, "h_sw" - sync-width, podobnie dla v. Co robi "v_fpe" i "v_bpe" nie wiem, wszędzie jest 1 (enable?). Niby proste a jednak. parametry dla v należy dobierać jak najkrótsze czyli wartości bliskie minimum z DS. Długie wartości powodowały brzydki rozbłysk ekranu po wyjściu z UBOOT-a a przed kernelem. Wydawało by się, że back-porch jest krytyczne bo DS podaje bez marginesu ale tak nie jest. Krytyczne okazało się coś zupełnie innego.
Otóż, na końcu jest jeszcze jeden parametr:
Code: c
Jest to wskaźnik na funkcje której zadaniem jest ustawienie "strength" pinów. Są tam 3 grupy: CLK, RGB i HS,VS,DE. Wszystkie glitch-e i paskudne zachowania obrazu zależą od tych wartości. Siła pinu jest od 0 do 3. Tutaj jedynie metoda prób i błędów, jeśli coś dzieje się w środku obrazu, np przejście z białego na czarne daje duszki pikselowe, to jest to relacja pomiędzy pinami RGB a CLK, jeśli coś dzieje się na końcu czyli na krawędzi to grzebiemy przy HS,VS,DE. Jeśli już będzie nam się to dobrze zachowywało dla jednego obrazu, to np. terminal tekstowy pokaże że coś drży i zaczynamy dostrajanie od nowa.
Ja ustaliłem:
Code: c
UBOOT ma łatwy sposób na podstawienie logo, po prostu plik "logo.bmp" w katalogu "/boot". Wrzuciłem tam obraz kontrolny i tak regulowałem aby wszystko było wyświetlane idealnie, obraz ma być bez żadnych drgań czy pikselków w niewłaściwych miejscach:
(trzeba przerobić na BMP).
Software - KERNEL:
UBOOT detektuje LCD i jego nazwę przekazuje do kernela jako parametr "lcd=", jeśli wybraliśmy "3" to odpowiada to nazwie LCD "S70" i na takiej podstawie drajwer kernela wybierze parametry.
Niestety, drajwer UBOOT-a nie jest spójny z drajwerem kernela i wszystkie zmiany musimy powtórzyć ręcznie. Plik: "linux-3.4.y/arch/arm/plat-s5p4418/nanopi2/lcds.c". Wyszukujemy parametry dla wyświetlacza "S70", kopiujemy z UBOOT-a i dodajemy odpowiednio funkcje dla "siły" pinów. Po tym, okazało się że jeszcze trochę regulacji właśnie w "sile" pinów było konieczne, bo choć obraz kontrolny był idealny to np. LXDE już pokazało pewne problemy. Też obraz konsoli w trybie tekstowym lekko drżał i kilka iteracji dla każdego wyświetlacza było koniecznych. Potem, to co poprawiłem w kernelu przeniosłem do UBOOT-a.
Uwaga co do częstotliwości. Jeśli specyfikacja podaje jaki min/max ma być zegar, to liczy się go tak:
Fclk = freq*(width+h_fp+h_bp+h_sw)*(height+v_fp+v_bp+v_sw)
Czyli jest to częstotliwość uwzględniająca wszystkie takty. Trzeba przeliczyć i sprawdzić czy to co jest w parametrze "freg" daje odpowiednią częstotliwość CLK.
Efekt:
To z czym nie było problemu to dotyk. Po prostu działa. Wymagał jedynie kalibracji w X11, w LXDE jest do tego narzędzie ale można też ręcznie.
Chciałem zrobić on/off korzystając z pinu GPIOB25 do backlight, ale nie zauważyłem, że 3.3V to za mało dla MCP1661. Też widzę że układ płytek jest nieco niefortunny i trzeb będzie to inaczej przemyśleć, w końcu to pierwszy prototyp.