altos/stm-vga: Implement VGA out from the STM processor
authorKeith Packard <keithp@keithp.com>
Sun, 20 Nov 2016 08:04:27 +0000 (00:04 -0800)
committerKeith Packard <keithp@keithp.com>
Sun, 20 Nov 2016 08:04:27 +0000 (00:04 -0800)
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>
17 files changed:
src/draw/5x7.bdf [new file with mode: 0644]
src/draw/Makefile [new file with mode: 0644]
src/draw/ao_blt.c [new file with mode: 0644]
src/draw/ao_draw.h [new file with mode: 0644]
src/draw/ao_font.h [new file with mode: 0644]
src/draw/ao_text.c [new file with mode: 0644]
src/draw/font-convert [new file with mode: 0755]
src/drivers/ao_vga.c [new file with mode: 0644]
src/drivers/ao_vga.h [new file with mode: 0644]
src/stm-vga/Makefile [new file with mode: 0644]
src/stm-vga/ao_demo.c [new file with mode: 0644]
src/stm-vga/ao_pins.h [new file with mode: 0644]
src/stm/Makefile.defs
src/stm/ao_dma_stm.c
src/stm/ao_i2c_stm.c
src/stm/ao_timer.c
src/stm/stm32l.h

diff --git a/src/draw/5x7.bdf b/src/draw/5x7.bdf
new file mode 100644 (file)
index 0000000..b511f28
--- /dev/null
@@ -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 (file)
index 0000000..0a542a1
--- /dev/null
@@ -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 (file)
index 0000000..2060f00
--- /dev/null
@@ -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 (file)
index 0000000..1ff3e74
--- /dev/null
@@ -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 (file)
index 0000000..ac424ef
--- /dev/null
@@ -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 (file)
index 0000000..68d6c2c
--- /dev/null
@@ -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 (executable)
index 0000000..2446592
--- /dev/null
@@ -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 (file)
index 0000000..24a645c
--- /dev/null
@@ -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 (file)
index 0000000..caec8f4
--- /dev/null
@@ -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 (file)
index 0000000..5db8c64
--- /dev/null
@@ -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 (file)
index 0000000..582e415
--- /dev/null
@@ -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 (file)
index 0000000..3526cb6
--- /dev/null
@@ -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_ */
index c3d2707faf76dae341d4b86943c58ce0e0b52242..255046293a4f952438cbf85f4d47c1718c6508f9 100644 (file)
@@ -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)
 
index 6d77966076a88aefeac0f8a281fa81b5ebe0b662..0c86b49af271255c93bdff9cd3c92c2bcb13a1a9 100644 (file)
@@ -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;
index 29a8f173f948682d81b1f367d07b20ec7c0687fe..59cad4951058fce99d360da9ce91cbc47f58720c 100644 (file)
@@ -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
index f86a51169293e78a4fb930f8e132f19557c378e7..b25dbd1acf071145f58b5c03745337db083db511 100644 (file)
@@ -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
index 463125e25f19ebea5472adbd1c0cab57eaa407ff..f42ed97caea69bb726ae9cc7404e3d8e5d4158ee 100644 (file)
@@ -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 {