diff options
| -rw-r--r-- | src/stm-demo/Makefile | 6 | ||||
| -rw-r--r-- | src/stm-demo/ao_demo.c | 5 | ||||
| -rw-r--r-- | src/stm-demo/ao_pins.h | 59 | ||||
| -rw-r--r-- | src/stm/ao-parse-font.5c | 174 | ||||
| -rw-r--r-- | src/stm/ao_arch.h | 4 | ||||
| -rw-r--r-- | src/stm/ao_lcd_font.c | 101 | ||||
| -rw-r--r-- | src/stm/ao_lcd_font.h | 1152 | ||||
| -rw-r--r-- | src/stm/ao_lcd_stm.c | 393 | 
8 files changed, 1888 insertions, 6 deletions
| diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 9e4f9e38..ecdf6b7f 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -42,14 +42,16 @@ ALTOS_SRC = \  	ao_stdio.c \  	ao_panic.c \  	ao_timer.c \ -	ao_serial_stm.c +	ao_serial_stm.c \ +	ao_lcd_stm.c \ +	ao_lcd_font.c  PRODUCT=StmDemo-v0.0  PRODUCT_DEF=-DSTM_DEMO  IDPRODUCT=0x000a  CPU=cortex-m3  CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) +CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC)  NICKLE=nickle diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 94527089..24566f9b 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -47,8 +47,9 @@ main(void)  	ao_serial_init();  	ao_timer_init();  	ao_cmd_init(); -	ao_led_init(LEDS_AVAILABLE); -	ao_add_task(&demo_task, ao_demo, "demo"); +//	ao_led_init(LEDS_AVAILABLE); +	ao_lcd_stm_init(); +//	ao_add_task(&demo_task, ao_demo, "demo");  	ao_start_scheduler();  	return 0; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index c72cd04b..8d7ed76b 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -19,8 +19,8 @@  #define _AO_PINS_H_  #define HAS_SERIAL_1		1 -#define HAS_SERIAL_2		1 -#define HAS_SERIAL_3		1 +#define HAS_SERIAL_2		0 +#define HAS_SERIAL_3		0  #define USE_SERIAL_STDIN	1  #define HAS_USB			0  #define HAS_BEEP		0 @@ -39,4 +39,59 @@  #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 +  #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao-parse-font.5c b/src/stm/ao-parse-font.5c new file mode 100644 index 00000000..fe785854 --- /dev/null +++ b/src/stm/ao-parse-font.5c @@ -0,0 +1,174 @@ +#!/usr/bin/env nickle +# +# Parse a 14-segment font file +# and construct the bitmasks for each +# character. Output is in the same +# format as the input: +# 	[5] = 0x1212, +# /* +# CHAR 37 '%' +# 	        +# 	|    /  +# 	|   /   +# 	        +# 	  /   | +# 	 /    | +# 	        +# */ +# +# Note that there can only be tabs before the glyph image +# as spaces are significant in the image itself. +# + +typedef struct { +	int		c; +	bool[14]	bits; +} glyph; + +exception done(); + +glyph read_glyph(file f) { +	int	c; + +	for (;;) { +		if (File::end(f)) +			raise done(); +		string	l = File::fgets(f); +		if (File::sscanf(l, "CHAR %d", &c) == 1) +			break; +	} + +	string strip_tab(string x) { +		int i = 0; +		while (i < String::length(x) && x[i] == '\t') +			i++; +		string n = String::substr(x, i, String::length(x) - i); +		while (String::length(n) < 7) +			n = n + " "; +		return n; +	} + +	string[7] lines = { [i] = strip_tab(File::fgets(f)) }; + +	glyph	g = { .c = c }; + +	g.bits[0] = lines[0][1] == '-'; + +	g.bits[1] = lines[1][0] == '|'; +	g.bits[2] = lines[1][1] == '\\'; +	g.bits[3] = lines[1][3] == '|'; +	g.bits[4] = lines[1][5] == '/'; +	g.bits[5] = lines[1][6] == '|'; + +	g.bits[6] = lines[3][1] == '-'; +	g.bits[7] = lines[3][4] == '-'; + +	g.bits[8] = lines[5][0] == '|'; +	g.bits[9] = lines[5][1] == '/'; +	g.bits[10] = lines[5][3] == '|'; +	g.bits[11] = lines[5][5] == '\\'; +	g.bits[12] = lines[5][6] == '|'; + +	g.bits[13] = lines[6][1] == '-'; +	return g; +} + +string[*] glyph_image(glyph g) { +	int[7][7] chars = { { ' ' ... } ... }; + +	if (g.bits[0]) +		for (int c = 1; c < 6; c++) +			chars[0][c] = '-'; + +	if (g.bits[1]) +		for (int r = 1; r < 3; r++) +			chars[r][0] = '|'; +	if (g.bits[2]) +		for (int p = 1; p < 3; p++) +			chars[p][p] = '\\'; +	if (g.bits[3]) +		for (int p = 1; p < 3; p++) +			chars[p][3] = '|'; +	if (g.bits[4]) +		for (int p = 1; p < 3; p++) +			chars[p][6-p] = '/'; +	if (g.bits[5]) +		for (int p = 1; p < 3; p++) +			chars[p][6] = '|'; + +	if (g.bits[6]) +		for (int p = 1; p < 3; p++) +			chars[3][p] = '-'; +	if (g.bits[7]) +		for (int p = 4; p < 6; p++) +			chars[3][p] = '-'; + +	if (g.bits[8]) +		for (int r = 4; r < 6; r++) +			chars[r][0] = '|'; +	if (g.bits[9]) +		for (int p = 4; p < 6; p++) +			chars[p][6-p] = '/'; +	if (g.bits[10]) +		for (int p = 4; p < 6; p++) +			chars[p][3] = '|'; +	if (g.bits[11]) +		for (int p = 4; p < 6; p++) +			chars[p][p] = '\\'; +	if (g.bits[12]) +		for (int p = 4; p < 6; p++) +			chars[p][6] = '|'; + +	if (g.bits[13]) +		for (int c = 1; c < 6; c++) +			chars[6][c] = '-'; +		 +	return (string[7]) { [i] = String::new(chars[i]) }; + +} + +int glyph_value(glyph g) { +	int	v = 0; + +	for (int b = 0; b < 14; b++) +		if (g.bits[b]) +			v |= (1 << b); +	return v; +} + +void write_glyph(file f, glyph g) { +	File::fprintf (f, "CHAR %d '%s'\n", g.c, g.c == 127 ? "DEL" : String::new(g.c)); +	string[7] lines = glyph_image(g); +	for (int i = 0; i < 7; i++) +		File::fprintf (f, "\t%s\n", lines[i]); +} + +autoload Sort; + +glyph[*] read_font(file f) { +	glyph[128 - 32] font = { [i] = read_glyph(f) }; + +	Sort::qsort(&font, bool func (glyph a, glyph b) = (a.c > b.c)); +	return font; +} + +glyph[*] font; +void init () { +	twixt (file f = File::open("ao_lcd_font.h", "r"); File::close(f)) { +		font = read_font(f); +	} +} + +void dump() { +	twixt(file f = File::open("ao_lcd_font.h.new", "w"); File::close(f)) { +		for (int i = 0; i < dim(font); i++) { +			File::fprintf (f, "\t[%d] = 0x%04x,\n", i, glyph_value(font[i])); +			File::fprintf (f, "/*\n"); +			write_glyph(f, font[i]); +			File::fprintf (f, "*/\n\n"); +		} +	} +} + +init(); +dump(); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index c4b98c7a..96cbfe85 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -155,5 +155,9 @@ struct ao_adc {   */  #define STM_APB1	(16000000 * 6 / 4) +void ao_lcd_stm_init(void); + +void ao_lcd_font_string(char *s); +  #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_lcd_font.c b/src/stm/ao_lcd_font.c new file mode 100644 index 00000000..f6074587 --- /dev/null +++ b/src/stm/ao_lcd_font.c @@ -0,0 +1,101 @@ +/* + * 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; version 2 of the License. + * + * 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> + +static const uint16_t ao_lcd_font[] = { +#include "ao_lcd_font.h" +}; + +/* +	 ----- 		0 +	|\ | /|		1 2 3 4 5 +	| \|/ | @		14 +	 -- -- 		6 7 +	| /|\ |		8 9 10 11 12	 +	|/ | \| @		14 +	 ----- 		13 +	        @		15 +*/ + +static const uint8_t	ao_bit_src[] = { +	 8,  7,  5,  6, +	13, 12,  0,  1, +	10, 14,  4,  9, +	11, 15,  3,  2 +}; + +static const uint8_t	ao_bit_dst[6][4] = { +	{  0,  1, 28, 29 }, +	{  2,  7, 26, 27 }, +	{  8,  9, 24, 25 }, +	{ 10, 11, 20, 21 }, +	{ 12, 13, 18, 19 }, +	{ 14, 15, 17, 16 }, +}; + +static void +ao_draw_glyph(uint8_t pos, uint16_t glyph) { +	uint8_t		col, seg, src, dst; +	uint32_t	ram; + +	for (col = 0; col < 4; col++) { +		for (seg = 0; seg < 4; seg++) { +			src = ao_bit_src[(col << 2) | seg]; +			dst = ao_bit_dst[pos][seg]; +			ram = stm_lcd.ram[col * 2]; +			ram &= ~(1 << dst); +			ram |= (uint32_t) ((glyph >> src) & 1) << dst; +			stm_lcd.ram[col*2] = ram; +		} +	} +} + +#define AO_LCD_FONT_COLON	(1 << 14) +#define AO_LCD_FONT_DECIMAL	(1 << 15) + +void +ao_lcd_font_char(uint8_t pos, char c, uint16_t flags) { +	if (pos > 5) +		pos = 5; +	if (c < ' ' || c > 127) +		c = 127; +	ao_draw_glyph(pos, ao_lcd_font[c - ' '] | flags); +} + +void +ao_lcd_font_string(char *s) { +	uint8_t	pos = 0; +	uint16_t flags; +	char c; + +	while (pos < 6 && (c = *s++)) { +		flags = 0; +		for (;;) { +			if (*s == ':') +				flags |= AO_LCD_FONT_COLON; +			else if (*s == '.') +				flags |= AO_LCD_FONT_DECIMAL; +			else +				break; +			s++; +		} +		ao_lcd_font_char(pos++, c, flags); +	} +	while (pos < 6) +		ao_lcd_font_char(pos++, ' ', 0); +} diff --git a/src/stm/ao_lcd_font.h b/src/stm/ao_lcd_font.h new file mode 100644 index 00000000..08adc9ab --- /dev/null +++ b/src/stm/ao_lcd_font.h @@ -0,0 +1,1152 @@ +	[0] = 0x0000, +/* +CHAR 32 ' ' +	        +	        +	        +	        +	        +	        +	        +*/ + +	[1] = 0x0102, +/* +CHAR 33 '!' +	        +	|       +	|       +	        +	|       +	|       +	        +*/ + +	[2] = 0x000a, +/* +CHAR 34 '"' +	        +	|  |    +	|  |    +	        +	        +	        +	        +*/ + +	[3] = 0x05e8, +/* +CHAR 35 '#' +	        +	   |  | +	   |  | +	 -- --  +	|  |    +	|  |    +	        +*/ + +	[4] = 0x34cb, +/* +CHAR 36 '$' +	 -----  +	|  |    +	|  |    +	 -- --  +	   |  | +	   |  | +	 -----  +*/ + +	[5] = 0x1212, +/* +CHAR 37 '%' +	        +	|    /  +	|   /   +	        +	  /   | +	 /    | +	        +*/ + +	[6] = 0x2955, +/* +CHAR 38 '&' +	 -----  +	 \   /  +	  \ /   +	 --     +	|   \   +	|    \  +	 -----  +*/ + +	[7] = 0x0008, +/* +CHAR 39 ''' +	        +	   |    +	   |    +	        +	        +	        +	        +*/ + +	[8] = 0x2103, +/* +CHAR 40 '(' +	 -----  +	|       +	|       +	        +	|       +	|       +	 -----  +*/ + +	[9] = 0x3021, +/* +CHAR 41 ')' +	 -----  +	      | +	      | +	        +	      | +	      | +	 -----  +*/ + +	[10] = 0x0e1c, +/* +CHAR 42 '*' +	        +	 \ | /  +	  \|/   +	        +	  /|\   +	 / | \  +	        +*/ + +	[11] = 0x04c8, +/* +CHAR 43 '+' +	        +	   |    +	   |    +	 -- --  +	   |    +	   |    +	        +*/ + +	[12] = 0x0200, +/* +CHAR 44 ',' +	        +	        +	        +	        +	  /     +	 /      +	        +*/ + +	[13] = 0x00c0, +/* +CHAR 45 '-' +	        +	        +	        +	 -- --  +	        +	        +	        +*/ + +	[14] = 0x0800, +/* +CHAR 46 '.' +	        +	        +	        +	        +	    \   +	     \  +	        +*/ + +	[15] = 0x0210, +/* +CHAR 47 '/' +	        +	     /  +	    /   +	        +	  /     +	 /      +	        +*/ + +	[16] = 0x3333, +/* +CHAR 48 '0' +	 -----  +	|    /| +	|   / | +	        +	| /   | +	|/    | +	 -----  +*/ + +	[17] = 0x1030, +/* +CHAR 49 '1' +	        +	     /| +	    / | +	        +	      | +	      | +	        +*/ + +	[18] = 0x21e1, +/* +CHAR 50 '2' +	 -----  +	      | +	      | +	 -- --  +	|       +	|       +	 -----  +*/ + +	[19] = 0x30a1, +/* +CHAR 51 '3' +	 -----  +	      | +	      | +	    --  +	      | +	      | +	 -----  +*/ + +	[20] = 0x10e2, +/* +CHAR 52 '4' +	        +	|     | +	|     | +	 -- --  +	      | +	      | +	        +*/ + +	[21] = 0x30c3, +/* +CHAR 53 '5' +	 -----  +	|       +	|       +	 -- --  +	      | +	      | +	 -----  +*/ + +	[22] = 0x31c3, +/* +CHAR 54 '6' +	 -----  +	|       +	|       +	 -- --  +	|     | +	|     | +	 -----  +*/ + +	[23] = 0x0411, +/* +CHAR 55 '7' +	 -----  +	     /  +	    /   +	        +	   |    +	   |    +	        +*/ + +	[24] = 0x31e3, +/* +CHAR 56 '8' +	 -----  +	|     | +	|     | +	 -- --  +	|     | +	|     | +	 -----  +*/ + +	[25] = 0x10e3, +/* +CHAR 57 '9' +	 -----  +	|     | +	|     | +	 -- --  +	      | +	      | +	        +*/ + +	[26] = 0x0408, +/* +CHAR 58 ':' +	        +	   |    +	   |    +	        +	   |    +	   |    +	        +*/ + +	[27] = 0x0208, +/* +CHAR 59 ';' +	        +	   |    +	   |    +	        +	  /     +	 /      +	        +*/ + +	[28] = 0x0810, +/* +CHAR 60 '<' +	        +	     /  +	    /   +	        +	    \   +	     \  +	        +*/ + +	[29] = 0x20c0, +/* +CHAR 61 '=' +	        +	        +	        +	 -- --  +	        +	        +	 -----  +*/ + +	[30] = 0x0204, +/* +CHAR 62 '>' +	        +	 \      +	  \     +	        +	  /     +	 /      +	        +*/ + +	[31] = 0x0413, +/* +CHAR 63 '?' +	 -----  +	|    /  +	|   /   +	        +	   |    +	   |    +	        +*/ + +	[32] = 0x39b3, +/* +CHAR 64 '@' +	 -----  +	|    /| +	|   / | +	    --  +	|   \ | +	|    \| +	 -----  +*/ + +	[33] = 0x11e3, +/* +CHAR 65 'A' +	 -----  +	|     | +	|     | +	 -- --  +	|     | +	|     | +	        +*/ + +	[34] = 0x34a9, +/* +CHAR 66 'B' +	 -----  +	   |  | +	   |  | +	    --  +	   |  | +	   |  | +	 -----  +*/ + +	[35] = 0x2103, +/* +CHAR 67 'C' +	 -----  +	|       +	|       +	        +	|       +	|       +	 -----  +*/ + +	[36] = 0x3429, +/* +CHAR 68 'D' +	 -----  +	   |  | +	   |  | +	        +	   |  | +	   |  | +	 -----  +*/ + +	[37] = 0x2143, +/* +CHAR 69 'E' +	 -----  +	|       +	|       +	 --     +	|       +	|       +	 -----  +*/ + +	[38] = 0x0143, +/* +CHAR 70 'F' +	 -----  +	|       +	|       +	 --     +	|       +	|       +	        +*/ + +	[39] = 0x3183, +/* +CHAR 71 'G' +	 -----  +	|       +	|       +	    --  +	|     | +	|     | +	 -----  +*/ + +	[40] = 0x11e2, +/* +CHAR 72 'H' +	        +	|     | +	|     | +	 -- --  +	|     | +	|     | +	        +*/ + +	[41] = 0x2409, +/* +CHAR 73 'I' +	 -----  +	   |    +	   |    +	        +	   |    +	   |    +	 -----  +*/ + +	[42] = 0x3120, +/* +CHAR 74 'J' +	        +	      | +	      | +	        +	|     | +	|     | +	 -----  +*/ + +	[43] = 0x0952, +/* +CHAR 75 'K' +	        +	|    /  +	|   /   +	 --     +	|   \   +	|    \  +	        +*/ + +	[44] = 0x2102, +/* +CHAR 76 'L' +	        +	|       +	|       +	        +	|       +	|       +	 -----  +*/ + +	[45] = 0x1136, +/* +CHAR 77 'M' +	        +	|\   /| +	| \ / | +	        +	|     | +	|     | +	        +*/ + +	[46] = 0x1926, +/* +CHAR 78 'N' +	        +	|\    | +	| \   | +	        +	|   \ | +	|    \| +	        +*/ + +	[47] = 0x3123, +/* +CHAR 79 'O' +	 -----  +	|     | +	|     | +	        +	|     | +	|     | +	 -----  +*/ + +	[48] = 0x01e3, +/* +CHAR 80 'P' +	 -----  +	|     | +	|     | +	 -- --  +	|       +	|       +	        +*/ + +	[49] = 0x3923, +/* +CHAR 81 'Q' +	 -----  +	|     | +	|     | +	        +	|   \ | +	|    \| +	 -----  +*/ + +	[50] = 0x09e3, +/* +CHAR 82 'R' +	 -----  +	|     | +	|     | +	 -- --  +	|   \   +	|    \  +	        +*/ + +	[51] = 0x3085, +/* +CHAR 83 'S' +	 -----  +	 \      +	  \     +	    --  +	      | +	      | +	 -----  +*/ + +	[52] = 0x0409, +/* +CHAR 84 'T' +	 -----  +	   |    +	   |    +	        +	   |    +	   |    +	        +*/ + +	[53] = 0x3122, +/* +CHAR 85 'U' +	        +	|     | +	|     | +	        +	|     | +	|     | +	 -----  +*/ + +	[54] = 0x0312, +/* +CHAR 86 'V' +	        +	|    /  +	|   /   +	        +	| /     +	|/      +	        +*/ + +	[55] = 0x1b22, +/* +CHAR 87 'W' +	        +	|     | +	|     | +	        +	| / \ | +	|/   \| +	        +*/ + +	[56] = 0x0a14, +/* +CHAR 88 'X' +	        +	 \   /  +	  \ /   +	        +	  / \   +	 /   \  +	        +*/ + +	[57] = 0x0414, +/* +CHAR 89 'Y' +	        +	 \   /  +	  \ /   +	        +	   |    +	   |    +	        +*/ + +	[58] = 0x2211, +/* +CHAR 90 'Z' +	 -----  +	     /  +	    /   +	        +	  /     +	 /      +	 -----  +*/ + +	[59] = 0x2103, +/* +CHAR 91 '[' +	 -----  +	|       +	|       +	        +	|       +	|       +	 -----  +*/ + +	[60] = 0x0804, +/* +CHAR 92 '\' +	        +	 \      +	  \     +	        +	    \   +	     \  +	        +*/ + +	[61] = 0x3021, +/* +CHAR 93 ']' +	 -----  +	      | +	      | +	        +	      | +	      | +	 -----  +*/ + +	[62] = 0x0023, +/* +CHAR 94 '^' +	 -----  +	|     | +	|     | +	        +	        +	        +	        +*/ + +	[63] = 0x2000, +/* +CHAR 95 '_' +	        +	        +	        +	        +	        +	        +	 -----  +*/ + +	[64] = 0x0004, +/* +CHAR 96 '`' +	        +	 \      +	  \     +	        +	        +	        +	        +*/ + +	[65] = 0x2540, +/* +CHAR 97 'a' +	        +	        +	        +	 --     +	|  |    +	|  |    +	 -----  +*/ + +	[66] = 0x2942, +/* +CHAR 98 'b' +	        +	|       +	|       +	 --     +	|   \   +	|    \  +	 -----  +*/ + +	[67] = 0x21c0, +/* +CHAR 99 'c' +	        +	        +	        +	 -- --  +	|       +	|       +	 -----  +*/ + +	[68] = 0x32a0, +/* +CHAR 100 'd' +	        +	      | +	      | +	    --  +	  /   | +	 /    | +	 -----  +*/ + +	[69] = 0x2340, +/* +CHAR 101 'e' +	        +	        +	        +	 --     +	| /     +	|/      +	 -----  +*/ + +	[70] = 0x0143, +/* +CHAR 102 'f' +	 -----  +	|       +	|       +	 --     +	|       +	|       +	        +*/ + +	[71] = 0x10a5, +/* +CHAR 103 'g' +	 -----  +	 \    | +	  \   | +	    --  +	      | +	      | +	        +*/ + +	[72] = 0x11c2, +/* +CHAR 104 'h' +	        +	|       +	|       +	 -- --  +	|     | +	|     | +	        +*/ + +	[73] = 0x0400, +/* +CHAR 105 'i' +	        +	        +	        +	        +	   |    +	   |    +	        +*/ + +	[74] = 0x3000, +/* +CHAR 106 'j' +	        +	        +	        +	        +	      | +	      | +	 -----  +*/ + +	[75] = 0x0c88, +/* +CHAR 107 'k' +	        +	   |    +	   |    +	    --  +	   |\   +	   | \  +	        +*/ + +	[76] = 0x0408, +/* +CHAR 108 'l' +	        +	   |    +	   |    +	        +	   |    +	   |    +	        +*/ + +	[77] = 0x15c0, +/* +CHAR 109 'm' +	        +	        +	        +	 -- --  +	|  |  | +	|  |  | +	        +*/ + +	[78] = 0x0940, +/* +CHAR 110 'n' +	        +	        +	        +	 --     +	|   \   +	|    \  +	        +*/ + +	[79] = 0x31c0, +/* +CHAR 111 'o' +	        +	        +	        +	 -- --  +	|     | +	|     | +	 -----  +*/ + +	[80] = 0x0146, +/* +CHAR 112 'p' +	        +	|\      +	| \     +	 --     +	|       +	|       +	        +*/ + +	[81] = 0x10b0, +/* +CHAR 113 'q' +	        +	     /| +	    / | +	    --  +	      | +	      | +	        +*/ + +	[82] = 0x0140, +/* +CHAR 114 'r' +	        +	        +	        +	 --     +	|       +	|       +	        +*/ + +	[83] = 0x2880, +/* +CHAR 115 's' +	        +	        +	        +	    --  +	    \   +	     \  +	 -----  +*/ + +	[84] = 0x2142, +/* +CHAR 116 't' +	        +	|       +	|       +	 --     +	|       +	|       +	 -----  +*/ + +	[85] = 0x3100, +/* +CHAR 117 'u' +	        +	        +	        +	        +	|     | +	|     | +	 -----  +*/ + +	[86] = 0x0300, +/* +CHAR 118 'v' +	        +	        +	        +	        +	| /     +	|/      +	        +*/ + +	[87] = 0x1b00, +/* +CHAR 119 'w' +	        +	        +	        +	        +	| / \ | +	|/   \| +	        +*/ + +	[88] = 0x0a14, +/* +CHAR 120 'x' +	        +	 \   /  +	  \ /   +	        +	  / \   +	 /   \  +	        +*/ + +	[89] = 0x3800, +/* +CHAR 121 'y' +	        +	        +	        +	        +	    \ | +	     \| +	 -----  +*/ + +	[90] = 0x2240, +/* +CHAR 122 'z' +	        +	        +	        +	 --     +	  /     +	 /      +	 -----  +*/ + +	[91] = 0x2245, +/* +CHAR 123 '{' +	 -----  +	 \      +	  \     +	 --     +	  /     +	 /      +	 -----  +*/ + +	[92] = 0x0408, +/* +CHAR 124 '|' +	        +	   |    +	   |    +	        +	   |    +	   |    +	        +*/ + +	[93] = 0x2891, +/* +CHAR 125 '}' +	 -----  +	     /  +	    /   +	    --  +	    \   +	     \  +	 -----  +*/ + +	[94] = 0x000e, +/* +CHAR 126 '~' +	        +	|\ |    +	| \|    +	        +	        +	        +	        +*/ + +	[95] = 0x3fff, +/* +CHAR 127 'DEL' +	 -----  +	|\ | /| +	| \|/ | +	 -- --  +	| /|\ | +	|/ | \| +	 -----  +*/ + diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c new file mode 100644 index 00000000..2d2fa9b3 --- /dev/null +++ b/src/stm/ao_lcd_stm.c @@ -0,0 +1,393 @@ +/* + * 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; version 2 of the License. + * + * 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> + +struct ao_lcd_segment { +	uint8_t	reg; +	uint8_t	bit; +}; + +#define A	0 +#define B	1 +#define C	2 +#define D	3 +#define E	4 + +static struct stm_gpio *gpios[] = { +	&stm_gpioa, +	&stm_gpiob, +	&stm_gpioc, +	&stm_gpiod, +	&stm_gpioe +}; + +static inline int ao_lcd_stm_seg_enabled(int seg) { +	if (seg < 32) +		return (AO_LCD_STM_SEG_ENABLED_0 >> seg) & 1; +	else +		return (AO_LCD_STM_SEG_ENABLED_1 >> (seg - 32)) & 1; +} + +static inline int ao_lcd_stm_com_enabled(int com) { +	return (AO_LCD_STM_COM_ENABLED >> com) & 1; +} + +#define AO_LCD_STM_GPIOA_SEGS_0	(		\ +		(1 << 0) |			\ +		(1 << 1) |			\ +		(1 << 2) |			\ +		(1 << 3) |			\ +		(1 << 4) |			\ +		(1 << 17)) + +#define AO_LCD_STM_GPIOA_SEGS_1 0 + +#define AO_LCD_STM_USES_GPIOA	(!!((AO_LCD_STM_GPIOA_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ +				    (AO_LCD_STM_GPIOA_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_GPIOB_SEGS_0	(		\ +		(1 << 5) |			\ +		(1 << 6) |			\ +		(1 << 7) |			\ +		(1 << 8) |			\ +		(1 << 9) |			\ +		(1 << 10) |			\ +		(1 << 11) |			\ +		(1 << 12) |			\ +		(1 << 13) |			\ +		(1 << 14) |			\ +		(1 << 15) |			\ +		(1 << 16)) + +#define AO_LCD_STM_GPIOB_SEGS_1 0 + +#if AO_LCD_28_ON_C + +#define AO_LCD_STM_GPIOC_28_SEGS	(	\ +		(1 << 28) |			\ +		(1 << 29) |			\ +		(1 << 30)) + +#define AO_LCD_STM_GPIOD_28_SEGS	(	\ +		(1 << 31)) + +#else +#define AO_LCD_STM_GPIOC_28_C_SEGS	0 + +#define AO_LCD_STM_GPIOD_28_SEGS	(	\ +		(1 << 28) |			\ +		(1 << 29) |			\ +		(1 << 30) |			\ +		(1 << 31)) +#endif + +#define AO_LCD_STM_GPIOC_SEGS_0	(		\ +		(1 << 18) |			\ +		(1 << 19) |			\ +		(1 << 20) |			\ +		(1 << 21) |			\ +		(1 << 22) |			\ +		(1 << 23) |			\ +		(1 << 24) |			\ +		(1 << 25) |			\ +		(1 << 26) |			\ +		(1 << 27) |			\ +		AO_LCD_STM_GPIOC_28_SEGS) + +#define AO_LCD_STM_GPIOC_SEGS_1 (		\ +		(1 << (40 - 32)) |		\ +		(1 << (41 - 32)) |		\ +		(1 << (42 - 32))) + +#define AO_LCD_STM_GPIOD_SEGS_0	(		\ +		AO_LCD_STM_GPIOD_28_SEGS) + +#define AO_LCD_STM_GPIOD_SEGS_1 (		\ +		(1 << (32 - 32)) |		\ +		(1 << (33 - 32)) |		\ +		(1 << (34 - 32)) |		\ +		(1 << (35 - 32)) |		\ +		(1 << (43 - 32))) + +#define AO_LCD_STM_GPIOE_SEGS_0	0 + +#define AO_LCD_STM_GPIOE_SEGS_1 (		\ +		(1 << (36 - 32)) |		\ +		(1 << (37 - 32)) |		\ +		(1 << (38 - 32)) |		\ +		(1 << (39 - 32))) + +#define AO_LCD_STM_USES_GPIOA	(!!((AO_LCD_STM_GPIOA_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ +				    (AO_LCD_STM_GPIOA_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + +#define AO_LCD_STM_USES_GPIOB	(!!((AO_LCD_STM_GPIOB_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ +				    (AO_LCD_STM_GPIOB_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_USES_GPIOC	(!!((AO_LCD_STM_GPIOC_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ +				    (AO_LCD_STM_GPIOC_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_USES_GPIOD	(!!((AO_LCD_STM_GPIOD_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ +				    (AO_LCD_STM_GPIOD_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + +#define AO_LCD_STM_USES_GPIOE	(!!((AO_LCD_STM_GPIOE_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ +				    (AO_LCD_STM_GPIOE_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +static const struct ao_lcd_segment segs[] = { +	{ A, 1 },	/* 0 */ +	{ A, 2 }, +	{ A, 3 }, +	{ A, 6 }, +		 +	{ A, 7 },	/* 4 */ +	{ B, 0 }, +	{ B, 1 }, +	{ B, 3 }, + +	{ B, 4 },	/* 8 */ +	{ B, 5 }, +	{ B, 10 }, +	{ B, 11 }, + +	{ B, 12 },	/* 12 */ +	{ B, 13 }, +	{ B, 14 }, +	{ B, 15 }, + +	{ B, 8 },	/* 16 */ +	{ A, 15 }, +	{ C, 0 }, +	{ C, 1 }, + +	{ C, 2 },	/* 20 */ +	{ C, 3 }, +	{ C, 4 }, +	{ C, 5 }, + +	{ C, 6 },	/* 24 */ +	{ C, 7 }, +	{ C, 8 }, +	{ C, 9 }, + +#if AO_LCD_28_ON_C +	{ C, 10 },	/* 28 */ +	{ C, 11 }, +	{ C, 12 }, +	{ D, 2 }, +#else +	{ D, 8 },	/* 28 */ +	{ D, 9 }, +	{ D, 10 }, +	{ D, 11 }, +#endif +	{ D, 12 },	/* 32 */ +	{ D, 13 }, +	{ D, 14 }, +	{ D, 15 }, +		 +	{ E, 0 },	/* 36 */ +	{ E, 1 }, +	{ E, 2 }, +	{ E, 3 }, + +	{ C, 10 },	/* 40 */ +	{ C, 11 }, +	{ C, 12 }, +	{ D, 2 }, +}; + +static const struct ao_lcd_segment coms[] = { +	{ A, 8 },	/* 0 */ +	{ A, 9 },	/* 1 */ +	{ A, 10 }, 	/* 2 */ +	{ B, 9 },	/* 3 */ +	{ C, 10 },	/* 4 */ +	{ C, 11 },	/* 5 */ +	{ C, 12 },	/* 6 */ +}; + +#define NSEG	(sizeof segs/sizeof segs[0]) +#define NCOM	(sizeof coms/sizeof coms[0]) + +static void +ao_lcd_stm_fcr_sync(void) +{ +	while ((stm_lcd.sr & (1 << STM_LCD_SR_FCRSF)) == 0) +		asm("nop"); +} + +static void +ao_lcd_stm_seg_set(void) +{ +	int	com, seg, val; +	int	n, bit; +	ao_cmd_decimal(); +	com = ao_cmd_lex_i; +	ao_cmd_decimal(); +	seg = ao_cmd_lex_u32; +	ao_cmd_decimal(); +	val = ao_cmd_lex_i; +	printf ("com: %d seg: %d val: %d\n", com, seg, val); +	n = (seg >> 5) & 1; +	if (com >= NCOM) +		com = NCOM-1; +	if (seg >= NSEG) +		seg = NSEG-1; +	if (val) +		stm_lcd.ram[com * 2 + n] |= (1 << (seg & 0x1f)); +	else +		stm_lcd.ram[com * 2 + n] &= ~(1 << (seg & 0x1f)); +	stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +static void +ao_lcd_stm_clear(void) +{ +	int	i; + +	for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++) +		stm_lcd.ram[i] = 0; +	stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +static void +ao_lcd_stm_text(void) +{ +	char	string[7]; +	uint8_t	c = 0; +	ao_cmd_white(); +	while (ao_cmd_lex_c != '\n' && c < sizeof (string)) { +		string[c++] = ao_cmd_lex_c; +		ao_cmd_lex(); +	} +	string[c++] = '\0'; +	ao_lcd_font_string(string); +	stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +const struct ao_cmds ao_lcd_stm_cmds[] = { +	{ ao_lcd_stm_seg_set,	"s <com> <seg> <value>\0Set LCD segment" }, +	{ ao_lcd_stm_clear,	"C\0Clear LCD" }, +	{ ao_lcd_stm_text,	"t <string>\0Write <string> to LCD" }, +	{ 0, NULL }, +}; + +void +ao_lcd_stm_init(void) +{ +	int s, c; +	int r; +	uint32_t	csr; + +	stm_rcc.ahbenr |= ((AO_LCD_STM_USES_GPIOA << STM_RCC_AHBENR_GPIOAEN) | +			   (AO_LCD_STM_USES_GPIOB << STM_RCC_AHBENR_GPIOBEN) | +			   (AO_LCD_STM_USES_GPIOC << STM_RCC_AHBENR_GPIOCEN) | +			   (AO_LCD_STM_USES_GPIOD << STM_RCC_AHBENR_GPIODEN) | +			   (AO_LCD_STM_USES_GPIOE << STM_RCC_AHBENR_GPIOEEN)); + +	stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_LCDEN); + +	/* Turn on the LSI clock */ +	if ((stm_rcc.csr & (1 << STM_RCC_CSR_LSIRDY)) == 0) { +		stm_rcc.csr |= (1 << STM_RCC_CSR_LSION); +		while ((stm_rcc.csr & (1 << STM_RCC_CSR_LSIRDY)) == 0) +			asm("nop"); +	} + +	/* Enable RTC clock config (required to change the RTC/LCD clock */ + +	stm_pwr.cr |= (1 << STM_PWR_CR_DBP); + +	/* Configure the LCDCLK - use the LSI clock */ + +	csr = stm_rcc.csr; +	csr &= ~(STM_RCC_CSR_RTCSEL_MASK << STM_RCC_CSR_RTCSEL); +	csr |= (STM_RCC_CSR_RTCSEL_LSI << STM_RCC_CSR_RTCSEL); +	stm_rcc.csr = csr; + +	for (s = 0; s < NSEG; s++) { +		uint8_t	reg = segs[s].reg; +		uint8_t bit = segs[s].bit; +			 +		if (ao_lcd_stm_seg_enabled(s)) { +			stm_moder_set(gpios[reg], bit, STM_MODER_ALTERNATE); +			stm_afr_set(gpios[reg], bit, STM_AFR_AF11); +		} +	} + +	for (c = 0; c < NCOM; c++) { +		uint8_t	reg = coms[c].reg; +		uint8_t bit = coms[c].bit; +			 +		if (ao_lcd_stm_com_enabled(c)) { +			stm_moder_set(gpios[reg], bit, STM_MODER_ALTERNATE); +			stm_afr_set(gpios[reg], bit, STM_AFR_AF11); +		} +	} + +	/* duty cycle 1/3, radio 352, frame rate about 33Hz */ +	stm_lcd.fcr = ((STM_LCD_FCR_PS_1 << STM_LCD_FCR_PS) | +		       (STM_LCD_FCR_DIV_31 << STM_LCD_FCR_DIV) | +		       (4 << STM_LCD_FCR_CC) | +		       (4 << STM_LCD_FCR_PON) | +		       (0 << STM_LCD_FCR_UDDIE) | +		       (0 << STM_LCD_FCR_SOFIE) | +		       (0 << STM_LCD_FCR_HD)); + +	ao_lcd_stm_fcr_sync(); + +	/* Program desired DUTY in LCD_CR */ +	/* Program desired BIAS in LCD_CR */ +	/* Enable mux seg */ +	/* Internal voltage source */ +	stm_lcd.cr = ((STM_LCD_CR_DUTY_1_4 << STM_LCD_CR_DUTY) | +		      (STM_LCD_CR_BIAS_1_3 << STM_LCD_CR_BIAS) | +		      (0 << STM_LCD_CR_VSEL) | +		      (1 << STM_LCD_CR_MUX_SEG)); + +	ao_lcd_stm_fcr_sync(); + +	/* Enable the display (LCDEN bit in LCD_CR) */ +	stm_lcd.cr |= (1 << STM_LCD_CR_LCDEN); + +	while ((stm_lcd.sr & (1 << STM_LCD_SR_RDY)) == 0) +		asm("nop"); + +	/* Load initial data into LCD_RAM and set the +	 * UDR bit in the LCD_SR register */ +	for (r = 0; r < NCOM; r++) { +		stm_lcd.ram[r*2] = 0; +		stm_lcd.ram[r*2 + 1] = 0; +	} + +	stm_lcd.sr = (1 << STM_LCD_SR_UDR); + +	/* Program desired frame rate (PS and DIV bits in LCD_FCR) */ + +	/* Program the contrast (CC bits in LCD_FCR) */ + +	/* Program optional features (BLINK, BLINKF, PON, DEAD, HD) */ + +	/* Program the required interrupts */ + +	/* All done */ +	ao_cmd_register(ao_lcd_stm_cmds); +} | 
