aboutsummaryrefslogtreecommitdiff
path: root/examples/efm32/tinygecko/efm32-tg-stk3300/lcd_demo/lcd_demo.c
blob: d4ddb74ea5228bf15ecfafd4e373c2321bbcdee6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * This file is part of the libopencm3 project.
 *
 * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This library 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

/** @file
 * Demo of the LCD display aboard the EFM32-TG-STK330 eval board.
 */

#include <libopencm3/efm32/tinygecko/cmu.h>
#include <libopencm3/efm32/tinygecko/gpio.h>
#include <libopencm3/efm32/tinygecko/lcd.h>
#include "../lightswitch/lightswitch-common.c"
void led_toggle(void) { gpio_toggle(GPIO_PD, GPIO7); }

void delay(void)
{
	int x;

	/* Start up delay until we mess with clock stuff, so the debugger can catch up. */
	for(x = 0; x < 10000000; ++x) led_on();
}

void lcd_init(void)
{
	/* LCD is a LE module. We're constantly powered on for now, so using
	 * HFCORECLK/2  */
	CMU_HFCORECLKEN0 |= CMU_HFCORECLKEN0_LE;
	CMU_LFCLKSEL = (CMU_LFCLKSEL & ~CMU_LFCLKSEL_LFA_MASK) | CMU_LFCLKSEL_LFA_HFCORECLKLEDIV2;
	/* We need to get this down to reasonable 100Hz from 14MHz, 7MHz at
	 * LFACLK, 70kHz after LFA prescaler, 10kHz after FDIV. Octaplexing
	 * brings us down to about 500Hz. */
	CMU_LFAPRESC0 |= CMU_LFAPRESC0_LCD_DIV128;
	CMU_LCDCTRL |= CMU_LCDCTRL_FDIV_MASK; /* factor 7+1 */

	/* If we don't wait for the prescaler to become ready, the "Do it" step
	 * won't pass. */
	while (CMU_SYNCBUSY & CMU_SYNCBUSY_LFAPRESC0);

	CMU_LFACLKEN0 |= CMU_LFACLKEN0_LCD;

	while (CMU_SYNCBUSY & CMU_SYNCBUSY_LFACLKEN0);

	/* Voltage is around 3.3V anyway, we don't need voltage boosting,
	 * leaving it disabled. I don't fully understand the implications of
	 * biasing yet, but it seems like he more biased the better, and will
	 * just affect frame rate negatively. */
	LCD_DISPCTRL = (LCD_DISPCTRL & ~(LCD_DISPCTRL_BIAS_MASK | LCD_DISPCTRL_MUX_MASK)) | LCD_DISPCTRL_BIAS_ONEFOURTH | LCD_DISPCTRL_MUX_OCTAPLEX;

	/* Segments default to disabled, enable the 20 relevant ones */
	LCD_SEGEN = ~(~0<<5);

	/* Do it */
	LCD_CTRL |= LCD_CTRL_EN;

	while (LCD_SYNCBUSY & LCD_SYNCBUSY_CTRL) led_off();
	led_on();
}

void set_bank(u8 com, u32 data)
{
	switch(com)
	{
		case 0: LCD_SEGD0L = data; break;
		case 1: LCD_SEGD1L = data; break;
		case 2: LCD_SEGD2L = data; break;
		case 3: LCD_SEGD3L = data; break;
		case 4: LCD_SEGD4L = data; break;
		case 5: LCD_SEGD5L = data; break;
		case 6: LCD_SEGD6L = data; break;
		case 7: LCD_SEGD7L = data; break;
	}
}

int main(void)
{
	u8 active_bit = 0;
	u8 active_com = 0;

	gpio_setup();

//	delay();

	lcd_init();

	/* "{FNORD}" with a gecko as generated by current generate_lcd_mapping.py */
set_bank(0, 0x000a00);
set_bank(1, 0x0031cb);
set_bank(2, 0x004622);
set_bank(3, 0x0012a8);
set_bank(4, 0x00481a);
set_bank(5, 0x001140);
set_bank(6, 0x004642);
set_bank(7, 0x0051ac);

	while(1)
	{
		if (pb0_get())
		{
			while(pb0_get());

			set_bank(active_com, ~0);
			active_bit = (active_bit + 1) % 21; /* one more to see where 0 is */
			set_bank(active_com, ~(1<<active_bit));
		}
		if (pb1_get())
		{
			while(pb1_get());

			set_bank(active_com, ~0);
			active_com = (active_com + 1) % 9; /* one more to see where 0 is */
			set_bank(active_com, ~(1<<active_bit));
		}
		led_toggle();
	}
}