tm16xx.h / tm16xx.c
------------------------------------------------------------------------------------------------
11.01.2019     R. Seelig

TM1637, TM1638, TM1651 sind rudimentaere Bausteine zum Betrieb von gemultiplten
Leuchtdiodenanzeigen mit gemeinsamer Anode (vorzugsweise 7 Segmentanzeigen).

Ausserdem unterstuetzen sie zusaetzlich das Einlesen von Tastern, sodass mit ihnen
einfache I/O Module aufgebaut werden koennen. Die vorliegende Software unterstuetzt
( Stand 11.01.2019 ) die beiden Bausteine TM1637 und TM1650. Hierbei unterstuetzt
TM1637 7-Segmentanzeigen mit gemeinsamer Anode, TM1650 unterstuetzt Anzeigen mit
gemeinsamer Kathode.


Features:

TM1637
------------------------------------------------------

                                +-------------+
                           GND  |  1       20 |  K2
                    SEG1 / KS1  |  2   T   19 |  K1
                    SEG2 / KS2  |  3   M   18 |  clk
                    SEG3 / KS3  |  4       17 |  dio
                    SEG4 / KS4  |  5   1   16 |  Vcc
                    SEG5 / KS5  |  6   6   15 |  GRID1
                    SEG6 / KS6  |  7   3   14 |  GRID2
                    SEG7 / KS7  |  8   7   13 |  GRID3
                    SEG8 / KS8  |  9       12 |  GRID4
                         GRID6  | 10       11 |  GRID5
                                +-------------+

 - LED-Treiber fuer maximal 6 x 8 Leuchtdioden ( sechs 7-Segmentanzeigen mit dp)
 - maximal 16 Tasten

TM1650
------------------------------------------------------

 - LED-Treiber fuer maximal 4 x 7 Leuchtdioden ( vier 7-Segmentanzeigen ohne dp)
 - maximal 7 Tasten

                                +-------------+
                         GRID1  |  1       16 |  SEG8 / KSP
                           SCL  |  2   T   15 |  SEG7 / KS17
                           SDA  |  3   M   14 |  SEG6 / KS16
                           GND  |  4       13 |  SEG5 / KS15
                         GRID2  |  5   1   12 |  SEG4 / KS14
                         GRID3  |  6   6   11 |  SEG3 / KS13
                         GRID4  |  7   5   10 |  Vcc
                   SEG1 / KS11  |  8   0    9 |  SEG2 / KS12
                                +-------------+

------------------------------------------------------

Die Bausteine werden ueber 2 Leitungen seriell synchron angesprochen. Das Kommunikations-
protokoll ist etwas "gewoehnungsbeduerftig".

Das Timing der Bausteine entspricht dem des gaengigen I2C Busses. Jedoch koennen
die Bausteine NICHT adressiert werden, d.h. sie haben keine Geraeteadresse und
stehen nach einem Startsignal auf dem Bus auf Empfang. Sie quittieren jedes Byte,
egal welches, mit einem Acknowledge.

Das senden eines Wertes erfolgt mit dem niederwertigsten Bit zuerst (im Gegensatz
zu vielen I2C Devices, bei dem ein hoeherwertiges Bit zuerst gesendet wird).


Der Anschluss des Bausteins an 7-Segmentanzeigen geschieht folgendermassen:

     a
    ---
 f | g | b       Segment |  a   |  b   |  c   |  d   |  e   |  f   |  g   | Dezimalpunkt (dp) |
    ---          ------------------------------------------------------------------------------
 e |   | c       Anschl. | SEG1 | SEG2 | SEG3 | SEG4 | SEG5 | SEG6 | SEG7 |        SEG8       |
    ---  .
     d

GRID1 steuert die hoechstwertigste Stelle der Anzeige an


GRID-Anschluesse fuer 4 stellige Anzeige
------------------------------------------------------------

      GRID1   GRID2   GRID2   GRID4
    .................................
    .   _   .   _   .   _   .   _   .
    .  |_|  .  |_|  .  |_|  .  |_|  .
    .  |_|  .  |_|  .  |_|  .  |_|  .
    .................................


GRID-Anschluesse fuer 6 stellige Anzeige
------------------------------------------------------------

      GRID1   GRID2   GRID2   GRID4   GRID5   GRID6
    .................................................
    .   _   .   _   .   _   .   _   .   _   .   _   .
    .  |_|  .  |_|  .  |_|  .  |_|  .  |_|  .  |_|  .
    .  |_|  .  |_|  .  |_|  .  |_|  .  |_|  .  |_|  .
    .................................................


Tastenanschluesse
------------------------------------------------------------

Die Anschluesse der TM16xx haben an den Pins doppelte Funktionen, d.h. die Anschluesse, die
zu den Segmenten der Anzeige gehen, gehen auch zu den Tasten.

Beim TM1650 gibt es vier gemultiplexte Tastenreihen zu je 7 Tastern, beim TM1637 2 Tastenreihen
zu je 8 Tastern.

Es wird keine Tastenmatrix gescannt, d.h. der Baustein wird die Nummer der hoechsten gedrueckten
Taste zurueck liefern.

Die Software
------------------------------------------------------------------------------------------------

###################################################################
                               tm16xx.h
###################################################################

Hier sind vom Benutzer benoetigte Angaben zu machen.

  tm1637_ctrl / tm650_ctrl

  Die beiden Define-Schalter bestimmen, fuer welchen der beiden Controller der Code eingebunden
  werden soll

  #define tm1637_ctrl               1         // 1 => Code wird fuer TM1637 erstellt;
                                              // 0 => Code wird nicht erstellt

  #define tm1650_ctrl               1         // Code wird fuer TM1650 erstellt
                                              // 0 => Code wird nicht erstellt

  Hinweis: es darf nur einer der beiden Controller ausgewaehlt werden

  enable_6dezdigit / enable_6dezdigit_nonull / enable_6hexdigit
  ----------------------------------------------------------------

  Die 3 Define-Schalter bestimmen, welcher Code inkludiert werden soll. In der folgenden
  Einstellung ist bspw. lediglich eine Ausgabe fuer 6 stellige Zahlen mit Unterdrueckung
  fuehrender Nullen eingebunden

  #define enable_6dezdigit          0         // Code fuer 6-stellige dezimale Anzeige einbinden
  #define enable_6dezdigit_nonull   1         // Code fuer 6-stellige dezimale Anzeige mit
                                              // Ausblendung fuehrender Nullen einbinden
  #define enable_6hexdigit          0         // Code fuer 6-stellige hexadezimale Anzeige einbinden


  Festlegen, mit welchen Pins der TM16xx mit dem Controller verbunden ist

  /* ----------------------------------------------------------
            Anschluss CLK und DIO  an den Controller
     ---------------------------------------------------------- */

  // CLK nach PC6

  #define scl_init()     PC6_input_init()
  #define bb_scl_lo()    { PC6_output_init(); PC6_clr(); }
  #define bb_scl_hi()    scl_init()

  // SDA nach PC5

  #define sda_init()     PC5_input_init()
  #define bb_sda_lo()    { PC5_output_init(); PC5_clr(); }
  #define bb_sda_hi()    sda_init()
  #define bb_is_sda()    is_PC5()

###################################################################
                               tm16xx.c
###################################################################

tm16xx.c enthaelt die fuer den Betrieb erforderlichen Funktionen
und eine globale Variable.

----------------------------------------------------------
       uint8_t    tm16_xofs = 0;
----------------------------------------------------------

                           tm16_xofs
       Beinhaltet die Position, um die eine Anzeigenausgabe ver-
       schoben wird. Wird hier bspw. 2 angegeben, so erscheint die
       Ausgabe fuer Digit 0 nicht an Digit 0, sondern an
       Digit 2, Digit 1 an Digit 3 etc. Dieses dient vor allem
       dafuer, wenn ein 4-stelliger Wert auf einem 6-stelligen
       Display rechts buendig ausgegeben werden soll.


----------------------------------------------------------
       void tm16_init(void)
----------------------------------------------------------

       initialisiert die Anschluesse des Controllers zur
       Kommunikation mit dem TM16xx Baustein und loescht die
       Anzeige


----------------------------------------------------------
       void tm16_setbright(uint8_t value)
----------------------------------------------------------

       setzt die Helligkeit der Anzeige, erlaubte Werte fuer
       value sind 0..7, Wert 8 fuer Anzeige aus.

       Hinweis: Die Helligkeit wird erst mit einem
       tm16_clear uebernommen !


----------------------------------------------------------
       void tm16_clear(void)
----------------------------------------------------------

       loescht die Anzeige (alle Segmente aus)


----------------------------------------------------------
       void tm16_setbmp(uint8_t pos, uint8_t value)
----------------------------------------------------------

       gibt ein "Bitmuster" auf einer Anzeigenstelle aus.
       Hierdurch ist es moeglich, jedes einzelne Segment einer
       Anzeige anzusteuern.

       pos:
         Anzeigeposition, auf der das Bitmuster ausgege ben
         werden soll. pos = 0 entspricht der linken (hoechst
         wertigen) Anzeige

       value:
          anzuzeigendes Bitmuster


----------------------------------------------------------
       void tm16_setzif(uint8_t pos, uint8_t zif)
----------------------------------------------------------
       gibt ein Ziffer an der angegebenen Position aus.
       Position 0 ist die linke (hoechstwertige) Stelle

       pos:
         Anzeigeposition, auf der das Bitmuster ausgege ben
         werden soll. pos = 0 entspricht der linken (hoechst
         wertigen) Anzeige

       zif:
          anzuzeigende Ziffer

----------------------------------------------------------
       void tm16_setseg(uint8_t pos, uint8_t seg)
----------------------------------------------------------

       setzt ein einzelnes Segment einer Anzeige.
       Position 0 ist die linke (hoechstwertige) Stelle.

       pos:
         Anzeigeposition, auf der das Bitmuster ausgege ben
         werden soll. pos = 0 entspricht der linken (hoechst
         wertigen) Anzeige

       seg:
          anzuzeigendes Segment. Segment A = 0


----------------------------------------------------------
       void tm16_setdez(int value, uint8_t dpanz)
----------------------------------------------------------

       gibt einen 4-stelligen dezimalen Wert auf der
       Anzeige aus

      value:
        auszugebender Wert

       dpanz:
         Position der Anzeige Dezimalpunkt, 1 entspricht
         Anzeige rechts (und somit keine Nachkommastelle)
         0 => es erfolgt keine Anzeige

----------------------------------------------------------
       void tm16_setdez6digit(uint32_t value, uint8_t dpanz)
----------------------------------------------------------

       gibt einen 6-stelligen dezimalen Wert auf der
       Anzeige aus

       value:
         auszugebender Wert

       dpanz:
         Position der Anzeige Dezimalpunkt, 1 entspricht
         Anzeige rechts (und somit keine Nachkommastelle)
         0 => es erfolgt keine Anzeige

----------------------------------------------------------
void tm16_setdez2(uint8_t value, uint8_t pos, uint8_t dpanz)
----------------------------------------------------------

       gibt einen 2-stelligen dezimalen Wert auf der
       Anzeige aus

       Uebergabe:
          value : anzuzeigender Wert
          pos   : Position des 2-stelligen Wertes
                      0 => Ausgabe auf der rechten Stelle
                      4 => Ausgabe auf der linken Stelle
         dpanz  : Dezimalpunktanzeige
                      0 => Dezimalpunkt an
                      1 => Dezimalpunkt aus

   ---------------------------------------------------------- */

----------------------------------------------------------
       void tm16_sethex(uint16_t value)
----------------------------------------------------------

       gibt einen 4-stelligen hexadezimalen Wert auf der
       Anzeige aus

       value:
         auszugebender Wert


----------------------------------------------------------
       void tm16_sethex6digit(uint32_t value)
----------------------------------------------------------

       gibt einen 6-stelligen hexadezimalen Wert auf der
       Anzeige aus

       value:
         auszugebender Wert

----------------------------------------------------------
       void tm16_setdez6digit_nonull(uint32_t value)
----------------------------------------------------------
       zeigt eine max. 6 stellige dezimale Zahl OHNE
       fuehrende Null an.

       value : auszugebender Wert
       dpanz : Position der Anzeige Dezimalpunkt, 1 ent-
               spricht Anzeige rechts (und somit keine
               Nachkommastelle)
               0 => es erfolgt keine Dezimalpunktanzeige

----------------------------------------------------------
      uint8_t tm16_readkey(void)
----------------------------------------------------------

      liest angeschlossene Tasten ein und gibt dieses als
      Argument zurueck.

      Es wird keine Tastenmatrix zurueck geliefert. Ist
      mehr als eine Taste aktiviert, wird nur die hoechste
      Taste zurueck geliefert. Somit ist es nicht moeglich
      mehrere Tasten gleichzeitig zu betaetigen.

