Commits

Trammell Hudson committed f9397b1 Draft

Support read/write contiguous blocks of LCD

  • Participants
  • Parent commits 6435a06

Comments (0)

Files changed (4)

 	uint8_t y = row * 8;
 
 	const char * f = font[c];
+	uint8_t bits[6];
 
-	for (uint8_t i = 0 ; i < 6 ; i++, x++)
+	for (uint8_t i = 0 ; i < 6 ; i++)
 	{
-		// this would be faster if we used the auto-increment
-		// functions, but has lots of special cases for crossing
-		// display boundaries.
-		uint8_t bits = pgm_read_byte(&f[i]);
+		uint8_t x = pgm_read_byte(&f[i]);
 		if (mod & FONT_UNDERLINE)
-			bits |= 0x80;
+			x |= 0x80;
 		if (mod & FONT_INVERSE)
-			bits = ~bits;
+			x = ~x;
+		bits[i] = x;
+	}
 
-		lcd_display(x, y, bits);
-	}
+	// If x spans a 50 pixel position, then split it up
+	// across the two display controllers.
+	if (col == 8 || col == 33)
+	{
+		lcd_write(x, y, bits, 2);
+		lcd_write(x+2, y, bits+2, 4);
+	} else
+	if (col == 16)
+	{
+		lcd_write(x, y, bits, 4);
+		lcd_write(x+4, y, bits+4, 2);
+	} else 
+		lcd_write(x, y, bits, 6);
 }
 }
 
 
-static inline uint8_t
-lcd_write(
-	const uint8_t byte
-)
-{
-	return lcd_command(byte, 1, 1);
-}
-
 
 static void
 lcd_vee(
  *
  * x goes from 0 to 50, y goes from 0 to 32, rounded to 8.
  */
-static uint8_t
-lcd_doit(
+static void
+lcd_bulk_write(
 	const uint8_t pin,
 	uint8_t x,
 	uint8_t y,
-	uint8_t val,
-	uint8_t write_dir
+	const uint8_t * buf,
+	uint8_t n
 )
 {
-	uint8_t rc = 0;
-
 	out(pin, 1);
 	lcd_command((y >> 3) << 6 | x, 0, 1);
-	lcd_command(val, 1, write_dir);
-	if (!write_dir)
-		rc = lcd_command(val, 1, 0); // get the data
+
+	for (uint8_t i = 0 ; i < n ; i++)
+		lcd_command(buf[i], 1, 1);
+
 	out(pin, 0);
-
-	return rc;
 }
 
 
  * x is ranged 0 to 240, for each pixel
  * y is ranged 0 to 64, rounded to 8
  */
-static uint8_t
-_lcd_select(
+void
+lcd_write(
 	uint8_t x,
 	uint8_t y,
-	uint8_t val,
-	uint8_t write_dir
+	const uint8_t * buf,
+	uint8_t n
 )
 {
-	uint8_t rc;
 	out(LCD_CS1, 1);
 
 	if (y < 32)
 	{
 		// Top half of the display
 		if (x < 50)
-			rc = lcd_doit(LCD_CS20, x - 0, y - 0, val, write_dir);
+			lcd_bulk_write(LCD_CS20, x - 0, y - 0, buf, n);
 		else
 		if (x < 100)
-			rc = lcd_doit(LCD_CS21, x - 50, y - 0, val, write_dir);
+			lcd_bulk_write(LCD_CS21, x - 50, y - 0, buf, n);
 		else
 		if (x < 150)
-			rc = lcd_doit(LCD_CS22, x - 100, y - 0, val, write_dir);
+			lcd_bulk_write(LCD_CS22, x - 100, y - 0, buf, n);
 		else
 		if (x < 200)
-			rc = lcd_doit(LCD_CS23, x - 150, y - 0, val, write_dir);
+			lcd_bulk_write(LCD_CS23, x - 150, y - 0, buf, n);
 		else
-			rc = lcd_doit(LCD_CS24, x - 200, y - 0, val, write_dir);
+			lcd_bulk_write(LCD_CS24, x - 200, y - 0, buf, n);
 	} else {
 		// Bottom half of the display
 		if (x < 50)
-			rc = lcd_doit(LCD_CS25, x - 0, y - 32, val, write_dir);
+			lcd_bulk_write(LCD_CS25, x - 0, y - 32, buf, n);
 		else
 		if (x < 100)
-			rc = lcd_doit(LCD_CS26, x - 50, y - 32, val, write_dir);
+			lcd_bulk_write(LCD_CS26, x - 50, y - 32, buf, n);
 		else
 		if (x < 150)
-			rc = lcd_doit(LCD_CS27, x - 100, y - 32, val, write_dir);
+			lcd_bulk_write(LCD_CS27, x - 100, y - 32, buf, n);
 		else
 		if (x < 200)
-			rc = lcd_doit(LCD_CS28, x - 150, y - 32, val, write_dir);
+			lcd_bulk_write(LCD_CS28, x - 150, y - 32, buf, n);
 		else
-			rc = lcd_doit(LCD_CS29, x - 200, y - 32, val, write_dir);
+			lcd_bulk_write(LCD_CS29, x - 200, y - 32, buf, n);
 	}
 
 	out(LCD_CS1, 0);
-	return rc;
 }
 
-void
-lcd_display(
+
+/** Enable the one chip, select the address and send/recv the byte.
+ *
+ * x goes from 0 to 50, y goes from 0 to 32, rounded to 8.
+ */
+static void
+lcd_bulk_read(
+	const uint8_t pin,
 	uint8_t x,
 	uint8_t y,
-	uint8_t val
+	uint8_t * buf,
+	uint8_t n
 )
 {
-	_lcd_select(x, y, val, 1);
+	out(pin, 1);
+	lcd_command((y >> 3) << 6 | x, 0, 1);
+	lcd_command(0, 1, 0); // dummy
+
+	for (int i = 0 ; i < n ; i++)
+		buf[i] = lcd_command(0, 1, 0);
+	out(pin, 0);
 }
 
-uint8_t
+
+void
 lcd_read(
 	uint8_t x,
-	uint8_t y
+	uint8_t y,
+	uint8_t * buf,
+	uint8_t n
 )
 {
-	return _lcd_select(x, y, 0, 0);
+	out(LCD_CS1, 1);
+
+	if (y < 32)
+	{
+		// Top half of the display
+		if (x < 50)
+			lcd_bulk_read(LCD_CS20, x - 0, y - 0, buf, n);
+		else
+		if (x < 100)
+			lcd_bulk_read(LCD_CS21, x - 50, y - 0, buf, n);
+		else
+		if (x < 150)
+			lcd_bulk_read(LCD_CS22, x - 100, y - 0, buf, n);
+		else
+		if (x < 200)
+			lcd_bulk_read(LCD_CS23, x - 150, y - 0, buf, n);
+		else
+			lcd_bulk_read(LCD_CS24, x - 200, y - 0, buf, n);
+	} else {
+		// Bottom half of the display
+		if (x < 50)
+			lcd_bulk_read(LCD_CS25, x - 0, y - 32, buf, n);
+		else
+		if (x < 100)
+			lcd_bulk_read(LCD_CS26, x - 50, y - 32, buf, n);
+		else
+		if (x < 150)
+			lcd_bulk_read(LCD_CS27, x - 100, y - 32, buf, n);
+		else
+		if (x < 200)
+			lcd_bulk_read(LCD_CS28, x - 150, y - 32, buf, n);
+		else
+			lcd_bulk_read(LCD_CS29, x - 200, y - 32, buf, n);
+	}
+
+	out(LCD_CS1, 0);
 }
 lcd_init(void);
 
 
-/** Display vertical column val at position x,y.
+/** Display an array of N columns starting at position x,y */
+extern void
+lcd_write(
+	uint8_t x,
+	uint8_t y,
+	const uint8_t * val,
+	uint8_t n
+);
+
+
+/** Read an array of N colums starting at position x,y */
+extern void
+lcd_read(
+	uint8_t x,
+	uint8_t y,
+	uint8_t * buf,
+	uint8_t n
+);
+
+
+/** Display a single vertical column val at position x,y.
  *
  * x is ranged 0 to 240, for each pixel
  * y is ranged 0 to 64, rounded to 8
  * MSB of val is at the top, LSB is at the bottom.
  */
-extern void
+static inline void
 lcd_display(
 	uint8_t x,
 	uint8_t y,
 	uint8_t val
-);
-
-
-/** Read a vertical colum at position x,y */
-extern uint8_t
-lcd_read(
-	uint8_t x,
-	uint8_t y
-);
-
+)
+{
+	lcd_write(x, y, &val, 1);
+}
 
 #endif
 
 	// We are scrolling.  Omg.  How do we do this.
 	cur_col = 0;
-	for (int j = 0 ; j < 240 ; j++)
+#define BLIT_WIDTH 50
+	static uint8_t bits[BLIT_WIDTH];
+
+	for (int x = 0 ; x < 240 ; x += BLIT_WIDTH)
 	{
-		for (int i = 0 ; i < MAX_ROWS-1 ; i++)
+		for (int y = 0 ; y < 64-8 ; y += 8)
 		{
-			uint8_t bits = lcd_read(j, (i+1)*8);
-			lcd_display(j, i*8, bits);
+			lcd_read(x, y+8, bits, BLIT_WIDTH);
+			lcd_write(x, y, bits, BLIT_WIDTH);
 		}
 	}