Subversion Repositories libSSD1306

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/*
2
 * Font.c
3
 
4
 *
5
 *  Created on: 20 Dec 2015
6
 *      Author: Mike
7
 */
8
#include <stdint.h>
9
#include <string.h>
10
#include "libSSD1306/ap_math.h"
11
#include "libSSD1306/SSD1306.h"
12
 
13
#include "libSSD1306/Font.h"
14
 
15
#include "libSSD1306/ascii-lucida.h"
16
 
17
uint8_t cursor_x;
18
uint8_t cursor_y;
19
 
20
/*
21
 * display text using a 5x7 bitmap font in ASCII letters
22
 */
3 mjames 23
static const unsigned char font[][5] =
24
  {
25
        { 0x00, 0x00, 0x00, 0x00, 0x00 },   //   0x20 32
26
        { 0x00, 0x00, 0x6f, 0x00, 0x00 },   // ! 0x21 33
27
        { 0x00, 0x07, 0x00, 0x07, 0x00 },   // " 0x22 34
28
        { 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // # 0x23 35
29
        { 0x2e, 0x2a, 0xff, 0x2a, 0x3a },  // $ 0x24 36
30
        { 0x23, 0x13, 0x08, 0x64, 0x62 },   // % 0x25 37
31
        { 0x36, 0x49, 0x56, 0x20, 0x50 },   // & 0x26 38
32
        { 0x00, 0x00, 0x07, 0x00, 0x00 },   // ' 0x27 39
33
        { 0x00, 0x1c, 0x22, 0x41, 0x00 },   // ( 0x28 40
34
        { 0x00, 0x41, 0x22, 0x1c, 0x00 },   // ) 0x29 41
35
        { 0x14, 0x08, 0x3e, 0x08, 0x14 },   // * 0x2a 42
36
        { 0x08, 0x08, 0x3e, 0x08, 0x08 },   // + 0x2b 43
37
        { 0x00, 0x50, 0x30, 0x00, 0x00 },   // , 0x2c 44
38
        { 0x08, 0x08, 0x08, 0x08, 0x08 },   // - 0x2d 45
39
        { 0x00, 0x60, 0x60, 0x00, 0x00 },   // . 0x2e 46
40
        { 0x20, 0x10, 0x08, 0x04, 0x02 },   // / 0x2f 47
41
        { 0x3e, 0x51, 0x49, 0x45, 0x3e },   // 0 0x30 48
42
        { 0x00, 0x42, 0x7f, 0x40, 0x00 },   // 1 0x31 49
43
        { 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2 0x32 50
44
        { 0x21, 0x41, 0x45, 0x4b, 0x31 },   // 3 0x33 51
45
        { 0x18, 0x14, 0x12, 0x7f, 0x10 },   // 4 0x34 52
46
        { 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5 0x35 53
47
        { 0x3c, 0x4a, 0x49, 0x49, 0x30 },   // 6 0x36 54
48
        { 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7 0x37 55
49
        { 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8 0x38 56
50
        { 0x06, 0x49, 0x49, 0x29, 0x1e },   // 9 0x39 57
51
        { 0x00, 0x36, 0x36, 0x00, 0x00 },   // : 0x3a 58
52
        { 0x00, 0x56, 0x36, 0x00, 0x00 },   // ; 0x3b 59
53
        { 0x08, 0x14, 0x22, 0x41, 0x00 },   // < 0x3c 60
54
        { 0x14, 0x14, 0x14, 0x14, 0x14 },   // = 0x3d 61
55
        { 0x00, 0x41, 0x22, 0x14, 0x08 },   // > 0x3e 62
56
        { 0x02, 0x01, 0x51, 0x09, 0x06 },   // ? 0x3f 63
57
        { 0x3e, 0x41, 0x5d, 0x49, 0x4e },   // @ 0x40 64
58
        { 0x7e, 0x09, 0x09, 0x09, 0x7e },   // A 0x41 65
59
        { 0x7f, 0x49, 0x49, 0x49, 0x36 },   // B 0x42 66
60
        { 0x3e, 0x41, 0x41, 0x41, 0x22 },   // C 0x43 67
61
        { 0x7f, 0x41, 0x41, 0x41, 0x3e },   // D 0x44 68
62
        { 0x7f, 0x49, 0x49, 0x49, 0x41 },   // E 0x45 69
63
        { 0x7f, 0x09, 0x09, 0x09, 0x01 },   // F 0x46 70
64
        { 0x3e, 0x41, 0x49, 0x49, 0x7a },   // G 0x47 71
65
        { 0x7f, 0x08, 0x08, 0x08, 0x7f },   // H 0x48 72
66
        { 0x00, 0x41, 0x7f, 0x41, 0x00 },   // I 0x49 73
67
        { 0x20, 0x40, 0x41, 0x3f, 0x01 },   // J 0x4a 74
68
        { 0x7f, 0x08, 0x14, 0x22, 0x41 },   // K 0x4b 75
69
        { 0x7f, 0x40, 0x40, 0x40, 0x40 },   // L 0x4c 76
70
        { 0x7f, 0x02, 0x0c, 0x02, 0x7f },   // M 0x4d 77
71
        { 0x7f, 0x04, 0x08, 0x10, 0x7f },   // N 0x4e 78
72
        { 0x3e, 0x41, 0x41, 0x41, 0x3e },   // O 0x4f 79
73
        { 0x7f, 0x09, 0x09, 0x09, 0x06 },   // P 0x50 80
74
        { 0x3e, 0x41, 0x51, 0x21, 0x5e },   // Q 0x51 81
75
        { 0x7f, 0x09, 0x19, 0x29, 0x46 },   // R 0x52 82
76
        { 0x46, 0x49, 0x49, 0x49, 0x31 },   // S 0x53 83
77
        { 0x01, 0x01, 0x7f, 0x01, 0x01 },   // T 0x54 84
78
        { 0x3f, 0x40, 0x40, 0x40, 0x3f },   // U 0x55 85
79
        { 0x0f, 0x30, 0x40, 0x30, 0x0f },   // V 0x56 86
80
        { 0x3f, 0x40, 0x30, 0x40, 0x3f },   // W 0x57 87
81
        { 0x63, 0x14, 0x08, 0x14, 0x63 },   // X 0x58 88
82
        { 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y 0x59 89
83
        { 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z 0x5a 90
84
        { 0x00, 0x00, 0x7f, 0x41, 0x00 },   // [ 0x5b 91
85
        { 0x02, 0x04, 0x08, 0x10, 0x20 },   // \ 0x5c 92
86
        { 0x00, 0x41, 0x7f, 0x00, 0x00 },   // ] 0x5d 93
87
        { 0x04, 0x02, 0x01, 0x02, 0x04 },   // ^ 0x5e 94
88
        { 0x40, 0x40, 0x40, 0x40, 0x40 },   // _ 0x5f 95
89
        { 0x00, 0x00, 0x03, 0x04, 0x00 },   // ` 0x60 96
90
        { 0x20, 0x54, 0x54, 0x54, 0x78 },   // a 0x61 97
91
        { 0x7f, 0x48, 0x44, 0x44, 0x38 },   // b 0x62 98
92
        { 0x38, 0x44, 0x44, 0x44, 0x44 },   // c 0x63 99
93
        { 0x38, 0x44, 0x44, 0x48, 0x7f },   // d 0x64 100
94
        { 0x38, 0x54, 0x54, 0x54, 0x18 },   // e 0x65 101
95
        { 0x08, 0x7e, 0x09, 0x01, 0x02 },   // f 0x66 102
96
        { 0x0c, 0x52, 0x52, 0x52, 0x3e },   // g 0x67 103
97
        { 0x7f, 0x08, 0x04, 0x04, 0x78 },   // h 0x68 104
98
        { 0x00, 0x44, 0x7d, 0x40, 0x00 },   // i 0x69 105
99
        { 0x20, 0x40, 0x44, 0x3d, 0x00 },   // j 0x6a 106
100
        { 0x00, 0x7f, 0x10, 0x28, 0x44 },   // k 0x6b 107
101
        { 0x00, 0x41, 0x7f, 0x40, 0x00 },   // l 0x6c 108
102
        { 0x7c, 0x04, 0x18, 0x04, 0x78 },   // m 0x6d 109
103
        { 0x7c, 0x08, 0x04, 0x04, 0x78 },   // n 0x6e 110
104
        { 0x38, 0x44, 0x44, 0x44, 0x38 },   // o 0x6f 111
105
        { 0x7c, 0x14, 0x14, 0x14, 0x08 },   // p 0x70 112
106
        { 0x08, 0x14, 0x14, 0x14, 0x7c },   // q 0x71 113
107
        { 0x7c, 0x08, 0x04, 0x04, 0x08 },   // r 0x72 114
108
        { 0x48, 0x54, 0x54, 0x54, 0x20 },   // s 0x73 115
109
        { 0x04, 0x3f, 0x44, 0x40, 0x20 },   // t 0x74 116
110
        { 0x3c, 0x40, 0x40, 0x20, 0x7c },   // u 0x75 117
111
        { 0x1c, 0x20, 0x40, 0x20, 0x1c },   // v 0x76 118
112
        { 0x3c, 0x40, 0x30, 0x40, 0x3c },   // w 0x77 119
113
        { 0x44, 0x28, 0x10, 0x28, 0x44 },   // x 0x78 120
114
        { 0x0c, 0x50, 0x50, 0x50, 0x3c },   // y 0x79 121
115
        { 0x44, 0x64, 0x54, 0x4c, 0x44 },   // z 0x7a 122
116
        { 0x00, 0x08, 0x36, 0x41, 0x41 },   // { 0x7b 123
117
        { 0x00, 0x00, 0x7f, 0x00, 0x00 },   // | 0x7c 124
118
        { 0x41, 0x41, 0x36, 0x08, 0x00 },   // } 0x7d 125
119
        { 0x08, 0x0c, 0x08, 0x18, 0x08 }, // ~ 0x7e 126
2 mjames 120
 
3 mjames 121
  };
2 mjames 122
 
123
#define extDegrees 0
124
 
3 mjames 125
static const unsigned char font_ext[][5] =
126
  {
2 mjames 127
 
3 mjames 128
  [extDegrees] =
129
    { 0x00, 0x06, 0x09, 0x06, 0x00 }, // a ° sign
2 mjames 130
 
3 mjames 131
    };
2 mjames 132
 
3 mjames 133
void
134
font_gotoxy (uint8_t x, uint8_t y)
2 mjames 135
{
3 mjames 136
  cursor_x = x;
137
  cursor_y = y;
2 mjames 138
}
139
 
3 mjames 140
void
141
font_putchar (uint8_t c)
2 mjames 142
{
3 mjames 143
  uint8_t *ptr = display_address () + cursor_x * 6 + cursor_y * WIDTH;
144
  int i;
145
  if ('\r' == c)
146
    {
147
      cursor_x = 0;
148
      cursor_y++;
149
      if (cursor_y >= HEIGHT / 8)
2 mjames 150
        {
3 mjames 151
          cursor_y = 0;
2 mjames 152
        }
3 mjames 153
      return;
154
    }
2 mjames 155
 
3 mjames 156
  for (i = 0; i < 5; i++)
157
    {
158
      if (c > ' ' && c < 0x80)
2 mjames 159
        {
3 mjames 160
          *ptr++ = font[c - ' '][i];
2 mjames 161
        }
3 mjames 162
      else if (c == '°')
163
        {
164
          *ptr++ = font_ext[extDegrees][i];
165
        }
166
      else
167
        {
168
          *ptr++ = 0;
169
        }
170
    }
171
  *ptr++ = 0;
2 mjames 172
 
3 mjames 173
  // move cursor
174
  cursor_x++;
175
  if (cursor_x >= WIDTH / 6)
176
    {
177
      cursor_x = 0;
178
      cursor_y++;
179
      if (cursor_y == HEIGHT / 8)
2 mjames 180
        {
3 mjames 181
          cursor_y = 0;
2 mjames 182
        }
3 mjames 183
    }
2 mjames 184
 
185
}
186
 
3 mjames 187
void
188
font_puts (uint8_t *s)
2 mjames 189
{
3 mjames 190
  while (s && *s)
191
    {
192
      font_putchar (*(s++));
193
    }
2 mjames 194
}
195
 
3 mjames 196
uint8_t
197
get_digits (uint16_t x, uint16_t y)
2 mjames 198
{
3 mjames 199
  return ((ascii_lucida_bits[(y * ascii_lucida_width) / 8 + (x / 8)]) >> (x & 7))
200
      & 1;
2 mjames 201
}
202
 
3 mjames 203
static uint8_t
204
format_num (char *buff, uint8_t digits, uint8_t dp_pos, int val)
2 mjames 205
{
206
  digits++;
207
  uint8_t pos = digits;
208
  uint8_t dp_loc = pos - dp_pos;
209
  uint8_t sign = 0;
3 mjames 210
  if (val < 0)
211
    {
212
      sign = 1;
213
      val = -val;
214
    }
2 mjames 215
 
3 mjames 216
  buff[pos] = 0;
2 mjames 217
  while (pos)
3 mjames 218
    {
219
      if (pos == dp_loc)
2 mjames 220
        {
3 mjames 221
          buff[--pos] = '.';
2 mjames 222
        }
3 mjames 223
      else
2 mjames 224
        {
3 mjames 225
          buff[--pos] = val % 10 + '0';
226
          val /= 10;
227
          if (val == 0 && pos < dp_loc)
228
            break;
2 mjames 229
        }
3 mjames 230
    }
231
  if (sign)
232
    {
233
      buff[--pos] = '-';
234
    }
235
  return digits;
2 mjames 236
}
237
 
3 mjames 238
void
239
font_digits (uint8_t digits, uint8_t dp_pos, int val)
2 mjames 240
{
3 mjames 241
  char buff[10] = "        ";
242
  format_num (buff, digits, dp_pos, val);
243
  font_puts ((unsigned char *)buff);
2 mjames 244
}
245
 
3 mjames 246
void
247
font_sig_digits (uint8_t x, uint8_t y, uint8_t right_justify, uint8_t dp_pos,
248
                 int val)
2 mjames 249
{
250
  char digits;
251
  char sign = 0;
252
  int uval;
253
  if (val < 0)
3 mjames 254
    {
255
      uval = -val;
256
      sign = 1; // mark as negative
257
    }
2 mjames 258
  else
3 mjames 259
    {
260
      uval = val;
261
    }
262
  if (uval < 10) // always one digit for a sign or space, one for a digit
263
    {
264
      digits = 1;
265
    }
266
  if (uval >= 10 && uval < 100)
267
    {
268
      digits = 2;
269
    }
270
  if (uval >= 100 && uval < 1000)
271
    {
272
      digits = 3;
273
    }
274
  if (uval >= 1000)
275
    {
276
      digits = 4;
277
    }
2 mjames 278
  // backup for the - sign if right justified
3 mjames 279
  if (right_justify)
280
    {
281
      if (dp_pos < 10)
282
        {
283
          digits += 2;
284
        }
285
      else
286
        {
287
          digits += 1;
288
        }
289
      x -= (digits);
290
    }
2 mjames 291
 
3 mjames 292
  font_gotoxy (x, y);
293
  font_digits (digits, dp_pos, val);
2 mjames 294
}
295
 
296
#define FONTX 10
297
#define FONTY 18
298
 
3 mjames 299
void
300
scan_xbm (void)
2 mjames 301
{
302
 
3 mjames 303
  int i, j;
2 mjames 304
 
3 mjames 305
  for (i = 0; i < FONTY; i++)
306
    {
307
      for (j = 0; j < FONTX * 6; j++)
2 mjames 308
        {
3 mjames 309
          drawPixel (j, i, get_digits (j, i));
2 mjames 310
        }
3 mjames 311
    }
2 mjames 312
}
313
 
3 mjames 314
void
315
print_large_string (char *string, int x, int y, int digits)
2 mjames 316
{
3 mjames 317
  int xt, yt, j;
318
  for (yt = 0; yt < FONTY; yt++) // iterate down scan lines
2 mjames 319
    {
3 mjames 320
      for (xt = 0; xt < digits; xt++)
321
        {
322
          for (j = 0; j < FONTX; j++)
323
            {
324
              unsigned char c = (string[xt] & 0x7F);
325
              if (c < 32)
326
                c = 32;
2 mjames 327
 
3 mjames 328
              drawPixel (x + j + xt * FONTX, y + yt,
329
                         get_digits (j + (c - 32) * FONTX, yt));
330
            }
2 mjames 331
        }
3 mjames 332
    }
2 mjames 333
 
334
}
335
 
3 mjames 336
void
337
print_digits (uint8_t x, uint8_t y, uint8_t digits, uint8_t dp_pos, int val)
2 mjames 338
{
339
 
3 mjames 340
  char buff[10] = "        ";
341
  uint8_t len = format_num (buff, digits, dp_pos, val);
342
  print_large_string (buff, x, y, len);
2 mjames 343
}
344
 
345
/* print a digit value 0 to 9 (not ASCII)  rotated by ang */
3 mjames 346
void
347
print_rotated (uint8_t x, uint8_t y, int ang, uint8_t val)
2 mjames 348
{
3 mjames 349
  int co = ap_cos (ang);
350
  int si = ap_sin (ang);
2 mjames 351
 
3 mjames 352
  int xt, yt;
2 mjames 353
 
3 mjames 354
  for (yt = 0; yt < FONTY; yt++) // iterate down scan lines
2 mjames 355
    {
3 mjames 356
      for (xt = 0; xt < FONTX; xt++)
357
        {
358
          if (get_digits (xt + (val + 16) * FONTX, yt))
359
            {
360
              int cx = xt - FONTX / 2;
361
              int cy = yt - FONTY / 2;
2 mjames 362
 
3 mjames 363
              int px = AP_SCALE(cx * co - cy * si);
364
              int py = AP_SCALE(cx * si + cy * co);
2 mjames 365
 
3 mjames 366
              drawPixel (x + px, y + py, WHITE);
367
            }
368
        }
369
    }
2 mjames 370
 
371
}
372