From 6da2f5846f2d28ea1f09f60ef2cc3f68113ac62a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 19:43:29 -0700 Subject: Add LCD device driver to STM32L port This enables the 6-digit 14-character display on the STM32L discovery board and provides an ascii output to it. Signed-off-by: Keith Packard --- src/stm/ao_lcd_stm.c | 393 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 src/stm/ao_lcd_stm.c (limited to 'src/stm/ao_lcd_stm.c') 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 + * + * 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 + +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 \0Set LCD segment" }, + { ao_lcd_stm_clear, "C\0Clear LCD" }, + { ao_lcd_stm_text, "t \0Write 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); +} -- cgit v1.2.3 From d236a5c7cd6e9b1d7192e801d63b4bd348cc2f12 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 20:02:30 -0700 Subject: Move LCD string output code to ao_lcd_font.c It's all very specific to the 14-segment display, so stick it there. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 1 + src/stm/ao_arch.h | 2 ++ src/stm/ao_lcd_font.c | 27 +++++++++++++++++++++++++++ src/stm/ao_lcd_stm.c | 15 --------------- 4 files changed, 30 insertions(+), 15 deletions(-) (limited to 'src/stm/ao_lcd_stm.c') diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 24566f9b..a672964b 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -49,6 +49,7 @@ main(void) ao_cmd_init(); // ao_led_init(LEDS_AVAILABLE); ao_lcd_stm_init(); + ao_lcd_font_init(); // ao_add_task(&demo_task, ao_demo, "demo"); ao_start_scheduler(); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 96cbfe85..61e62f5d 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -157,6 +157,8 @@ struct ao_adc { void ao_lcd_stm_init(void); +void ao_lcd_font_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 index f6074587..2bd787ed 100644 --- a/src/stm/ao_lcd_font.c +++ b/src/stm/ao_lcd_font.c @@ -99,3 +99,30 @@ ao_lcd_font_string(char *s) { while (pos < 6) ao_lcd_font_char(pos++, ' ', 0); } + +static void +ao_lcd_font_text(void) +{ + char string[20]; + uint8_t c = 0; + ao_cmd_white(); + while (ao_cmd_lex_c != '\n' && c < sizeof (string) - 1) { + 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_font_cmds[] = { + { ao_lcd_font_text, "t \0Write to LCD" }, + { 0, NULL } +}; + +void +ao_lcd_font_init(void) +{ + ao_cmd_register(ao_lcd_font_cmds); +} + diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index 2d2fa9b3..f68cf165 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -268,25 +268,10 @@ ao_lcd_stm_clear(void) 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 \0Set LCD segment" }, { ao_lcd_stm_clear, "C\0Clear LCD" }, - { ao_lcd_stm_text, "t \0Write to LCD" }, { 0, NULL }, }; -- cgit v1.2.3 From 419a801131c1034f1fa149a67850290431cbda72 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:39:10 -0700 Subject: altos: Configure STM LCD driver for giant LCD digits These devices require static mode. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 2 +- src/stm/ao_lcd_stm.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/stm/ao_lcd_stm.c') diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 232c2313..73ace558 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -166,7 +166,7 @@ main(void) ao_timer_init(); ao_dma_init(); ao_cmd_init(); -// ao_lcd_stm_init(); + ao_lcd_stm_init(); // ao_lcd_font_init(); ao_spi_init(); ao_i2c_init(); diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index f68cf165..b1909444 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -328,10 +328,14 @@ ao_lcd_stm_init(void) } } + /* Disable the LCD */ + stm_lcd.cr = 0; + /* 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) | + stm_lcd.fcr = ((STM_LCD_FCR_PS_16 << STM_LCD_FCR_PS) | + (STM_LCD_FCR_DIV_20 << STM_LCD_FCR_DIV) | (4 << STM_LCD_FCR_CC) | + (0 << STM_LCD_FCR_DEAD) | (4 << STM_LCD_FCR_PON) | (0 << STM_LCD_FCR_UDDIE) | (0 << STM_LCD_FCR_SOFIE) | @@ -343,8 +347,8 @@ ao_lcd_stm_init(void) /* 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) | + stm_lcd.cr = ((STM_LCD_CR_DUTY_STATIC << STM_LCD_CR_DUTY) | + (STM_LCD_CR_BIAS_1_2 << STM_LCD_CR_BIAS) | (0 << STM_LCD_CR_VSEL) | (1 << STM_LCD_CR_MUX_SEG)); -- cgit v1.2.3 From 304909b7534768bfc8da62954effb37ba86806ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:34:12 -0700 Subject: altos: Provide interface for STM LCD driver. This provides a simple function interface for driving the LCD segments in the STM chip. It also uses the update complete interrupt to block LCD users during flush. Signed-off-by: Keith Packard --- src/stm/ao_lcd_stm.c | 109 ++++++++++++++++++++++++++++++++++----------------- src/stm/ao_lcd_stm.h | 30 ++++++++++++++ 2 files changed, 102 insertions(+), 37 deletions(-) create mode 100644 src/stm/ao_lcd_stm.h (limited to 'src/stm/ao_lcd_stm.c') diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index b1909444..0f9a8eb5 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -16,6 +16,7 @@ */ #include +#include struct ao_lcd_segment { uint8_t reg; @@ -88,7 +89,7 @@ static inline int ao_lcd_stm_com_enabled(int com) { (1 << 31)) #else -#define AO_LCD_STM_GPIOC_28_C_SEGS 0 +#define AO_LCD_STM_GPIOC_28_SEGS 0 #define AO_LCD_STM_GPIOD_28_SEGS ( \ (1 << 28) | \ @@ -227,6 +228,21 @@ static const struct ao_lcd_segment coms[] = { #define NSEG (sizeof segs/sizeof segs[0]) #define NCOM (sizeof coms/sizeof coms[0]) +static uint8_t ao_lcd_update_active; + +void +stm_lcd_isr(void) +{ + if (stm_lcd.sr & (1 << STM_LCD_SR_UDD)) { + stm_lcd.clr = (1 << STM_LCD_CLR_UDDC); + if (ao_lcd_update_active) { + ao_lcd_update_active = 0; + ao_wakeup(&ao_lcd_update_active); + } + } +} + + static void ao_lcd_stm_fcr_sync(void) { @@ -234,6 +250,45 @@ ao_lcd_stm_fcr_sync(void) asm("nop"); } +void +ao_lcd_flush(void) +{ + cli(); + ao_lcd_update_active = 1; + stm_lcd.sr = (1 << STM_LCD_SR_UDR); + while (ao_lcd_update_active) + ao_sleep(&ao_lcd_update_active); + sei(); +} + +void +ao_lcd_clear(void) +{ + uint8_t i; + + for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++) + stm_lcd.ram[i] = 0; + ao_lcd_flush(); +} + +void +ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value) +{ + uint8_t n; + + if (digit >= NCOM) + digit = NCOM-1; + if (segment >= NSEG) + segment = NSEG-1; + + n = (segment >> 5) & 1; + if (value) + stm_lcd.ram[digit * 2 + n] |= (1 << (segment & 0x1f)); + else + stm_lcd.ram[digit * 2 + n] &= ~(1 << (segment & 0x1f)); +} + +#if 0 static void ao_lcd_stm_seg_set(void) { @@ -246,34 +301,16 @@ ao_lcd_stm_seg_set(void) 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); + ao_lcd_set(com, seg, val); + ao_lcd_flush(); } -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); -} - - -const struct ao_cmds ao_lcd_stm_cmds[] = { +static const struct ao_cmds ao_lcd_stm_cmds[] = { { ao_lcd_stm_seg_set, "s \0Set LCD segment" }, - { ao_lcd_stm_clear, "C\0Clear LCD" }, + { ao_lcd_clear, "C\0Clear LCD" }, { 0, NULL }, }; +#endif void ao_lcd_stm_init(void) @@ -332,14 +369,14 @@ ao_lcd_stm_init(void) stm_lcd.cr = 0; /* duty cycle 1/3, radio 352, frame rate about 33Hz */ - stm_lcd.fcr = ((STM_LCD_FCR_PS_16 << STM_LCD_FCR_PS) | + stm_lcd.fcr = ((STM_LCD_FCR_PS_8 << STM_LCD_FCR_PS) | (STM_LCD_FCR_DIV_20 << STM_LCD_FCR_DIV) | - (4 << STM_LCD_FCR_CC) | + (7 << STM_LCD_FCR_CC) | (0 << STM_LCD_FCR_DEAD) | - (4 << STM_LCD_FCR_PON) | - (0 << STM_LCD_FCR_UDDIE) | + (1 << STM_LCD_FCR_PON) | + (1 << STM_LCD_FCR_UDDIE) | (0 << STM_LCD_FCR_SOFIE) | - (0 << STM_LCD_FCR_HD)); + (1 << STM_LCD_FCR_HD)); ao_lcd_stm_fcr_sync(); @@ -347,10 +384,10 @@ ao_lcd_stm_init(void) /* Program desired BIAS in LCD_CR */ /* Enable mux seg */ /* Internal voltage source */ - stm_lcd.cr = ((STM_LCD_CR_DUTY_STATIC << STM_LCD_CR_DUTY) | + stm_lcd.cr = ((AO_LCD_DUTY << STM_LCD_CR_DUTY) | (STM_LCD_CR_BIAS_1_2 << STM_LCD_CR_BIAS) | (0 << STM_LCD_CR_VSEL) | - (1 << STM_LCD_CR_MUX_SEG)); + (0 << STM_LCD_CR_MUX_SEG)); ao_lcd_stm_fcr_sync(); @@ -362,12 +399,6 @@ ao_lcd_stm_init(void) /* 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) */ @@ -376,7 +407,11 @@ ao_lcd_stm_init(void) /* Program optional features (BLINK, BLINKF, PON, DEAD, HD) */ /* Program the required interrupts */ + stm_nvic_set_enable(STM_ISR_LCD_POS); + stm_nvic_set_priority(STM_ISR_LCD_POS, AO_STM_NVIC_LOW_PRIORITY); /* All done */ +#if 0 ao_cmd_register(ao_lcd_stm_cmds); +#endif } diff --git a/src/stm/ao_lcd_stm.h b/src/stm/ao_lcd_stm.h new file mode 100644 index 00000000..14667546 --- /dev/null +++ b/src/stm/ao_lcd_stm.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; 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. + */ + +#ifndef _AO_LCD_STM_H_ +#define _AO_LCD_STM_H_ + +void +ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value); + +void +ao_lcd_clear(void); + +void +ao_lcd_flush(void); + +#endif /* _AO_LCD_STM_H_ */ -- cgit v1.2.3