Subversion Repositories libSSD1306

Rev

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

  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.  */
  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
  120.  
  121.   };
  122.  
  123. #define extDegrees 0
  124.  
  125. static const unsigned char font_ext[][5] =
  126.   {
  127.  
  128.   [extDegrees] =
  129.     { 0x00, 0x06, 0x09, 0x06, 0x00 }, // a ° sign
  130.  
  131.     };
  132.  
  133. void
  134. font_gotoxy (uint8_t x, uint8_t y)
  135. {
  136.   cursor_x = x;
  137.   cursor_y = y;
  138. }
  139.  
  140. void
  141. font_putchar (uint8_t c)
  142. {
  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)
  150.         {
  151.           cursor_y = 0;
  152.         }
  153.       return;
  154.     }
  155.  
  156.   for (i = 0; i < 5; i++)
  157.     {
  158.       if (c > ' ' && c < 0x80)
  159.         {
  160.           *ptr++ = font[c - ' '][i];
  161.         }
  162.       else if (c == '°')
  163.         {
  164.           *ptr++ = font_ext[extDegrees][i];
  165.         }
  166.       else
  167.         {
  168.           *ptr++ = 0;
  169.         }
  170.     }
  171.   *ptr++ = 0;
  172.  
  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)
  180.         {
  181.           cursor_y = 0;
  182.         }
  183.     }
  184.  
  185. }
  186.  
  187. void
  188. font_puts (uint8_t *s)
  189. {
  190.   while (s && *s)
  191.     {
  192.       font_putchar (*(s++));
  193.     }
  194. }
  195.  
  196. uint8_t
  197. get_digits (uint16_t x, uint16_t y)
  198. {
  199.   return ((ascii_lucida_bits[(y * ascii_lucida_width) / 8 + (x / 8)]) >> (x & 7))
  200.       & 1;
  201. }
  202.  
  203. static uint8_t
  204. format_num (char *buff, uint8_t digits, uint8_t dp_pos, int val)
  205. {
  206.   digits++;
  207.   uint8_t pos = digits;
  208.   uint8_t dp_loc = pos - dp_pos;
  209.   uint8_t sign = 0;
  210.   if (val < 0)
  211.     {
  212.       sign = 1;
  213.       val = -val;
  214.     }
  215.  
  216.   buff[pos] = 0;
  217.   while (pos)
  218.     {
  219.       if (pos == dp_loc)
  220.         {
  221.           buff[--pos] = '.';
  222.         }
  223.       else
  224.         {
  225.           buff[--pos] = val % 10 + '0';
  226.           val /= 10;
  227.           if (val == 0 && pos < dp_loc)
  228.             break;
  229.         }
  230.     }
  231.   if (sign)
  232.     {
  233.       buff[--pos] = '-';
  234.     }
  235.   return digits;
  236. }
  237.  
  238. void
  239. font_digits (uint8_t digits, uint8_t dp_pos, int val)
  240. {
  241.   char buff[10] = "        ";
  242.   format_num (buff, digits, dp_pos, val);
  243.   font_puts ((unsigned char *)buff);
  244. }
  245.  
  246. void
  247. font_sig_digits (uint8_t x, uint8_t y, uint8_t right_justify, uint8_t dp_pos,
  248.                  int val)
  249. {
  250.   char digits;
  251.   char sign = 0;
  252.   int uval;
  253.   if (val < 0)
  254.     {
  255.       uval = -val;
  256.       sign = 1; // mark as negative
  257.     }
  258.   else
  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.     }
  278.   // backup for the - sign if right justified
  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.     }
  291.  
  292.   font_gotoxy (x, y);
  293.   font_digits (digits, dp_pos, val);
  294. }
  295.  
  296. #define FONTX 10
  297. #define FONTY 18
  298.  
  299. void
  300. scan_xbm (void)
  301. {
  302.  
  303.   int i, j;
  304.  
  305.   for (i = 0; i < FONTY; i++)
  306.     {
  307.       for (j = 0; j < FONTX * 6; j++)
  308.         {
  309.           drawPixel (j, i, get_digits (j, i));
  310.         }
  311.     }
  312. }
  313.  
  314. void
  315. print_large_string (char *string, int x, int y, int digits)
  316. {
  317.   int xt, yt, j;
  318.   for (yt = 0; yt < FONTY; yt++) // iterate down scan lines
  319.     {
  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;
  327.  
  328.               drawPixel (x + j + xt * FONTX, y + yt,
  329.                          get_digits (j + (c - 32) * FONTX, yt));
  330.             }
  331.         }
  332.     }
  333.  
  334. }
  335.  
  336. void
  337. print_digits (uint8_t x, uint8_t y, uint8_t digits, uint8_t dp_pos, int val)
  338. {
  339.  
  340.   char buff[10] = "        ";
  341.   uint8_t len = format_num (buff, digits, dp_pos, val);
  342.   print_large_string (buff, x, y, len);
  343. }
  344.  
  345. /* print a digit value 0 to 9 (not ASCII)  rotated by ang */
  346. void
  347. print_rotated (uint8_t x, uint8_t y, int ang, uint8_t val)
  348. {
  349.   int co = ap_cos (ang);
  350.   int si = ap_sin (ang);
  351.  
  352.   int xt, yt;
  353.  
  354.   for (yt = 0; yt < FONTY; yt++) // iterate down scan lines
  355.     {
  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;
  362.  
  363.               int px = AP_SCALE(cx * co - cy * si);
  364.               int py = AP_SCALE(cx * si + cy * co);
  365.  
  366.               drawPixel (x + px, y + py, WHITE);
  367.             }
  368.         }
  369.     }
  370.  
  371. }
  372.  
  373.