מזה זמן רב אני מנהל מלחמת חורמה עקרונית נגד האיטיות של מסך TFT-LCD קטן ושל הספריות שנכתבו עבורו על ידי Adafruit. כבר הצגתי בעבר את אופטימיזציית ציור הקווים הקצרים, אך כידוע, עם האוכל בא התיאבון: גם האתגר עצמו מרתק, וגם יש לעיסוק הזה משמעות אמתית עבור פרויקט ספציפי שאני עובד עליו (וכנראה גם עבור פרויקטים עתידיים). אז אחרי הפסקה ממושכת אני חוזר אל המסך, והפעם אציג אופטימיזציה של הפעולה הבסיסית ביותר – ציור פיקסל יחיד.
רקע טכני
השבב שמנהל את המסך (ILI9325) מסוגל, בתיאוריה, לקבל נתונים ב"חבילות" של 8 ביט (בייט אחד) או של 16 ביט (מה שנקרא Word). ההתלבטות בין האופציות האלה נחסכה ממני, כי החיווט של המודול של Adafruit שברשותי מותאם ל-8 ביט בלבד. אלא שבייט יחיד אינו מספיק בשביל מגוון הצבעים שהמסך הזה מציע. במפרט הטכני (עמ' 28, בקישור שבתחילת הפסקה) מצוינות שלוש דרכים לשלוח נתוני צבעים לשבב, וכולן מחייבות העברה של שני בייטים (או אפילו שלושה) בזה אחר זה. הסיבה היא שהמסך עובד או עם 262,144 צבעים (6 ביטים לחלק האדום של הצבע, 6 לירוק ו-6 לכחול – סה"כ 18 ביטים לפיקסל) או עם 65,536 צבעים (5 לאדום, 6 לירוק ו-5 לכחול – סה"כ 16).
ההעברה של כל בייט מתבצעת כך: ראשית, אנחנו המשתמשים מכינים את שמונת הפינים של הנתונים ו"שמים" בהם את הערכים הרצויים. לאחר מכן, אנחנו שולחים למסך פקודה דרך פין אחר, שאומרת לו שהערך מוכן והוא מוזמן לקרוא אותו. ככה נפתח למעשה פתח לאופטימיזציה מסוימת, שקוד הספריה של Adafruit מנצל אותו היטב בהרבה הזדמנויות: אם במקרה הבייט הבא זהה לבייט הקודם, אין צורך לעדכן מחדש את הפינים של הנתונים – צריך רק לשלוח שוב פקודת קריאה למסך! החיסכון כאן אולי לא עצום אבל ממשי, וכשאנחנו רוצים למשל למלא שטח בפיקסלים שחורים (כי בצבע השחור, כל הביטים הם 0) אפילו העין שלנו יכולה להבחין בהבדל.
לרוע המזל, כמובן, ברוב הצבעים הבייט השני לא זהה לבייט הראשון. למעשה, מתוך עשרות אלפי הצבעים האפשריים, יש בדיוק 256 צבעים שבהם שני הבייטים זהים (חצי נקודה למי שהבין למה 🙂 ). יחד עם זאת…
5 גוונים של אפור, גג
…יחד עם זאת, כילד ביליתי הרבה, הרבה יותר מדי שעות מול מסכי מחשב עתיקים עם 256 צבעים או פחות, ואני יודע שבתנאים מסוימים אפשר להשיג תוצאות מעולות גם עם לוח צבעים (Palette) מצומצם להפליא. אם אצליח להסתפק, עבור רוב התצוגה אם לא כולה, בלוח מצומצם שכזה, אוכל לזרז פקודות ציור רבות במידה ניכרת.
השאלה היא, אילו מין צבעים אקבל כשאצמיד שני בייטים זהים ואגזור מהם ביטים בתבנית 5-6-5 שהמסך מצפה לה. אני, לפחות, לא מסוגל לעשות חישובים והערכות כאלה בראש, אז כתבתי בדלפי תוכנה קטנה שעושה בדיוק את זה: עוברת על כל ערכי הבייטים האפשריים ומייצרת את הצבעים שנוצרים מצמדים זהים בפורמט 5-6-5. את הפרטים הקטנים של התוכנה הזו אשאיר לכם כתרגיל תכנות; ככה זה נראה בסופו של דבר:
תוכנה להצגת ובחירת צבעים בפורמט 5-6-5 מבייטים כפולים (לחצו להגדלה)
כשאני מעביר את העכבר על צבע מסוים, הוא מופיע במלבן הגדול משמאל למטה, ומוצג גם ערך הבייט שיוצר אותו. לוח הצבעים הזה הפתיע אותי לטובה. הוא אמנם לא מושלם – חסרים לי מאד הגוונים האפורים, למשל – אבל בגדול, אפשר למצוא בו גוונים מספיק קרובים לכל מה שאצטרך בתצוגה של הפרויקט, ויותר מזה.
רגע האמת
לקחתי את פונקציית ציור הפיקסל המקורית מהספריות, שמקבלת משתנה בן שני בייטים בתור הצבע, ויצרתי גרסה משלי שמקבלת בייט אחד בלבד ו"משדרת" אותו פעמיים כפי שתואר קודם. ככה נראה פלט שלה (הוא נראה טוב יותר במציאות):
הגרסה הזו של הפונקציה ממוטבת למהירות בעוד כמה מובנים, ובמבחן "לפי העין" היא פועלת בכ-50% מהר יותר מאשר המקורית. ביישומים שעליהם אני חושב לא יהיו לי הרבה הזדמנויות לצייר פיקסלים בודדים, אך האופטימיזציה הקטנה הזו תקדם אותי מאד לקראת הדברים החשובים באמת – עליהם אדבר בהמשך…