From c5734e9e38bc583aff305e3c534cfb8b9088bc71 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 20 Nov 2016 21:02:59 -0800 Subject: [PATCH] altos/draw: Add a reasonable API for drawing, add lines. Also, move the demo drawing into the stm-vga app and out of the vga driver. Signed-off-by: Keith Packard --- src/draw/ao_blt.c | 1 + src/draw/ao_copy.c | 75 +++++++++++++++ src/draw/ao_draw.h | 137 +++++++++++--------------- src/draw/ao_draw_int.h | 128 +++++++++++++++++++++++++ src/draw/ao_font.h | 138 --------------------------- src/draw/ao_line.c | 164 ++++++++++++++++++++++++++++++++ src/draw/ao_rect.c | 55 +++++++++++ src/draw/ao_text.c | 51 +++++++--- src/draw/font-convert | 20 +++- src/drivers/ao_vga.c | 211 +++++++++++++++-------------------------- src/drivers/ao_vga.h | 17 +++- src/stm-vga/Makefile | 8 +- src/stm-vga/ao_demo.c | 81 +++++++++++++--- src/stm-vga/ao_pins.h | 1 + 14 files changed, 698 insertions(+), 389 deletions(-) create mode 100644 src/draw/ao_copy.c create mode 100644 src/draw/ao_draw_int.h delete mode 100644 src/draw/ao_font.h create mode 100644 src/draw/ao_line.c create mode 100644 src/draw/ao_rect.c 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 + * + * 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 + * + * 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 + * + * 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 + * + * 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; @@ -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); } 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 -- 2.30.2