altos/draw: Add a reasonable API for drawing, add lines. lisp
authorKeith Packard <keithp@keithp.com>
Mon, 21 Nov 2016 05:02:59 +0000 (21:02 -0800)
committerKeith Packard <keithp@keithp.com>
Mon, 21 Nov 2016 05:02:59 +0000 (21:02 -0800)
Also, move the demo drawing into the stm-vga app and out of the vga
driver.

Signed-off-by: Keith Packard <keithp@keithp.com>
14 files changed:
src/draw/ao_blt.c
src/draw/ao_copy.c [new file with mode: 0644]
src/draw/ao_draw.h
src/draw/ao_draw_int.h [new file with mode: 0644]
src/draw/ao_font.h [deleted file]
src/draw/ao_line.c [new file with mode: 0644]
src/draw/ao_rect.c [new file with mode: 0644]
src/draw/ao_text.c
src/draw/font-convert
src/drivers/ao_vga.c
src/drivers/ao_vga.h
src/stm-vga/Makefile
src/stm-vga/ao_demo.c
src/stm-vga/ao_pins.h

index 2060f00756c6a5adde1f919b6179b92ae909e475..e3f45221c9091612d2de59daf5d8e0ccc716aa20 100644 (file)
@@ -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 (file)
index 0000000..47067bb
--- /dev/null
@@ -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);
+       }
+}
+
index 1ff3e748a923b529f17eb4578f9241d9bb587372..f7dc75bf5f671c4015e2ab1fc64e71bb8bf82fee 100644 (file)
 #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 (file)
index 0000000..6980147
--- /dev/null
@@ -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 (file)
index ac424ef..0000000
+++ /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 (file)
index 0000000..b427892
--- /dev/null
@@ -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 (file)
index 0000000..fee7bbd
--- /dev/null
@@ -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);
+       }
+}
+
index 68d6c2cfd7f6817b08d7087a6fbd95d4f737f737..18e3924d823b51a8641094a6c03c77d3feac8893 100644 (file)
 
 #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;
        }
 }
index 2446592b34698ef51400162ba47c0ecd597f06d9..80297cf98883e077fd3cc87563c372b573c4c329 100755 (executable)
@@ -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)) {
index 0e9c6706996244d8d248360580b4aa003f17bbc4..00574b4009e764b623886414f1579fffea3721de 100644 (file)
 
 /* 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);
        }
 }
index caec8f481c802a36522c2c9a71c9dc9b692b2266..31b3a4f7491399f1f486fdd1248b72c905465270 100644 (file)
@@ -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_ */
index 5db8c64110cf7154dcb131ce87c1ea222e108ec4..2a600330f024193b4f66c3c6a3795b6f3321ede5 100644 (file)
@@ -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
index 3b582cc2ec41dfc46357e24f38942d4b16efe503..eaeaf0708a2cdeed79760bd6a12eb88696c31555 100644 (file)
@@ -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;
@@ -85,10 +97,51 @@ 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);
 }
 
index 0e5a1903a235f713a6f32aaa32b557ddc31082db..f543ef5342177940a30553aa1b6804543e5090e8 100644 (file)
@@ -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