summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-11-20 00:04:27 -0800
committerKeith Packard <keithp@keithp.com>2016-11-20 00:04:27 -0800
commite6518cf1ddfc087ca25fa1494f993ce03e43e138 (patch)
tree8351ae428fcfcc70c210803eba8bc4fb912b8302
parent86f1c4b04946956f40755286bd9554828d5c8728 (diff)
altos/stm-vga: Implement VGA out from the STM processor
Generates vsync/hsync using timers and pixel data using the SPI port. 320x240 video using 640x480 mode and a 24MHz "pixel" clock. Includes the beginings of rendering code for the frame buffer, including bitblt, solid fill and text with a 5x7 font. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--src/draw/5x7.bdf3190
-rw-r--r--src/draw/Makefile4
-rw-r--r--src/draw/ao_blt.c293
-rw-r--r--src/draw/ao_draw.h129
-rw-r--r--src/draw/ao_font.h138
-rw-r--r--src/draw/ao_text.c44
-rwxr-xr-xsrc/draw/font-convert138
-rw-r--r--src/drivers/ao_vga.c363
-rw-r--r--src/drivers/ao_vga.h33
-rw-r--r--src/stm-vga/Makefile76
-rw-r--r--src/stm-vga/ao_demo.c59
-rw-r--r--src/stm-vga/ao_pins.h205
-rw-r--r--src/stm/Makefile.defs4
-rw-r--r--src/stm/ao_dma_stm.c27
-rw-r--r--src/stm/ao_i2c_stm.c3
-rw-r--r--src/stm/ao_timer.c28
-rw-r--r--src/stm/stm32l.h15
17 files changed, 4731 insertions, 18 deletions
diff --git a/src/draw/5x7.bdf b/src/draw/5x7.bdf
new file mode 100644
index 00000000..b511f289
--- /dev/null
+++ b/src/draw/5x7.bdf
@@ -0,0 +1,3190 @@
+STARTFONT 2.1
+COMMENT Copyright 1991 Massachusetts Institute of Technology
+COMMENT
+COMMENT Permission to use, copy, modify, and distribute this software
+COMMENT and its documentation for any purpose and without fee is
+COMMENT hereby granted, provided that the above copyright notice
+COMMENT appear in all copies and that both that copyright notice and
+COMMENT this permission notice appear in supporting documentation,
+COMMENT and that the name of M.I.T. not be used in advertising or
+COMMENT publicity pertaining to distribution of the software without
+COMMENT specific, written prior permission. M.I.T. makes no
+COMMENT representations about the suitability of this software for
+COMMENT any purpose. It is provided "as is" without express or
+COMMENT implied warranty.
+COMMENT
+COMMENT M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+COMMENT INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+COMMENT FITNESS, IN NO EVENT SHALL M.I.T. BE LIABLE FOR ANY SPECIAL,
+COMMENT INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+COMMENT RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+COMMENT ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+COMMENT ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+COMMENT OF THIS SOFTWARE.
+COMMENT
+COMMENT Author: Stephen Gildea, MIT X Consortium, June 1991
+COMMENT
+FONT -Misc-Fixed-Medium-R-Normal--7-70-75-75-C-50-ISO8859-1
+SIZE 7 75 75
+FONTBOUNDINGBOX 5 7 0 -1
+STARTPROPERTIES 21
+FONTNAME_REGISTRY ""
+FOUNDRY "Misc"
+FAMILY_NAME "Fixed"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 7
+POINT_SIZE 70
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 50
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+FONT_ASCENT 6
+FONT_DESCENT 1
+UNDERLINE_POSITION 0
+DESTINATION 1
+DEFAULT_CHAR 0
+COPYRIGHT "Copyright 1991 Massachusetts Institute of Technology"
+ENDPROPERTIES
+CHARS 224
+STARTCHAR C000
+ENCODING 0
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+f0
+f0
+f0
+f0
+f0
+00
+ENDCHAR
+STARTCHAR C001
+ENCODING 1
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+70
+f8
+70
+20
+00
+ENDCHAR
+STARTCHAR C002
+ENCODING 2
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+50
+a0
+50
+a0
+00
+ENDCHAR
+STARTCHAR C003
+ENCODING 3
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+e0
+a0
+a0
+70
+20
+20
+ENDCHAR
+STARTCHAR C004
+ENCODING 4
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+80
+c0
+b0
+20
+30
+20
+ENDCHAR
+STARTCHAR C005
+ENCODING 5
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+80
+c0
+60
+50
+60
+50
+ENDCHAR
+STARTCHAR C006
+ENCODING 6
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+c0
+30
+20
+30
+20
+ENDCHAR
+STARTCHAR C007
+ENCODING 7
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+50
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C010
+ENCODING 8
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+70
+20
+00
+70
+00
+00
+ENDCHAR
+STARTCHAR C011
+ENCODING 9
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+d0
+b0
+90
+20
+20
+30
+ENDCHAR
+STARTCHAR C012
+ENCODING 10
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+a0
+a0
+40
+70
+20
+20
+ENDCHAR
+STARTCHAR C013
+ENCODING 11
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+e0
+00
+00
+00
+ENDCHAR
+STARTCHAR C014
+ENCODING 12
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+e0
+20
+20
+20
+ENDCHAR
+STARTCHAR C015
+ENCODING 13
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+38
+20
+20
+20
+ENDCHAR
+STARTCHAR C016
+ENCODING 14
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR C017
+ENCODING 15
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+f8
+20
+20
+20
+ENDCHAR
+STARTCHAR C020
+ENCODING 16
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+f8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C021
+ENCODING 17
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 6 7 0 -1
+BITMAP
+00
+00
+f8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C022
+ENCODING 18
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+f8
+00
+00
+00
+ENDCHAR
+STARTCHAR C023
+ENCODING 19
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+f8
+00
+00
+ENDCHAR
+STARTCHAR C024
+ENCODING 20
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+f8
+00
+ENDCHAR
+STARTCHAR C025
+ENCODING 21
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+38
+20
+20
+20
+ENDCHAR
+STARTCHAR C026
+ENCODING 22
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+e0
+20
+20
+20
+ENDCHAR
+STARTCHAR C027
+ENCODING 23
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 6 7 0 -1
+BITMAP
+20
+20
+20
+f8
+00
+00
+00
+ENDCHAR
+STARTCHAR C030
+ENCODING 24
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+f8
+20
+20
+20
+ENDCHAR
+STARTCHAR C031
+ENCODING 25
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR C032
+ENCODING 26
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+10
+20
+40
+20
+10
+70
+00
+ENDCHAR
+STARTCHAR C033
+ENCODING 27
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+10
+20
+40
+70
+00
+ENDCHAR
+STARTCHAR C034
+ENCODING 28
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+50
+50
+50
+00
+ENDCHAR
+STARTCHAR C035
+ENCODING 29
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+10
+70
+20
+70
+40
+00
+ENDCHAR
+STARTCHAR C036
+ENCODING 30
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+30
+40
+e0
+40
+b0
+00
+ENDCHAR
+STARTCHAR C037
+ENCODING 31
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR C040
+ENCODING 32
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR !
+ENCODING 33
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+20
+20
+00
+20
+00
+ENDCHAR
+STARTCHAR "
+ENCODING 34
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+50
+50
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR #
+ENCODING 35
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+50
+f8
+50
+f8
+50
+00
+ENDCHAR
+STARTCHAR $
+ENCODING 36
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+70
+a0
+70
+28
+70
+00
+ENDCHAR
+STARTCHAR %
+ENCODING 37
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+90
+20
+40
+90
+10
+00
+ENDCHAR
+STARTCHAR &
+ENCODING 38
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+40
+a0
+40
+a0
+50
+00
+ENDCHAR
+STARTCHAR '
+ENCODING 39
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+40
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR (
+ENCODING 40
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR )
+ENCODING 41
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR *
+ENCODING 42
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+a0
+40
+e0
+40
+a0
+00
+ENDCHAR
+STARTCHAR +
+ENCODING 43
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+20
+f8
+20
+20
+00
+ENDCHAR
+STARTCHAR ,
+ENCODING 44
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+60
+40
+80
+ENDCHAR
+STARTCHAR -
+ENCODING 45
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+f0
+00
+00
+00
+ENDCHAR
+STARTCHAR .
+ENCODING 46
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+60
+60
+00
+ENDCHAR
+STARTCHAR /
+ENCODING 47
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+10
+20
+40
+80
+00
+00
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+a0
+a0
+a0
+40
+00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+c0
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+10
+20
+40
+f0
+00
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+10
+60
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+60
+a0
+f0
+20
+20
+00
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+80
+e0
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+10
+20
+20
+40
+40
+00
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+70
+10
+60
+00
+ENDCHAR
+STARTCHAR :
+ENCODING 58
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+60
+60
+00
+60
+60
+00
+ENDCHAR
+STARTCHAR ;
+ENCODING 59
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+60
+60
+00
+60
+40
+80
+ENDCHAR
+STARTCHAR <
+ENCODING 60
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+40
+80
+40
+20
+00
+ENDCHAR
+STARTCHAR =
+ENCODING 61
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+f0
+00
+f0
+00
+00
+ENDCHAR
+STARTCHAR >
+ENCODING 62
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+80
+40
+20
+40
+80
+00
+ENDCHAR
+STARTCHAR ?
+ENCODING 63
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+20
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR @
+ENCODING 64
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+b0
+b0
+80
+60
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+90
+e0
+90
+90
+e0
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+80
+80
+90
+60
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+90
+90
+90
+90
+e0
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+80
+b0
+90
+70
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+f0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+10
+10
+10
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+a0
+c0
+c0
+a0
+90
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+80
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+f0
+f0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+d0
+d0
+b0
+b0
+90
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+90
+90
+e0
+80
+80
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+d0
+60
+10
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+90
+90
+e0
+a0
+90
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+40
+20
+90
+60
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+60
+60
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+f0
+f0
+90
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+60
+60
+90
+90
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+a0
+a0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+10
+20
+40
+80
+f0
+00
+ENDCHAR
+STARTCHAR [
+ENCODING 91
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+80
+80
+80
+80
+e0
+00
+ENDCHAR
+STARTCHAR \
+ENCODING 92
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+80
+40
+20
+10
+00
+00
+ENDCHAR
+STARTCHAR ]
+ENCODING 93
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+20
+20
+20
+20
+e0
+00
+ENDCHAR
+STARTCHAR ^
+ENCODING 94
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR _
+ENCODING 95
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+f0
+00
+ENDCHAR
+STARTCHAR `
+ENCODING 96
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+40
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+e0
+90
+90
+e0
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+60
+80
+80
+60
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+10
+10
+70
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+50
+40
+e0
+40
+40
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+90
+60
+80
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+e0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+00
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+00
+20
+20
+20
+a0
+40
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+a0
+c0
+a0
+90
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+a0
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+e0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+e0
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+90
+90
+70
+10
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+e0
+90
+80
+80
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 6 7 0 -1
+BITMAP
+00
+00
+70
+c0
+30
+e0
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+40
+e0
+40
+40
+30
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+a0
+a0
+a0
+40
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+90
+f0
+f0
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+90
+50
+20
+40
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+f0
+20
+40
+f0
+00
+ENDCHAR
+STARTCHAR {
+ENCODING 123
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+c0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR |
+ENCODING 124
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR }
+ENCODING 125
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 6 7 0 -1
+BITMAP
+80
+40
+60
+40
+40
+80
+00
+ENDCHAR
+STARTCHAR ~
+ENCODING 126
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Blank
+ENCODING 127
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C160
+ENCODING 160
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C161
+ENCODING 161
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+00
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR C162
+ENCODING 162
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+70
+a0
+a0
+70
+20
+ENDCHAR
+STARTCHAR C163
+ENCODING 163
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+30
+40
+e0
+40
+b0
+00
+ENDCHAR
+STARTCHAR C164
+ENCODING 164
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+88
+70
+50
+70
+88
+00
+ENDCHAR
+STARTCHAR C165
+ENCODING 165
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+a0
+40
+e0
+40
+40
+00
+ENDCHAR
+STARTCHAR C166
+ENCODING 166
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+20
+20
+00
+20
+20
+00
+ENDCHAR
+STARTCHAR C167
+ENCODING 167
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+30
+40
+60
+50
+30
+10
+60
+ENDCHAR
+STARTCHAR C168
+ENCODING 168
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C169
+ENCODING 169
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+88
+a8
+c8
+a8
+88
+70
+ENDCHAR
+STARTCHAR C170
+ENCODING 170
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+a0
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C171
+ENCODING 171
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+48
+90
+48
+00
+00
+ENDCHAR
+STARTCHAR C172
+ENCODING 172
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+f0
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR C173
+ENCODING 173
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+f0
+00
+00
+00
+ENDCHAR
+STARTCHAR C174
+ENCODING 174
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+88
+e8
+c8
+c8
+88
+70
+ENDCHAR
+STARTCHAR C175
+ENCODING 175
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C176
+ENCODING 176
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+50
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C177
+ENCODING 177
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+20
+f8
+20
+20
+f8
+00
+ENDCHAR
+STARTCHAR C178
+ENCODING 178
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+20
+40
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR C179
+ENCODING 179
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+60
+20
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR C180
+ENCODING 180
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C181
+ENCODING 181
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR C182
+ENCODING 182
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+d0
+d0
+50
+50
+50
+00
+ENDCHAR
+STARTCHAR C183
+ENCODING 183
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C184
+ENCODING 184
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+00
+00
+00
+20
+40
+ENDCHAR
+STARTCHAR C185
+ENCODING 185
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+60
+20
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR C186
+ENCODING 186
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C187
+ENCODING 187
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+48
+90
+00
+00
+ENDCHAR
+STARTCHAR C188
+ENCODING 188
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+80
+90
+30
+70
+10
+ENDCHAR
+STARTCHAR C189
+ENCODING 189
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+80
+80
+b0
+10
+20
+30
+ENDCHAR
+STARTCHAR C190
+ENCODING 190
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+c0
+c0
+40
+d0
+30
+70
+10
+ENDCHAR
+STARTCHAR C191
+ENCODING 191
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+00
+40
+80
+a0
+40
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C193
+ENCODING 193
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C194
+ENCODING 194
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C195
+ENCODING 195
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C196
+ENCODING 196
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C197
+ENCODING 197
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+f0
+90
+90
+00
+ENDCHAR
+STARTCHAR C198
+ENCODING 198
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+a0
+b0
+e0
+a0
+b0
+00
+ENDCHAR
+STARTCHAR C199
+ENCODING 199
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+80
+80
+90
+60
+40
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR C201
+ENCODING 201
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR C202
+ENCODING 202
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR C203
+ENCODING 203
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+00
+ENDCHAR
+STARTCHAR C204
+ENCODING 204
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C205
+ENCODING 205
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C206
+ENCODING 206
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C207
+ENCODING 207
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+40
+40
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C208
+ENCODING 208
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+e0
+50
+d0
+50
+50
+e0
+00
+ENDCHAR
+STARTCHAR C209
+ENCODING 209
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+b0
+90
+d0
+b0
+b0
+90
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C211
+ENCODING 211
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C212
+ENCODING 212
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C213
+ENCODING 213
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C214
+ENCODING 214
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C215
+ENCODING 215
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR C216
+ENCODING 216
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+70
+b0
+b0
+d0
+d0
+e0
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C218
+ENCODING 218
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C219
+ENCODING 219
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C220
+ENCODING 220
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+90
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C221
+ENCODING 221
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+a0
+a0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR C222
+ENCODING 222
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+e0
+90
+e0
+80
+80
+00
+ENDCHAR
+STARTCHAR C223
+ENCODING 223
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+90
+e0
+90
+d0
+a0
+80
+ENDCHAR
+STARTCHAR a-grave
+ENCODING 224
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C225
+ENCODING 225
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C226
+ENCODING 226
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+50
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C227
+ENCODING 227
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C228
+ENCODING 228
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+00
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C229
+ENCODING 229
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+60
+70
+90
+b0
+50
+00
+ENDCHAR
+STARTCHAR C230
+ENCODING 230
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+b0
+a0
+70
+00
+ENDCHAR
+STARTCHAR C231
+ENCODING 231
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+60
+80
+80
+60
+40
+ENDCHAR
+STARTCHAR e-grave
+ENCODING 232
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR C233
+ENCODING 233
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR C234
+ENCODING 234
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR C235
+ENCODING 235
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+00
+60
+b0
+c0
+60
+00
+ENDCHAR
+STARTCHAR C236
+ENCODING 236
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+80
+40
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C237
+ENCODING 237
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+80
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C238
+ENCODING 238
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+a0
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C239
+ENCODING 239
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+00
+c0
+40
+40
+e0
+00
+ENDCHAR
+STARTCHAR C240
+ENCODING 240
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+30
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C241
+ENCODING 241
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+e0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR C242
+ENCODING 242
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C243
+ENCODING 243
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C244
+ENCODING 244
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C245
+ENCODING 245
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+a0
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C246
+ENCODING 246
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+a0
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR C247
+ENCODING 247
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+60
+00
+f0
+00
+60
+00
+ENDCHAR
+STARTCHAR C248
+ENCODING 248
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+00
+70
+b0
+d0
+e0
+00
+ENDCHAR
+STARTCHAR C249
+ENCODING 249
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+40
+20
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR C250
+ENCODING 250
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR C251
+ENCODING 251
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+60
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR C252
+ENCODING 252
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+00
+90
+90
+90
+70
+00
+ENDCHAR
+STARTCHAR C253
+ENCODING 253
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+20
+40
+90
+90
+50
+20
+40
+ENDCHAR
+STARTCHAR C254
+ENCODING 254
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+00
+80
+e0
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR C255
+ENCODING 255
+SWIDTH 686 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+50
+00
+90
+90
+50
+20
+40
+ENDCHAR
+ENDFONT
diff --git a/src/draw/Makefile b/src/draw/Makefile
new file mode 100644
index 00000000..0a542a1f
--- /dev/null
+++ b/src/draw/Makefile
@@ -0,0 +1,4 @@
+BDF=5x7.bdf
+
+ao_font.h: font-convert $(BDF)
+ nickle font-convert $(BDF) > $@
diff --git a/src/draw/ao_blt.c b/src/draw/ao_blt.c
new file mode 100644
index 00000000..2060f007
--- /dev/null
+++ b/src/draw/ao_blt.c
@@ -0,0 +1,293 @@
+/*
+ * 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"
+
+#define O 0
+#define I AO_ALLONES
+
+struct ao_merge_rop {
+ uint32_t ca1, cx1, ca2, cx2;
+};
+
+const struct ao_merge_rop ao_merge_rop[16] = {
+ {O, O, O, O}, /* clear 0x0 0 */
+ {I, O, O, O}, /* and 0x1 src AND dst */
+ {I, O, I, O}, /* andReverse 0x2 src AND NOT dst */
+ {O, O, I, O}, /* copy 0x3 src */
+ {I, I, O, O}, /* andInverted 0x4 NOT src AND dst */
+ {O, I, O, O}, /* noop 0x5 dst */
+ {O, I, I, O}, /* xor 0x6 src XOR dst */
+ {I, I, I, O}, /* or 0x7 src OR dst */
+ {I, I, I, I}, /* nor 0x8 NOT src AND NOT dst */
+ {O, I, I, I}, /* equiv 0x9 NOT src XOR dst */
+ {O, I, O, I}, /* invert 0xa NOT dst */
+ {I, I, O, I}, /* orReverse 0xb src OR NOT dst */
+ {O, O, I, I}, /* copyInverted 0xc NOT src */
+ {I, O, I, I}, /* orInverted 0xd NOT src OR dst */
+ {I, O, O, I}, /* nand 0xe NOT src OR NOT dst */
+ {O, O, O, I}, /* set 0xf 1 */
+};
+
+#define ao_do_merge_rop(src, dst) \
+ (((dst) & (((src) & _ca1) ^ _cx1)) ^ (((src) & _ca2) ^ _cx2))
+
+#define ao_do_dst_invarient_merge_rop(src) (((src) & _ca2) ^ _cx2)
+
+#define ao_do_mask_merge_rop(src, dst, mask) \
+ (((dst) & ((((src) & _ca1) ^ _cx1) | ~(mask))) ^ ((((src) & _ca2) ^ _cx2) & (mask)))
+
+#define ao_dst_invarient_merge_rop() (_ca1 == 0 && _cx1 == 0)
+
+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)
+{
+ uint32_t *src, *dst;
+ uint32_t _ca1, _cx1, _ca2, _cx2;
+ uint8_t dst_invarient;
+ uint32_t startmask, endmask;
+ int16_t nmiddle, n;
+ uint32_t bits1, bits;
+ int16_t left_shift, right_shift;
+
+ _ca1 = ao_merge_rop[rop].ca1;
+ _cx1 = ao_merge_rop[rop].cx1;
+ _ca2 = ao_merge_rop[rop].ca2;
+ _cx2 = ao_merge_rop[rop].cx2;
+ dst_invarient = ao_dst_invarient_merge_rop();
+
+ if (upsidedown) {
+ src_line += (height - 1) * src_stride;
+ dst_line += (height - 1) * dst_stride;
+ src_stride = -src_stride;
+ dst_stride = -dst_stride;
+ }
+
+ ao_mask_bits(dst_x, width, startmask, nmiddle, endmask);
+ if (reverse) {
+ src_line += ((src_x + width - 1) >> AO_SHIFT) + 1;
+ dst_line += ((dst_x + width - 1) >> AO_SHIFT) + 1;
+ src_x = (src_x + width - 1) & AO_MASK;
+ dst_x = (dst_x + width - 1) & AO_MASK;
+ } else {
+ src_line += src_x >> AO_SHIFT;
+ dst_line += dst_x >> AO_SHIFT;
+ src_x &= AO_MASK;
+ dst_x &= AO_MASK;
+ }
+ if (src_x == dst_x) {
+ while (height--) {
+ src = src_line;
+ src_line += src_stride;
+ dst = dst_line;
+ dst_line += dst_stride;
+ if (reverse) {
+ if (endmask) {
+ bits = *--src;
+ --dst;
+ *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
+ }
+ n = nmiddle;
+ if (dst_invarient) {
+ while (n--)
+ *--dst = ao_do_dst_invarient_merge_rop(*--src);
+ }
+ else {
+ while (n--) {
+ bits = *--src;
+ --dst;
+ *dst = ao_do_merge_rop(bits, *dst);
+ }
+ }
+ if (startmask) {
+ bits = *--src;
+ --dst;
+ *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
+ }
+ }
+ else {
+ if (startmask) {
+ bits = *src++;
+ *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
+ dst++;
+ }
+ n = nmiddle;
+ if (dst_invarient) {
+ while (n--)
+ *dst++ = ao_do_dst_invarient_merge_rop(*src++);
+ }
+ else {
+ while (n--) {
+ bits = *src++;
+ *dst = ao_do_merge_rop(bits, *dst);
+ dst++;
+ }
+ }
+ if (endmask) {
+ bits = *src;
+ *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
+ }
+ }
+ }
+ } else {
+ if (src_x > dst_x) {
+ left_shift = src_x - dst_x;
+ right_shift = AO_UNIT - left_shift;
+ } else {
+ right_shift = dst_x - src_x;
+ left_shift = AO_UNIT - right_shift;
+ }
+ while (height--) {
+ src = src_line;
+ src_line += src_stride;
+ dst = dst_line;
+ dst_line += dst_stride;
+
+ bits1 = 0;
+ if (reverse) {
+ if (src_x < dst_x)
+ bits1 = *--src;
+ if (endmask) {
+ bits = ao_right(bits1, right_shift);
+ if (ao_right(endmask, left_shift)) {
+ bits1 = *--src;
+ bits |= ao_left(bits1, left_shift);
+ }
+ --dst;
+ *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
+ }
+ n = nmiddle;
+ if (dst_invarient) {
+ while (n--) {
+ bits = ao_right(bits1, right_shift);
+ bits1 = *--src;
+ bits |= ao_left(bits1, left_shift);
+ --dst;
+ *dst = ao_do_dst_invarient_merge_rop(bits);
+ }
+ } else {
+ while (n--) {
+ bits = ao_right(bits1, right_shift);
+ bits1 = *--src;
+ bits |= ao_left(bits1, left_shift);
+ --dst;
+ *dst = ao_do_merge_rop(bits, *dst);
+ }
+ }
+ if (startmask) {
+ bits = ao_right(bits1, right_shift);
+ if (ao_right(startmask, left_shift)) {
+ bits1 = *--src;
+ bits |= ao_left(bits1, left_shift);
+ }
+ --dst;
+ *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
+ }
+ }
+ else {
+ if (src_x > dst_x)
+ bits1 = *src++;
+ if (startmask) {
+ bits = ao_left(bits1, left_shift);
+ if (ao_left(startmask, right_shift)) {
+ bits1 = *src++;
+ bits |= ao_right(bits1, right_shift);
+ }
+ *dst = ao_do_mask_merge_rop(bits, *dst, startmask);
+ dst++;
+ }
+ n = nmiddle;
+ if (dst_invarient) {
+ while (n--) {
+ bits = ao_left(bits1, left_shift);
+ bits1 = *src++;
+ bits |= ao_right(bits1, right_shift);
+ *dst = ao_do_dst_invarient_merge_rop(bits);
+ dst++;
+ }
+ }
+ else {
+ while (n--) {
+ bits = ao_left(bits1, left_shift);
+ bits1 = *src++;
+ bits |= ao_right(bits1, right_shift);
+ *dst = ao_do_merge_rop(bits, *dst);
+ dst++;
+ }
+ }
+ if (endmask) {
+ bits = ao_left(bits1, left_shift);
+ if (ao_left(endmask, right_shift)) {
+ bits1 = *src;
+ bits |= ao_right(bits1, right_shift);
+ }
+ *dst = ao_do_mask_merge_rop(bits, *dst, endmask);
+ }
+ }
+ }
+ }
+}
+
+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)
+{
+ uint32_t startmask, endmask;
+ int16_t nmiddle;
+ int16_t n;
+
+ dst += dst_x >> AO_SHIFT;
+ dst_x &= AO_MASK;
+
+ ao_mask_bits(dst_x, width, startmask, nmiddle, endmask);
+
+ if (startmask)
+ dst_stride--;
+
+ dst_stride -= nmiddle;
+ while (height--) {
+ if (startmask) {
+ *dst = ao_do_mask_rrop(*dst, and, xor, startmask);
+ dst++;
+ }
+ n = nmiddle;
+ if (!and)
+ while (n--)
+ *dst++ = xor;
+ else
+ while (n--) {
+ *dst = ao_do_rrop(*dst, and, xor);
+ dst++;
+ }
+ if (endmask)
+ *dst = ao_do_mask_rrop(*dst, and, xor, endmask);
+ dst += dst_stride;
+ }
+}
diff --git a/src/draw/ao_draw.h b/src/draw/ao_draw.h
new file mode 100644
index 00000000..1ff3e748
--- /dev/null
+++ b/src/draw/ao_draw.h
@@ -0,0 +1,129 @@
+/*
+ * 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_H_
+#define _AO_DRAW_H_
+
+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);
+
+void
+ao_text(char *string,
+ uint32_t *dst_line,
+ int16_t dst_stride,
+ int16_t dst_x);
+
+#define AO_ROP_CLEAR 0x0
+#define AO_ROP_COPY 0x3
+#define AO_ROP_SET 0xf
+
+#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;
+}
+
+#define AO_CLEAR 0x0 /* 0 */
+#define AO_AND 0x1 /* src AND dst */
+#define AO_AND_REVERSE 0x2 /* src AND NOT dst */
+#define AO_COPY 0x3 /* src */
+#define AO_AND_INVERTED 0x4 /* NOT src AND dst */
+#define AO_NOOP 0x5 /* dst */
+#define AO_XOR 0x6 /* src XOR dst */
+#define AO_OR 0x7 /* src OR dst */
+#define AO_NOR 0x8 /* NOT src AND NOT dst */
+#define AO_EQUIV 0x9 /* NOT src XOR dst */
+#define AO_INVERT 0xa /* NOT dst */
+#define AO_OR_REVERSE 0xb /* src OR NOT dst */
+#define AO_COPY_INVERTED 0xc /* NOT src */
+#define AO_OR_INVERTED 0xd /* NOT src OR dst */
+#define AO_NAND 0xe /* NOT src OR NOT dst */
+#define AO_SET 0xf /* 1 */
+
+#endif /* _AO_DRAW_H_ */
diff --git a/src/draw/ao_font.h b/src/draw/ao_font.h
new file mode 100644
index 00000000..ac424ef9
--- /dev/null
+++ b/src/draw/ao_font.h
@@ -0,0 +1,138 @@
+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_text.c b/src/draw/ao_text.c
new file mode 100644
index 00000000..68d6c2cf
--- /dev/null
+++ b/src/draw/ao_text.c
@@ -0,0 +1,44 @@
+/*
+ * 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_font.h"
+
+void
+ao_text(char *string,
+ uint32_t *dst_line,
+ int16_t dst_stride,
+ int16_t dst_x)
+{
+ char c;
+ uint32_t src[GLYPH_HEIGHT];
+
+ while ((c = *string++)) {
+ uint8_t *bytes = &glyph_bytes[glyph_pos[(uint8_t) c]];
+ int h;
+
+ 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;
+ }
+}
diff --git a/src/draw/font-convert b/src/draw/font-convert
new file mode 100755
index 00000000..2446592b
--- /dev/null
+++ b/src/draw/font-convert
@@ -0,0 +1,138 @@
+#!/usr/bin/nickle
+
+typedef struct {
+ int[] bytes;
+ int width;
+ int height;
+ int encoding;
+ int location;
+} glyph_t;
+
+typedef struct {
+ glyph_t[...] glyphs;
+ int default_char;
+} font_t;
+
+glyph_t
+read_glyph(file f)
+{
+ glyph_t glyph = { .encoding = -1, .bytes = (int[...]){}, .width = 0 };
+
+ while (!File::end(f)) {
+ string l = fgets(f);
+
+ string[*] tokens = String::split(l, " ");
+ if (dim(tokens) == 0)
+ continue;
+
+ switch (tokens[0]) {
+ case "ENCODING":
+ glyph.encoding = atoi(tokens[1]);
+ break;
+ case "BBX":
+ glyph.width = atoi(tokens[1]);
+ glyph.height = atoi(tokens[2]);
+ break;
+ case "ENDCHAR":
+ return glyph;
+ case "BITMAP":
+ while (!File::end(f)) {
+ string l = fgets(f);
+ if (l == "ENDCHAR")
+ return glyph;
+ glyph.bytes[dim(glyph.bytes)] = atoi(l, 16);
+ }
+ break;
+ }
+ }
+ return glyph;
+}
+
+font_t read_font(file f) {
+ font_t font = { .glyphs = {}, .default_char = -1 };
+
+ while (!File::end(f)) {
+ string l = File::fgets(f);
+
+ string[*] tokens = String::split(l, " ");
+ if (tokens[0] == "DEFAULT_CHAR")
+ font.default_char = atoi(tokens[1]);
+ if (tokens[0] == "CHARS")
+ break;
+ }
+ while (!File::end(f)) {
+ glyph_t glyph = read_glyph(f);
+ if (glyph.encoding == -1)
+ break;
+ font.glyphs[dim(font.glyphs)] = glyph;
+ }
+ return font;
+}
+
+int
+flip_byte(int x)
+{
+ int dest = 0;
+
+ for (int i = 0; i < 8; i++)
+ dest |= ((x >> (7 - i)) & 1) << i;
+ return dest;
+}
+
+void print_font(font_t font) {
+ int width = font.glyphs[0].width;
+ int height = font.glyphs[0].height;
+ int[256] pos = { -1 ... };
+ int[...] bytes;
+
+ if (false) {
+ for (int i = 1; i < dim(font.glyphs); i++) {
+ if (font.glyphs[i].width != width ||
+ font.glyphs[i].height != height)
+ {
+ File::fprintf(stderr, "font not constant size, glyph %d is %dx%d\n",
+ font.glyphs[i].encoding, font.glyphs[i].width, font.glyphs[i].height);
+ exit(1);
+ }
+ }
+ }
+
+ if (font.default_char == -1)
+ font.default_char = font.glyphs[0].encoding;
+
+ /* build byte array */
+ for (int i = 0; i < dim(font.glyphs); i++) {
+ pos[font.glyphs[i].encoding] = dim(bytes);
+ for (int b = 0; b < dim(font.glyphs[i].bytes); b++)
+ bytes[dim(bytes)] = font.glyphs[i].bytes[b];
+ }
+
+ /* Fill in default glyph */
+ for (int i = 0; i < dim(pos); i++)
+ if (pos[i] == -1)
+ pos[i] = pos[font.default_char];
+
+ printf("static uint8_t glyph_bytes[] = {");
+ for (int b = 0; b < dim(bytes); b++) {
+ if ((b & 15) == 0)
+ printf("\n\t");
+ printf("0x%02x, ", flip_byte(bytes[b]));
+ }
+ printf("\n};\n\n");
+
+ printf("static uint16_t glyph_pos[] = {");
+ for (int i = 0; i < dim(pos); i++) {
+ if ((i & 7) == 0)
+ printf("\n\t");
+ printf("%4d, ", pos[i]);
+ }
+ printf("\n};\n\n");
+
+ printf("#define GLYPH_WIDTH %d\n", width);
+ printf("#define GLYPH_HEIGHT %d\n", height);
+}
+
+twixt (file f = File::open(argv[1], "r"); File::close(f)) {
+ font_t font = read_font(f);
+ print_font(font);
+}
diff --git a/src/drivers/ao_vga.c b/src/drivers/ao_vga.c
new file mode 100644
index 00000000..24a645c7
--- /dev/null
+++ b/src/drivers/ao_vga.c
@@ -0,0 +1,363 @@
+/*
+ * 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_vga.h"
+
+/* 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,
+
+ .vactive = 480,
+ .vsync_start = 481,
+ .vsync_end = 484,
+ .vtotal = 497
+};
+
+const struct ao_modeline vga_640x480x30 = {
+ .dot_clock = 120000000, /* 12.00MHz dot, 29.82kHz line, 30.00Hz frame */
+
+ .hactive = 640,
+ .hsync_start = 656,
+ .hsync_end = 720,
+ .htotal = 800,
+
+ .vactive = 480,
+ .vsync_start = 481,
+ .vsync_end = 484,
+ .vtotal = 497
+};
+
+#define mode vga_640x480x60
+
+#define WIDTH_BYTES (AO_VGA_WIDTH >> 3)
+#define SCANOUT ((WIDTH_BYTES + 2) >> 1)
+
+uint32_t ao_vga_fb[AO_VGA_STRIDE * AO_VGA_HEIGHT];
+
+static uint32_t *scanline;
+
+#define DMA_INDEX STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX)
+
+static int line;
+static int vblank;
+
+#define DMA_CCR(en) ((0 << STM_DMA_CCR_MEM2MEM) | \
+ (STM_DMA_CCR_PL_VERY_HIGH << STM_DMA_CCR_PL) | \
+ (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) | \
+ (STM_DMA_CCR_PSIZE_16 << STM_DMA_CCR_PSIZE) | \
+ (1 << STM_DMA_CCR_MINC) | \
+ (0 << STM_DMA_CCR_PINC) | \
+ (0 << STM_DMA_CCR_CIRC) | \
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) | \
+ (0 << STM_DMA_CCR_TCIE) | \
+ (en << STM_DMA_CCR_EN))
+
+int vblank_off = 13;
+
+void stm_tim2_isr(void)
+{
+ ao_arch_block_interrupts();
+ if (!vblank) {
+ /* Disable */
+ stm_dma.channel[DMA_INDEX].ccr = DMA_CCR(0);
+ /* Reset DMA engine for the next scanline */
+ stm_dma.channel[DMA_INDEX].cndtr = SCANOUT;
+ /* Enable */
+ stm_dma.channel[DMA_INDEX].ccr = DMA_CCR(1);
+ }
+ stm_tim2.sr = ~(1 << STM_TIM234_SR_CC2IF);
+ line = stm_tim3.cnt;
+ if (vblank_off <= line && line < (AO_VGA_HEIGHT << 1) + vblank_off + 12) {
+ vblank = 0;
+ if ((line - vblank_off) & 1)
+ scanline += AO_VGA_STRIDE;
+ } else {
+ scanline = ao_vga_fb;
+ vblank = 1;
+ }
+ stm_dma.channel[DMA_INDEX].cmar = scanline;
+ ao_arch_release_interrupts();
+}
+
+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,
+ 0);
+
+ ao_text("BL",
+ ao_vga_fb + (240 - 7) * AO_VGA_STRIDE,
+ AO_VGA_STRIDE,
+ 0);
+}
+
+void
+ao_vga_init(void)
+{
+ /* Initialize spi2 using PB15 for output */
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
+
+ stm_ospeedr_set(&stm_gpiob, 15, STM_OSPEEDR_40MHz);
+ stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5);
+
+ /* turn on SPI */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
+
+ stm_spi2.cr1 = ((1 << STM_SPI_CR1_BIDIMODE) | /* Two wire mode */
+ (1 << STM_SPI_CR1_BIDIOE) |
+ (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */
+ (0 << STM_SPI_CR1_CRCNEXT) |
+ (1 << STM_SPI_CR1_DFF) |
+ (0 << STM_SPI_CR1_RXONLY) |
+ (1 << STM_SPI_CR1_SSM) | /* Software SS handling */
+ (1 << STM_SPI_CR1_SSI) | /* ... */
+ (1 << STM_SPI_CR1_LSBFIRST) | /* Little endian */
+ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */
+ (0 << STM_SPI_CR1_BR) | /* baud rate to pclk/2 */
+ (1 << STM_SPI_CR1_MSTR) |
+ (0 << STM_SPI_CR1_CPOL) | /* Format 0 */
+ (0 << STM_SPI_CR1_CPHA));
+ stm_spi2.cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+ (0 << STM_SPI_CR2_RXNEIE) |
+ (0 << STM_SPI_CR2_ERRIE) |
+ (0 << STM_SPI_CR2_SSOE) |
+ (1 << STM_SPI_CR2_TXDMAEN) |
+ (0 << STM_SPI_CR2_RXDMAEN));
+
+ (void) stm_spi2.dr;
+ (void) stm_spi2.sr;
+
+ /* Grab the DMA channel for SPI2 MOSI */
+ stm_dma.channel[DMA_INDEX].cpar = &stm_spi2.dr;
+ stm_dma.channel[DMA_INDEX].cmar = ao_vga_fb;
+
+ /* hclock on timer 2 */
+
+ /* Turn on timer 2 */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM2EN);
+
+ /* Turn on GPIOA */
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
+
+ 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;
+
+ /* Channel 2 trigger scanout */
+ /* wait for the time to start scanout */
+ stm_tim2.ccr2 = 90;
+
+ 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) |
+ (0 << STM_TIM234_CCMR1_OC2FE) |
+
+ (0 << STM_TIM234_CCMR1_OC1CE) |
+ (STM_TIM234_CCMR1_OC1M_PWM_MODE_1 << STM_TIM234_CCMR1_OC1M) |
+ (1 << STM_TIM234_CCMR1_OC1PE) |
+ (0 << STM_TIM234_CCMR1_OC1FE) |
+ (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S));
+
+ stm_tim2.arr = mode.htotal;
+ stm_tim2.cnt = 0;
+
+ /* Update the register contents */
+ stm_tim2.egr |= (1 << STM_TIM234_EGR_UG);
+
+ /* Enable the timer */
+
+ /* Enable the output */
+ stm_tim2.ccer = ((0 << STM_TIM234_CCER_CC1NP) |
+ (STM_TIM234_CCER_CC1P_ACTIVE_LOW << STM_TIM234_CCER_CC1P) |
+ (1 << STM_TIM234_CCER_CC1E));
+
+ stm_tim2.cr2 = ((0 << STM_TIM234_CR2_TI1S) |
+ (STM_TIM234_CR2_MMS_UPDATE << STM_TIM234_CR2_MMS) |
+ (0 << STM_TIM234_CR2_CCDS));
+
+ stm_tim2.smcr = 0;
+
+ stm_tim2.dier = ((1 << STM_TIM234_DIER_CC2IE));
+
+ stm_tim2.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) |
+ (1 << STM_TIM234_CR1_ARPE) |
+ (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) |
+ (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) |
+ (0 << STM_TIM234_CR1_OPM) |
+ (1 << STM_TIM234_CR1_URS) |
+ (0 << STM_TIM234_CR1_UDIS) |
+ (0 << STM_TIM234_CR1_CEN));
+
+ /* Configure pins */
+
+ /* PA5 is Timer 2 CH1 output */
+ 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) */
+
+ 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.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) |
+ (0 << STM_TIM234_CCMR1_OC2PE) |
+ (0 << STM_TIM234_CCMR1_OC2FE) |
+
+ (0 << STM_TIM234_CCMR1_OC1CE) |
+ (STM_TIM234_CCMR1_OC1M_PWM_MODE_1 << STM_TIM234_CCMR1_OC1M) |
+ (1 << STM_TIM234_CCMR1_OC1PE) |
+ (0 << STM_TIM234_CCMR1_OC1FE) |
+ (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S));
+
+ stm_tim3.arr = mode.vtotal;
+ stm_tim3.cnt = 0;
+
+ /* Update the register contents */
+ stm_tim3.egr |= (1 << STM_TIM234_EGR_UG);
+
+ /* Enable the timer */
+
+ /* Enable the output */
+ stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC1NP) |
+ (STM_TIM234_CCER_CC1P_ACTIVE_LOW << STM_TIM234_CCER_CC1P) |
+ (1 << STM_TIM234_CCER_CC1E));
+
+ stm_tim3.cr2 = ((0 << STM_TIM234_CR2_TI1S) |
+ (STM_TIM234_CR2_MMS_UPDATE << STM_TIM234_CR2_MMS) |
+ (0 << STM_TIM234_CR2_CCDS));
+
+ stm_tim3.smcr = 0;
+ stm_tim3.smcr = ((0 << STM_TIM234_SMCR_ETP) |
+ (0 << STM_TIM234_SMCR_ECE) |
+ (STM_TIM234_SMCR_ETPS_OFF << STM_TIM234_SMCR_ETPS) |
+ (STM_TIM234_SMCR_ETF_NONE << STM_TIM234_SMCR_ETF) |
+ (0 << STM_TIM234_SMCR_MSM) |
+ (STM_TIM234_SMCR_TS_ITR1 << STM_TIM234_SMCR_TS) |
+ (0 << STM_TIM234_SMCR_OCCS) |
+ (STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK << STM_TIM234_SMCR_SMS));
+
+ stm_tim3.dier = 0;
+
+ stm_tim3.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) |
+ (1 << STM_TIM234_CR1_ARPE) |
+ (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) |
+ (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) |
+ (0 << STM_TIM234_CR1_OPM) |
+ (1 << STM_TIM234_CR1_URS) |
+ (0 << STM_TIM234_CR1_UDIS) |
+ (1 << STM_TIM234_CR1_CEN));
+
+ /* Configure pins */
+
+ /* PB4 is Timer 3 CH1 output */
+ 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_enable(STM_ISR_TIM2_POS);
+}
+
+void
+ao_vga_enable(int enable)
+{
+ if (enable) {
+ vblank_off = enable;
+ ao_vga_fb_init();
+ stm_tim2.cr1 |= (1 << STM_TIM234_CR1_CEN);
+ stm_systick.csr &= ~(1 << STM_SYSTICK_CSR_ENABLE);
+ } else {
+ 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
new file mode 100644
index 00000000..caec8f48
--- /dev/null
+++ b/src/drivers/ao_vga.h
@@ -0,0 +1,33 @@
+/*
+ * 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_VGA_H_
+#define _AO_VGA_H_
+
+#include "ao_draw.h"
+
+void
+ao_vga_init(void);
+
+void
+ao_vga_enable(int active);
+
+#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];
+
+#endif /* _AO_VGA_H_ */
diff --git a/src/stm-vga/Makefile b/src/stm-vga/Makefile
new file mode 100644
index 00000000..5db8c641
--- /dev/null
+++ b/src/stm-vga/Makefile
@@ -0,0 +1,76 @@
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_vga.h \
+ ao_draw.h \
+ ao_font.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_boot_chain.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_lcd_stm.c \
+ ao_lcd_font.c \
+ ao_blt.c \
+ ao_text.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
+
+PRODUCT=StmVga-v0.0
+IDPRODUCT=0x000a
+
+CFLAGS = $(STM_CFLAGS) -g -Os
+
+PROG=stm-vga-$(VERSION)
+ELF=$(PROG).elf
+IHX=$(PROG).ihx
+
+SRC=$(ALTOS_SRC) ao_demo.c
+OBJ=$(SRC:.c=.o)
+
+all: $(ELF) $(IHX)
+
+$(ELF): Makefile $(OBJ)
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o *.elf *.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/stm-vga/ao_demo.c b/src/stm-vga/ao_demo.c
new file mode 100644
index 00000000..582e4156
--- /dev/null
+++ b/src/stm-vga/ao_demo.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2011 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include <ao_exti.h>
+#include <ao_event.h>
+#include <ao_quadrature.h>
+#include <ao_button.h>
+#include <ao_boot.h>
+#include <ao_vga.h>
+
+static void
+ao_video_toggle(void)
+{
+ ao_cmd_decimal();
+ ao_vga_enable(ao_cmd_lex_i);
+}
+
+__code struct ao_cmds ao_demo_cmds[] = {
+ { ao_video_toggle, "V\0Toggle video" },
+ { 0, NULL }
+};
+
+int
+main(void)
+{
+ ao_clock_init();
+
+ ao_task_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_GREEN);
+ ao_led_off(AO_LED_BLUE);
+ ao_timer_init();
+ ao_dma_init();
+ ao_cmd_init();
+ ao_vga_init();
+ ao_usb_init();
+
+ ao_cmd_register(&ao_demo_cmds[0]);
+
+ ao_start_scheduler();
+ return 0;
+}
diff --git a/src/stm-vga/ao_pins.h b/src/stm-vga/ao_pins.h
new file mode 100644
index 00000000..3526cb6c
--- /dev/null
+++ b/src/stm-vga/ao_pins.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright © 2012 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* Bridge SB17 on the board and use the MCO from the other chip */
+#define AO_HSE 8000000
+#define AO_HSE_BYPASS 1
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+/* SYSCLK = 24MHz */
+#define AO_PLLDIV 4
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_4)
+
+/* HCLK = 24MHZ (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at HCLK/1 */
+#define AO_APB1_PRESCALER 1
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_1
+
+/* Run APB2 at HCLK/1 */
+#define AO_APB2_PRESCALER 1
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_1
+
+#define HAS_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PB6_PB7 1
+#define SERIAL_1_PA9_PA10 0
+
+#define HAS_SERIAL_2 0
+#define USE_SERIAL_2_STDIN 0
+#define SERIAL_2_PA2_PA3 0
+#define SERIAL_2_PD5_PD6 1
+
+#define HAS_SERIAL_3 0
+#define USE_SERIAL_3_STDIN 1
+#define SERIAL_3_PB10_PB11 0
+#define SERIAL_3_PC10_PC11 0
+#define SERIAL_3_PD8_PD9 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PB3_PB4_PB5 1
+#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2 0
+
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define PACKET_HAS_SLAVE 0
+
+#define STM_DMA1_5_STOLEN 1
+
+#define AO_BOOT_CHAIN 1
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOBEN
+#define LED_PORT (&stm_gpiob)
+#define LED_PIN_GREEN 7
+#define LED_PIN_BLUE 6
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+#define AO_LED_BLUE (1 << LED_PIN_BLUE)
+#define AO_LED_PANIC AO_LED_BLUE
+
+#define LEDS_AVAILABLE (AO_LED_BLUE | AO_LED_GREEN)
+
+#define AO_LCD_STM_SEG_ENABLED_0 ( \
+ (1 << 0) | /* PA1 */ \
+ (1 << 1) | /* PA2 */ \
+ (1 << 2) | /* PA3 */ \
+ (0 << 3) | /* PA6 */ \
+ (0 << 4) | /* PA7 */ \
+ (0 << 5) | /* PB0 */ \
+ (0 << 6) | /* PB1 */ \
+ (1 << 7) | /* PB3 */ \
+ (1 << 8) | /* PB4 */ \
+ (1 << 9) | /* PB5 */ \
+ (1 << 10) | /* PB10 */ \
+ (1 << 11) | /* PB11 */ \
+ (1 << 12) | /* PB12 */ \
+ (1 << 13) | /* PB13 */ \
+ (1 << 14) | /* PB14 */ \
+ (1 << 15) | /* PB15 */ \
+ (1 << 16) | /* PB8 */ \
+ (1 << 17) | /* PA15 */ \
+ (1 << 18) | /* PC0 */ \
+ (1 << 19) | /* PC1 */ \
+ (1 << 20) | /* PC2 */ \
+ (1 << 21) | /* PC3 */ \
+ (0 << 22) | /* PC4 */ \
+ (0 << 23) | /* PC5 */ \
+ (1 << 24) | /* PC6 */ \
+ (1 << 25) | /* PC7 */ \
+ (1 << 26) | /* PC8 */ \
+ (1 << 27) | /* PC9 */ \
+ (1 << 28) | /* PC10 or PD8 */ \
+ (1 << 29) | /* PC11 or PD9 */ \
+ (0 << 30) | /* PC12 or PD10 */ \
+ (0 << 31)) /* PD2 or PD11 */
+
+#define AO_LCD_STM_SEG_ENABLED_1 ( \
+ (0 << 0) | /* PD12 */ \
+ (0 << 1) | /* PD13 */ \
+ (0 << 2) | /* PD14 */ \
+ (0 << 3) | /* PD15 */ \
+ (0 << 4) | /* PE0 */ \
+ (0 << 5) | /* PE1 */ \
+ (0 << 6) | /* PE2 */ \
+ (0 << 7)) /* PE3 */
+
+#define AO_LCD_STM_COM_ENABLED ( \
+ (1 << 0) | /* PA8 */ \
+ (1 << 1) | /* PA9 */ \
+ (1 << 2) | /* PA10 */ \
+ (1 << 3) | /* PB9 */ \
+ (0 << 4) | /* PC10 */ \
+ (0 << 5) | /* PC11 */ \
+ (0 << 6)) /* PC12 */
+
+#define AO_LCD_28_ON_C 1
+
+#define AO_LCD_DUTY STM_LCD_CR_DUTY_STATIC
+
+#define HAS_ADC 1
+
+#define AO_ADC_RING 32
+
+struct ao_adc {
+ uint16_t tick;
+ int16_t idd;
+ int16_t temp;
+ int16_t vref;
+};
+
+#define AO_ADC_IDD 4
+#define AO_ADC_PIN0_PORT (&stm_gpioa)
+#define AO_ADC_PIN0_PIN 4
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN))
+#define AO_ADC_TEMP 16
+#define AO_ADC_VREF 17
+
+#define HAS_ADC_TEMP 1
+
+#define AO_DATA_RING 32
+#define AO_NUM_ADC 3
+
+#define AO_ADC_SQ1 AO_ADC_IDD
+#define AO_ADC_SQ2 AO_ADC_TEMP
+#define AO_ADC_SQ3 AO_ADC_VREF
+
+#define HAS_I2C_1 1
+#define I2C_1_PB6_PB7 0
+#define I2C_1_PB8_PB9 1
+
+#define HAS_I2C_2 0
+#define I2C_2_PB10_PB11 0
+
+#define AO_EVENT 1
+
+#define AO_QUADRATURE_COUNT 2
+#define AO_QUADRATURE_MODE AO_EXTI_MODE_PULL_UP
+
+#define AO_QUADRATURE_0_PORT &stm_gpioc
+#define AO_QUADRATURE_0_A 1
+#define AO_QUADRATURE_0_B 0
+
+#define AO_QUADRATURE_1_PORT &stm_gpioc
+#define AO_QUADRATURE_1_A 3
+#define AO_QUADRATURE_1_B 2
+
+#define AO_BUTTON_COUNT 2
+#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP
+
+#define AO_BUTTON_0_PORT &stm_gpioc
+#define AO_BUTTON_0 6
+
+#define AO_BUTTON_1_PORT &stm_gpioc
+#define AO_BUTTON_1 7
+
+#define AO_TICK_TYPE uint32_t
+#define AO_TICK_SIGNED int32_t
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs
index c3d2707f..25504629 100644
--- a/src/stm/Makefile.defs
+++ b/src/stm/Makefile.defs
@@ -1,4 +1,4 @@
-vpath % ../stm:../product:../drivers:../kernel:../util:../kalman:../aes:../math:..
+vpath % ../stm:../product:../drivers:../kernel:../util:../kalman:../aes:../math:../draw:..
vpath make-altitude ../util
vpath make-kalman ../util
vpath kalman.5c ../kalman
@@ -26,7 +26,7 @@ LIBS=$(PDCLIB_LIBS_M3) -lgcc
WARN_FLAGS=-Wall -Wextra -Werror
-AO_CFLAGS=-I. -I../stm -I../kernel -I../drivers -I../math -I.. $(PDCLIB_INCLUDES)
+AO_CFLAGS=-I. -I../stm -I../kernel -I../drivers -I../math -I../draw -I.. $(PDCLIB_INCLUDES)
STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb \
-ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c
index 6d779660..0c86b49a 100644
--- a/src/stm/ao_dma_stm.c
+++ b/src/stm/ao_dma_stm.c
@@ -29,7 +29,6 @@ uint8_t ao_dma_done[NUM_DMA];
static struct ao_dma_config ao_dma_config[NUM_DMA];
static uint8_t ao_dma_allocated[NUM_DMA];
static uint8_t ao_dma_mutex[NUM_DMA];
-static uint8_t ao_dma_active;
static void
ao_dma_isr(uint8_t index) {
@@ -51,10 +50,18 @@ void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); }
void stm_dma1_channel2_isr(void) { ao_dma_isr(STM_DMA_INDEX(2)); }
void stm_dma1_channel3_isr(void) { ao_dma_isr(STM_DMA_INDEX(3)); }
void stm_dma1_channel4_isr(void) { ao_dma_isr(STM_DMA_INDEX(4)); }
+#ifdef STM_DMA1_5_STOLEN
+#define LEAVE_DMA_ON
+#else
void stm_dma1_channel5_isr(void) { ao_dma_isr(STM_DMA_INDEX(5)); }
+#endif
void stm_dma1_channel6_isr(void) { ao_dma_isr(STM_DMA_INDEX(6)); }
void stm_dma1_channel7_isr(void) { ao_dma_isr(STM_DMA_INDEX(7)); }
+#ifndef LEAVE_DMA_ON
+static uint8_t ao_dma_active;
+#endif
+
void
ao_dma_set_transfer(uint8_t index,
volatile void *peripheral,
@@ -68,10 +75,12 @@ ao_dma_set_transfer(uint8_t index,
ao_dma_mutex[index] = 0xff;
} else
ao_mutex_get(&ao_dma_mutex[index]);
+#ifndef LEAVE_DMA_ON
ao_arch_critical(
if (ao_dma_active++ == 0)
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN);
);
+#endif
stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
stm_dma.channel[index].cndtr = count;
stm_dma.channel[index].cpar = peripheral;
@@ -96,10 +105,12 @@ void
ao_dma_done_transfer(uint8_t index)
{
stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+#ifndef LEAVE_DMA_ON
ao_arch_critical(
if (--ao_dma_active == 0)
stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN);
);
+#endif
if (ao_dma_allocated[index])
ao_dma_mutex[index] = 0;
else
@@ -120,10 +131,12 @@ ao_dma_dump_cmd(void)
{
int i;
+#ifndef LEAVE_DMA_ON
ao_arch_critical(
if (ao_dma_active++ == 0)
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN);
);
+#endif
printf ("isr %08x ifcr%08x\n", stm_dma.isr, stm_dma.ifcr);
for (i = 0; i < NUM_DMA; i++)
printf("%d: done %d allocated %d mutex %2d ccr %04x cndtr %04x cpar %08x cmar %08x isr %08x\n",
@@ -136,10 +149,12 @@ ao_dma_dump_cmd(void)
stm_dma.channel[i].cpar,
stm_dma.channel[i].cmar,
ao_dma_config[i].isr);
+#ifndef LEAVE_DMA_ON
ao_arch_critical(
if (--ao_dma_active == 0)
stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN);
);
+#endif
}
static const struct ao_cmds ao_dma_cmds[] = {
@@ -153,7 +168,17 @@ ao_dma_init(void)
{
int index;
+#ifdef LEAVE_DMA_ON
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN);
+#endif
for (index = 0; index < STM_NUM_DMA; index++) {
+#if STM_DMA1_5_STOLEN
+ if (index == STM_DMA_INDEX(5)) {
+ ao_dma_allocated[index] = 1;
+ ao_dma_mutex[index] = 0xff;
+ continue;
+ }
+#endif
stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index);
stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4);
ao_dma_allocated[index] = 0;
diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c
index 29a8f173..59cad495 100644
--- a/src/stm/ao_i2c_stm.c
+++ b/src/stm/ao_i2c_stm.c
@@ -75,6 +75,9 @@ uint8_t ao_i2c_mutex[STM_NUM_I2C];
#if AO_PCLK1 == 16000000
# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_16_MHZ
#endif
+#if AO_PCLK1 == 24000000
+# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_24_MHZ
+#endif
#if AO_PCLK1 == 32000000
# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_32_MHZ
#endif
diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c
index f86a5116..b25dbd1a 100644
--- a/src/stm/ao_timer.c
+++ b/src/stm/ao_timer.c
@@ -42,31 +42,30 @@ volatile __data uint8_t ao_data_count;
void stm_systick_isr(void)
{
+ ao_arch_release_interrupts();
ao_validate_cur_stack();
- if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
- ++ao_tick_count;
+ ++ao_tick_count;
#if HAS_TASK_QUEUE
- if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
- ao_task_check_alarm((uint16_t) ao_tick_count);
+ if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
+ ao_task_check_alarm((uint16_t) ao_tick_count);
#endif
#if AO_DATA_ALL
- if (++ao_data_count == ao_data_interval) {
- ao_data_count = 0;
+ if (++ao_data_count == ao_data_interval) {
+ ao_data_count = 0;
#if HAS_FAKE_FLIGHT
- if (ao_fake_flight_active)
- ao_fake_flight_poll();
- else
+ if (ao_fake_flight_active)
+ ao_fake_flight_poll();
+ else
#endif
- ao_adc_poll();
+ ao_adc_poll();
#if (AO_DATA_ALL & ~(AO_DATA_ADC))
- ao_wakeup((void *) &ao_data_count);
+ ao_wakeup((void *) &ao_data_count);
#endif
- }
+ }
#endif
#ifdef AO_TIMER_HOOK
- AO_TIMER_HOOK;
+ AO_TIMER_HOOK;
#endif
- }
}
#if HAS_ADC
@@ -90,6 +89,7 @@ ao_timer_init(void)
stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) |
(1 << STM_SYSTICK_CSR_TICKINT) |
(STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE));
+ stm_nvic.shpr15_12 |= 0xff << 24;
}
#endif
diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h
index 463125e2..f42ed97c 100644
--- a/src/stm/stm32l.h
+++ b/src/stm/stm32l.h
@@ -897,7 +897,11 @@ struct stm_nvic {
vuint32_t sc; /* 0xc10 0xe000ed10 System Control Register */
vuint32_t cc; /* 0xc14 0xe000ed14 Configuration Control Register */
- uint8_t _unusedc18[0xe00 - 0xc18];
+ vuint32_t shpr7_4; /* 0xc18 0xe000ed18 System Hander Priority Registers */
+ vuint32_t shpr11_8; /* 0xc1c */
+ vuint32_t shpr15_12; /* 0xc20 */
+
+ uint8_t _unusedc18[0xe00 - 0xc24];
vuint32_t stir; /* 0xe00 */
};
@@ -1594,6 +1598,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2;
#define STM_I2C_CR2_FREQ_4_MHZ 4
#define STM_I2C_CR2_FREQ_8_MHZ 8
#define STM_I2C_CR2_FREQ_16_MHZ 16
+#define STM_I2C_CR2_FREQ_24_MHZ 24
#define STM_I2C_CR2_FREQ_32_MHZ 32
#define STM_I2C_CR2_FREQ_MASK 0x3f
@@ -1740,6 +1745,12 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7
#define STM_TIM234_SMCR_SMS_MASK 7
+#define STM_TIM234_DIER_CC4IE 4
+#define STM_TIM234_DIER_CC3IE 3
+#define STM_TIM234_DIER_CC2IE 2
+#define STM_TIM234_DIER_CC1IE 1
+#define STM_TIM234_DIER_UIE 0
+
#define STM_TIM234_SR_CC4OF 12
#define STM_TIM234_SR_CC3OF 11
#define STM_TIM234_SR_CC2OF 10
@@ -1849,6 +1860,8 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
#define STM_TIM234_CCER_CC2E 4
#define STM_TIM234_CCER_CC1NP 3
#define STM_TIM234_CCER_CC1P 1
+#define STM_TIM234_CCER_CC1P_ACTIVE_HIGH 0
+#define STM_TIM234_CCER_CC1P_ACTIVE_LOW 1
#define STM_TIM234_CCER_CC1E 0
struct stm_usb {