1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
diff --git a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
index 54d4d73..40ee799 100644
--- a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
+++ b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
@@ -78,14 +78,11 @@ static bool display_on = false; /* is the display turned on? */
 #define R_VERT_RAM_ADDR_POS     0x45

 /* Flip Flag */
-#define R_ENTRY_MODE_HORZ_NORMAL 0x7030
-#define R_ENTRY_MODE_HORZ_FLIPPED 0x7000
+#define R_ENTRY_MODE_HORZ_NORMAL 0x1030
+#define R_ENTRY_MODE_HORZ_FLIPPED 0x1000
 static unsigned short r_entry_mode = R_ENTRY_MODE_HORZ_NORMAL;
-#define R_ENTRY_MODE_VERT 0x7038
-#define R_ENTRY_MODE_SOLID_VERT  0x1038
-/* FIXME */
-#define R_ENTRY_MODE_VIDEO_NORMAL 0x7038
-#define R_ENTRY_MODE_VIDEO_FLIPPED 0x7018
+#define R_ENTRY_MODE_VIDEO_NORMAL 0x1038
+#define R_ENTRY_MODE_VIDEO_FLIPPED 0x1008

 /* Reverse Flag */
 #define R_DISP_CONTROL_NORMAL 0x0004
@@ -175,6 +172,41 @@ void lcd_set_flip(bool yesno)
 }
 #endif

+
+/* FIXME : find the datasheet for this RENESAS controller so we identify the
+ * registers used in windowing code (not present in HD66789R) */
+
+static void lcd_window(int xmin, int ymin, int xmax, int ymax, bool blit)
+{
+    if (display_flipped)
+    {
+        int tmp; // for swapping min / max
+
+        tmp = xmin;
+        xmin = LCD_WIDTH - 1 + xoffset - xmax;
+        xmax = LCD_WIDTH - 1 + xoffset - tmp;
+
+        tmp = ymax;
+        ymax = LCD_HEIGHT - ymin;
+        ymin = LCD_HEIGHT - tmp;
+    }
+    else
+    {
+        xmin += xoffset;
+        xmax += xoffset;
+    }
+
+    lcd_write_reg(0x46, (xmax << 8) | xmin);
+    lcd_write_reg(0x47, ymax);
+    lcd_write_reg(0x48, ymin);
+    lcd_write_reg(0x20, xmin);
+
+    if (blit)
+        lcd_write_reg(R_RAM_ADDR_SET, display_flipped ? ymin + 1 : ymax - 1);
+    else
+        lcd_write_reg(R_RAM_ADDR_SET, display_flipped ? ymax : ymin);
+}
+
 static void _display_on(void)
 {
     /* Initialise in the same way as the original firmare */
@@ -208,15 +240,11 @@ static void _display_on(void)
     lcd_write_reg(R_GAMMA_AMP_ADJ_RES_POS, 0);
     lcd_write_reg(R_GAMMA_AMP_AVG_ADJ_RES_NEG, 0);

-    lcd_write_reg(R_1ST_SCR_DRV_POS, (LCD_WIDTH - 1));
+    lcd_window(0, 0, LCD_WIDTH - 1, LCD_HEIGHT - 1, false);
+
+    lcd_write_reg(R_1ST_SCR_DRV_POS, ((LCD_WIDTH + xoffset - 1) << 8) | xoffset);
     lcd_write_reg(R_2ND_SCR_DRV_POS, 0);
-    lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (LCD_WIDTH - 1));
-    lcd_write_reg(R_VERT_RAM_ADDR_POS, 0);
-    lcd_write_reg(0x46, (((LCD_WIDTH - 1) + xoffset) << 8) | xoffset);
-    lcd_write_reg(0x47, (LCD_HEIGHT - 1));
-    lcd_write_reg(0x48, 0x0);

-    lcd_write_reg(R_DISP_CONTROL1, 0x11);
     lcd_write_reg(R_DISP_CONTROL1, 0x13 | r_disp_control_rev);

     display_on = true;  /* must be done before calling lcd_update() */
@@ -279,25 +307,6 @@ bool lcd_active(void)

 /*** update functions ***/

-/* FIXME : find the datasheet for this RENESAS controller so we identify the
- * registers used in windowing code (not present in HD66789R) */
-
-/* Set horizontal window addresses */
-static void lcd_window_x(int xmin, int xmax)
-{
-    xmin += xoffset;
-    xmax += xoffset;
-    lcd_write_reg(R_HORIZ_RAM_ADDR_POS + 2, (xmax << 8) | xmin);
-    lcd_write_reg(R_RAM_ADDR_SET - 1, xmin);
-}
-
-/* Set vertical window addresses */
-static void lcd_window_y(int ymin, int ymax)
-{
-    lcd_write_reg(R_VERT_RAM_ADDR_POS + 2, ymax);
-    lcd_write_reg(R_VERT_RAM_ADDR_POS + 3, ymin);
-    lcd_write_reg(R_RAM_ADDR_SET, ymin);
-}

 static unsigned lcd_yuv_options = 0;

@@ -346,13 +355,11 @@ void lcd_blit_yuv(unsigned char * const src[3],
     lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VIDEO_NORMAL);
 #endif

-    lcd_window_x(x, x + width - 1);
-
     if (lcd_yuv_options & LCD_YUV_DITHER)
     {
         do
         {
-            lcd_window_y(y, y + 1);
+            lcd_window(x, y, x+width-1, y+1, true);

             lcd_write_cmd(R_WRITE_DATA_2_GRAM);

@@ -368,7 +375,7 @@ void lcd_blit_yuv(unsigned char * const src[3],
     {
         do
         {
-            lcd_window_y(y, y + 1);
+            lcd_window(x, y, x+width-1, y+1, true);

             lcd_write_cmd(R_WRITE_DATA_2_GRAM);

@@ -394,8 +401,7 @@ void lcd_update(void)

     lcd_write_reg(R_ENTRY_MODE, r_entry_mode);

-    lcd_window_x(0, LCD_WIDTH - 1);
-    lcd_window_y(0, LCD_HEIGHT - 1);
+    lcd_window(0, 0, LCD_WIDTH-1, LCD_HEIGHT-1, false);

     lcd_write_cmd(R_WRITE_DATA_2_GRAM);

@@ -436,8 +442,7 @@ void lcd_update_rect(int x, int y, int width, int height)
     width = (width + (x & 1) + 1) & ~1;
     x &= ~1;

-    lcd_window_x(x, x + width - 1);
-    lcd_window_y(y, y + height -1);
+    lcd_window(x, y, x+width-1, y+height-1, false);

     lcd_write_cmd(R_WRITE_DATA_2_GRAM);