summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-11-20 21:02:59 -0800
committerKeith Packard <keithp@keithp.com>2016-11-20 21:02:59 -0800
commitc5734e9e38bc583aff305e3c534cfb8b9088bc71 (patch)
treef02f3dafea7e704a7164011700c56289ab9fed0a
parent83cfc271e37f568cb1d821cf6a96750f3ca3854c (diff)
altos/draw: Add a reasonable API for drawing, add lines.lisp
Also, move the demo drawing into the stm-vga app and out of the vga driver. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--src/draw/ao_blt.c1
-rw-r--r--src/draw/ao_copy.c75
-rw-r--r--src/draw/ao_draw.h137
-rw-r--r--src/draw/ao_draw_int.h128
-rw-r--r--src/draw/ao_font.h138
-rw-r--r--src/draw/ao_line.c164
-rw-r--r--src/draw/ao_rect.c55
-rw-r--r--src/draw/ao_text.c51
-rwxr-xr-xsrc/draw/font-convert20
-rw-r--r--src/drivers/ao_vga.c211
-rw-r--r--src/drivers/ao_vga.h17
-rw-r--r--src/stm-vga/Makefile8
-rw-r--r--src/stm-vga/ao_demo.c81
-rw-r--r--src/stm-vga/ao_pins.h1
14 files changed, 698 insertions, 389 deletions
diff --git a/src/draw/ao_blt.c b/src/draw/ao_blt.c
index 2060f007..e3f45221 100644
--- a/src/draw/ao_blt.c
+++ b/src/draw/ao_blt.c
@@ -14,6 +14,7 @@
#include "ao.h"
#include "ao_draw.h"
+#include "ao_draw_int.h"
#define O 0
#define I AO_ALLONES
diff --git a/src/draw/ao_copy.c b/src/draw/ao_copy.c
new file mode 100644
index 00000000..47067bb8
--- /dev/null
+++ b/src/draw/ao_copy.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+
+#define bound(val,max,other) do { \
+ if (val < 0) { \
+ other -= val; \
+ val = 0; \
+ } \
+ if (val > max) { \
+ other -= (val - max); \
+ val = max; \
+ } \
+ } while (0)
+
+#define bound2(a, max_a, b, max_b) do { \
+ bound(a, max_a, b); \
+ bound(b, max_b, a); \
+ } while (0)
+
+void
+ao_copy(const struct ao_bitmap *dst,
+ int16_t dst_x,
+ int16_t dst_y,
+ int16_t width,
+ int16_t height,
+ const struct ao_bitmap *src,
+ int16_t src_x,
+ int16_t src_y,
+ uint8_t rop)
+{
+ int16_t dst_x2 = dst_x + width, dst_y2 = dst_y + height;
+ int16_t src_x2 = src_x + width, src_y2 = src_y + height;
+ uint8_t reverse = 0;
+ uint8_t upsidedown = 0;
+
+ bound2(dst_x, dst->width, src_x, src->width);
+ bound2(dst_x2, dst->width, src_x2, src->width);
+ bound2(dst_y, dst->height, src_y, src->height);
+ bound2(dst_y2, dst->height, src_y2, src->height);
+
+ if (dst == src) {
+ reverse = (dst_x > src_x);
+ upsidedown = (dst_y > src_y);
+ }
+
+ if (dst_x < dst_x2 && dst_y < dst_y2) {
+ ao_blt(src->base + src_y * src->stride,
+ src->stride,
+ src_x,
+ dst->base + dst_y * dst->stride,
+ dst->stride,
+ dst_x,
+ dst_x2 - dst_x,
+ dst_y2 - dst_y,
+ rop,
+ reverse,
+ upsidedown);
+ }
+}
+
diff --git a/src/draw/ao_draw.h b/src/draw/ao_draw.h
index 1ff3e748..f7dc75bf 100644
--- a/src/draw/ao_draw.h
+++ b/src/draw/ao_draw.h
@@ -15,99 +15,74 @@
#ifndef _AO_DRAW_H_
#define _AO_DRAW_H_
+struct ao_bitmap {
+ uint32_t *base;
+ int16_t stride; /* in units */
+ int16_t width; /* in pixels */
+ int16_t height; /* in pixels */
+};
+
void
-ao_blt(uint32_t *src_line,
- int16_t src_stride,
- int16_t src_x,
- uint32_t *dst_line,
- int16_t dst_stride,
- int16_t dst_x,
- int16_t width,
- int16_t height,
- uint8_t rop,
- uint8_t reverse,
- uint8_t upsidedown);
+ao_copy(const struct ao_bitmap *dst,
+ int16_t dst_x,
+ int16_t dst_y,
+ int16_t width,
+ int16_t height,
+ const struct ao_bitmap *src,
+ int16_t src_x,
+ int16_t src_y,
+ uint8_t rop);
void
-ao_solid(uint32_t and,
- uint32_t xor,
- uint32_t *dst,
- int16_t dst_stride,
- int16_t dst_x,
- int16_t width,
- int16_t height);
+ao_rect(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ int16_t width,
+ int16_t height,
+ uint32_t fill,
+ uint8_t rop);
void
-ao_text(char *string,
- uint32_t *dst_line,
- int16_t dst_stride,
- int16_t dst_x);
+ao_line(const struct ao_bitmap *dst,
+ int16_t x1,
+ int16_t y1,
+ int16_t x2,
+ int16_t y2,
+ uint32_t fill,
+ uint8_t rop);
-#define AO_ROP_CLEAR 0x0
-#define AO_ROP_COPY 0x3
-#define AO_ROP_SET 0xf
+void
+ao_text(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ char *string,
+ uint32_t fill,
+ uint8_t rop);
+
+struct ao_font {
+ int width;
+ int height;
+ int ascent;
+ int descent;
+};
+
+extern const struct ao_font ao_font;
#define AO_SHIFT 5
#define AO_UNIT (1 << AO_SHIFT)
#define AO_MASK (AO_UNIT - 1)
#define AO_ALLONES ((uint32_t) -1)
-static inline uint32_t
-ao_left(uint32_t bits, int16_t shift) {
- return bits >> shift;
-}
-
-static inline uint32_t
-ao_right(uint32_t bits, int16_t shift) {
- return bits << shift;
-}
-
-static inline uint32_t
-ao_right_mask(int16_t x) {
- if ((AO_UNIT - x) & AO_MASK)
- return ao_left(AO_ALLONES,(AO_UNIT - x) & AO_MASK);
- else
- return 0;
-}
-
-static inline uint32_t
-ao_left_mask(int16_t x) {
- if (x & AO_MASK)
- return ao_right(AO_ALLONES, x & AO_MASK);
- else
- return 0;
-}
-
-static inline uint32_t
-ao_bits_mask(int16_t x, int16_t w) {
- return ao_right(AO_ALLONES, x & AO_MASK) &
- ao_left(AO_ALLONES,(AO_UNIT - (x + w)) & AO_MASK);
-}
-
-#define ao_mask_bits(x,w,l,n,r) { \
- n = (w); \
- r = ao_right_mask((x)+n); \
- l = ao_left_mask(x); \
- if (l) { \
- n -= AO_UNIT - ((x) & AO_MASK); \
- if (n < 0) { \
- n = 0; \
- l &= r; \
- r = 0; \
- } \
- } \
- n >>= AO_SHIFT; \
-}
-
-static inline uint32_t
-ao_do_mask_rrop(uint32_t dst, uint32_t and, uint32_t xor, uint32_t mask) {
- return (dst & (and | ~mask)) ^ (xor & mask);
-}
-
-static inline uint32_t
-ao_do_rrop(uint32_t dst, uint32_t and, uint32_t xor) {
- return (dst & and) ^ xor;
-}
+/*
+ * dst
+ * 0 1
+ *
+ * 0 a b
+ * src
+ * 1 c d
+ *
+ * ROP = abcd
+ */
#define AO_CLEAR 0x0 /* 0 */
#define AO_AND 0x1 /* src AND dst */
diff --git a/src/draw/ao_draw_int.h b/src/draw/ao_draw_int.h
new file mode 100644
index 00000000..6980147b
--- /dev/null
+++ b/src/draw/ao_draw_int.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _AO_DRAW_INT_H_
+#define _AO_DRAW_INT_H_
+
+static inline uint32_t
+ao_expand(uint32_t bits)
+{
+ return ~((bits & 1)-1);
+}
+
+static inline uint32_t
+ao_xor(uint8_t rop, uint32_t fg)
+{
+ fg = ao_expand(fg);
+
+ return (fg & ao_expand(rop >> 1)) |
+ (~fg & ao_expand(rop >> 3));
+}
+
+static inline uint32_t
+ao_and(uint8_t rop, uint32_t fg)
+{
+ fg = ao_expand(fg);
+
+ return (fg & ao_expand(rop ^ (rop >> 1))) |
+ (~fg & ao_expand((rop>>2) ^ (rop>>3)));
+}
+
+static inline uint32_t
+ao_left(uint32_t bits, int16_t shift) {
+ return bits >> shift;
+}
+
+static inline uint32_t
+ao_right(uint32_t bits, int16_t shift) {
+ return bits << shift;
+}
+
+static inline uint32_t
+ao_right_mask(int16_t x) {
+ if ((AO_UNIT - x) & AO_MASK)
+ return ao_left(AO_ALLONES,(AO_UNIT - x) & AO_MASK);
+ else
+ return 0;
+}
+
+static inline uint32_t
+ao_left_mask(int16_t x) {
+ if (x & AO_MASK)
+ return ao_right(AO_ALLONES, x & AO_MASK);
+ else
+ return 0;
+}
+
+static inline uint32_t
+ao_bits_mask(int16_t x, int16_t w) {
+ return ao_right(AO_ALLONES, x & AO_MASK) &
+ ao_left(AO_ALLONES,(AO_UNIT - (x + w)) & AO_MASK);
+}
+
+#define ao_mask_bits(x,w,l,n,r) { \
+ n = (w); \
+ r = ao_right_mask((x)+n); \
+ l = ao_left_mask(x); \
+ if (l) { \
+ n -= AO_UNIT - ((x) & AO_MASK); \
+ if (n < 0) { \
+ n = 0; \
+ l &= r; \
+ r = 0; \
+ } \
+ } \
+ n >>= AO_SHIFT; \
+}
+
+static inline uint32_t
+ao_do_mask_rrop(uint32_t dst, uint32_t and, uint32_t xor, uint32_t mask) {
+ return (dst & (and | ~mask)) ^ (xor & mask);
+}
+
+static inline uint32_t
+ao_do_rrop(uint32_t dst, uint32_t and, uint32_t xor) {
+ return (dst & and) ^ xor;
+}
+
+void
+ao_blt(uint32_t *src_line,
+ int16_t src_stride,
+ int16_t src_x,
+ uint32_t *dst_line,
+ int16_t dst_stride,
+ int16_t dst_x,
+ int16_t width,
+ int16_t height,
+ uint8_t rop,
+ uint8_t reverse,
+ uint8_t upsidedown);
+
+void
+ao_solid(uint32_t and,
+ uint32_t xor,
+ uint32_t *dst,
+ int16_t dst_stride,
+ int16_t dst_x,
+ int16_t width,
+ int16_t height);
+
+int16_t
+ao_glyph(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ uint8_t c,
+ uint8_t rop);
+
+#endif /* _AO_DRAW_INT_H_ */
diff --git a/src/draw/ao_font.h b/src/draw/ao_font.h
deleted file mode 100644
index ac424ef9..00000000
--- a/src/draw/ao_font.h
+++ /dev/null
@@ -1,138 +0,0 @@
-static uint8_t glyph_bytes[] = {
- 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x04, 0x0e, 0x1f, 0x0e, 0x04, 0x00, 0x0a, 0x05,
- 0x0a, 0x05, 0x0a, 0x05, 0x00, 0x05, 0x07, 0x05, 0x05, 0x0e, 0x04, 0x04, 0x03, 0x01, 0x03, 0x0d,
- 0x04, 0x0c, 0x04, 0x03, 0x01, 0x03, 0x06, 0x0a, 0x06, 0x0a, 0x01, 0x01, 0x03, 0x0c, 0x04, 0x0c,
- 0x04, 0x04, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0e, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x09,
- 0x0b, 0x0d, 0x09, 0x04, 0x04, 0x0c, 0x05, 0x05, 0x05, 0x02, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04,
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04,
- 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x1f, 0x00, 0x04, 0x04, 0x04, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04,
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x02, 0x04, 0x08, 0x0e, 0x00, 0x02, 0x04, 0x08,
- 0x04, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x0e, 0x04, 0x0e,
- 0x02, 0x00, 0x00, 0x0c, 0x02, 0x07, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, 0x0a, 0x0a,
- 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x00, 0x00, 0x0e, 0x05, 0x0e,
- 0x14, 0x0e, 0x00, 0x01, 0x09, 0x04, 0x02, 0x09, 0x08, 0x00, 0x00, 0x02, 0x05, 0x02, 0x05, 0x0a,
- 0x00, 0x06, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x04, 0x00, 0x02,
- 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, 0x00, 0x05, 0x02, 0x07, 0x02, 0x05, 0x00, 0x00, 0x04, 0x04,
- 0x1f, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00,
- 0x02, 0x05, 0x05, 0x05, 0x05, 0x02, 0x00, 0x02, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x06, 0x09,
- 0x08, 0x04, 0x02, 0x0f, 0x00, 0x0f, 0x08, 0x06, 0x08, 0x09, 0x06, 0x00, 0x04, 0x06, 0x05, 0x0f,
- 0x04, 0x04, 0x00, 0x0f, 0x01, 0x07, 0x08, 0x09, 0x06, 0x00, 0x06, 0x01, 0x07, 0x09, 0x09, 0x06,
- 0x00, 0x0f, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x06, 0x09, 0x06, 0x09, 0x09, 0x06, 0x00, 0x06,
- 0x09, 0x09, 0x0e, 0x08, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06,
- 0x00, 0x06, 0x02, 0x01, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f,
- 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x02, 0x01, 0x00, 0x02, 0x05, 0x04, 0x02, 0x00, 0x02, 0x00,
- 0x06, 0x09, 0x0d, 0x0d, 0x01, 0x06, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x07, 0x09,
- 0x07, 0x09, 0x09, 0x07, 0x00, 0x06, 0x09, 0x01, 0x01, 0x09, 0x06, 0x00, 0x07, 0x09, 0x09, 0x09,
- 0x09, 0x07, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x01,
- 0x00, 0x06, 0x09, 0x01, 0x0d, 0x09, 0x0e, 0x00, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07,
- 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06, 0x00, 0x09, 0x05, 0x03,
- 0x03, 0x05, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x09, 0x09,
- 0x09, 0x00, 0x09, 0x0b, 0x0b, 0x0d, 0x0d, 0x09, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00,
- 0x07, 0x09, 0x09, 0x07, 0x01, 0x01, 0x00, 0x06, 0x09, 0x09, 0x09, 0x0b, 0x06, 0x08, 0x07, 0x09,
- 0x09, 0x07, 0x05, 0x09, 0x00, 0x06, 0x09, 0x02, 0x04, 0x09, 0x06, 0x00, 0x07, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x06, 0x06,
- 0x00, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x06, 0x06, 0x09, 0x09, 0x00, 0x05,
- 0x05, 0x05, 0x02, 0x02, 0x02, 0x00, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x0f, 0x00, 0x07, 0x01, 0x01,
- 0x01, 0x01, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04,
- 0x07, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
- 0x03, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x01, 0x01,
- 0x07, 0x09, 0x09, 0x07, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x06, 0x00, 0x08, 0x08, 0x0e, 0x09,
- 0x09, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x04, 0x0a, 0x02, 0x07, 0x02, 0x02,
- 0x00, 0x00, 0x00, 0x0e, 0x09, 0x06, 0x01, 0x0e, 0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x00, 0x02,
- 0x00, 0x03, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x05, 0x02, 0x01, 0x01, 0x05,
- 0x03, 0x05, 0x09, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x05, 0x0f, 0x09,
- 0x09, 0x00, 0x00, 0x00, 0x07, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x06, 0x09, 0x09, 0x06, 0x00,
- 0x00, 0x00, 0x07, 0x09, 0x09, 0x07, 0x01, 0x00, 0x00, 0x0e, 0x09, 0x09, 0x0e, 0x08, 0x00, 0x00,
- 0x07, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x03, 0x0c, 0x07, 0x00, 0x02, 0x02, 0x07, 0x02,
- 0x02, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x02,
- 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x06, 0x06, 0x09, 0x00, 0x00,
- 0x00, 0x09, 0x09, 0x0a, 0x04, 0x02, 0x00, 0x00, 0x0f, 0x04, 0x02, 0x0f, 0x00, 0x04, 0x02, 0x03,
- 0x02, 0x02, 0x04, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x06, 0x02, 0x02,
- 0x01, 0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04,
- 0x0e, 0x05, 0x05, 0x0e, 0x04, 0x00, 0x0c, 0x02, 0x07, 0x02, 0x0d, 0x00, 0x00, 0x11, 0x0e, 0x0a,
- 0x0e, 0x11, 0x00, 0x05, 0x05, 0x02, 0x07, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04,
- 0x00, 0x0c, 0x02, 0x06, 0x0a, 0x0c, 0x08, 0x06, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
- 0x11, 0x15, 0x13, 0x15, 0x11, 0x0e, 0x06, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
- 0x09, 0x12, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
- 0x00, 0x00, 0x0e, 0x11, 0x17, 0x13, 0x13, 0x11, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x1f, 0x00, 0x06, 0x04,
- 0x02, 0x06, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x06, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x07, 0x01, 0x0e, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a,
- 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x04,
- 0x06, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
- 0x12, 0x09, 0x00, 0x00, 0x01, 0x01, 0x01, 0x09, 0x0c, 0x0e, 0x08, 0x01, 0x01, 0x01, 0x0d, 0x08,
- 0x04, 0x0c, 0x03, 0x03, 0x02, 0x0b, 0x0c, 0x0e, 0x08, 0x02, 0x00, 0x02, 0x01, 0x05, 0x02, 0x00,
- 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09,
- 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f,
- 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x0e, 0x05, 0x0d, 0x07, 0x05, 0x0d,
- 0x00, 0x06, 0x09, 0x01, 0x01, 0x09, 0x06, 0x02, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f,
- 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07,
- 0x01, 0x01, 0x0f, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02,
- 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00,
- 0x07, 0x0a, 0x0b, 0x0a, 0x0a, 0x07, 0x00, 0x0d, 0x09, 0x0b, 0x0d, 0x0d, 0x09, 0x00, 0x06, 0x09,
- 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09,
- 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06,
- 0x00, 0x00, 0x00, 0x09, 0x06, 0x06, 0x09, 0x00, 0x0e, 0x0d, 0x0d, 0x0b, 0x0b, 0x07, 0x00, 0x09,
- 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09,
- 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x05, 0x05, 0x05, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x07, 0x09, 0x07, 0x01, 0x01, 0x00, 0x06, 0x09, 0x07, 0x09, 0x0b, 0x05, 0x01,
- 0x02, 0x04, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x04, 0x02, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x04, 0x0a,
- 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x0a, 0x05, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x0a, 0x00, 0x0e, 0x09,
- 0x0d, 0x0a, 0x00, 0x06, 0x06, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x0d, 0x05, 0x0e,
- 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x06, 0x02, 0x02, 0x04, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x04,
- 0x02, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x02, 0x05, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x05, 0x00, 0x06,
- 0x0d, 0x03, 0x06, 0x00, 0x01, 0x02, 0x03, 0x02, 0x02, 0x07, 0x00, 0x02, 0x01, 0x03, 0x02, 0x02,
- 0x07, 0x00, 0x02, 0x05, 0x03, 0x02, 0x02, 0x07, 0x00, 0x05, 0x00, 0x03, 0x02, 0x02, 0x07, 0x00,
- 0x02, 0x0c, 0x06, 0x09, 0x09, 0x06, 0x00, 0x0a, 0x05, 0x07, 0x09, 0x09, 0x09, 0x00, 0x02, 0x04,
- 0x06, 0x09, 0x09, 0x06, 0x00, 0x04, 0x02, 0x06, 0x09, 0x09, 0x06, 0x00, 0x06, 0x00, 0x06, 0x09,
- 0x09, 0x06, 0x00, 0x0a, 0x05, 0x06, 0x09, 0x09, 0x06, 0x00, 0x05, 0x00, 0x06, 0x09, 0x09, 0x06,
- 0x00, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x0d, 0x0b, 0x07, 0x00, 0x02,
- 0x04, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x04, 0x02, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x06, 0x00, 0x09,
- 0x09, 0x09, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x04, 0x02, 0x09, 0x09, 0x0a,
- 0x04, 0x02, 0x00, 0x01, 0x07, 0x09, 0x09, 0x07, 0x01, 0x0a, 0x00, 0x09, 0x09, 0x0a, 0x04, 0x02,
-};
-
-static uint16_t glyph_pos[] = {
- 0, 7, 14, 21, 28, 35, 42, 49,
- 56, 63, 70, 77, 84, 91, 98, 105,
- 112, 119, 126, 133, 140, 147, 154, 161,
- 168, 175, 182, 189, 196, 203, 210, 217,
- 224, 231, 238, 245, 252, 259, 266, 273,
- 280, 287, 294, 301, 308, 315, 322, 329,
- 336, 343, 350, 357, 364, 371, 378, 385,
- 392, 399, 406, 413, 420, 427, 434, 441,
- 448, 455, 462, 469, 476, 483, 490, 497,
- 504, 511, 518, 525, 532, 539, 546, 553,
- 560, 567, 574, 581, 588, 595, 602, 609,
- 616, 623, 630, 637, 644, 651, 658, 665,
- 672, 679, 686, 693, 700, 707, 714, 721,
- 728, 735, 742, 749, 756, 763, 770, 777,
- 784, 791, 798, 805, 812, 819, 826, 833,
- 840, 847, 854, 861, 868, 875, 882, 889,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 896, 903, 910, 917, 924, 931, 938, 945,
- 952, 959, 966, 973, 980, 987, 994, 1001,
- 1008, 1015, 1022, 1029, 1036, 1043, 1050, 1057,
- 1064, 1071, 1078, 1085, 1092, 1099, 1106, 1113,
- 1120, 1127, 1134, 1141, 1148, 1155, 1162, 1169,
- 1176, 1183, 1190, 1197, 1204, 1211, 1218, 1225,
- 1232, 1239, 1246, 1253, 1260, 1267, 1274, 1281,
- 1288, 1295, 1302, 1309, 1316, 1323, 1330, 1337,
- 1344, 1351, 1358, 1365, 1372, 1379, 1386, 1393,
- 1400, 1407, 1414, 1421, 1428, 1435, 1442, 1449,
- 1456, 1463, 1470, 1477, 1484, 1491, 1498, 1505,
- 1512, 1519, 1526, 1533, 1540, 1547, 1554, 1561,
-};
-
-#define GLYPH_WIDTH 5
-#define GLYPH_HEIGHT 7
diff --git a/src/draw/ao_line.c b/src/draw/ao_line.c
new file mode 100644
index 00000000..b427892b
--- /dev/null
+++ b/src/draw/ao_line.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+
+#define ao_mask(x,w) (ao_right(AO_ALLONES,(x) & AO_MASK) & \
+ ao_left(AO_ALLONES,(FB_UNIT - ((x)+(w))) & AO_MASK))
+
+
+/* out of clip region codes */
+#define OUT_LEFT 0x08
+#define OUT_RIGHT 0x04
+#define OUT_ABOVE 0x02
+#define OUT_BELOW 0x01
+
+/* major axis for bresenham's line */
+#define X_AXIS 0
+#define Y_AXIS 1
+
+static void
+ao_bres(const struct ao_bitmap *dst_bitmap,
+ int16_t signdx,
+ int16_t signdy,
+ int16_t axis,
+ int16_t x1,
+ int16_t y1,
+ int16_t e,
+ int16_t e1,
+ int16_t e3,
+ int16_t len,
+ uint32_t and,
+ uint32_t xor)
+{
+ int16_t stride = dst_bitmap->stride;
+ uint32_t *dst = dst_bitmap->base;
+ uint32_t mask0, mask;
+
+ mask0 = 1;
+ if (signdx < 0)
+ mask0 = ao_right(1, AO_UNIT - 1);
+
+ if (signdy < 0)
+ stride = -stride;
+
+ dst = dst + y1 * stride + (x1 >> AO_SHIFT);
+ mask = ao_right(1, x1 & AO_MASK);
+
+ while (len--) {
+ /* clip each point */
+
+ if (0 <= x1 && x1 < dst_bitmap->width &&
+ 0 <= y1 && y1 < dst_bitmap->height)
+ *dst = ao_do_mask_rrop(*dst, and, xor, mask);
+
+ if (axis == X_AXIS) {
+ if (signdx < 0)
+ mask = ao_left(mask, 1);
+ else
+ mask = ao_right(mask, 1);
+ if (!mask) {
+ dst += signdx;
+ mask = mask0;
+ }
+ x1 += signdx;
+ e += e1;
+ if (e >= 0) {
+ dst += stride;
+ e += e3;
+ y1 += signdy;
+ }
+ } else {
+ dst += stride;
+ e += e1;
+ y1 += signdy;
+ if (e >= 0) {
+ if (signdx < 0)
+ mask = ao_left(mask, 1);
+ else
+ mask = ao_right(mask, 1);
+ if (!mask) {
+ dst += signdx;
+ mask = mask0;
+ }
+ e += e3;
+ x1 += signdx;
+ }
+ }
+ }
+}
+
+
+#define bound(val,max) do { \
+ if (val < 0) { \
+ val = 0; \
+ } \
+ if (val > max) { \
+ val = max; \
+ } \
+ } while (0)
+
+void
+ao_line(const struct ao_bitmap *dst,
+ int16_t x1,
+ int16_t y1,
+ int16_t x2,
+ int16_t y2,
+ uint32_t fill,
+ uint8_t rop)
+{
+ int16_t adx, ady;
+ int16_t e, e1, e2, e3;
+ int16_t signdx = 1, signdy = 1;
+ int16_t axis;
+ int16_t len;
+
+ if ((adx = x2 - x1) < 0) {
+ adx = -adx;
+ signdx = -1;
+ }
+ if ((ady = y2 - y1) < 0) {
+ ady = -ady;
+ signdy = -1;
+ }
+
+ if (adx > ady) {
+ axis = X_AXIS;
+ e1 = ady << 1;
+ e2 = e1 - (adx << 1);
+ e = e1 - adx;
+ len = adx;
+ } else {
+ axis = Y_AXIS;
+ e1 = adx << 1;
+ e2 = e1 - (ady << 1);
+ e = e1 - ady;
+ len = ady;
+ }
+
+ e3 = e2 - e1;
+ e = e - e1;
+
+ ao_bres(dst,
+ signdx,
+ signdy,
+ axis,
+ x1,
+ y1,
+ e, e1, e3, len,
+ ao_and(rop, fill),
+ ao_xor(rop, fill));
+}
diff --git a/src/draw/ao_rect.c b/src/draw/ao_rect.c
new file mode 100644
index 00000000..fee7bbd5
--- /dev/null
+++ b/src/draw/ao_rect.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include "ao.h"
+#include "ao_draw.h"
+#include "ao_draw_int.h"
+
+#define bound(val,max) do { \
+ if (val < 0) { \
+ val = 0; \
+ } \
+ if (val > max) { \
+ val = max; \
+ } \
+ } while (0)
+
+void
+ao_rect(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ int16_t width,
+ int16_t height,
+ uint32_t fill,
+ uint8_t rop)
+{
+ int16_t x2 = x + width;
+ int16_t y2 = y + height;
+
+ bound(x, dst->width);
+ bound(x2, dst->width);
+ bound(y, dst->height);
+ bound(y2, dst->height);
+
+ if (x < x2 && y < y2) {
+ ao_solid(ao_and(rop, fill),
+ ao_xor(rop, fill),
+ dst->base + y * dst->stride,
+ dst->stride,
+ x,
+ x2 - x,
+ y2 - y);
+ }
+}
+
diff --git a/src/draw/ao_text.c b/src/draw/ao_text.c
index 68d6c2cf..18e3924d 100644
--- a/src/draw/ao_text.c
+++ b/src/draw/ao_text.c
@@ -14,31 +14,52 @@
#include "ao.h"
#include "ao_draw.h"
+#include "ao_draw_int.h"
#include "ao_font.h"
+const struct ao_font ao_font = {
+ .width = GLYPH_WIDTH,
+ .height = GLYPH_HEIGHT,
+ .ascent = GLYPH_ASCENT,
+ .descent = GLYPH_HEIGHT - GLYPH_ASCENT,
+};
+
void
-ao_text(char *string,
- uint32_t *dst_line,
- int16_t dst_stride,
- int16_t dst_x)
+ao_text(const struct ao_bitmap *dst,
+ int16_t x,
+ int16_t y,
+ char *string,
+ uint32_t fill,
+ uint8_t rop)
{
- char c;
uint32_t src[GLYPH_HEIGHT];
+ char c;
+ int h;
+
+ struct ao_bitmap src_bitmap = {
+ .base = src,
+ .stride = 1,
+ .width = GLYPH_WIDTH,
+ .height = GLYPH_HEIGHT
+ };
+
+ y -= GLYPH_ASCENT;
+
+ rop = (rop & 3) | 0x4;
+
+ if ((fill&1) == 0)
+ rop ^= 3;
while ((c = *string++)) {
- uint8_t *bytes = &glyph_bytes[glyph_pos[(uint8_t) c]];
- int h;
+ uint8_t *bytes = &glyph_bytes[glyph_pos[(uint8_t) c]];
for (h = 0; h < GLYPH_HEIGHT; h++)
src[h] = bytes[h];
- ao_blt(src, 1, 0,
- dst_line, dst_stride,
- dst_x,
- GLYPH_WIDTH,
- GLYPH_HEIGHT,
- AO_AND_INVERTED,
- 0, 0);
- dst_x += GLYPH_WIDTH;
+ ao_copy(dst,
+ x, y, GLYPH_WIDTH, GLYPH_HEIGHT,
+ &src_bitmap,
+ 0, 0, rop);
+ x += GLYPH_WIDTH;
}
}
diff --git a/src/draw/font-convert b/src/draw/font-convert
index 2446592b..80297cf9 100755
--- a/src/draw/font-convert
+++ b/src/draw/font-convert
@@ -11,6 +11,7 @@ typedef struct {
typedef struct {
glyph_t[...] glyphs;
int default_char;
+ int ascent;
} font_t;
glyph_t
@@ -29,8 +30,10 @@ read_glyph(file f)
case "ENCODING":
glyph.encoding = atoi(tokens[1]);
break;
- case "BBX":
+ case "DWIDTH":
glyph.width = atoi(tokens[1]);
+ break;
+ case "BBX":
glyph.height = atoi(tokens[2]);
break;
case "ENDCHAR":
@@ -50,15 +53,23 @@ read_glyph(file f)
font_t read_font(file f) {
font_t font = { .glyphs = {}, .default_char = -1 };
+ bool in_head = true;
- while (!File::end(f)) {
+ while (in_head && !File::end(f)) {
string l = File::fgets(f);
string[*] tokens = String::split(l, " ");
- if (tokens[0] == "DEFAULT_CHAR")
+ switch (tokens[0]) {
+ case "DEFAULT_CHAR":
font.default_char = atoi(tokens[1]);
- if (tokens[0] == "CHARS")
break;
+ case "FONT_ASCENT":
+ font.ascent = atoi(tokens[1]);
+ break;
+ case "CHARS":
+ in_head = false;
+ break;
+ }
}
while (!File::end(f)) {
glyph_t glyph = read_glyph(f);
@@ -130,6 +141,7 @@ void print_font(font_t font) {
printf("#define GLYPH_WIDTH %d\n", width);
printf("#define GLYPH_HEIGHT %d\n", height);
+ printf("#define GLYPH_ASCENT %d\n", font.ascent);
}
twixt (file f = File::open(argv[1], "r"); File::close(f)) {
diff --git a/src/drivers/ao_vga.c b/src/drivers/ao_vga.c
index 0e9c6706..00574b40 100644
--- a/src/drivers/ao_vga.c
+++ b/src/drivers/ao_vga.c
@@ -17,55 +17,52 @@
/* VGA output from the SPI port */
-struct ao_modeline {
- long dot_clock; /* in Hz */
-
- /* All timings are in pixels, with the first pixel out at 0,0 */
- int hactive; /* active pixels */
- int hsync_start; /* start of hsync pulse */
- int hsync_end; /* end of hsync pulse */
- int htotal; /* total h pixels */
-
- int vactive; /* active scalines */
- int vsync_start; /* start of vsync pulse */
- int vsync_end; /* end of vsync pulse */
- int vtotal; /* total scanlines */
-};
-
-const struct ao_modeline vga_640x480x60 = {
- .dot_clock = 23856000, /* 23.86MHz dot, 29.82kHz line, 60.00Hz frame */
-
- .hactive = 640,
- .hsync_start = 656,
- .hsync_end = 720,
- .htotal = 800,
+/* GRF formula for 640x480 yields a pixel clock very close to 24MHz. Pad by
+ * three scanlines to hit exactly that value
+ */
- .vactive = 480,
- .vsync_start = 481,
- .vsync_end = 484,
- .vtotal = 497
-};
+#define HACTIVE 640
+#define HSYNC_START 656
+#define HSYNC_END 720
+#define HTOTAL 800
-const struct ao_modeline vga_640x480x30 = {
- .dot_clock = 120000000, /* 12.00MHz dot, 29.82kHz line, 30.00Hz frame */
+#define VACTIVE 480
+#define VSYNC_START 481
+#define VSYNC_END 484
+#define VTOTAL 500
- .hactive = 640,
- .hsync_start = 656,
- .hsync_end = 720,
- .htotal = 800,
+/*
+ * The horizontal counter is set so that the end of hsync is reached
+ * at the maximum counter value. That means that the hblank interval
+ * is offset by HSYNC_END. We send 16 bits of zeros (which looks like
+ * 32 pixels), so the start is offset by this much
+ */
- .vactive = 480,
- .vsync_start = 490,
- .vsync_end = 492,
- .vtotal = 525,
-};
+#define HSYNC (HSYNC_END - HSYNC_START)
+#define HBLANK_END (HTOTAL - HSYNC_END)
+#define HBLANK_START (HBLANK_END + HACTIVE + 32)
-#define mode vga_640x480x60
+/*
+ * The vertical counter is set so that the end of vsync is reached at
+ * the maximum counter value. That means that the vblank interval is
+ * offset by VSYNC_END. We send a blank line at the start of the
+ * frame, so each of these is off by one
+ */
+#define VSYNC (VSYNC_END - VSYNC_START)
+#define VBLANK_END (VTOTAL - VSYNC_END - 1)
+#define VBLANK_START (VBLANK_END + VACTIVE + 1)
#define WIDTH_BYTES (AO_VGA_WIDTH >> 3)
#define SCANOUT ((WIDTH_BYTES+2) >> 1)
-uint32_t ao_vga_fb[AO_VGA_STRIDE * AO_VGA_HEIGHT];
+uint32_t ao_vga_fb_all[AO_VGA_STRIDE * (AO_VGA_HEIGHT + AO_VGA_VPAD)];
+
+const struct ao_bitmap ao_vga_bitmap = {
+ .base = ao_vga_fb,
+ .stride = AO_VGA_STRIDE,
+ .width = AO_VGA_WIDTH,
+ .height = AO_VGA_HEIGHT
+};
static uint32_t *scanline;
@@ -85,7 +82,6 @@ static int vblank;
(0 << STM_DMA_CCR_TCIE) | \
(en << STM_DMA_CCR_EN))
-int vblank_off = 25;
void stm_tim2_isr(void)
{
@@ -100,75 +96,17 @@ void stm_tim2_isr(void)
}
stm_tim2.sr = ~(1 << STM_TIM234_SR_CC2IF);
line = stm_tim3.cnt;
- if (vblank_off <= line && line < ((AO_VGA_HEIGHT-1) << 1) + vblank_off) {
+
+ if (VBLANK_END <= line && line < VBLANK_START) {
vblank = 0;
- if (((line - vblank_off) & 1) == 0)
+ if (((line - VBLANK_END) & 1))
scanline += AO_VGA_STRIDE;
- } else {
- if (!vblank) {
-// stm_systick_isr();
- scanline = ao_vga_fb;
- vblank = 1;
- }
+ } else if (!vblank) {
+ scanline = ao_vga_fb_all;
+ vblank = 1;
}
}
-static void
-ao_vga_fb_init(void)
-{
- ao_solid(0x0, AO_ALLONES,
- ao_vga_fb,
- AO_VGA_STRIDE,
- 0,
- AO_VGA_WIDTH,
- AO_VGA_HEIGHT);
-
- ao_solid(0x0, 0x0,
- ao_vga_fb + 10 * AO_VGA_STRIDE,
- AO_VGA_STRIDE,
- 10,
- 10,
- 10);
-
-
- ao_solid(0x0, 0x0,
- ao_vga_fb + 220 * AO_VGA_STRIDE,
- AO_VGA_STRIDE,
- 10,
- 10,
- 10);
-
- ao_solid(0x0, 0x0,
- ao_vga_fb + 10 * AO_VGA_STRIDE,
- AO_VGA_STRIDE,
- 220,
- 10,
- 10);
-
- ao_solid(0x0, 0x0,
- ao_vga_fb + 220 * AO_VGA_STRIDE,
- AO_VGA_STRIDE,
- 220,
- 10,
- 10);
-
- ao_text("Hello, Bdale!",
- ao_vga_fb + 100 * AO_VGA_STRIDE,
- AO_VGA_STRIDE,
- 20);
-
- ao_text("UL",
- ao_vga_fb,
- AO_VGA_STRIDE,
- 1);
-
- ao_text("BL",
- ao_vga_fb + (240 - 7) * AO_VGA_STRIDE,
- AO_VGA_STRIDE,
- 1);
-
- memset(ao_vga_fb + 120 * AO_VGA_STRIDE, '\0', WIDTH_BYTES);
-}
void
ao_vga_init(void)
@@ -210,26 +148,28 @@ ao_vga_init(void)
stm_dma.channel[DMA_INDEX].cpar = &stm_spi1.dr;
stm_dma.channel[DMA_INDEX].cmar = ao_vga_fb;
- /* hclock on timer 2 */
-
+ /*
+ * Hsync Configuration
+ */
/* Turn on timer 2 */
stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM2EN);
- /* Turn on GPIOA */
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
-
+ /* tim2 runs at full speed */
stm_tim2.psc = 0;
/* Disable channels while modifying */
stm_tim2.ccer = 0;
/* Channel 1 hsync PWM values */
- stm_tim2.ccr1 = mode.hsync_end - mode.hsync_start;
+ stm_tim2.ccr1 = HSYNC;
/* Channel 2 trigger scanout */
/* wait for the time to start scanout */
- stm_tim2.ccr2 = mode.htotal - mode.hsync_end;
+ stm_tim2.ccr2 = HBLANK_END - 10;
+ /* Configure channel 1 to output on the pin and
+ * channel 2 to to set the trigger for the vsync timer
+ */
stm_tim2.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) |
(STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH << STM_TIM234_CCMR1_OC2M) |
(1 << STM_TIM234_CCMR1_OC2PE) |
@@ -241,7 +181,9 @@ ao_vga_init(void)
(0 << STM_TIM234_CCMR1_OC1FE) |
(STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S));
- stm_tim2.arr = mode.htotal;
+ /* One scanline */
+ stm_tim2.arr = HTOTAL;
+
stm_tim2.cnt = 0;
/* Update the register contents */
@@ -258,8 +200,10 @@ ao_vga_init(void)
(STM_TIM234_CR2_MMS_UPDATE << STM_TIM234_CR2_MMS) |
(0 << STM_TIM234_CR2_CCDS));
+ /* hsync is not a slave timer */
stm_tim2.smcr = 0;
+ /* Send an interrupt on channel 2 */
stm_tim2.dier = ((1 << STM_TIM234_DIER_CC2IE));
stm_tim2.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) |
@@ -271,26 +215,24 @@ ao_vga_init(void)
(0 << STM_TIM234_CR1_UDIS) |
(0 << STM_TIM234_CR1_CEN));
- /* Configure pins */
-
- /* PA5 is Timer 2 CH1 output */
+ /* Hsync is on PA5 which is Timer 2 CH1 output */
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
stm_ospeedr_set(&stm_gpioa, 5, STM_OSPEEDR_40MHz);
stm_afr_set(&stm_gpioa, 5, STM_AFR_AF1);
- /* Turn on timer 3, slaved to timer 1 using ITR1 (table 61) */
-
- /* Use CH1 on PB6 (AF2) */
+ /*
+ * Vsync configuration
+ */
+ /* Turn on timer 3, slaved to timer 1 using ITR1 (table 61) */
stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM3EN);
- /* Turn on GPIOB */
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
-
/* No prescale */
stm_tim3.psc = 0;
/* Channel 1 vsync PWM values */
- stm_tim3.ccr1 = mode.vsync_end - mode.vsync_start;
+ stm_tim3.ccr1 = VSYNC;
+
stm_tim3.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) |
(0 << STM_TIM234_CCMR1_OC2PE) |
(0 << STM_TIM234_CCMR1_OC2FE) |
@@ -301,7 +243,7 @@ ao_vga_init(void)
(0 << STM_TIM234_CCMR1_OC1FE) |
(STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S));
- stm_tim3.arr = mode.vtotal;
+ stm_tim3.arr = VTOTAL;
stm_tim3.cnt = 0;
/* Update the register contents */
@@ -339,27 +281,32 @@ ao_vga_init(void)
(0 << STM_TIM234_CR1_UDIS) |
(1 << STM_TIM234_CR1_CEN));
- /* Configure pins */
-
- /* PB4 is Timer 3 CH1 output */
+ /* Vsync is on PB4 which is is Timer 3 CH1 output */
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
stm_ospeedr_set(&stm_gpiob, 4, STM_OSPEEDR_40MHz);
stm_afr_set(&stm_gpiob, 4, STM_AFR_AF2);
/* Enable the scanline interrupt */
- stm_nvic_set_priority(STM_ISR_TIM2_POS, 0);
+ stm_nvic_set_priority(STM_ISR_TIM2_POS, AO_STM_NVIC_NON_MASK_PRIORITY);
stm_nvic_set_enable(STM_ISR_TIM2_POS);
}
+uint8_t enabled;
+
void
ao_vga_enable(int enable)
{
if (enable) {
- vblank_off = enable;
- ao_vga_fb_init();
+ if (!enabled) {
+ ++ao_task_minimize_latency;
+ enabled = 1;
+ }
stm_tim2.cr1 |= (1 << STM_TIM234_CR1_CEN);
-// stm_systick.csr &= ~(1 << STM_SYSTICK_CSR_ENABLE);
} else {
+ if (enabled) {
+ --ao_task_minimize_latency;
+ enabled = 0;
+ }
stm_tim2.cr1 &= ~(1 << STM_TIM234_CR1_CEN);
-// stm_systick.csr |= (1 << STM_SYSTICK_CSR_ENABLE);
}
}
diff --git a/src/drivers/ao_vga.h b/src/drivers/ao_vga.h
index caec8f48..31b3a4f7 100644
--- a/src/drivers/ao_vga.h
+++ b/src/drivers/ao_vga.h
@@ -23,11 +23,22 @@ ao_vga_init(void);
void
ao_vga_enable(int active);
+/* Active frame buffer */
#define AO_VGA_WIDTH 320
#define AO_VGA_HEIGHT 240
-#define AO_VGA_PAD 64
-#define AO_VGA_STRIDE ((AO_VGA_WIDTH + AO_VGA_PAD) >> AO_SHIFT)
-extern uint32_t ao_vga_fb[AO_VGA_STRIDE * AO_VGA_HEIGHT];
+/* Pad on the right so that there are zeros on the output after the line */
+#define AO_VGA_HPAD 64
+
+/* Pad above so there's a scanline of zeros before the screen starts */
+#define AO_VGA_VPAD 1
+
+#define AO_VGA_STRIDE ((AO_VGA_WIDTH + AO_VGA_HPAD) >> AO_SHIFT)
+
+extern uint32_t ao_vga_fb_all[AO_VGA_STRIDE * (AO_VGA_HEIGHT + AO_VGA_VPAD)];
+
+#define ao_vga_fb (ao_vga_fb_all + AO_VGA_STRIDE)
+
+extern const struct ao_bitmap ao_vga_bitmap;
#endif /* _AO_VGA_H_ */
diff --git a/src/stm-vga/Makefile b/src/stm-vga/Makefile
index 5db8c641..2a600330 100644
--- a/src/stm-vga/Makefile
+++ b/src/stm-vga/Makefile
@@ -14,6 +14,7 @@ INC = \
ao_product.h \
ao_vga.h \
ao_draw.h \
+ ao_draw_int.h \
ao_font.h
#
@@ -32,16 +33,19 @@ ALTOS_SRC = \
ao_timer.c \
ao_lcd_stm.c \
ao_lcd_font.c \
+ ao_vga.c \
ao_blt.c \
+ ao_copy.c \
+ ao_rect.c \
ao_text.c \
+ ao_line.c \
ao_mutex.c \
ao_dma_stm.c \
ao_adc_stm.c \
ao_data.c \
ao_i2c_stm.c \
ao_usb_stm.c \
- ao_exti_stm.c \
- ao_vga.c
+ ao_exti_stm.c
PRODUCT=StmVga-v0.0
IDPRODUCT=0x000a
diff --git a/src/stm-vga/ao_demo.c b/src/stm-vga/ao_demo.c
index 3b582cc2..eaeaf070 100644
--- a/src/stm-vga/ao_demo.c
+++ b/src/stm-vga/ao_demo.c
@@ -46,21 +46,33 @@ ao_ball(void)
while (!ball_enable)
ao_sleep(&ball_enable);
for (;;) {
- ao_solid(AO_ALLONES,
- AO_ALLONES,
- ao_vga_fb + ball_y * AO_VGA_STRIDE,
- AO_VGA_STRIDE,
- ball_x,
- BALL_WIDTH,
- BALL_HEIGHT);
+ ao_line(&ao_vga_bitmap,
+ -100, -100, ball_x*2, ball_y*2,
+ 1, AO_XOR);
+ ao_text(&ao_vga_bitmap,
+ ball_x, ball_y - 10,
+ "Hello, Bdale!",
+ 1, AO_XOR);
+ ao_rect(&ao_vga_bitmap,
+ ball_x, ball_y,
+ BALL_WIDTH,
+ BALL_HEIGHT,
+ 1,
+ AO_XOR);
ao_delay(AO_MS_TO_TICKS(10));
- ao_solid(AO_ALLONES,
- AO_ALLONES,
- ao_vga_fb + ball_y * AO_VGA_STRIDE,
- AO_VGA_STRIDE,
- ball_x,
- BALL_WIDTH,
- BALL_HEIGHT);
+ ao_rect(&ao_vga_bitmap,
+ ball_x, ball_y,
+ BALL_WIDTH,
+ BALL_HEIGHT,
+ 1,
+ AO_XOR);
+ ao_text(&ao_vga_bitmap,
+ ball_x, ball_y - 10,
+ "Hello, Bdale!",
+ 1, AO_XOR);
+ ao_line(&ao_vga_bitmap,
+ -100, -100, ball_x*2, ball_y*2,
+ 1, AO_XOR);
if (!ball_enable)
break;
ball_x += ball_dx;
@@ -86,9 +98,50 @@ ao_ball(void)
}
static void
+ao_fb_init(void)
+{
+ ao_rect(&ao_vga_bitmap,
+ 0, 0, AO_VGA_WIDTH, AO_VGA_HEIGHT,
+ 1, AO_COPY);
+
+ ao_rect(&ao_vga_bitmap,
+ 10, 10, 10, 10,
+ 0, AO_COPY);
+
+ ao_rect(&ao_vga_bitmap,
+ AO_VGA_WIDTH - 20, 10, 10, 10,
+ 0, AO_COPY);
+
+ ao_rect(&ao_vga_bitmap,
+ 10, AO_VGA_HEIGHT - 20, 10, 10,
+ 0, AO_COPY);
+
+ ao_rect(&ao_vga_bitmap,
+ AO_VGA_WIDTH - 20, AO_VGA_HEIGHT - 20, 10, 10,
+ 0, AO_COPY);
+
+ ao_text(&ao_vga_bitmap,
+ 20, 100,
+ "Hello, Bdale!",
+ 0, AO_COPY);
+
+ ao_text(&ao_vga_bitmap,
+ 1, ao_font.ascent,
+ "UL",
+ 0, AO_COPY);
+
+ ao_text(&ao_vga_bitmap,
+ 1, AO_VGA_HEIGHT - ao_font.descent,
+ "BL",
+ 0, AO_COPY);
+}
+
+static void
ao_video_toggle(void)
{
ao_cmd_decimal();
+ if (ao_cmd_lex_i)
+ ao_fb_init();
ao_vga_enable(ao_cmd_lex_i);
}
diff --git a/src/stm-vga/ao_pins.h b/src/stm-vga/ao_pins.h
index 0e5a1903..f543ef53 100644
--- a/src/stm-vga/ao_pins.h
+++ b/src/stm-vga/ao_pins.h
@@ -68,6 +68,7 @@
#define HAS_USB 1
#define HAS_BEEP 0
#define PACKET_HAS_SLAVE 0
+#define HAS_TASK_QUEUE 1
#define STM_DMA1_3_STOLEN 1