Subversion Repositories chibiosIgnition

Rev

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

  1. /*********************************************************************
  2.  This is a library for our Monochrome OLEDs based on SSD1306 drivers
  3.  
  4.  Pick one up today in the adafruit shop!
  5.  ------> http://www.adafruit.com/category/63_98
  6.  
  7.  These displays use SPI to communicate, 4 or 5 pins are required to
  8.  interface
  9.  
  10.  Adafruit invests time and resources providing this open source code,
  11.  please support Adafruit and open-source hardware by purchasing
  12.  products from Adafruit!
  13.  
  14.  Written by Limor Fried/Ladyada  for Adafruit Industries.
  15.  BSD license, check license.txt for more information
  16.  All text above, and the splash screen below must be included in any redistribution
  17.  
  18.  This code is taken from the ADAfruit library - it is used for playing with an OLED screen
  19.  
  20.  *********************************************************************/
  21.  
  22. #include "ch.h"
  23. #include "hal.h"
  24.  
  25. #include <stdint.h>
  26. #include <string.h>
  27. #include "SSD1306.h"
  28. #include "spiInterface.h"
  29.  
  30. #define swap(x,y) { typeof(x)t = x; x=y; y=t; }
  31. #define abs(x)      ((x)>0?(x):-(x))
  32.  
  33. static uint8_t rotation = 0;
  34. const uint16_t WIDTH = SSD1306_LCDWIDTH;
  35. const uint16_t HEIGHT = SSD1306_LCDHEIGHT;
  36.  
  37. // the memory buffer for the LCD
  38.  
  39. // pointer to the current display - affects buffer used and also chipselect
  40.  
  41. uint8_t display_buffer[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH
  42.                 / 8];
  43.  
  44. inline uint8_t * display_address(void) {
  45.         return (uint8_t *) (&display_buffer[0]);
  46. }
  47.  
  48. inline uint8_t getRotation(void) {
  49.         return rotation;
  50. }
  51.  
  52. inline int16_t width(void) {
  53.         switch (rotation) {
  54.         case 0:
  55.                 return WIDTH;
  56.                 break;
  57.         case 1:
  58.                 return WIDTH;
  59.                 break;
  60.         case 2:
  61.                 return HEIGHT;
  62.                 break;
  63.         case 3:
  64.                 return -WIDTH;
  65.                 break;
  66.         }
  67.         return 0;
  68. }
  69.  
  70. inline int16_t height(void) {
  71.         switch (rotation) {
  72.         case 0:
  73.                 return HEIGHT;
  74.                 break;
  75.         case 1:
  76.                 return HEIGHT;
  77.                 break;
  78.         case 2:
  79.                 return WIDTH;
  80.                 break;
  81.         case 3:
  82.                 return -HEIGHT;
  83.                 break;
  84.         }
  85.         return 0;
  86. }
  87.  
  88.  
  89. // the most basic function, set a single pixel
  90. inline void drawPixel(int16_t x, int16_t y, uint16_t color) {
  91.         if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
  92.                 return;
  93.  
  94.         // check rotation, move pixel around if necessary
  95.         switch (getRotation()) {
  96.         case 1:
  97.                 swap(x, y)
  98.                 ;
  99.                 x = WIDTH - x - 1;
  100.                 break;
  101.         case 2:
  102.                 x = WIDTH - x - 1;
  103.                 y = HEIGHT - y - 1;
  104.                 break;
  105.         case 3:
  106.                 swap(x, y)
  107.                 ;
  108.                 y = HEIGHT - y - 1;
  109.                 break;
  110.         }
  111.  
  112.         // x is which column
  113.         switch (color) {
  114.         case BLACK:
  115.                 display_buffer[x + (y / 8) * SSD1306_LCDWIDTH] &= ~(1 << (y & 7));
  116.                 break;
  117.  
  118.         default:
  119.         case WHITE:
  120.                 display_buffer[x + (y / 8) * SSD1306_LCDWIDTH] |= (1 << (y & 7));
  121.                 break;
  122.  
  123.         case INVERT:
  124.                 display_buffer[x + (y / 8) * SSD1306_LCDWIDTH] ^= (1 << (y & 7));
  125.                 break;
  126.         }
  127. }
  128.  
  129. void ssd1306_begin(uint8_t vccstate, uint8_t i2caddr) {
  130.  
  131.         (void) i2caddr;
  132.         ssd1306resetDisplay();
  133.  
  134.  
  135. #if defined SSD1306_128_32
  136.                 // Init sequence for 128x32 OLED module
  137.                 ssd1306commandSPIwrite(SSD1306_DISPLAYOFF);// 0xAE
  138.                 ssd1306commandSPIwrite(SSD1306_SETDISPLAYCLOCKDIV);// 0xD5
  139.                 ssd1306commandSPIwrite(0x80);// the suggested ratio 0x80
  140.                 ssd1306commandSPIwrite(SSD1306_SETMULTIPLEX);// 0xA8
  141.                 ssd1306commandSPIwrite(0x1F);
  142.                 ssd1306commandSPIwrite(SSD1306_SETDISPLAYOFFSET);// 0xD3
  143.                 ssd1306commandSPIwrite(0x0);// no offset
  144.                 ssd1306commandSPIwrite(SSD1306_SETSTARTLINE | 0x0);// line #0
  145.                 ssd1306commandSPIwrite(SSD1306_CHARGEPUMP);// 0x8D
  146.                 if (vccstate == SSD1306_EXTERNALVCC)
  147.                 {       ssd1306commandSPIwrite(0x10);}
  148.                 else
  149.                 {       ssd1306commandSPIwrite(0x14);}
  150.                 ssd1306commandSPIwrite(SSD1306_MEMORYMODE);                    // 0x20
  151.                 ssd1306commandSPIwrite(0x00);// 0x0 act like ks0108
  152.                 ssd1306commandSPIwrite(SSD1306_SEGREMAP | 0x1);
  153.                 ssd1306commandSPIwrite(SSD1306_COMSCANDEC);
  154.                 ssd1306commandSPIwrite(SSD1306_SETCOMPINS);// 0xDA
  155.                 ssd1306commandSPIwrite(0x02);
  156.                 ssd1306commandSPIwrite(SSD1306_SETCONTRAST);// 0x81
  157.                 ssd1306commandSPIwrite(0x8F);
  158.                 ssd1306commandSPIwrite(SSD1306_SETPRECHARGE);// 0xd9
  159.                 if (vccstate == SSD1306_EXTERNALVCC)
  160.                 {       ssd1306commandSPIwrite(0x22);}
  161.                 else
  162.                 {       ssd1306commandSPIwrite(0xF1);}
  163.                 ssd1306commandSPIwrite(SSD1306_SETVCOMDETECT);                 // 0xDB
  164.                 ssd1306commandSPIwrite(0x40);
  165.                 ssd1306commandSPIwrite(SSD1306_DISPLAYALLON_RESUME);// 0xA4
  166.                 ssd1306commandSPIwrite(SSD1306_NORMALDISPLAY);// 0xA6
  167. #endif
  168.  
  169. #if defined SSD1306_128_64
  170.                 // Init sequence for 128x64 OLED module
  171.                 ssd1306commandSPIwrite(SSD1306_DISPLAYOFF);                    // 0xAE
  172.                 ssd1306commandSPIwrite(SSD1306_SETDISPLAYCLOCKDIV);            // 0xD5
  173.                 ssd1306commandSPIwrite(0x80);                                  // the suggested ratio 0x80
  174.                 ssd1306commandSPIwrite(SSD1306_SETMULTIPLEX);                  // 0xA8
  175.                 ssd1306commandSPIwrite(0x3F);
  176.                 ssd1306commandSPIwrite(SSD1306_SETDISPLAYOFFSET);              // 0xD3
  177.                 ssd1306commandSPIwrite(0x0);                                   // no offset
  178.                 ssd1306commandSPIwrite(SSD1306_SETSTARTLINE | 0x0);            // line #0
  179.                 ssd1306commandSPIwrite(SSD1306_CHARGEPUMP);                    // 0x8D
  180.                 if (vccstate == SSD1306_EXTERNALVCC) {
  181.                         ssd1306commandSPIwrite(0x10);
  182.                 } else {
  183.                         ssd1306commandSPIwrite(0x14);
  184.                 }
  185.                 ssd1306commandSPIwrite(SSD1306_MEMORYMODE);                    // 0x20
  186.                 ssd1306commandSPIwrite(0x00);                            // 0x0 act like ks0108
  187.                 ssd1306commandSPIwrite(SSD1306_SEGREMAP | 0x1);
  188.                 ssd1306commandSPIwrite(SSD1306_COMSCANDEC);
  189.                 ssd1306commandSPIwrite(SSD1306_SETCOMPINS);                    // 0xDA
  190.                 ssd1306commandSPIwrite(0x12);
  191.                 ssd1306commandSPIwrite(SSD1306_SETCONTRAST);                   // 0x81
  192.                 if (vccstate == SSD1306_EXTERNALVCC) {
  193.                         ssd1306commandSPIwrite(0x9F);
  194.                 } else {
  195.                         ssd1306commandSPIwrite(0xCF);
  196.                 }
  197.                 ssd1306commandSPIwrite(SSD1306_SETPRECHARGE);                  // 0xd9
  198.                 if (vccstate == SSD1306_EXTERNALVCC) {
  199.                         ssd1306commandSPIwrite(0x22);
  200.                 } else {
  201.                         ssd1306commandSPIwrite(0xF1);
  202.                 }
  203.                 ssd1306commandSPIwrite(SSD1306_SETVCOMDETECT);                 // 0xDB
  204.                 ssd1306commandSPIwrite(0x40);
  205.                 ssd1306commandSPIwrite(SSD1306_DISPLAYALLON_RESUME);           // 0xA4
  206.                 ssd1306commandSPIwrite(SSD1306_NORMALDISPLAY);                 // 0xA6
  207. #endif
  208.  
  209.                 ssd1306commandSPIwrite(SSD1306_DISPLAYON);               //--turn on oled panel
  210.  
  211. }
  212.  
  213. void invertDisplay(uint8_t i) {
  214.         if (i) {
  215.                 ssd1306commandSPIwrite(SSD1306_INVERTDISPLAY);
  216.         } else {
  217.                 ssd1306commandSPIwrite(SSD1306_NORMALDISPLAY);
  218.         }
  219. }
  220.  
  221.  
  222. // startscrollright
  223. // Activate a right handed scroll for rows start through stop
  224. // Hint, the display is 16 rows tall. To scroll the whole display, run:
  225. // display.scrollright(0x00, 0x0F)
  226. void startscrollright(uint8_t start, uint8_t stop) {
  227.         ssd1306commandSPIwrite(SSD1306_RIGHT_HORIZONTAL_SCROLL);
  228.         ssd1306commandSPIwrite(0X00);
  229.         ssd1306commandSPIwrite(start);
  230.         ssd1306commandSPIwrite(0X00);
  231.         ssd1306commandSPIwrite(stop);
  232.         ssd1306commandSPIwrite(0X00);
  233.         ssd1306commandSPIwrite(0XFF);
  234.         ssd1306commandSPIwrite(SSD1306_ACTIVATE_SCROLL);
  235. }
  236.  
  237. // startscrollleft
  238. // Activate a right handed scroll for rows start through stop
  239. // Hint, the display is 16 rows tall. To scroll the whole display, run:
  240. // display.scrollright(0x00, 0x0F)
  241. void startscrollleft(uint8_t start, uint8_t stop) {
  242.         ssd1306commandSPIwrite(SSD1306_LEFT_HORIZONTAL_SCROLL);
  243.         ssd1306commandSPIwrite(0X00);
  244.         ssd1306commandSPIwrite(start);
  245.         ssd1306commandSPIwrite(0X00);
  246.         ssd1306commandSPIwrite(stop);
  247.         ssd1306commandSPIwrite(0X00);
  248.         ssd1306commandSPIwrite(0XFF);
  249.         ssd1306commandSPIwrite(SSD1306_ACTIVATE_SCROLL);
  250. }
  251.  
  252. // startscrolldiagright
  253. // Activate a diagonal scroll for rows start through stop
  254. // Hint, the display is 16 rows tall. To scroll the whole display, run:
  255. // display.scrollright(0x00, 0x0F)
  256. void startscrolldiagright(uint8_t start, uint8_t stop) {
  257.         ssd1306commandSPIwrite(SSD1306_SET_VERTICAL_SCROLL_AREA);
  258.         ssd1306commandSPIwrite(0X00);
  259.         ssd1306commandSPIwrite(SSD1306_LCDHEIGHT);
  260.         ssd1306commandSPIwrite(SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
  261.         ssd1306commandSPIwrite(0X00);
  262.         ssd1306commandSPIwrite(start);
  263.         ssd1306commandSPIwrite(0X00);
  264.         ssd1306commandSPIwrite(stop);
  265.         ssd1306commandSPIwrite(0X01);
  266.         ssd1306commandSPIwrite(SSD1306_ACTIVATE_SCROLL);
  267. }
  268.  
  269. // startscrolldiagleft
  270. // Activate a diagonal scroll for rows start through stop
  271. // Hint, the display is 16 rows tall. To scroll the whole display, run:
  272. // display.scrollright(0x00, 0x0F)
  273. void startscrolldiagleft(uint8_t start, uint8_t stop) {
  274.         ssd1306commandSPIwrite(SSD1306_SET_VERTICAL_SCROLL_AREA);
  275.         ssd1306commandSPIwrite(0X00);
  276.         ssd1306commandSPIwrite(SSD1306_LCDHEIGHT);
  277.         ssd1306commandSPIwrite(SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
  278.         ssd1306commandSPIwrite(0X00);
  279.         ssd1306commandSPIwrite(start);
  280.         ssd1306commandSPIwrite(0X00);
  281.         ssd1306commandSPIwrite(stop);
  282.         ssd1306commandSPIwrite(0X01);
  283.         ssd1306commandSPIwrite(SSD1306_ACTIVATE_SCROLL);
  284. }
  285.  
  286. void stopscroll(void) {
  287.         ssd1306commandSPIwrite(SSD1306_DEACTIVATE_SCROLL);
  288. }
  289.  
  290. // Dim the display
  291. // dim = true: display is dimmed
  292. // dim = false: display is normal
  293. void dim(uint8_t contrast) {
  294.  
  295.         // the range of contrast to too small to be really useful
  296.         // it is useful to dim the display
  297.         ssd1306commandSPIwrite(SSD1306_SETCONTRAST);
  298.         ssd1306commandSPIwrite(contrast);
  299. }
  300.  
  301. void display(void) {
  302.  
  303.  
  304.         // select entire display as window to write into
  305.         ssd1306commandSPIwrite(SSD1306_COLUMNADDR);
  306.         ssd1306commandSPIwrite(0);   // Column start address (0 = reset)
  307.         ssd1306commandSPIwrite(SSD1306_RAMWIDTH-1); // Column end address (127 = reset)
  308.  
  309.         ssd1306commandSPIwrite(SSD1306_PAGEADDR);
  310.         ssd1306commandSPIwrite(0); // Page start address (0 = reset)
  311.         ssd1306commandSPIwrite((SSD1306_LCDHEIGHT == 64) ? 7 : 3); // Page end address
  312.  
  313.         int row;
  314.  
  315.         int col = SSD1306_RAMWIDTH == 132 ? 2 : 0;
  316.         for (row = 0; row < SSD1306_LCDHEIGHT / 8; row++) {
  317.                 // set the cursor to
  318.                 ssd1306commandSPIwrite(0xB0 + row); //set page address
  319.                 ssd1306commandSPIwrite(col & 0xf); //set lower column address
  320.                 ssd1306commandSPIwrite(0x10 | (col >> 4)); //set higher column address
  321.  
  322.                 ssd1306SendDisplay(
  323.                                 (uint8_t *) (&display_buffer[0]) + row * SSD1306_LCDWIDTH,
  324.                                 SSD1306_LCDWIDTH);
  325.  
  326.         }
  327.  
  328. }
  329.  
  330. // clear everything
  331. void clearDisplay(void) {
  332.         memset(&display_buffer, 0, (SSD1306_LCDWIDTH * SSD1306_LCDHEIGHT / 8));
  333. }
  334.  
  335.  
  336. /* using Bresenham draw algorithm */
  337. void drawLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t color) {
  338.         int16_t x,   y,
  339.                 dx,  dy,    //deltas
  340.                         dx2, dy2,       //scaled deltas
  341.                     ix,  iy,    //increase rate on the x and y axis
  342.                         err;    //the error term
  343.         uint16_t i;             //looping variable
  344.  
  345.         // identify the first pixel
  346.         x = x1;
  347.         y = y1;
  348.  
  349.         // difference between starting and ending points
  350.         dx = x2 - x1;
  351.         dy = y2 - y1;
  352.  
  353.         // calculate direction of the vector and store in ix and iy
  354.         if (dx >= 0)
  355.                 ix = 1;
  356.  
  357.         if (dx < 0) {
  358.                 ix = -1;
  359.                 dx = abs(dx);
  360.         }
  361.  
  362.         if (dy >= 0)
  363.                 iy = 1;
  364.  
  365.         if (dy < 0) {
  366.                 iy = -1;
  367.                 dy = abs(dy);
  368.         }
  369.  
  370.         // scale deltas and store in dx2 and dy2
  371.         dx2 = dx * 2;
  372.         dy2 = dy * 2;
  373.  
  374. // all  variables are set and it's time to enter the main loop.
  375.  
  376.         if (dx > dy)    // dx is the major axis
  377.                         {
  378.                 // initialize the error term
  379.                 err = dy2 - dx;
  380.  
  381.                 for (i = 0; i <= dx; i++) {
  382.                         drawPixel(x, y, color);
  383.                         if (err >= 0) {
  384.                                 err -= dx2;
  385.                                 y += iy;
  386.                         }
  387.                         err += dy2;
  388.                         x += ix;
  389.                 }
  390.         }
  391.  
  392.         else            // dy is the major axis
  393.         {
  394.                 // initialize the error term
  395.                 err = dx2 - dy;
  396.  
  397.                 for (i = 0; i <= dy; i++) {
  398.                         drawPixel(x, y, color);
  399.                         if (err >= 0) {
  400.                                 err -= dy2;
  401.                                 x += ix;
  402.                         }
  403.                         err += dx2;
  404.                         y += iy;
  405.                 }
  406.         }
  407. }
  408.