X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fstm%2Fao_lcd_stm.c;h=1947012b86000357445af1ce739a7616cbb03fbf;hb=refs%2Fheads%2Fmaster;hp=b19094440a9ff8f1027510f026f8266a150e0396;hpb=419a801131c1034f1fa149a67850290431cbda72;p=fw%2Faltos diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index b1909444..47246678 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -3,7 +3,8 @@ * * 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. + * 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 @@ -16,6 +17,11 @@ */ #include +#include + +#ifndef LCD_DEBUG +#define LCD_DEBUG 0 +#endif struct ao_lcd_segment { uint8_t reg; @@ -36,14 +42,14 @@ static struct stm_gpio *gpios[] = { &stm_gpioe }; -static inline int ao_lcd_stm_seg_enabled(int seg) { +static inline int ao_lcd_stm_seg_enabled(uint32_t 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) { +static inline int ao_lcd_stm_com_enabled(uint32_t com) { return (AO_LCD_STM_COM_ENABLED >> com) & 1; } @@ -88,7 +94,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 +233,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,59 +255,103 @@ ao_lcd_stm_fcr_sync(void) asm("nop"); } -static void -ao_lcd_stm_seg_set(void) +void +ao_lcd_flush(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; + ao_arch_block_interrupts(); + ao_lcd_update_active = 1; + stm_lcd.sr = (1 << STM_LCD_SR_UDR); + while (ao_lcd_update_active) + ao_sleep(&ao_lcd_update_active); + ao_arch_release_interrupts(); +} + +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(); +} + +#ifdef AO_SEGMENT_MAP +#if AO_LCD_PER_DIGIT +static const struct ao_lcd_map { + uint8_t com, seg; +} ao_lcd_map[AO_LCD_DIGITS * AO_LCD_SEGMENTS] = AO_SEGMENT_MAP; +#else +static const uint8_t ao_lcd_map[] = AO_SEGMENT_MAP; +#endif +#endif + +void +ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value) +{ + uint8_t n; + uint8_t com, seg; + +#ifdef AO_SEGMENT_MAP +#if AO_LCD_PER_DIGIT + n = (uint8_t) (digit * AO_LCD_SEGMENTS + segment); + com = ao_lcd_map[n].com; + seg = ao_lcd_map[n].seg; +#else + com = digit; + seg = ao_lcd_map[segment]; +#endif +#else + com = digit; + seg = segment; +#endif if (com >= NCOM) com = NCOM-1; if (seg >= NSEG) seg = NSEG-1; - if (val) - stm_lcd.ram[com * 2 + n] |= (1 << (seg & 0x1f)); + +#if LCD_DEBUG + printf ("digit %d segment %d -> com %d seg %d\n", digit, segment, com, seg); +#endif + n = (seg >> 5) & 1; + if (value) + stm_lcd.ram[com * 2 + n] |= (1UL << (seg & 0x1f)); else - stm_lcd.ram[com * 2 + n] &= ~(1 << (seg & 0x1f)); - stm_lcd.sr = (1 << STM_LCD_SR_UDR); + stm_lcd.ram[com * 2 + n] &= ~(1UL << (seg & 0x1f)); } +#if LCD_DEBUG static void -ao_lcd_stm_clear(void) +ao_lcd_stm_seg_set(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); + int com, seg, val; + int n, bit; + com = ao_cmd_decimal(); + seg = ao_cmd_decimal(); + val = ao_cmd_decimal(); + printf ("com: %d seg: %d val: %d\n", com, seg, val); + ao_lcd_set(com, seg, val); + ao_lcd_flush(); } - -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, "x\0Clear LCD" }, { 0, NULL }, }; +#endif void ao_lcd_stm_init(void) { - int s, c; - int r; + unsigned int s, c; 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.ahbenr |= (((uint32_t) AO_LCD_STM_USES_GPIOA << STM_RCC_AHBENR_GPIOAEN) | + ((uint32_t) AO_LCD_STM_USES_GPIOB << STM_RCC_AHBENR_GPIOBEN) | + ((uint32_t) AO_LCD_STM_USES_GPIOC << STM_RCC_AHBENR_GPIOCEN) | + ((uint32_t) AO_LCD_STM_USES_GPIOD << STM_RCC_AHBENR_GPIODEN) | + ((uint32_t) AO_LCD_STM_USES_GPIOE << STM_RCC_AHBENR_GPIOEEN)); stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_LCDEN); @@ -332,14 +397,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 +412,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 +427,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 +435,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 LCD_DEBUG ao_cmd_register(ao_lcd_stm_cmds); +#endif }