*
* 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
#include <ao.h>
#include <ao_lcd_stm.h>
+#ifndef LCD_DEBUG
+#define LCD_DEBUG 0
+#endif
+
struct ao_lcd_segment {
uint8_t reg;
uint8_t bit;
&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;
}
void
ao_lcd_flush(void)
{
- cli();
+ 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);
- sei();
+ ao_arch_release_interrupts();
}
void
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;
- if (digit >= NCOM)
- digit = NCOM-1;
- if (segment >= NSEG)
- segment = NSEG-1;
+#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;
- n = (segment >> 5) & 1;
+#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[digit * 2 + n] |= (1 << (segment & 0x1f));
+ stm_lcd.ram[com * 2 + n] |= (1UL << (seg & 0x1f));
else
- stm_lcd.ram[digit * 2 + n] &= ~(1 << (segment & 0x1f));
+ stm_lcd.ram[com * 2 + n] &= ~(1UL << (seg & 0x1f));
}
-#if 0
+#if LCD_DEBUG
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;
+ 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();
static const struct ao_cmds ao_lcd_stm_cmds[] = {
{ ao_lcd_stm_seg_set, "s <com> <seg> <value>\0Set LCD segment" },
- { ao_lcd_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);
stm_nvic_set_priority(STM_ISR_LCD_POS, AO_STM_NVIC_LOW_PRIORITY);
/* All done */
-#if 0
+#if LCD_DEBUG
ao_cmd_register(ao_lcd_stm_cmds);
#endif
}