Hi Bill,
Update. I looked at the attached Arduino library and they send a lot of
commands during initialization like yoiu do using the procedure
sh1106_command(). This procedure is as follows for IIC:
void Adafruit_SH1106::SH1106_command(uint8_t c) {
// I2C
uint8_t control = 0x00; // Co = 0, D/C = 0
Wire.beginTransmission(_i2caddr);
WIRE_WRITE(control);
WIRE_WRITE(c);
Wire.endTransmission();
}
So they send all data starting with a transmission of zero. I cannot find in
the documentation why that works but maybe it does.
Kind regards,
Rob
________________________________
Van: [email protected] <[email protected]> namens Rob CJ
<[email protected]>
Verzonden: donderdag 15 januari 2026 18:07
Aan: [email protected] <[email protected]>
Onderwerp: Re: [jallib] Re: Update SSD1306 library supporting bigger font
Hi Bill,
First quick analisys starting at the intialize routine. You start a
transmission and then you send bytes but it does not work that way since the
device has various registers and it needs to know to which register you are
addressing. Instead you better call the procedure that start a transmission,
sends the command and the data and stops the transmission.
For example for setting the contrast. You use the following at the
initialization after you have sent other data too:
_sh1106_write_byte(_sh1106_SET_CONTRAST)
_sh1106_write_byte(0x9F) -- A = 0x9F or 0xCF P = 0xAF
But you should send the contrast command (control byte) followed by the
contrast data in each transmission like in the procedure set_contrast()
_sh1106_start_transmission(_sh1106_COMMAND_TRANSMISSION)
_sh1106_write_byte(_sh1106_SET_CONTRAST)
_sh1106_write_byte(contrast)
_sh1106_stop_transmission()
I noticed you based this on an olderversion of the ssd1306 library. In the
newer version I removed the include of the IIC library which has to be done by
the main program (as it should according to the JAL style guide).
I hope this helps for the first step.
Kind regards,
Rob
________________________________
Van: [email protected] <[email protected]> namens Bill Beek
<[email protected]>
Verzonden: woensdag 14 januari 2026 20:43
Aan: jallib <[email protected]>
Onderwerp: Re: [jallib] Re: Update SSD1306 library supporting bigger font
Hi Rob,
Not working at all, see picture. I studied several arduino libs but that didn't
give me a solution.
While the programmers write, that it is a small modification of the SSD1306, I
don't see it.
When I use the 1306 with this lib, the first line written from right to left
with the text in mirrored image.
Kind regards, Bill.
On Wednesday, January 14, 2026 at 6:57:06 PM UTC+1 Rob CJ wrote:
Hi Bill,
That may take some time because those datasheets are not always that clear,
especially Chinese ones.
Have you looked at an Arduino library for this display? That often gives an
idea about how things should work. I know for example that I could never have
written the library for the ili9341LCD without some info I got from the Arduino
library and I still wonder how they figured out certain settings while the
documentation did not give any clue on that.
Is nothing working or are certain things not working?
Kind regards,
Rob
________________________________
Van: [email protected] <[email protected]> namens Bill Beek
<[email protected]>
Verzonden: dinsdag 13 januari 2026 20:24
Aan: jallib <[email protected]>
Onderwerp: Re: [jallib] Re: Update SSD1306 library supporting bigger font
Hi Rob,
I tried to make the SSD1306 library suitable for the SH1106, but it won’t work.
Addressing the memory is different, with line, page and column addresses.
Because I don’t fully understand the 1306 lib, it is difficult for me to make
it work.
Maybe you want to look at the data sheet to make some suggestions.
I send the lib along. I deleted the SPI and scroll functions to keep it simple.
Thank you in advance, and best wishes for 2026 to the group.
Bill.
On Thursday, September 25, 2025 at 9:48:13 PM UTC+2 Rob CJ wrote:
Hi Bill.
FYI. I finished the update of the glcd_ssd1306 library and the sample files.
Tested it with all JAL Fonts using I2C and SPI and all seem to work fine.
I uploaded it to GitHub so it should be in the bee package of the upcoming
weekend.
Since the version you have works for the 12x16 font it did not yet work for all
available JAL fonts but that has been fixed. As said before, the IIC and SPI
libraries now need to be included by the main program as to make the library
compliant with the JAL style guide. It now also gives more flexibilty since you
can now also use SPI 2 and I2C 2 if you needed that but it is a breaking change
with the previous version of the library. Examples are given in de sample files.
Kind regards,
Rob
________________________________
Van: [email protected] <[email protected]> namens Rob CJ
<[email protected]>
Verzonden: donderdag 25 september 2025 19:05
Aan: jallib <[email protected]>
Onderwerp: Re: [jallib] Re: Update SSD1306 library supporting bigger font
Hi Bill,
Good to hear that it works. As I mentioned before the IC on the module operates
at 3.3 Volts and the pins are not 5 Volt tollerant so be careful with that.
Today I tested the library with all available JAL fonts and they - after some
smalle modifications to the library - all work now. I also moved the IIC and
SPI part out of the library and moved that to the main program. The library
checks which interface (I2C software, I2C hardware, I2C harware 2, SPI hardware
and SPI hardware 2) is included by the main program and uses that interface
automagically. The only setting that remains for the interface is the SPI
software, for all others interfaces it is just including the required interface
before including the ssd1306 library and it will then use that interface for
the communication with SSD1306 module.
I added a text with a bigger font to the current sample programs so that users
can see that that works too. It works for I2C but I still need to test it for
SPI as wel. If all works then I will upload the updated library and the updated
sample programs.
Good luck with the project. I think this was a nice extension of the
functionality of this library.
Kind regards,
Rob
________________________________
Van: [email protected] <[email protected]> namens Bill Beek
<[email protected]>
Verzonden: woensdag 24 september 2025 19:49
Aan: jallib <[email protected]>
Onderwerp: Re: [jallib] Re: Update SSD1306 library supporting bigger font
Hi Rob,
The 12x16 font now works fine, the error was on my side, the hex file worked
fine as expected.
After compilation of your program it went wrong again.
After investigation, the glcd_font lib turned out to be corrupted, so I
apologize for the inconvenience.
I have looked at the I2C lines, and also see that interference signals are
getting bigger as the voltage increases between 3 and 5 Volts.
What I also noticed was that the pulses were not very steep,
which is of course due to by the weak pullups.
After placing 2 x 4k7 resistors it looked much better and realized a more
stable data transfer.
I noticed that the display regularly fails at 5V, after placing the resistors
everything worked well at 5 Volts.
According to my info there is some kind of voltage regulator on the display
board which would make it applicable from 3 to 5 Volt.
Many thanks for the good work,
Kind regards, Bill.
On Wednesday, September 24, 2025 at 7:01:50 PM UTC+2 Rob CJ wrote:
Hi Bill,
Attached the JAL testprogram I used and the hex file.
Kind regards,
Rob
________________________________
Van: [email protected] <[email protected]> namens Bill Beek
<[email protected]>
Verzonden: dinsdag 23 september 2025 19:29
Aan: jallib <[email protected]>
Onderwerp: Re: [jallib] Re: Update SSD1306 library supporting bigger font
P.S. send me the hex file for the 18F1825 so i can see of that is okay with my
setting.
On Tuesday, September 23, 2025 at 7:25:46 PM UTC+2 Bill Beek wrote:
Hi Rob,
Only the display on IC2 and 3.3V I don't understand it either, are you sure
that the posted lib is the same as in your test?
That could explain the problem.
On Tuesday, September 23, 2025 at 6:34:28 PM UTC+2 Rob CJ wrote:
Hi Bill,
I cannot explain this. I will do some more testing and also test it with the
SPI interface.
Did you try it without any other connections to the IIC bus and at 3.3. Volt?
Kind regards,
Rob
________________________________
Van: [email protected] <[email protected]> namens Bill Beek
<[email protected]>
Verzonden: dinsdag 23 september 2025 17:25
Aan: jallib <[email protected]>
Onderwerp: Re: [jallib] Re: Update SSD1306 library supporting bigger font
Hi Rob,
Some extra information about the topic.
I tested also with a 18f1825 and sw I2C and as expected, got the same image as
in the photo I posted.
If the 6x8 font is used, everything works well even with the 18f2520, which is
equipped with the tiny bootloader
which works handy and fast for me.
The 16F1825 is programmed with the pickit 2. I hope that you are able to locate
the problem.
Kind regards, Bill.
On Monday, September 22, 2025 at 8:15:03 PM UTC+2 Bill Beek wrote:
Hi Rob,
Tested without the ina3221, delete the I2C code lines from the program and Vcc
3,3V but nothing changed.
So I wondered if it's possible that the lib you posted is not the same as in
your test?
The 1306 is powered by wires under the board.
Kind regards, Bill.
On Monday, September 22, 2025 at 7:02:08 PM UTC+2 Rob CJ wrote:
Hi Bill,
The only thing I found is that you include and initialize i2c_hardware. As you
may remember this is currently also done by the ssd1306 and I am not sure if
this messes things up so I commented that part out. I also commented out the
include of glcd_common since that is needed by the ssd1306 library so it is
included there. I also moved the selection of the font but that should not make
a difference. I attached the update.
For the final version of the updated library you have to include and initialize
i2c_hardware but not yet for this version.
So it should work but not sure if the I2c_hardware has messed things up (I do
not think so).
Unfortunately I do not have an 18F2520 to test it.
I see you have two devices on the IIC bus. Did you also test with without the
INA3221?
And to be sure. Although the module works at +5V you should not pull-up the SDA
and SCL lines to +5Volt. If you have connected both the INA3221 and the SSD1306
to +5V, the INA3221 will pull-up the lines to +5V and that can kill the module.
Last but not least. As I mentioned before the SSD1306 module generates a lot of
noise on the SDA and SCL lines and that is gone if you use it on 3.3 Volt.
So for this test. Only connect the SSD1306 and use it (including the PIC) at
3.3 Volt and see if that works. If that is the case and you want to use it
together with the INA3221 at +5V then use a level shifter between the PIC and
the SSD1306.
BTW. I do not see any power connection to the SDD1306 🙂.
Kind regards,
Rob
________________________________
Van: [email protected] <[email protected]> namens Bill Beek
<[email protected]>
Verzonden: maandag 22 september 2025 12:26
Aan: jallib <[email protected]>
Onderwerp: [jallib] Re: Update SSD1306 library supporting bigger font
Hi Rob,
I tested the lib but the same problem exist.
I added your name at the lib to be sure that the right lib was used.
You can see what's happens on the picture.
I can't understand what I have done wrong so I added my program.
Kind regards, Bill.
On Sunday, September 21, 2025 at 1:38:05 PM UTC+2 [email protected] wrote:
Hi Bill,
It took me quite some time to figure this out. First of all, you cannot read
data from the SSD1306. This means that I cannot write characters using pixels.
So I looked at the procedure ssd1306_write_char() which writes ... characters.
This procedure does not require the big cache that you normally need when
writing characters as pixels or when using graphics in general.
Currently the SSD1306 library worked correctly for the 6x8 font and that was
only because that is a vertical font and that matches how the SSD1306 displays
the data. This seems to be one of the view (or the only?) vertical font, all
other - larger - fonts are horizontal fonts and that causes the problem when
using them.
So I added code to this procedure that checks if the used font is a horizontal
font and if so it rotates the character 90 degrees to match the SSD1306 display
and splits the character up into smaller pieces since the SSD1306 works with
pages (0..7) each 8 pixels high. If a font is bigger than 8 pixels, it needs to
be spit up and divided over 2 pages.
I attached the library including a picture that shows the 12x16 font working. I
still need to test this for other font sizes and I need to clean the library up
since currently the limit is 12x16 and if you use a smaller font I could save
data space. So please give it try. You do not need any special setting for this
only that you are using text mode.
Next to cleaning the library up I am planning to move the IIC and SPI part from
this library to the main program so that it is not included by this library
anymore. This is in line with the JAL style guide but it results in a breaking
change for anyone who is currently using the library since incuding IIC or SPI
and initializing them moves to the main program.
Kind regards,
Rob
--
You received this message because you are subscribed to the Google Groups
"jallib" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/jallib/5f33c130-d73d-4080-b8c4-03900fba52a9n%40googlegroups.com<https://groups.google.com/d/msgid/jallib/5f33c130-d73d-4080-b8c4-03900fba52a9n%40googlegroups.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to the Google Groups
"jallib" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/jallib/cdba0988-9ce1-4ca3-8c43-d9a18f9d3d12n%40googlegroups.com<https://groups.google.com/d/msgid/jallib/cdba0988-9ce1-4ca3-8c43-d9a18f9d3d12n%40googlegroups.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to the Google Groups
"jallib" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/jallib/d0a75094-24de-4dc6-a426-0b52e37d3a6cn%40googlegroups.com<https://groups.google.com/d/msgid/jallib/d0a75094-24de-4dc6-a426-0b52e37d3a6cn%40googlegroups.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to the Google Groups
"jallib" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/jallib/7b59ff16-9193-40ab-955c-5c804d9b4cbfn%40googlegroups.com<https://groups.google.com/d/msgid/jallib/7b59ff16-9193-40ab-955c-5c804d9b4cbfn%40googlegroups.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to the Google Groups
"jallib" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/jallib/AM7PR02MB6098BC3AE041ABF60033D863E61FA%40AM7PR02MB6098.eurprd02.prod.outlook.com<https://groups.google.com/d/msgid/jallib/AM7PR02MB6098BC3AE041ABF60033D863E61FA%40AM7PR02MB6098.eurprd02.prod.outlook.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to the Google Groups
"jallib" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/jallib/91b559f2-374c-49ba-bba9-2b20f51257fen%40googlegroups.com<https://groups.google.com/d/msgid/jallib/91b559f2-374c-49ba-bba9-2b20f51257fen%40googlegroups.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to a topic in the Google
Groups "jallib" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/jallib/JdXGKBOcq1A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
[email protected]<mailto:[email protected]>.
To view this discussion visit
https://groups.google.com/d/msgid/jallib/7947f9c7-ce70-4f06-ac3a-242c11b0a3f9n%40googlegroups.com<https://groups.google.com/d/msgid/jallib/7947f9c7-ce70-4f06-ac3a-242c11b0a3f9n%40googlegroups.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to a topic in the Google
Groups "jallib" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/jallib/JdXGKBOcq1A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
[email protected]<mailto:[email protected]>.
To view this discussion visit
https://groups.google.com/d/msgid/jallib/AM0PR02MB4052718D79F34A45306986E3E68CA%40AM0PR02MB4052.eurprd02.prod.outlook.com<https://groups.google.com/d/msgid/jallib/AM0PR02MB4052718D79F34A45306986E3E68CA%40AM0PR02MB4052.eurprd02.prod.outlook.com?utm_medium=email&utm_source=footer>.
--
You received this message because you are subscribed to the Google Groups
"jallib" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/jallib/AM0PR02MB4052B27EF710DFCE381116E5E68CA%40AM0PR02MB4052.eurprd02.prod.outlook.com.
/*********************************************************************
This is a library for our Monochrome OLEDs based on SSD1306 drivers
Pick one up today in the adafruit shop!
------> http://www.adafruit.com/category/63_98
These displays use SPI to communicate, 4 or 5 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above, and the splash screen below must be included in any redistribution
*********************************************************************/
/*********************************************************************
I change the adafruit SSD1306 to SH1106
SH1106 driver similar to SSD1306 so, just change the display() method.
However, SH1106 driver don't provide several functions such as scroll commands.
*********************************************************************/
#include <avr/pgmspace.h>
#ifndef __SAM3X8E__
#include <util/delay.h>
#endif
#include <stdlib.h>
#include <Wire.h>
#include "Adafruit_GFX.h"
#include "Adafruit_SH1106.h"
// the memory buffer for the LCD
static uint8_t buffer[SH1106_LCDHEIGHT * SH1106_LCDWIDTH / 8] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFF,
#if (SH1106_LCDHEIGHT * SH1106_LCDWIDTH > 96*16)
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x8C, 0x8E, 0x84, 0x00, 0x00, 0x80, 0xF8,
0xF8, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80,
0x00, 0xE0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0x01, 0x01,
0x01, 0x01, 0x83, 0xFF, 0xFF, 0x00, 0x00, 0x7C, 0xFE, 0xC7, 0x01, 0x01, 0x01, 0x01, 0x83, 0xFF,
0xFF, 0xFF, 0x00, 0x38, 0xFE, 0xC7, 0x83, 0x01, 0x01, 0x01, 0x83, 0xC7, 0xFF, 0xFF, 0x00, 0x00,
0x01, 0xFF, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x7F, 0xFF,
0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF,
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x8F,
0x8F, 0x9F, 0xBF, 0xFF, 0xFF, 0xC3, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC,
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x01, 0x03, 0x03, 0x03,
0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01,
0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00,
0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x03,
0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
#if (SH1106_LCDHEIGHT == 64)
0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x0F,
0x87, 0xC7, 0xF7, 0xFF, 0xFF, 0x1F, 0x1F, 0x3D, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7D, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x00, 0x30, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F,
0x0F, 0x07, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00,
0x00, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xF8, 0x1C, 0x0E,
0x06, 0x06, 0x06, 0x0C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFC,
0xFE, 0xFC, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0xE6, 0xCE, 0x84, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0x06,
0x06, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xC0, 0xF8,
0xFC, 0x4E, 0x46, 0x46, 0x46, 0x4E, 0x7C, 0x78, 0x40, 0x18, 0x3C, 0x76, 0xE6, 0xCE, 0xCC, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x0C,
0x18, 0x18, 0x0C, 0x06, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0E, 0x0C, 0x18, 0x0C, 0x0F,
0x07, 0x01, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00,
0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x07,
0x07, 0x0C, 0x0C, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
#endif
#endif
};
#define sh1106_swap(a, b) { int16_t t = a; a = b; b = t; }
// the most basic function, set a single pixel
void Adafruit_SH1106::drawPixel(int16_t x, int16_t y, uint16_t color) {
if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
return;
// check rotation, move pixel around if necessary
switch (getRotation()) {
case 1:
sh1106_swap(x, y);
x = WIDTH - x - 1;
break;
case 2:
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
break;
case 3:
sh1106_swap(x, y);
y = HEIGHT - y - 1;
break;
}
// x is which column
switch (color)
{
case WHITE: buffer[x+ (y/8)*SH1106_LCDWIDTH] |= (1 << (y&7)); break;
case BLACK: buffer[x+ (y/8)*SH1106_LCDWIDTH] &= ~(1 << (y&7)); break;
case INVERSE: buffer[x+ (y/8)*SH1106_LCDWIDTH] ^= (1 << (y&7)); break;
}
}
Adafruit_SH1106::Adafruit_SH1106(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SH1106_LCDWIDTH, SH1106_LCDHEIGHT) {
cs = CS;
rst = RST;
dc = DC;
sclk = SCLK;
sid = SID;
hwSPI = false;
}
// constructor for hardware SPI - we indicate DataCommand, ChipSelect, Reset
Adafruit_SH1106::Adafruit_SH1106(int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SH1106_LCDWIDTH, SH1106_LCDHEIGHT) {
dc = DC;
rst = RST;
cs = CS;
hwSPI = true;
}
// initializer for I2C - we only indicate the reset pin!
Adafruit_SH1106::Adafruit_SH1106(int8_t reset) :
Adafruit_GFX(SH1106_LCDWIDTH, SH1106_LCDHEIGHT) {
sclk = dc = cs = sid = -1;
rst = reset;
}
void Adafruit_SH1106::begin(uint8_t vccstate, uint8_t i2caddr, bool reset) {
_vccstate = vccstate;
_i2caddr = i2caddr;
// set pin directions
if (sid != -1){
pinMode(dc, OUTPUT);
pinMode(cs, OUTPUT);
csport = portOutputRegister(digitalPinToPort(cs));
cspinmask = digitalPinToBitMask(cs);
dcport = portOutputRegister(digitalPinToPort(dc));
dcpinmask = digitalPinToBitMask(dc);
if (!hwSPI){
// set pins for software-SPI
pinMode(sid, OUTPUT);
pinMode(sclk, OUTPUT);
clkport = portOutputRegister(digitalPinToPort(sclk));
clkpinmask = digitalPinToBitMask(sclk);
mosiport = portOutputRegister(digitalPinToPort(sid));
mosipinmask = digitalPinToBitMask(sid);
}
if (hwSPI){
SPI.begin ();
#ifdef __SAM3X8E__
SPI.setClockDivider (9); // 9.3 MHz
#else
SPI.setClockDivider (SPI_CLOCK_DIV2); // 8 MHz
#endif
}
}
else
{
// I2C Init
Wire.begin();
#ifdef __SAM3X8E__
// Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL)
TWI1->TWI_CWGR = 0;
TWI1->TWI_CWGR = ((VARIANT_MCK / (2 * 400000)) - 4) * 0x101;
#endif
}
if (reset) {
// Setup reset pin direction (used by both SPI and I2C)
pinMode(rst, OUTPUT);
digitalWrite(rst, HIGH);
// VDD (3.3V) goes high at start, lets just chill for a ms
delay(1);
// bring reset low
digitalWrite(rst, LOW);
// wait 10ms
delay(10);
// bring out of reset
digitalWrite(rst, HIGH);
// turn on VCC (9V?)
}
#if defined SH1106_128_32
// Init sequence for 128x32 OLED module
SH1106_command(SH1106_DISPLAYOFF); // 0xAE
SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
SH1106_command(0x80); // the suggested ratio 0x80
SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
SH1106_command(0x1F);
SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
SH1106_command(0x0); // no offset
SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
SH1106_command(SH1106_CHARGEPUMP); // 0x8D
if (vccstate == SH1106_EXTERNALVCC)
{ SH1106_command(0x10); }
else
{ SH1106_command(0x14); }
SH1106_command(SH1106_MEMORYMODE); // 0x20
SH1106_command(0x00); // 0x0 act like ks0108
SH1106_command(SH1106_SEGREMAP | 0x1);
SH1106_command(SH1106_COMSCANDEC);
SH1106_command(SH1106_SETCOMPINS); // 0xDA
SH1106_command(0x02);
SH1106_command(SH1106_SETCONTRAST); // 0x81
SH1106_command(0x8F);
SH1106_command(SH1106_SETPRECHARGE); // 0xd9
if (vccstate == SH1106_EXTERNALVCC)
{ SH1106_command(0x22); }
else
{ SH1106_command(0xF1); }
SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
SH1106_command(0x40);
SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
#endif
#if defined SH1106_128_64
// Init sequence for 128x64 OLED module
SH1106_command(SH1106_DISPLAYOFF); // 0xAE
SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
SH1106_command(0x80); // the suggested ratio 0x80
SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
SH1106_command(0x3F);
SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
SH1106_command(0x00); // no offset
SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0 0x40
SH1106_command(SH1106_CHARGEPUMP); // 0x8D
if (vccstate == SH1106_EXTERNALVCC)
{ SH1106_command(0x10); }
else
{ SH1106_command(0x14); }
SH1106_command(SH1106_MEMORYMODE); // 0x20
SH1106_command(0x00); // 0x0 act like ks0108
SH1106_command(SH1106_SEGREMAP | 0x1);
SH1106_command(SH1106_COMSCANDEC);
SH1106_command(SH1106_SETCOMPINS); // 0xDA
SH1106_command(0x12);
SH1106_command(SH1106_SETCONTRAST); // 0x81
if (vccstate == SH1106_EXTERNALVCC)
{ SH1106_command(0x9F); }
else
{ SH1106_command(0xCF); }
SH1106_command(SH1106_SETPRECHARGE); // 0xd9
if (vccstate == SH1106_EXTERNALVCC)
{ SH1106_command(0x22); }
else
{ SH1106_command(0xF1); }
SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
SH1106_command(0x40);
SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
#endif
#if defined SH1106_96_16
// Init sequence for 96x16 OLED module
SH1106_command(SH1106_DISPLAYOFF); // 0xAE
SH1106_command(SH1106_SETDISPLAYCLOCKDIV); // 0xD5
SH1106_command(0x80); // the suggested ratio 0x80
SH1106_command(SH1106_SETMULTIPLEX); // 0xA8
SH1106_command(0x0F);
SH1106_command(SH1106_SETDISPLAYOFFSET); // 0xD3
SH1106_command(0x00); // no offset
SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
SH1106_command(SH1106_CHARGEPUMP); // 0x8D
if (vccstate == SH1106_EXTERNALVCC)
{ SH1106_command(0x10); }
else
{ SH1106_command(0x14); }
SH1106_command(SH1106_MEMORYMODE); // 0x20
SH1106_command(0x00); // 0x0 act like ks0108
SH1106_command(SH1106_SEGREMAP | 0x1);
SH1106_command(SH1106_COMSCANDEC);
SH1106_command(SH1106_SETCOMPINS); // 0xDA
SH1106_command(0x2); //ada x12
SH1106_command(SH1106_SETCONTRAST); // 0x81
if (vccstate == SH1106_EXTERNALVCC)
{ SH1106_command(0x10); }
else
{ SH1106_command(0xAF); }
SH1106_command(SH1106_SETPRECHARGE); // 0xd9
if (vccstate == SH1106_EXTERNALVCC)
{ SH1106_command(0x22); }
else
{ SH1106_command(0xF1); }
SH1106_command(SH1106_SETVCOMDETECT); // 0xDB
SH1106_command(0x40);
SH1106_command(SH1106_DISPLAYALLON_RESUME); // 0xA4
SH1106_command(SH1106_NORMALDISPLAY); // 0xA6
#endif
SH1106_command(SH1106_DISPLAYON);//--turn on oled panel
}
void Adafruit_SH1106::invertDisplay(uint8_t i) {
if (i) {
SH1106_command(SH1106_INVERTDISPLAY);
} else {
SH1106_command(SH1106_NORMALDISPLAY);
}
}
void Adafruit_SH1106::SH1106_command(uint8_t c) {
if (sid != -1)
{
// SPI
//digitalWrite(cs, HIGH);
*csport |= cspinmask;
//digitalWrite(dc, LOW);
*dcport &= ~dcpinmask;
//digitalWrite(cs, LOW);
*csport &= ~cspinmask;
fastSPIwrite(c);
//digitalWrite(cs, HIGH);
*csport |= cspinmask;
}
else
{
// I2C
uint8_t control = 0x00; // Co = 0, D/C = 0
Wire.beginTransmission(_i2caddr);
WIRE_WRITE(control);
WIRE_WRITE(c);
Wire.endTransmission();
}
}
// startscrollright
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(0x00, 0x0F)
/*void Adafruit_SH1106::startscrollright(uint8_t start, uint8_t stop){
SH1106_command(SH1106_RIGHT_HORIZONTAL_SCROLL);
SH1106_command(0X00);
SH1106_command(start);
SH1106_command(0X00);
SH1106_command(stop);
SH1106_command(0X00);
SH1106_command(0XFF);
SH1106_command(SH1106_ACTIVATE_SCROLL);
}
// startscrollleft
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(0x00, 0x0F)
void Adafruit_SH1106::startscrollleft(uint8_t start, uint8_t stop){
SH1106_command(SH1106_LEFT_HORIZONTAL_SCROLL);
SH1106_command(0X00);
SH1106_command(start);
SH1106_command(0X00);
SH1106_command(stop);
SH1106_command(0X00);
SH1106_command(0XFF);
SH1106_command(SH1106_ACTIVATE_SCROLL);
}
// startscrolldiagright
// Activate a diagonal scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(0x00, 0x0F)
void Adafruit_SH1106::startscrolldiagright(uint8_t start, uint8_t stop){
SH1106_command(SH1106_SET_VERTICAL_SCROLL_AREA);
SH1106_command(0X00);
SH1106_command(SH1106_LCDHEIGHT);
SH1106_command(SH1106_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
SH1106_command(0X00);
SH1106_command(start);
SH1106_command(0X00);
SH1106_command(stop);
SH1106_command(0X01);
SH1106_command(SH1106_ACTIVATE_SCROLL);
}
// startscrolldiagleft
// Activate a diagonal scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(0x00, 0x0F)
void Adafruit_SH1106::startscrolldiagleft(uint8_t start, uint8_t stop){
SH1106_command(SH1106_SET_VERTICAL_SCROLL_AREA);
SH1106_command(0X00);
SH1106_command(SH1106_LCDHEIGHT);
SH1106_command(SH1106_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
SH1106_command(0X00);
SH1106_command(start);
SH1106_command(0X00);
SH1106_command(stop);
SH1106_command(0X01);
SH1106_command(SH1106_ACTIVATE_SCROLL);
}
void Adafruit_SH1106::stopscroll(void){
SH1106_command(SH1106_DEACTIVATE_SCROLL);
}
// Dim the display
// dim = true: display is dimmed
// dim = false: display is normal
void Adafruit_SH1106::dim(boolean dim) {
uint8_t contrast;
if (dim) {
contrast = 0; // Dimmed display
} else {
if (_vccstate == SH1106_EXTERNALVCC) {
contrast = 0x9F;
} else {
contrast = 0xCF;
}
}
// the range of contrast to too small to be really useful
// it is useful to dim the display
SH1106_command(SH1106_SETCONTRAST);
SH1106_command(contrast);
}*/
void Adafruit_SH1106::SH1106_data(uint8_t c) {
if (sid != -1)
{
// SPI
//digitalWrite(cs, HIGH);
*csport |= cspinmask;
//digitalWrite(dc, HIGH);
*dcport |= dcpinmask;
//digitalWrite(cs, LOW);
*csport &= ~cspinmask;
fastSPIwrite(c);
//digitalWrite(cs, HIGH);
*csport |= cspinmask;
}
else
{
// I2C
uint8_t control = 0x40; // Co = 0, D/C = 1
Wire.beginTransmission(_i2caddr);
WIRE_WRITE(control);
WIRE_WRITE(c);
Wire.endTransmission();
}
}
/*#define SH1106_SETLOWCOLUMN 0x00
#define SH1106_SETHIGHCOLUMN 0x10
#define SH1106_SETSTARTLINE 0x40*/
void Adafruit_SH1106::display(void) {
SH1106_command(SH1106_SETLOWCOLUMN | 0x0); // low col = 0
SH1106_command(SH1106_SETHIGHCOLUMN | 0x0); // hi col = 0
SH1106_command(SH1106_SETSTARTLINE | 0x0); // line #0
//Serial.println(TWBR, DEC);
//Serial.println(TWSR & 0x3, DEC);
// I2C
//height >>= 3;
//width >>= 3;
byte height=64;
byte width=132;
byte m_row = 0;
byte m_col = 2;
height >>= 3;
width >>= 3;
//Serial.println(width);
int p = 0;
byte i, j, k =0;
if(sid != -1)
{
for ( i = 0; i < height; i++) {
// send a bunch of data in one xmission
SH1106_command(0xB0 + i + m_row);//set page address
SH1106_command(m_col & 0xf);//set lower column address
SH1106_command(0x10 | (m_col >> 4));//set higher column address
for( j = 0; j < 8; j++){
// SPI
*csport |= cspinmask;
*dcport |= dcpinmask;
*csport &= ~cspinmask;
for ( k = 0; k < width; k++, p++) {
fastSPIwrite(buffer[p]);
}
*csport |= cspinmask;
}
}
}
else{
// save I2C bitrate
#ifndef __SAM3X8E__
uint8_t twbrbackup = TWBR;
TWBR = 12; // upgrade to 400KHz!
#endif
for ( i = 0; i < height; i++) {
// send a bunch of data in one xmission
SH1106_command(0xB0 + i + m_row);//set page address
SH1106_command(m_col & 0xf);//set lower column address
SH1106_command(0x10 | (m_col >> 4));//set higher column address
for( j = 0; j < 8; j++){
Wire.beginTransmission(_i2caddr);
Wire.write(0x40);
for ( k = 0; k < width; k++, p++) {
Wire.write(buffer[p]);
}
Wire.endTransmission();
}
}
#ifndef __SAM3X8E__
TWBR = twbrbackup;
#endif
}
}
/*void Adafruit_SH1106::display(void) {
SH1106_command(SH1106_COLUMNADDR);
SH1106_command(0); // Column start address (0 = reset)
SH1106_command(SH1106_LCDWIDTH-1); // Column end address (127 = reset)
SH1106_command(SH1106_PAGEADDR);
SH1106_command(0); // Page start address (0 = reset)
#if SH1106_LCDHEIGHT == 64
SH1106_command(7); // Page end address
#endif
#if SH1106_LCDHEIGHT == 32
SH1106_command(3); // Page end address
#endif
#if SH1106_LCDHEIGHT == 16
SH1106_command(1); // Page end address
#endif
if (sid != -1)
{
// SPI
*csport |= cspinmask;
*dcport |= dcpinmask;
*csport &= ~cspinmask;
for (uint16_t i=0; i<(SH1106_LCDWIDTH*SH1106_LCDHEIGHT/8); i++) {
fastSPIwrite(buffer[i]);
//SH1106_data(buffer[i]);
}
*csport |= cspinmask;
}
else
{
// save I2C bitrate
#ifndef __SAM3X8E__
uint8_t twbrbackup = TWBR;
TWBR = 12; // upgrade to 400KHz!
#endif
//Serial.println(TWBR, DEC);
//Serial.println(TWSR & 0x3, DEC);
// I2C
int k = 0;
for (uint16_t i=0; i<(SH1106_LCDWIDTH*SH1106_LCDHEIGHT/8); i++) {
// send a bunch of data in one xmission
if(k < 2)
{
k++;
continue;
}
Wire.beginTransmission(_i2caddr);
WIRE_WRITE(0x40);
for (uint8_t x=0; x<16; x++) {
WIRE_WRITE(buffer[i]);
i++;
}
i--;
Wire.endTransmission();
}
#ifndef __SAM3X8E__
TWBR = twbrbackup;
#endif
}
}
*/
// clear everything
void Adafruit_SH1106::clearDisplay(void) {
memset(buffer, 0, (SH1106_LCDWIDTH*SH1106_LCDHEIGHT/8));
}
inline void Adafruit_SH1106::fastSPIwrite(uint8_t d) {
if(hwSPI) {
(void)SPI.transfer(d);
} else {
for(uint8_t bit = 0x80; bit; bit >>= 1) {
*clkport &= ~clkpinmask;
if(d & bit) *mosiport |= mosipinmask;
else *mosiport &= ~mosipinmask;
*clkport |= clkpinmask;
}
}
//*csport |= cspinmask;
}
void Adafruit_SH1106::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
boolean bSwap = false;
switch(rotation) {
case 0:
// 0 degree rotation, do nothing
break;
case 1:
// 90 degree rotation, swap x & y for rotation, then invert x
bSwap = true;
sh1106_swap(x, y);
x = WIDTH - x - 1;
break;
case 2:
// 180 degree rotation, invert x and y - then shift y around for height.
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
x -= (w-1);
break;
case 3:
// 270 degree rotation, swap x & y for rotation, then invert y and adjust y for w (not to become h)
bSwap = true;
sh1106_swap(x, y);
y = HEIGHT - y - 1;
y -= (w-1);
break;
}
if(bSwap) {
drawFastVLineInternal(x, y, w, color);
} else {
drawFastHLineInternal(x, y, w, color);
}
}
void Adafruit_SH1106::drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) {
// Do bounds/limit checks
if(y < 0 || y >= HEIGHT) { return; }
// make sure we don't try to draw below 0
if(x < 0) {
w += x;
x = 0;
}
// make sure we don't go off the edge of the display
if( (x + w) > WIDTH) {
w = (WIDTH - x);
}
// if our width is now negative, punt
if(w <= 0) { return; }
// set up the pointer for movement through the buffer
register uint8_t *pBuf = buffer;
// adjust the buffer pointer for the current row
pBuf += ((y/8) * SH1106_LCDWIDTH);
// and offset x columns in
pBuf += x;
register uint8_t mask = 1 << (y&7);
switch (color)
{
case WHITE: while(w--) { *pBuf++ |= mask; }; break;
case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
case INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
}
}
void Adafruit_SH1106::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
bool bSwap = false;
switch(rotation) {
case 0:
break;
case 1:
// 90 degree rotation, swap x & y for rotation, then invert x and adjust x for h (now to become w)
bSwap = true;
sh1106_swap(x, y);
x = WIDTH - x - 1;
x -= (h-1);
break;
case 2:
// 180 degree rotation, invert x and y - then shift y around for height.
x = WIDTH - x - 1;
y = HEIGHT - y - 1;
y -= (h-1);
break;
case 3:
// 270 degree rotation, swap x & y for rotation, then invert y
bSwap = true;
sh1106_swap(x, y);
y = HEIGHT - y - 1;
break;
}
if(bSwap) {
drawFastHLineInternal(x, y, h, color);
} else {
drawFastVLineInternal(x, y, h, color);
}
}
void Adafruit_SH1106::drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color) {
// do nothing if we're off the left or right side of the screen
if(x < 0 || x >= WIDTH) { return; }
// make sure we don't try to draw below 0
if(__y < 0) {
// __y is negative, this will subtract enough from __h to account for __y being 0
__h += __y;
__y = 0;
}
// make sure we don't go past the height of the display
if( (__y + __h) > HEIGHT) {
__h = (HEIGHT - __y);
}
// if our height is now negative, punt
if(__h <= 0) {
return;
}
// this display doesn't need ints for coordinates, use local byte registers for faster juggling
register uint8_t y = __y;
register uint8_t h = __h;
// set up the pointer for fast movement through the buffer
register uint8_t *pBuf = buffer;
// adjust the buffer pointer for the current row
pBuf += ((y/8) * SH1106_LCDWIDTH);
// and offset x columns in
pBuf += x;
// do the first partial byte, if necessary - this requires some masking
register uint8_t mod = (y&7);
if(mod) {
// mask off the high n bits we want to set
mod = 8-mod;
// note - lookup table results in a nearly 10% performance improvement in fill* functions
// register uint8_t mask = ~(0xFF >> (mod));
static uint8_t premask[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
register uint8_t mask = premask[mod];
// adjust the mask if we're not going to reach the end of this byte
if( h < mod) {
mask &= (0XFF >> (mod-h));
}
switch (color)
{
case WHITE: *pBuf |= mask; break;
case BLACK: *pBuf &= ~mask; break;
case INVERSE: *pBuf ^= mask; break;
}
// fast exit if we're done here!
if(h<mod) { return; }
h -= mod;
pBuf += SH1106_LCDWIDTH;
}
// write solid bytes while we can - effectively doing 8 rows at a time
if(h >= 8) {
if (color == INVERSE) { // separate copy of the code so we don't impact performance of the black/white write version with an extra comparison per loop
do {
*pBuf=~(*pBuf);
// adjust the buffer forward 8 rows worth of data
pBuf += SH1106_LCDWIDTH;
// adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
h -= 8;
} while(h >= 8);
}
else {
// store a local value to work with
register uint8_t val = (color == WHITE) ? 255 : 0;
do {
// write our value in
*pBuf = val;
// adjust the buffer forward 8 rows worth of data
pBuf += SH1106_LCDWIDTH;
// adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now)
h -= 8;
} while(h >= 8);
}
}
// now do the final partial byte, if necessary
if(h) {
mod = h & 7;
// this time we want to mask the low bits of the byte, vs the high bits we did above
// register uint8_t mask = (1 << mod) - 1;
// note - lookup table results in a nearly 10% performance improvement in fill* functions
static uint8_t postmask[8] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
register uint8_t mask = postmask[mod];
switch (color)
{
case WHITE: *pBuf |= mask; break;
case BLACK: *pBuf &= ~mask; break;
case INVERSE: *pBuf ^= mask; break;
}
}
}