Subversion Repositories libOLED

Rev

Rev 3 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * displayclass.cpp
  3.  *
  4.  *  Created on: 31 Oct 2020
  5.  *      Author: mike
  6.  */
  7.  
  8. #include "libOLED/displayclass.H"
  9.  
  10. #include <cstring>
  11. #include <cstdlib>
  12. namespace
  13. {
  14.   uint8_t const SSD1306_SETCONTRAST = 0x81;
  15.   uint8_t const SSD1306_DISPLAYALLON_RESUME = 0xA4;
  16.   uint8_t const SSD1306_DISPLAYALLON = 0xA5;
  17.   uint8_t const SSD1306_NORMALDISPLAY = 0xA6;
  18.   uint8_t const SSD1306_INVERTDISPLAY = 0xA7;
  19.   uint8_t const SSD1306_DISPLAYOFF = 0xAE;
  20.   uint8_t const SSD1306_DISPLAYON = 0xAF;
  21.  
  22.   uint8_t const SSD1306_SETDISPLAYOFFSET = 0xD3;
  23.   uint8_t const SSD1306_SETCOMPINS = 0xDA;
  24.  
  25.   uint8_t const SSD1306_SETVCOMDETECT = 0xDB;
  26.  
  27.   uint8_t const SSD1306_SETDISPLAYCLOCKDIV = 0xD5;
  28.   uint8_t const SSD1306_SETPRECHARGE = 0xD9;
  29.  
  30.   uint8_t const SSD1306_SETMULTIPLEX = 0xA8;
  31.  
  32.   uint8_t const SSD1306_SETLOWCOLUMN = 0x00;
  33.   uint8_t const SSD1306_SETHIGHCOLUMN = 0x10;
  34.  
  35.   uint8_t const SSD1306_SETSTARTLINE = 0x40;
  36.  
  37.   uint8_t const SSD1306_MEMORYMODE = 0x20;
  38.   uint8_t const SSD1306_COLUMNADDR = 0x21;
  39.   uint8_t const SSD1306_PAGEADDR = 0x22;
  40.  
  41.   uint8_t const SSD1306_COMSCANINC = 0xC0;
  42.   uint8_t const SSD1306_COMSCANDEC = 0xC8;
  43.  
  44.   uint8_t const SSD1306_SEGREMAP = 0xA0;
  45.  
  46.   uint8_t const SSD1306_CHARGEPUMP = 0x8D;
  47.  
  48.   uint8_t const SSD1306_EXTERNALVCC = 0x1;
  49.   uint8_t const SSD1306_SWITCHCAPVCC = 0x2;
  50.  
  51. // Scrolling #defines
  52.   uint8_t const SSD1306_ACTIVATE_SCROLL = 0x2F;
  53.   uint8_t const SSD1306_DEACTIVATE_SCROLL = 0x2E;
  54.   uint8_t const SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3;
  55.   uint8_t const SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26;
  56.   uint8_t const SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27;
  57.   uint8_t const SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29;
  58.   uint8_t const SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A;
  59.  
  60.   template<class T>
  61.     void
  62.     swap (T &x, T &y)
  63.     {
  64.       T temp = x;
  65.       x = y;
  66.       y = temp;
  67.     }
  68.  
  69.   template<class T>
  70.     T
  71.     abs (T x)
  72.     {
  73.       return x < 0 ? -x : x;
  74.     }
  75.  
  76.  
  77.  
  78. }
  79. // provided to allow a destructor to destroy something not deleted
  80. // this is only OK because destructors shouldnt be needed
  81. void operator delete(void * data, unsigned int f)
  82.  {
  83.    (void)data;
  84.    (void)f;
  85.  }
  86.  
  87. // provided to implement an "error handler" on pure virtual
  88. extern "C" void __cxa_pure_virtual()
  89. {
  90.   while(1);
  91. }
  92.  
  93. display_t::display_t (int const width, int const height, int const ramwidth,
  94.                       uint8_t *const data) :
  95.     m_width (width), m_height (height), m_ramwidth (ramwidth), m_cursor_x (0), m_cursor_y (
  96.         0), m_rotation (0), m_data (data)
  97. {
  98. }
  99.  
  100. display_t::~display_t()
  101. {
  102.  
  103. }
  104.  
  105. void
  106. display_t::display_t::init ()
  107. {
  108.   uint8_t const vccstate = SSD1306_EXTERNALVCC;
  109.  
  110.   oledReset ();
  111.  
  112.   oledSetCD (0);
  113.  
  114.   // Init sequence for 128x32 or 128x64  OLED module
  115.   oledWrite (SSD1306_DISPLAYOFF); // 0xAE
  116.   oledWrite (SSD1306_SETDISPLAYCLOCKDIV); // 0xD5
  117.   oledWrite (0x80); // the suggested ratio 0x80
  118.   oledWrite (SSD1306_SETMULTIPLEX); // 0xA8
  119.   oledWrite (m_height - 1);
  120.   oledWrite (SSD1306_SETDISPLAYOFFSET); // 0xD3
  121.   oledWrite (0x0); // no offset
  122.   oledWrite (SSD1306_SETSTARTLINE | 0x0); // line #0
  123.   oledWrite (SSD1306_CHARGEPUMP); // 0x8D
  124.   oledWrite (vccstate == SSD1306_EXTERNALVCC ? 0x10 : 0x14);
  125.   oledWrite (SSD1306_MEMORYMODE);                    // 0x20
  126.   oledWrite (0x00);                    // 0x0 act like ks0108
  127.   oledWrite (SSD1306_SEGREMAP | 0x1);
  128.   oledWrite (SSD1306_COMSCANDEC);
  129.   oledWrite (SSD1306_SETCOMPINS);                    // 0xDA
  130.   oledWrite (m_height == 32 ? 0x02 : 0x12);
  131.   oledWrite (SSD1306_SETCONTRAST);                    // 0x81
  132.   oledWrite (vccstate == SSD1306_EXTERNALVCC ? 0x9F : 0xCF);
  133.   oledWrite (SSD1306_SETPRECHARGE);                    // 0xd9
  134.   oledWrite (vccstate == SSD1306_EXTERNALVCC ? 0x22 : 0xF1);
  135.   oledWrite (SSD1306_SETVCOMDETECT);                 // 0xDB
  136.   oledWrite (0x40);
  137.   oledWrite (SSD1306_DISPLAYALLON_RESUME);                 // 0xA4
  138.   oledWrite (SSD1306_NORMALDISPLAY);                 // 0xA6
  139.  
  140.   oledWrite (SSD1306_DISPLAYON);             //--turn on oled panel
  141.  
  142.   clearDisplay ();
  143.  
  144. }
  145.  
  146. uint8_t
  147. display_t::getRotation (void)
  148. {
  149.   return m_rotation;
  150. }
  151.  
  152. int16_t
  153. display_t::width (void)
  154. {
  155.   switch (m_rotation)
  156.     {
  157.     case 0:
  158.       return m_width;
  159.       break;
  160.     case 1:
  161.       return m_width;
  162.       break;
  163.     case 2:
  164.       return m_height;
  165.       break;
  166.     case 3:
  167.       return -m_width;
  168.       break;
  169.     }
  170.   return 0;
  171. }
  172.  
  173. int16_t
  174. display_t::height (void)
  175. {
  176.   switch (m_rotation)
  177.     {
  178.     case 0:
  179.       return m_height;
  180.       break;
  181.     case 1:
  182.       return m_height;
  183.       break;
  184.     case 2:
  185.       return m_width;
  186.       break;
  187.     case 3:
  188.       return -m_height;
  189.       break;
  190.     }
  191.   return 0;
  192. }
  193.  
  194. // the most basic function, set a single pixel
  195. inline void
  196. display_t::drawPixel (int16_t x, int16_t y, colour_t color)
  197. {
  198.   if ((x < 0) || (x >= m_width) || (y < 0) || (y >= m_height))
  199.     return;
  200.  
  201.   // check rotation, move pixel around if necessary
  202.   switch (m_rotation)
  203.     {
  204.     case 1:
  205.       swap (x, y);
  206.       x = m_width - x - 1;
  207.       break;
  208.     case 2:
  209.       x = m_width - x - 1;
  210.       y = m_height - y - 1;
  211.       break;
  212.     case 3:
  213.       swap (x, y);
  214.       y = m_height - y - 1;
  215.       break;
  216.     }
  217.  
  218.   // x is which column
  219.   switch (color)
  220.     {
  221.     case BLACK:
  222.       m_data[x + (y / 8) * m_width] &= ~(1 << (y & 7));
  223.       break;
  224.  
  225.     default:
  226.     case WHITE:
  227.       m_data[x + (y / 8) * m_width] |= (1 << (y & 7));
  228.       break;
  229.  
  230.     case INVERT:
  231.       m_data[x + (y / 8) * m_width] ^= (1 << (y & 7));
  232.       break;
  233.     }
  234. }
  235.  
  236. void
  237. display_t::invertDisplay (uint8_t i)
  238. {
  239.   oledSetCD (0);
  240.   oledWrite (i ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
  241. }
  242.  
  243. // startscrollright
  244. // Activate a right handed scroll for rows start through stop
  245. // Hint, the display is 16 rows tall. To scroll the whole display, run:
  246. // display.scrollright(0x00, 0x0F)
  247. void
  248. display_t::startscrollright (uint8_t start, uint8_t stop)
  249. {
  250.   oledSetCD (0);
  251.   oledWrite (SSD1306_RIGHT_HORIZONTAL_SCROLL);
  252.   oledWrite (0X00);
  253.   oledWrite (start);
  254.   oledWrite (0X00);
  255.   oledWrite (stop);
  256.   oledWrite (0X00);
  257.   oledWrite (0XFF);
  258.   oledWrite (SSD1306_ACTIVATE_SCROLL);
  259. }
  260.  
  261. // startscrollleft
  262. // Activate a right handed scroll for rows start through stop
  263. // Hint, the display is 16 rows tall. To scroll the whole display, run:
  264. // display.scrollright(0x00, 0x0F)
  265. void
  266. display_t::startscrollleft (uint8_t start, uint8_t stop)
  267. {
  268.   oledSetCD (0);
  269.   oledWrite (SSD1306_LEFT_HORIZONTAL_SCROLL);
  270.   oledWrite (0X00);
  271.   oledWrite (start);
  272.   oledWrite (0X00);
  273.   oledWrite (stop);
  274.   oledWrite (0X00);
  275.   oledWrite (0XFF);
  276.   oledWrite (SSD1306_ACTIVATE_SCROLL);
  277. }
  278.  
  279. // startscrolldiagright
  280. // Activate a diagonal scroll for rows start through stop
  281. // Hint, the display is 16 rows tall. To scroll the whole display, run:
  282. // display.scrollright(0x00, 0x0F)
  283. void
  284. display_t::startscrolldiagright (uint8_t start, uint8_t stop)
  285. {
  286.   oledSetCD (0);
  287.   oledWrite (SSD1306_SET_VERTICAL_SCROLL_AREA);
  288.   oledWrite (0X00);
  289.   oledWrite (m_height);
  290.   oledWrite (SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
  291.   oledWrite (0X00);
  292.   oledWrite (start);
  293.   oledWrite (0X00);
  294.   oledWrite (stop);
  295.   oledWrite (0X01);
  296.   oledWrite (SSD1306_ACTIVATE_SCROLL);
  297. }
  298.  
  299. // startscrolldiagleft
  300. // Activate a diagonal scroll for rows start through stop
  301. // Hint, the display is 16 rows tall. To scroll the whole display, run:
  302. // display.scrollright(0x00, 0x0F)
  303. void
  304. display_t::startscrolldiagleft (uint8_t start, uint8_t stop)
  305. {
  306.   oledSetCD (0);
  307.   oledWrite (SSD1306_SET_VERTICAL_SCROLL_AREA);
  308.   oledWrite (0X00);
  309.   oledWrite (m_height);
  310.   oledWrite (SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
  311.   oledWrite (0X00);
  312.   oledWrite (start);
  313.   oledWrite (0X00);
  314.   oledWrite (stop);
  315.   oledWrite (0X01);
  316.   oledWrite (SSD1306_ACTIVATE_SCROLL);
  317. }
  318.  
  319. void
  320. display_t::stopscroll (void)
  321. {
  322.   oledSetCD (0);
  323.   oledWrite (SSD1306_DEACTIVATE_SCROLL);
  324. }
  325.  
  326. // Dim the display
  327. // dim = true: display is dimmed
  328. // dim = false: display is normal
  329. void
  330. display_t::dim (uint8_t contrast)
  331. {
  332.  
  333.   // the range of contrast to too small to be really useful
  334.   // it is useful to dim the display
  335.  
  336.   oledSetCD (0);
  337.   oledWrite (SSD1306_SETCONTRAST);
  338.   oledWrite (contrast);
  339. }
  340.  
  341. void
  342. display_t::display (void)
  343. {
  344.   oledSetCD (0);
  345.   // select entire display as window to write into
  346.   oledWrite (SSD1306_COLUMNADDR);
  347.   oledWrite (0);   // Column start address (0 = reset)
  348.   oledWrite (m_ramwidth - 1); // Column end address (127 = reset)
  349.  
  350.   oledWrite (SSD1306_PAGEADDR);
  351.   oledWrite (0); // Page start address (0 = reset)
  352.   oledWrite ((m_height == 64) ? 7 : 3); // Page end address
  353.  
  354.   int row;
  355.  
  356.   int col = m_ramwidth == 132 ? 2 : 0;
  357.   for (row = 0; row < m_height / 8; row++)
  358.     {
  359.       oledSetCD (0);
  360.       // set the cursor to
  361.       oledWrite (0xB0 + row); //set page address
  362.       oledWrite (col & 0xf); //set lower column address
  363.       oledWrite (0x10 | (col >> 4)); //set higher column address
  364.  
  365.       oledSetCD (1);
  366.       oledWrite (m_data + row * m_width, m_width);
  367.  
  368.     }
  369.  
  370. }
  371.  
  372. // clear everything
  373. void
  374. display_t::clearDisplay (void)
  375. {
  376.   memset (m_data, 0, dataSize (m_width, m_height));
  377. }
  378.  
  379. /* using Bresenham draw algorithm */
  380. void
  381. display_t::drawLine (int16_t x1, int16_t y1, int16_t x2, int16_t y2,
  382.                      colour_t color)
  383. {
  384.   int16_t x, y, dx, dy,    //deltas
  385.       dx2, dy2, //scaled deltas
  386.       ix, iy,   //increase rate on the x and y axis
  387.       err;      //the error term
  388.   uint16_t i;           //looping variable
  389.  
  390.   // identify the first pixel
  391.   x = x1;
  392.   y = y1;
  393.  
  394.   // difference between starting and ending points
  395.   dx = x2 - x1;
  396.   dy = y2 - y1;
  397.  
  398.   // calculate direction of the vector and store in ix and iy
  399.   if (dx >= 0)
  400.     ix = 1;
  401.  
  402.   if (dx < 0)
  403.     {
  404.       ix = -1;
  405.       dx = abs (dx);
  406.     }
  407.  
  408.   if (dy >= 0)
  409.     iy = 1;
  410.  
  411.   if (dy < 0)
  412.     {
  413.       iy = -1;
  414.       dy = abs (dy);
  415.     }
  416.  
  417.   // scale deltas and store in dx2 and dy2
  418.   dx2 = dx * 2;
  419.   dy2 = dy * 2;
  420.  
  421. // all  variables are set and it's time to enter the main loop.
  422.  
  423.   if (dx > dy)  // dx is the major axis
  424.     {
  425.       // initialize the error term
  426.       err = dy2 - dx;
  427.  
  428.       for (i = 0; i <= dx; i++)
  429.         {
  430.           drawPixel (x, y, color);
  431.           if (err >= 0)
  432.             {
  433.               err -= dx2;
  434.               y += iy;
  435.             }
  436.           err += dy2;
  437.           x += ix;
  438.         }
  439.     }
  440.  
  441.   else          // dy is the major axis
  442.     {
  443.       // initialize the error term
  444.       err = dx2 - dy;
  445.  
  446.       for (i = 0; i <= dy; i++)
  447.         {
  448.           drawPixel (x, y, color);
  449.           if (err >= 0)
  450.             {
  451.               err -= dy2;
  452.               x += ix;
  453.             }
  454.           err += dx2;
  455.           y += iy;
  456.         }
  457.     }
  458. }
  459.  
  460. void
  461. printString (font_t &font, char *string, int length, colour_t colour)
  462. {
  463.   (void) font;
  464.   (void) string;
  465.   (void) length;
  466.   (void) colour;
  467. }
  468.  
  469. void
  470. printChar (font_t &font, char c, colour_t colour)
  471. {
  472.   (void) font;
  473.   (void) c;
  474.   (void) colour;
  475. }
  476.