altos: Work on MAX6691 driver
[fw/altos] / src / stm / ao_lcd_stm.c
index 0f9a8eb53ee4325ab2c55f24be7df6b413a9604d..1947012b86000357445af1ce739a7616cbb03fbf 100644 (file)
@@ -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
 #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;
@@ -253,12 +258,12 @@ ao_lcd_stm_fcr_sync(void)
 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
@@ -271,35 +276,59 @@ ao_lcd_clear(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 = 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] |= (1 << (seg & 0x1f));
        else
-               stm_lcd.ram[digit * 2 + n] &= ~(1 << (segment & 0x1f));
+               stm_lcd.ram[com * 2 + n] &= ~(1 << (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();
@@ -307,7 +336,7 @@ ao_lcd_stm_seg_set(void)
 
 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
@@ -315,8 +344,7 @@ static const struct ao_cmds ao_lcd_stm_cmds[] = {
 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) |
@@ -411,7 +439,7 @@ ao_lcd_stm_init(void)
        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
 }