Arduino SLx-2016 Display Driver

The Osram SLx-2016 alphanumeric LED displays look great, they are quite easy to interface and, last but not least, quite expensive. I bought one to play with at Conrad some time ago. It was gathering dust for a while, but I stubled upon it again today and kludged together a small piece of Arduino code to talk to my nice and shiny green (SLG-2016) display.

I might use this later in a PID mod for my Rancilio Silvia espresso machine. But for now, here is the code. Hope it is of use to someone:

slx-2016.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 *  SLx-2016 display interfacing test for the Arduino Diecimila
 *  Hessel Schut, hessel@isquared.nl
 *  version 0.32 
 * 
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

// address lines
int a0 = 3;
int a1 = 4;

// !wr (write, active low)
int _wr = 2;

int d7 = 5; // too few pins on port C. borrow another


void setup()
{
  // define pin modes
  pinMode(a0, OUTPUT);
  pinMode(a1, OUTPUT);
  pinMode(_wr, OUTPUT);
  pinMode(d7, OUTPUT);

  // port C (the Arduino analog pins) is used as data bus 
  // set data direction register of this port to output
  DDRC |= B11111111;

  // display string on init
  char test[] = "init";

  // flash init string
  for (int i = 0; i <= 10; i++) {

    clearDisplay();
    delay(50);

    for (int pos = 0; pos <= 3; pos++) {
      writeDigit(3 - pos, test[pos]);
    };
    delay(50);

  };

  delay(1000);
  // setup finished, jump to loop()
}


void clearDisplay() {
  // The 2016 has a pin for this, but this is more economic on IO pins: 
  for (int pos = 0; pos <= 3; pos++) {
    // write a bunch of spaces to the display
    writeDigit(3 - pos, 0x20);
  };
}

// write a character 'dchar' in position 'digit' on the display
void writeDigit(int digit, char dchar) {

  // set address, the SLx-2016 defines address 0 as the rightmost digit
  digitalWrite(a0, digit&1);
  digitalWrite(a1, digit&2);

  // initialize write cycle
  digitalWrite(_wr, LOW);

  // write character data
  PORTC = dchar;
  digitalWrite(d7, dchar & B01000000); // port C is 6 bits breed, ascii 7... ;)

  // finish write cycle
  digitalWrite(_wr, HIGH);
}

// write ascii text to the display
void print_slx2016(char mesg_string[]) {

  // initialize display buff
  char disp[5] = "    ";

  clearDisplay();

  if (strlen(mesg_string) > 4) {
    // scroll through the message
    for (int pos = 0; pos < strlen(mesg_string); pos++) {
      writeDigit(0, mesg_string[pos]);
      for (int offset = 1; offset <= 3; offset++) {
        if (pos > (offset - 1)) {
          writeDigit(offset, mesg_string[pos - offset]);
        };
      };

      delay(200);
    };
  }
  else {
    // string fits on display, no scrolling

    // assign mesg_str to blank display buffer
    for (int i = 0; i <= strlen(mesg_string) - 1; i++) {
      disp[i] = mesg_string[i];
    };
    // write display buffer to display
    for (int pos = 0; pos <= 3; pos++) {
      writeDigit(3 - pos, disp[pos]);
    };
  };
}

// int to ascii string ('borrowed' from http://www.jb.man.ac.uk/~slowe/cpp/itoa.html)
char* itoa(int val, int base){
  static char buf[32] = {
    0  };

  int i = 30;

  for(; val && i ; --i, val /= base)

    buf[i] = "0123456789abcdef"[val % base];

  return &buf[i+1];  
}

// get length of string (iterate until nul terminator)
int strlen(char *str) {
  char *i;
  for (i=str; *i; i++);
  return i-str;
}

void loop() {
  print_slx2016("Hello, world!");
  delay(500);

  for (int n = 0; n <=9999; n++) {
    print_slx2016(itoa(n, 10));
    delay(15);
  };
  delay(500);
}

Comments