This commit is contained in:
Oliver Brandmueller 2018-07-27 09:39:08 +02:00
commit c96856935d
150 changed files with 339919 additions and 1722 deletions

120
README.md
View File

@ -4,6 +4,8 @@
--> see development branch of this repository for latest alpha version <--
<img src="img/Paxcounter-title.jpg">
<img src="img/Paxcounter-ttgo.jpg">
<img src="img/Paxcounter-lolin.gif">
# Use case
@ -11,7 +13,7 @@ Paxcounter is a proof-of-concept device for metering passenger flows in realtime
Intention of this project is to do this without intrusion in privacy: You don't need to track people owned devices, if you just want to count them. Therefore, Paxcounter does not persistenly store MAC adresses and does no kind of fingerprinting the scanned devices.
Bonus of this project is that metered data is transferred via a LoRaWAN network, not via usual GSM/LTE or Wifi uplink.
Metered counts are transferred to a server via a LoRaWAN network, and/or a local SPI cable interface.
You can build this project battery powered and reach a full day uptime with a single 18650 Li-Ion cell.
@ -19,41 +21,43 @@ This can all be done with a single small and cheap ESP32 board for less than $20
# Hardware
Supported ESP32 based LoRa IoT boards:
**Supported ESP32 based boards**:
- **Heltec LoRa-32**
- **TTGOv1**
- **TTGOv2**
- **TTGOv2.1**
- **TTGO T-Beam**
- **Pycom LoPy**
- **Pycom LoPy4**
- **Pycom FiPy**
- **LoLin32** + [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora)
- **LoLin32 Lite** + [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora)
*LoRa & SPI*:
- Heltec: LoRa-32
- TTGO: T3_v1, T3_v2, T3_v2.1, T-Beam
- Pycom: LoPy, LoPy4, FiPy
- WeMos: LoLin32 + [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora),
LoLin32lite + [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora)
*SPI only*: (coming soon)
- Pyom: WiPy
- WeMos: LoLin32, LoLin32 Lite, WeMos D32
Depending on board hardware following features are supported:
- LED
- OLED Display
- RGB LED
- button
- silicon unique ID
- battery voltage monitoring
- Button
- Silicon unique ID
- Battery voltage monitoring
- GPS
Target platform must be selected in [platformio.ini](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/platformio.ini).<br>
Hardware dependent settings (pinout etc.) are stored in board files in /hal directory.<br>
<b>3D printable cases</b> can be found (and, if wanted so, ordered) on Thingiverse, see
<A HREF="https://www.thingiverse.com/thing:2670713">Heltec</A> and <A HREF="https://www.thingiverse.com/thing:2811127">TTGOv2</A>, for example.<br>
<A HREF="https://www.thingiverse.com/thing:2670713">Heltec</A>, <A HREF="https://www.thingiverse.com/thing:2811127">TTGOv2</A>, <A HREF="https://www.thingiverse.com/thing:3005574">TTGOv2.1</A> for example.<br>
<b>Power consumption</b> was metered at around 1000mW, depending on board (i.e. has display or not) and user settings in paxcounter.conf. If you are limited on battery, you may want to save around 30% power by disabling bluetooth (commenting out line *#define BLECOUNTER* in paxcounter.conf).
<b>Power consumption</b> was metered at around 750 - 1000mW, depending on board and user settings in paxcounter.conf. If you are limited on battery, you may want to save around 30% power by disabling bluetooth (commenting out line *#define BLECOUNTER* in paxcounter.conf).
# Preparing
Before compiling the code,
- **edit paxcounter.conf** and taylor settings in this file according to your needs and use case. Please take care of the duty cycle regulations of the LoRaWAN network you're going to use.
- **edit paxcounter.conf** and tailor settings in this file according to your needs and use case. Please take care of the duty cycle regulations of the LoRaWAN network you're going to use.
- **create file loraconf.h in your local /src directory** using the template [loraconf.sample.h](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/src/loraconf.sample.h) and populate it with your personal APPEUI und APPKEY for the LoRaWAN network. If you're using popular <A HREF="https://thethingsnetwork.org">TheThingsNetwork</A> you can copy&paste the keys from TTN console or output of ttnctl.
@ -121,26 +125,52 @@ If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you
To track a paxcounter device with on board GPS and at the same time contribute to TTN coverage mapping, you simply activate the [TTNmapper integration](https://www.thethingsnetwork.org/docs/applications/ttnmapper/) in TTN Console. The formats *plain* and *packed* generate the fields `latitude`, `longitude` and `hdop` required by ttnmapper.
Hereafter described is the default *plain* format.
Hereafter described is the default *plain* format, which uses MSB bit numbering.
**LoRaWAN Port #1:**
Paxcounter data
**Port #1:** Paxcount data
byte 1-2: Number of unique pax, first seen on Wifi
byte 3-4: Number of unique pax, first seen on Bluetooth [0 if BT disabled]
bytes 5-18: GPS data, format see Port #4 (appended only, if GPS is present and has a fix)
GPS data (only, if GPS is present and has a fix)
**Port #2:** Device status query result
bytes 5-8: GPS latitude
bytes 9-12: GPS longitude
bytes 13-14: GPS number of satellites
bytes 15-16: GPS HDOP
bytes 17-18: GPS altitude [meter]
byte 1-2: Battery or USB Voltage [mV], 0 if unreadable
byte 3-10: Uptime [seconds]
bytes 11-14: CPU temperature [°C]
**LoRaWAN Port #2:**
**Port #3:** Device configuration query result
byte 1: Lora SF (7..12) [default 9]
byte 2: Lora TXpower (2..15) [default 15]
byte 3: Lora ADR (1=on, 0=off) [default 1]
byte 4: Screensaver status (1=on, 0=off) [default 0]
byte 5: Display status (1=on, 0=off) [default 0]
byte 6: Counter mode (0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed) [default 0]
bytes 7-8: RSSI limiter threshold value (negative) [default 0]
byte 9: Lora Payload send cycle in seconds/2 (0..255) [default 120]
byte 10: Wifi channel switch interval in seconds/100 (0..255) [default 50]
byte 11: Bluetooth channel switch interval in seconds/100 (0..255) [efault 10]
byte 12: Bluetooth scanner status (1=on, 0=0ff) [default 1]
byte 13: Wifi antenna switch (0=internal, 1=external) [default 0]
byte 14: Vendorfilter mode (0=disabled, 1=enabled) [default 0]
byte 15: RGB LED luminosity (0..100 %) [default 30]
byte 16: GPS send data mode (1=on, 0=ff) [default 1]
bytes 17-27: Software version (ASCII format, terminating with zero)
**Port #4:** GPS query result
bytes 1-4: Latitude
bytes 5-8: Longitude
byte 9: Number of satellites
bytes 10-11: HDOP
bytes 12-13: Altitude [meter]
**Port #5:** Button pressed signal
byte 1: static value 0x01
- see remote control -
[**plain_decoder.js**](src/TTN/plain_decoder.js)
@ -277,38 +307,16 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
0x80 get device configuration
device answers with it's current configuration. The configuration is a C structure declared in file [main.h](src/main.h#L13-L31) with the following definition:
byte 1: Lora SF (7..12) [default 9]
byte 2: Lora TXpower (2..15) [default 15]
byte 3: Lora ADR (1=on, 0=off) [default 1]
byte 4: Screensaver status (1=on, 0=off) [default 0]
byte 5: Display status (1=on, 0=off) [default 0]
byte 6: Counter mode (0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed) [default 0]
bytes 7-8: RSSI limiter threshold value (negative) [default 0]
byte 9: Lora Payload send cycle in seconds/2 (0..255) [default 120]
byte 10: Wifi channel switch interval in seconds/100 (0..255) [default 50]
byte 11: Bluetooth channel switch interval in seconds/100 (0..255) [efault 10]
byte 12: Bluetooth scanner status (1=on, 0=0ff) [default 1]
byte 13: Wifi antenna switch (0=internal, 1=external) [default 0]
byte 14: Vendorfilter mode (0=disabled, 1=enabled) [default 0]
byte 15: RGB LED luminosity (0..100 %) [default 30]
byte 16: GPS send data mode (1=on, 0=ff) [default 1]
bytes 17-27: Software version (ASCII format, terminating with zero)
Device answers with it's current configuration on Port 3.
0x81 get device status
bytes 1-2: Battery voltage in millivolt, 0 if unreadable
bytes 3-10: Uptime in seconds
bytes 11-14: Chip temperature in degrees celsius
Device answers with it's current status on Port 2.
0x84 get device GPS status
bytes 1-4: Latitude
bytes 5-8: Longitude
byte 9: Number of satellites
byte 10-11: HDOP
bytes 12-13: altidute [meter]
Device answers with it's current status on Port 4.
# License

BIN
img/Paxcounter-lolin.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
img/Paxcounter-ttgo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -0,0 +1,49 @@
{
"description": "Monochrome LCD, OLED and eInk Library. Display controller: SSD1305, SSD1306, SSD1309, SSD1322, SSD1325, SSD1327, SSD1329, SSD1606, SSD1607, SH1106, SH1107, SH1122, T6963, RA8835, LC7981, PCD8544, PCF8812, HX1230, UC1601, UC1604, UC1608, UC1610, UC1611, UC1701, ST7565, ST7567, ST7588, ST75256, NT7534, IST3020, ST7920, LD7032, KS0108, SED1520, SBN1661, IL3820, MAX7219. Interfaces: I2C, SPI, Parallel.",
"repository": {
"url": "https://github.com/olikraus/U8g2_Arduino",
"type": "git"
},
"platforms": [
"atmelavr",
"atmelsam",
"espressif32",
"espressif8266",
"intel_arc32",
"microchippic32",
"nordicnrf51",
"nordicnrf52",
"ststm32",
"teensy",
"timsp430"
],
"export": {
"exclude": [
"extras",
"docs",
"tests",
"test",
"*.doxyfile",
"*.pdf"
],
"include": null
},
"authors": [
{
"maintainer": true,
"name": "oliver",
"url": null,
"email": "olikraus@gmail.com"
}
],
"keywords": [
"display"
],
"id": 942,
"name": "U8g2",
"frameworks": [
"arduino"
],
"version": "2.23.12",
"homepage": "https://github.com/olikraus/u8g2"
}

View File

@ -0,0 +1,84 @@
The U8g2lib code (http://code.google.com/p/u8g2/ and
https://github.com/olikraus/U8g2_Arduino) is licensed under the terms of
the new-bsd license (two-clause bsd license).
See also: http://www.opensource.org/licenses/bsd-license.php
The repository and optionally the releases contain icons, which are
derived from the WPZOOM Developer Icon Set:
http://www.wpzoom.com/wpzoom/new-freebie-wpzoom-developer-icon-set-154-free-icons/
WPZOOM Developer Icon Set by WPZOOM is licensed under a Creative Commons
Attribution-ShareAlike 3.0 Unported License.
Fonts are licensed under different conditions.
See
https://github.com/olikraus/u8g2/wiki/fntgrp
for detailed information on the licensing conditions for each font.
============ X11 Fonts COUR, HELV, NCEN, TIM, SYMB ============
For fonts derived from the following files, the license below applies.
COURB08.BDF COURB10.BDF COURB12.BDF COURB14.BDF COURB18.BDF
COURB24.BDF COURR08.BDF COURR10.BDF COURR12.BDF COURR14.BDF
COURR18.BDF COURR24.BDF HELVB08.BDF HELVB10.BDF HELVB12.BDF HELVB14.BDF
HELVB18.BDF HELVB24.BDF HELVR08.BDF HELVR10.BDF HELVR12.BDF HELVR14.BDF
HELVR18.BDF HELVR24.BDF NCENB08.BDF NCENB10.BDF NCENB12.BDF
NCENB14.BDF NCENB18.BDF NCENB24.BDF NCENR08.BDF NCENR10.BDF
NCENR12.BDF NCENR14.BDF NCENR18.BDF NCENR24.BDF SYMB08.BDF SYMB10.BDF
SYMB12.BDF SYMB14.BDF SYMB18.BDF SYMB24.BDF TIMB08.BDF TIMB10.BDF
TIMB12.BDF TIMB14.BDF TIMB18.BDF TIMB24.BDF TIMR08.BDF TIMR10.BDF
TIMR12.BDF TIMR14.BDF TIMR18.BDF TIMR24.BDF
Copyright 1984-1989, 1994 Adobe Systems Incorporated.
Copyright 1988, 1994 Digital Equipment Corporation.
Adobe is a trademark of Adobe Systems Incorporated which may be
registered in certain jurisdictions.
Permission to use these trademarks is hereby granted only in
association with the images described in this file.
Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notices appear in all
copies and that both those copyright notices and this permission
notice appear in supporting documentation, and that the names of
Adobe Systems and Digital Equipment Corporation not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission. Adobe Systems and
Digital Equipment Corporation make no representations about the
suitability of this software for any purpose. It is provided "as
is" without express or implied warranty.
============ BSD License for U8g2lib Code ============
Universal 8bit Graphics Library (http://code.google.com/p/u8g2/ and
https://github.com/olikraus/U8g2_Arduino)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,12 @@
# U8g2_Arduino: Arduino Monochrome Graphics Library
![https://raw.githubusercontent.com/wiki/olikraus/u8g2/img/uc1701_dogs102_uno_board_320.jpg](https://raw.githubusercontent.com/wiki/olikraus/u8g2/img/uc1701_dogs102_uno_board_320.jpg)
U8glib V2 library for Arduino
Description: https://github.com/olikraus/u8g2/wiki
Issue Tracker: https://github.com/olikraus/u8g2/issues
Download (2.23.12): https://github.com/olikraus/U8g2_Arduino/archive/master.zip

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
name=U8g2
version=2.23.12
author=oliver <olikraus@gmail.com>
maintainer=oliver <olikraus@gmail.com>
sentence=Monochrome LCD, OLED and eInk Library. Display controller: SSD1305, SSD1306, SSD1309, SSD1322, SSD1325, SSD1327, SSD1329, SSD1606, SSD1607, SH1106, SH1107, SH1122, T6963, RA8835, LC7981, PCD8544, PCF8812, HX1230, UC1601, UC1604, UC1608, UC1610, UC1611, UC1701, ST7565, ST7567, ST7588, ST75256, NT7534, IST3020, ST7920, LD7032, KS0108, SED1520, SBN1661, IL3820, MAX7219. Interfaces: I2C, SPI, Parallel.
paragraph=Monochrome LCD, OLED and eInk Library. Successor of U8glib. Supported display controller: SSD1305, SSD1306, SSD1309, SSD1322, SSD1325, SSD1327, SSD1329, SSD1606, SSD1607, SH1106, SH1107, SH1122, T6963, RA8835, LC7981, PCD8544, PCF8812, HX1230, UC1601, UC1604, UC1608, UC1610, UC1611, UC1701, ST7565, ST7567, ST7588, ST75256, NT7534, IST3020, ST7920, LD7032, KS0108, SED1520, SBN1661, IL3820, MAX7219. Supported interfaces: I2C, SPI, Parallel. Features: UTF8, >700 fonts, U8x8 char output.
category=Display
url=https://github.com/olikraus/u8g2
architectures=*
license=BSD-2-Clause

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,218 @@
/*
u8g2_bitmap.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
void u8g2_SetBitmapMode(u8g2_t *u8g2, uint8_t is_transparent) {
u8g2->bitmap_transparency = is_transparent;
}
/*
x,y Position on the display
len Length of bitmap line in pixel. Note: This differs from u8glib which had a bytecount here.
b Pointer to the bitmap line.
Only draw pixels which are set.
*/
void u8g2_DrawHorizontalBitmap(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, const uint8_t *b)
{
uint8_t mask;
uint8_t color = u8g2->draw_color;
uint8_t ncolor = (color == 0 ? 1 : 0);
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+len, y+1) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
mask = 128;
while(len > 0)
{
if ( *b & mask ) {
u8g2->draw_color = color;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
} else if ( u8g2->bitmap_transparency == 0 ) {
u8g2->draw_color = ncolor;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
}
x++;
mask >>= 1;
if ( mask == 0 )
{
mask = 128;
b++;
}
len--;
}
u8g2->draw_color = color;
}
/* u8glib compatible bitmap draw function */
void u8g2_DrawBitmap(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t cnt, u8g2_uint_t h, const uint8_t *bitmap)
{
u8g2_uint_t w;
w = cnt;
w *= 8;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
while( h > 0 )
{
u8g2_DrawHorizontalBitmap(u8g2, x, y, w, bitmap);
bitmap += cnt;
y++;
h--;
}
}
void u8g2_DrawHXBM(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, const uint8_t *b)
{
uint8_t mask;
uint8_t color = u8g2->draw_color;
uint8_t ncolor = (color == 0 ? 1 : 0);
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+len, y+1) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
mask = 1;
while(len > 0) {
if ( *b & mask ) {
u8g2->draw_color = color;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
} else if ( u8g2->bitmap_transparency == 0 ) {
u8g2->draw_color = ncolor;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
}
x++;
mask <<= 1;
if ( mask == 0 )
{
mask = 1;
b++;
}
len--;
}
u8g2->draw_color = color;
}
void u8g2_DrawXBM(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
{
u8g2_uint_t blen;
blen = w;
blen += 7;
blen >>= 3;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
while( h > 0 )
{
u8g2_DrawHXBM(u8g2, x, y, w, bitmap);
bitmap += blen;
y++;
h--;
}
}
void u8g2_DrawHXBMP(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, const uint8_t *b)
{
uint8_t mask;
uint8_t color = u8g2->draw_color;
uint8_t ncolor = (color == 0 ? 1 : 0);
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+len, y+1) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
mask = 1;
while(len > 0)
{
if( u8x8_pgm_read(b) & mask ) {
u8g2->draw_color = color;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
} else if( u8g2->bitmap_transparency == 0 ) {
u8g2->draw_color = ncolor;
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
}
x++;
mask <<= 1;
if ( mask == 0 )
{
mask = 1;
b++;
}
len--;
}
u8g2->draw_color = color;
}
void u8g2_DrawXBMP(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
{
u8g2_uint_t blen;
blen = w;
blen += 7;
blen >>= 3;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
while( h > 0 )
{
u8g2_DrawHXBMP(u8g2, x, y, w, bitmap);
bitmap += blen;
y++;
h--;
}
}

View File

@ -0,0 +1,207 @@
/*
u8g2_box.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/*
draw a filled box
restriction: does not work for w = 0 or h = 0
*/
void u8g2_DrawBox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
{
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
while( h != 0 )
{
u8g2_DrawHVLine(u8g2, x, y, w, 0);
y++;
h--;
}
}
/*
draw a frame (empty box)
restriction: does not work for w = 0 or h = 0
ToDo:
pixel in the corners are drawn twice. This could be optimized.
*/
void u8g2_DrawFrame(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
{
u8g2_uint_t xtmp = x;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
u8g2_DrawHVLine(u8g2, x, y, w, 0);
u8g2_DrawHVLine(u8g2, x, y, h, 1);
x+=w;
x--;
u8g2_DrawHVLine(u8g2, x, y, h, 1);
y+=h;
y--;
u8g2_DrawHVLine(u8g2, xtmp, y, w, 0);
}
void u8g2_DrawRBox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
{
u8g2_uint_t xl, yu;
u8g2_uint_t yl, xr;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
xl = x;
xl += r;
yu = y;
yu += r;
xr = x;
xr += w;
xr -= r;
xr -= 1;
yl = y;
yl += h;
yl -= r;
yl -= 1;
u8g2_DrawDisc(u8g2, xl, yu, r, U8G2_DRAW_UPPER_LEFT);
u8g2_DrawDisc(u8g2, xr, yu, r, U8G2_DRAW_UPPER_RIGHT);
u8g2_DrawDisc(u8g2, xl, yl, r, U8G2_DRAW_LOWER_LEFT);
u8g2_DrawDisc(u8g2, xr, yl, r, U8G2_DRAW_LOWER_RIGHT);
{
u8g2_uint_t ww, hh;
ww = w;
ww -= r;
ww -= r;
xl++;
yu++;
if ( ww >= 3 )
{
ww -= 2;
u8g2_DrawBox(u8g2, xl, y, ww, r+1);
u8g2_DrawBox(u8g2, xl, yl, ww, r+1);
}
hh = h;
hh -= r;
hh -= r;
//h--;
if ( hh >= 3 )
{
hh -= 2;
u8g2_DrawBox(u8g2, x, yu, w, hh);
}
}
}
void u8g2_DrawRFrame(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
{
u8g2_uint_t xl, yu;
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+w, y+h) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
xl = x;
xl += r;
yu = y;
yu += r;
{
u8g2_uint_t yl, xr;
xr = x;
xr += w;
xr -= r;
xr -= 1;
yl = y;
yl += h;
yl -= r;
yl -= 1;
u8g2_DrawCircle(u8g2, xl, yu, r, U8G2_DRAW_UPPER_LEFT);
u8g2_DrawCircle(u8g2, xr, yu, r, U8G2_DRAW_UPPER_RIGHT);
u8g2_DrawCircle(u8g2, xl, yl, r, U8G2_DRAW_LOWER_LEFT);
u8g2_DrawCircle(u8g2, xr, yl, r, U8G2_DRAW_LOWER_RIGHT);
}
{
u8g2_uint_t ww, hh;
ww = w;
ww -= r;
ww -= r;
hh = h;
hh -= r;
hh -= r;
xl++;
yu++;
if ( ww >= 3 )
{
ww -= 2;
h--;
u8g2_DrawHLine(u8g2, xl, y, ww);
u8g2_DrawHLine(u8g2, xl, y+h, ww);
}
if ( hh >= 3 )
{
hh -= 2;
w--;
u8g2_DrawVLine(u8g2, x, yu, hh);
u8g2_DrawVLine(u8g2, x+w, yu, hh);
}
}
}

View File

@ -0,0 +1,132 @@
/*
u8g2_buffer.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#include <string.h>
/*============================================*/
void u8g2_ClearBuffer(u8g2_t *u8g2)
{
size_t cnt;
cnt = u8g2_GetU8x8(u8g2)->display_info->tile_width;
cnt *= u8g2->tile_buf_height;
cnt *= 8;
memset(u8g2->tile_buf_ptr, 0, cnt);
}
/*============================================*/
static void u8g2_send_tile_row(u8g2_t *u8g2, uint8_t src_tile_row, uint8_t dest_tile_row)
{
uint8_t *ptr;
uint16_t offset;
uint8_t w;
w = u8g2_GetU8x8(u8g2)->display_info->tile_width;
offset = src_tile_row;
ptr = u8g2->tile_buf_ptr;
offset *= w;
offset *= 8;
ptr += offset;
u8x8_DrawTile(u8g2_GetU8x8(u8g2), 0, dest_tile_row, w, ptr);
}
/*
write the buffer to the display RAM.
For most displays, this will make the content visible to the user.
Some displays (like the SSD1606) require a u8x8_RefreshDisplay()
*/
static void u8g2_send_buffer(u8g2_t *u8g2) U8X8_NOINLINE;
static void u8g2_send_buffer(u8g2_t *u8g2)
{
uint8_t src_row;
uint8_t src_max;
uint8_t dest_row;
uint8_t dest_max;
src_row = 0;
src_max = u8g2->tile_buf_height;
dest_row = u8g2->tile_curr_row;
dest_max = u8g2_GetU8x8(u8g2)->display_info->tile_height;
do
{
u8g2_send_tile_row(u8g2, src_row, dest_row);
src_row++;
dest_row++;
} while( src_row < src_max && dest_row < dest_max );
}
/* same as u8g2_send_buffer but also send the DISPLAY_REFRESH message (used by SSD1606) */
void u8g2_SendBuffer(u8g2_t *u8g2)
{
u8g2_send_buffer(u8g2);
u8x8_RefreshDisplay( u8g2_GetU8x8(u8g2) );
}
/*============================================*/
void u8g2_SetBufferCurrTileRow(u8g2_t *u8g2, uint8_t row)
{
u8g2->tile_curr_row = row;
u8g2->cb->update(u8g2);
}
void u8g2_FirstPage(u8g2_t *u8g2)
{
if ( u8g2->is_auto_page_clear )
{
u8g2_ClearBuffer(u8g2);
}
u8g2_SetBufferCurrTileRow(u8g2, 0);
}
uint8_t u8g2_NextPage(u8g2_t *u8g2)
{
uint8_t row;
u8g2_send_buffer(u8g2);
row = u8g2->tile_curr_row;
row += u8g2->tile_buf_height;
if ( row >= u8g2_GetU8x8(u8g2)->display_info->tile_height )
{
u8x8_RefreshDisplay( u8g2_GetU8x8(u8g2) );
return 0;
}
if ( u8g2->is_auto_page_clear )
{
u8g2_ClearBuffer(u8g2);
}
u8g2_SetBufferCurrTileRow(u8g2, row);
return 1;
}

View File

@ -0,0 +1,479 @@
/*
u8g2_box.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/*==============================================*/
/* Circle */
static void u8g2_draw_circle_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option) U8G2_NOINLINE;
static void u8g2_draw_circle_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G2_DRAW_UPPER_RIGHT )
{
u8g2_DrawPixel(u8g2, x0 + x, y0 - y);
u8g2_DrawPixel(u8g2, x0 + y, y0 - x);
}
/* upper left */
if ( option & U8G2_DRAW_UPPER_LEFT )
{
u8g2_DrawPixel(u8g2, x0 - x, y0 - y);
u8g2_DrawPixel(u8g2, x0 - y, y0 - x);
}
/* lower right */
if ( option & U8G2_DRAW_LOWER_RIGHT )
{
u8g2_DrawPixel(u8g2, x0 + x, y0 + y);
u8g2_DrawPixel(u8g2, x0 + y, y0 + x);
}
/* lower left */
if ( option & U8G2_DRAW_LOWER_LEFT )
{
u8g2_DrawPixel(u8g2, x0 - x, y0 + y);
u8g2_DrawPixel(u8g2, x0 - y, y0 + x);
}
}
static void u8g2_draw_circle(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)
{
u8g2_int_t f;
u8g2_int_t ddF_x;
u8g2_int_t ddF_y;
u8g2_uint_t x;
u8g2_uint_t y;
f = 1;
f -= rad;
ddF_x = 1;
ddF_y = 0;
ddF_y -= rad;
ddF_y *= 2;
x = 0;
y = rad;
u8g2_draw_circle_section(u8g2, x, y, x0, y0, option);
while ( x < y )
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
u8g2_draw_circle_section(u8g2, x, y, x0, y0, option);
}
}
void u8g2_DrawCircle(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)
{
/* check for bounding box */
#ifdef U8G2_WITH_INTERSECTION
{
if ( u8g2_IsIntersection(u8g2, x0-rad, y0-rad, x0+rad+1, y0+rad+1) == 0 )
return;
}
#endif /* U8G2_WITH_INTERSECTION */
/* draw circle */
u8g2_draw_circle(u8g2, x0, y0, rad, option);
}
/*==============================================*/
/* Disk */
static void u8g2_draw_disc_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option) U8G2_NOINLINE;
static void u8g2_draw_disc_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G2_DRAW_UPPER_RIGHT )
{
u8g2_DrawVLine(u8g2, x0+x, y0-y, y+1);
u8g2_DrawVLine(u8g2, x0+y, y0-x, x+1);
}
/* upper left */
if ( option & U8G2_DRAW_UPPER_LEFT )
{
u8g2_DrawVLine(u8g2, x0-x, y0-y, y+1);
u8g2_DrawVLine(u8g2, x0-y, y0-x, x+1);
}
/* lower right */
if ( option & U8G2_DRAW_LOWER_RIGHT )
{
u8g2_DrawVLine(u8g2, x0+x, y0, y+1);
u8g2_DrawVLine(u8g2, x0+y, y0, x+1);
}
/* lower left */
if ( option & U8G2_DRAW_LOWER_LEFT )
{
u8g2_DrawVLine(u8g2, x0-x, y0, y+1);
u8g2_DrawVLine(u8g2, x0-y, y0, x+1);
}
}
static void u8g2_draw_disc(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)
{
u8g2_int_t f;
u8g2_int_t ddF_x;
u8g2_int_t ddF_y;
u8g2_uint_t x;
u8g2_uint_t y;
f = 1;
f -= rad;
ddF_x = 1;
ddF_y = 0;
ddF_y -= rad;
ddF_y *= 2;
x = 0;
y = rad;
u8g2_draw_disc_section(u8g2, x, y, x0, y0, option);
while ( x < y )
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
u8g2_draw_disc_section(u8g2, x, y, x0, y0, option);
}
}
void u8g2_DrawDisc(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t option)
{
/* check for bounding box */
#ifdef U8G2_WITH_INTERSECTION
{
if ( u8g2_IsIntersection(u8g2, x0-rad, y0-rad, x0+rad+1, y0+rad+1) == 0 )
return;
}
#endif /* U8G2_WITH_INTERSECTION */
/* draw disc */
u8g2_draw_disc(u8g2, x0, y0, rad, option);
}
/*==============================================*/
/* Ellipse */
/*
Source:
Foley, Computer Graphics, p 90
*/
static void u8g2_draw_ellipse_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option) U8G2_NOINLINE;
static void u8g2_draw_ellipse_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G2_DRAW_UPPER_RIGHT )
{
u8g2_DrawPixel(u8g2, x0 + x, y0 - y);
}
/* upper left */
if ( option & U8G2_DRAW_UPPER_LEFT )
{
u8g2_DrawPixel(u8g2, x0 - x, y0 - y);
}
/* lower right */
if ( option & U8G2_DRAW_LOWER_RIGHT )
{
u8g2_DrawPixel(u8g2, x0 + x, y0 + y);
}
/* lower left */
if ( option & U8G2_DRAW_LOWER_LEFT )
{
u8g2_DrawPixel(u8g2, x0 - x, y0 + y);
}
}
static void u8g2_draw_ellipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)
{
u8g2_uint_t x, y;
u8g2_long_t xchg, ychg;
u8g2_long_t err;
u8g2_long_t rxrx2;
u8g2_long_t ryry2;
u8g2_long_t stopx, stopy;
rxrx2 = rx;
rxrx2 *= rx;
rxrx2 *= 2;
ryry2 = ry;
ryry2 *= ry;
ryry2 *= 2;
x = rx;
y = 0;
xchg = 1;
xchg -= rx;
xchg -= rx;
xchg *= ry;
xchg *= ry;
ychg = rx;
ychg *= rx;
err = 0;
stopx = ryry2;
stopx *= rx;
stopy = 0;
while( stopx >= stopy )
{
u8g2_draw_ellipse_section(u8g2, x, y, x0, y0, option);
y++;
stopy += rxrx2;
err += ychg;
ychg += rxrx2;
if ( 2*err+xchg > 0 )
{
x--;
stopx -= ryry2;
err += xchg;
xchg += ryry2;
}
}
x = 0;
y = ry;
xchg = ry;
xchg *= ry;
ychg = 1;
ychg -= ry;
ychg -= ry;
ychg *= rx;
ychg *= rx;
err = 0;
stopx = 0;
stopy = rxrx2;
stopy *= ry;
while( stopx <= stopy )
{
u8g2_draw_ellipse_section(u8g2, x, y, x0, y0, option);
x++;
stopx += ryry2;
err += xchg;
xchg += ryry2;
if ( 2*err+ychg > 0 )
{
y--;
stopy -= rxrx2;
err += ychg;
ychg += rxrx2;
}
}
}
void u8g2_DrawEllipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)
{
/* check for bounding box */
#ifdef U8G2_WITH_INTERSECTION
{
if ( u8g2_IsIntersection(u8g2, x0-rx, y0-ry, x0+rx+1, y0+ry+1) == 0 )
return;
}
#endif /* U8G2_WITH_INTERSECTION */
u8g2_draw_ellipse(u8g2, x0, y0, rx, ry, option);
}
/*==============================================*/
/* Filled Ellipse */
static void u8g2_draw_filled_ellipse_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option) U8G2_NOINLINE;
static void u8g2_draw_filled_ellipse_section(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t x0, u8g2_uint_t y0, uint8_t option)
{
/* upper right */
if ( option & U8G2_DRAW_UPPER_RIGHT )
{
u8g2_DrawVLine(u8g2, x0+x, y0-y, y+1);
}
/* upper left */
if ( option & U8G2_DRAW_UPPER_LEFT )
{
u8g2_DrawVLine(u8g2, x0-x, y0-y, y+1);
}
/* lower right */
if ( option & U8G2_DRAW_LOWER_RIGHT )
{
u8g2_DrawVLine(u8g2, x0+x, y0, y+1);
}
/* lower left */
if ( option & U8G2_DRAW_LOWER_LEFT )
{
u8g2_DrawVLine(u8g2, x0-x, y0, y+1);
}
}
static void u8g2_draw_filled_ellipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)
{
u8g2_uint_t x, y;
u8g2_long_t xchg, ychg;
u8g2_long_t err;
u8g2_long_t rxrx2;
u8g2_long_t ryry2;
u8g2_long_t stopx, stopy;
rxrx2 = rx;
rxrx2 *= rx;
rxrx2 *= 2;
ryry2 = ry;
ryry2 *= ry;
ryry2 *= 2;
x = rx;
y = 0;
xchg = 1;
xchg -= rx;
xchg -= rx;
xchg *= ry;
xchg *= ry;
ychg = rx;
ychg *= rx;
err = 0;
stopx = ryry2;
stopx *= rx;
stopy = 0;
while( stopx >= stopy )
{
u8g2_draw_filled_ellipse_section(u8g2, x, y, x0, y0, option);
y++;
stopy += rxrx2;
err += ychg;
ychg += rxrx2;
if ( 2*err+xchg > 0 )
{
x--;
stopx -= ryry2;
err += xchg;
xchg += ryry2;
}
}
x = 0;
y = ry;
xchg = ry;
xchg *= ry;
ychg = 1;
ychg -= ry;
ychg -= ry;
ychg *= rx;
ychg *= rx;
err = 0;
stopx = 0;
stopy = rxrx2;
stopy *= ry;
while( stopx <= stopy )
{
u8g2_draw_filled_ellipse_section(u8g2, x, y, x0, y0, option);
x++;
stopx += ryry2;
err += xchg;
xchg += ryry2;
if ( 2*err+ychg > 0 )
{
y--;
stopy -= rxrx2;
err += ychg;
ychg += rxrx2;
}
}
}
void u8g2_DrawFilledEllipse(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t option)
{
/* check for bounding box */
#ifdef U8G2_WITH_INTERSECTION
{
if ( u8g2_IsIntersection(u8g2, x0-rx, y0-ry, x0+rx+1, y0+ry+1) == 0 )
return;
}
#endif /* U8G2_WITH_INTERSECTION */
u8g2_draw_filled_ellipse(u8g2, x0, y0, rx, ry, option);
}

View File

@ -0,0 +1,54 @@
/*
u8g2_cleardisplay.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/* Clear screen buffer & display reliable for all u8g2 displays. */
/* This is done with u8g2 picture loop, because we can not use the u8x8 function in all cases */
void u8g2_ClearDisplay(u8g2_t *u8g2)
{
u8g2_FirstPage(u8g2);
do {
} while ( u8g2_NextPage(u8g2) );
/*
This function is usually called during startup (u8g2.begin()).
However the user might want to use full buffer mode with clear and
send commands.
This will not work because the current tile row is modified by the picture
loop above. To fix this, reset the tile row to 0, issue #370
A workaround would be, that the user sets the current tile row to 0 manually.
*/
u8g2_SetBufferCurrTileRow(u8g2, 0);
}

View File

@ -0,0 +1,690 @@
/* u8g2_d_memory.c */
/* generated code, codebuild, u8g2 project */
#include "u8g2.h"
uint8_t *u8g2_m_16_4_1(uint8_t *page_cnt)
{
static uint8_t buf[128];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_16_4_2(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_16_4_f(uint8_t *page_cnt)
{
static uint8_t buf[512];
*page_cnt = 4;
return buf;
}
uint8_t *u8g2_m_16_8_1(uint8_t *page_cnt)
{
static uint8_t buf[128];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_16_8_2(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)
{
static uint8_t buf[1024];
*page_cnt = 8;
return buf;
}
uint8_t *u8g2_m_9_5_1(uint8_t *page_cnt)
{
static uint8_t buf[72];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_9_5_2(uint8_t *page_cnt)
{
static uint8_t buf[144];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_9_5_f(uint8_t *page_cnt)
{
static uint8_t buf[360];
*page_cnt = 5;
return buf;
}
uint8_t *u8g2_m_8_4_1(uint8_t *page_cnt)
{
static uint8_t buf[64];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_8_4_2(uint8_t *page_cnt)
{
static uint8_t buf[128];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_8_4_f(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 4;
return buf;
}
uint8_t *u8g2_m_8_16_1(uint8_t *page_cnt)
{
static uint8_t buf[64];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_8_16_2(uint8_t *page_cnt)
{
static uint8_t buf[128];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_8_16_f(uint8_t *page_cnt)
{
static uint8_t buf[1024];
*page_cnt = 16;
return buf;
}
uint8_t *u8g2_m_12_12_1(uint8_t *page_cnt)
{
static uint8_t buf[96];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_12_12_2(uint8_t *page_cnt)
{
static uint8_t buf[192];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_12_12_f(uint8_t *page_cnt)
{
static uint8_t buf[1152];
*page_cnt = 12;
return buf;
}
uint8_t *u8g2_m_16_16_1(uint8_t *page_cnt)
{
static uint8_t buf[128];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_16_16_2(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_16_16_f(uint8_t *page_cnt)
{
static uint8_t buf[2048];
*page_cnt = 16;
return buf;
}
uint8_t *u8g2_m_20_20_1(uint8_t *page_cnt)
{
static uint8_t buf[160];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_20_20_2(uint8_t *page_cnt)
{
static uint8_t buf[320];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_20_20_f(uint8_t *page_cnt)
{
static uint8_t buf[3200];
*page_cnt = 20;
return buf;
}
uint8_t *u8g2_m_32_8_1(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_32_8_2(uint8_t *page_cnt)
{
static uint8_t buf[512];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_32_8_f(uint8_t *page_cnt)
{
static uint8_t buf[2048];
*page_cnt = 8;
return buf;
}
uint8_t *u8g2_m_8_6_1(uint8_t *page_cnt)
{
static uint8_t buf[64];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_8_6_2(uint8_t *page_cnt)
{
static uint8_t buf[128];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_8_6_f(uint8_t *page_cnt)
{
static uint8_t buf[384];
*page_cnt = 6;
return buf;
}
uint8_t *u8g2_m_6_8_1(uint8_t *page_cnt)
{
static uint8_t buf[48];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_6_8_2(uint8_t *page_cnt)
{
static uint8_t buf[96];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_6_8_f(uint8_t *page_cnt)
{
static uint8_t buf[384];
*page_cnt = 8;
return buf;
}
uint8_t *u8g2_m_12_2_1(uint8_t *page_cnt)
{
static uint8_t buf[96];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_12_2_2(uint8_t *page_cnt)
{
static uint8_t buf[192];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_12_2_f(uint8_t *page_cnt)
{
static uint8_t buf[192];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_32_4_1(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_32_4_2(uint8_t *page_cnt)
{
static uint8_t buf[512];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_32_4_f(uint8_t *page_cnt)
{
static uint8_t buf[1024];
*page_cnt = 4;
return buf;
}
uint8_t *u8g2_m_16_12_1(uint8_t *page_cnt)
{
static uint8_t buf[128];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_16_12_2(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_16_12_f(uint8_t *page_cnt)
{
static uint8_t buf[1536];
*page_cnt = 12;
return buf;
}
uint8_t *u8g2_m_24_4_1(uint8_t *page_cnt)
{
static uint8_t buf[192];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_24_4_2(uint8_t *page_cnt)
{
static uint8_t buf[384];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_24_4_f(uint8_t *page_cnt)
{
static uint8_t buf[768];
*page_cnt = 4;
return buf;
}
uint8_t *u8g2_m_13_8_1(uint8_t *page_cnt)
{
static uint8_t buf[104];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_13_8_2(uint8_t *page_cnt)
{
static uint8_t buf[208];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_13_8_f(uint8_t *page_cnt)
{
static uint8_t buf[832];
*page_cnt = 8;
return buf;
}
uint8_t *u8g2_m_11_6_1(uint8_t *page_cnt)
{
static uint8_t buf[88];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_11_6_2(uint8_t *page_cnt)
{
static uint8_t buf[176];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_11_6_f(uint8_t *page_cnt)
{
static uint8_t buf[528];
*page_cnt = 6;
return buf;
}
uint8_t *u8g2_m_12_9_1(uint8_t *page_cnt)
{
static uint8_t buf[96];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_12_9_2(uint8_t *page_cnt)
{
static uint8_t buf[192];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_12_9_f(uint8_t *page_cnt)
{
static uint8_t buf[864];
*page_cnt = 9;
return buf;
}
uint8_t *u8g2_m_24_8_1(uint8_t *page_cnt)
{
static uint8_t buf[192];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_24_8_2(uint8_t *page_cnt)
{
static uint8_t buf[384];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_24_8_f(uint8_t *page_cnt)
{
static uint8_t buf[1536];
*page_cnt = 8;
return buf;
}
uint8_t *u8g2_m_30_8_1(uint8_t *page_cnt)
{
static uint8_t buf[240];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_30_8_2(uint8_t *page_cnt)
{
static uint8_t buf[480];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_30_8_f(uint8_t *page_cnt)
{
static uint8_t buf[1920];
*page_cnt = 8;
return buf;
}
uint8_t *u8g2_m_30_15_1(uint8_t *page_cnt)
{
static uint8_t buf[240];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_30_15_2(uint8_t *page_cnt)
{
static uint8_t buf[480];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_30_15_f(uint8_t *page_cnt)
{
static uint8_t buf[3600];
*page_cnt = 15;
return buf;
}
uint8_t *u8g2_m_30_16_1(uint8_t *page_cnt)
{
static uint8_t buf[240];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_30_16_2(uint8_t *page_cnt)
{
static uint8_t buf[480];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_30_16_f(uint8_t *page_cnt)
{
static uint8_t buf[3840];
*page_cnt = 16;
return buf;
}
uint8_t *u8g2_m_20_16_1(uint8_t *page_cnt)
{
static uint8_t buf[160];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_20_16_2(uint8_t *page_cnt)
{
static uint8_t buf[320];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_20_16_f(uint8_t *page_cnt)
{
static uint8_t buf[2560];
*page_cnt = 16;
return buf;
}
uint8_t *u8g2_m_20_13_1(uint8_t *page_cnt)
{
static uint8_t buf[160];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_20_13_2(uint8_t *page_cnt)
{
static uint8_t buf[320];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_20_13_f(uint8_t *page_cnt)
{
static uint8_t buf[2080];
*page_cnt = 13;
return buf;
}
uint8_t *u8g2_m_30_20_1(uint8_t *page_cnt)
{
static uint8_t buf[240];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_30_20_2(uint8_t *page_cnt)
{
static uint8_t buf[480];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_30_20_f(uint8_t *page_cnt)
{
static uint8_t buf[4800];
*page_cnt = 20;
return buf;
}
uint8_t *u8g2_m_17_4_1(uint8_t *page_cnt)
{
static uint8_t buf[136];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_17_4_2(uint8_t *page_cnt)
{
static uint8_t buf[272];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_17_4_f(uint8_t *page_cnt)
{
static uint8_t buf[544];
*page_cnt = 4;
return buf;
}
uint8_t *u8g2_m_17_8_1(uint8_t *page_cnt)
{
static uint8_t buf[136];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_17_8_2(uint8_t *page_cnt)
{
static uint8_t buf[272];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_17_8_f(uint8_t *page_cnt)
{
static uint8_t buf[1088];
*page_cnt = 8;
return buf;
}
uint8_t *u8g2_m_32_16_1(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_32_16_2(uint8_t *page_cnt)
{
static uint8_t buf[512];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_32_16_f(uint8_t *page_cnt)
{
static uint8_t buf[4096];
*page_cnt = 16;
return buf;
}
uint8_t *u8g2_m_32_20_1(uint8_t *page_cnt)
{
static uint8_t buf[256];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_32_20_2(uint8_t *page_cnt)
{
static uint8_t buf[512];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_32_20_f(uint8_t *page_cnt)
{
static uint8_t buf[5120];
*page_cnt = 20;
return buf;
}
uint8_t *u8g2_m_22_13_1(uint8_t *page_cnt)
{
static uint8_t buf[176];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_22_13_2(uint8_t *page_cnt)
{
static uint8_t buf[352];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_22_13_f(uint8_t *page_cnt)
{
static uint8_t buf[2288];
*page_cnt = 13;
return buf;
}
uint8_t *u8g2_m_20_10_1(uint8_t *page_cnt)
{
static uint8_t buf[160];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_20_10_2(uint8_t *page_cnt)
{
static uint8_t buf[320];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_20_10_f(uint8_t *page_cnt)
{
static uint8_t buf[1600];
*page_cnt = 10;
return buf;
}
uint8_t *u8g2_m_22_9_1(uint8_t *page_cnt)
{
static uint8_t buf[176];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_22_9_2(uint8_t *page_cnt)
{
static uint8_t buf[352];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_22_9_f(uint8_t *page_cnt)
{
static uint8_t buf[1584];
*page_cnt = 9;
return buf;
}
uint8_t *u8g2_m_25_25_1(uint8_t *page_cnt)
{
static uint8_t buf[200];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_25_25_2(uint8_t *page_cnt)
{
static uint8_t buf[400];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_25_25_f(uint8_t *page_cnt)
{
static uint8_t buf[5000];
*page_cnt = 25;
return buf;
}
uint8_t *u8g2_m_37_16_1(uint8_t *page_cnt)
{
static uint8_t buf[296];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_37_16_2(uint8_t *page_cnt)
{
static uint8_t buf[592];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_37_16_f(uint8_t *page_cnt)
{
static uint8_t buf[4736];
*page_cnt = 16;
return buf;
}
uint8_t *u8g2_m_40_30_1(uint8_t *page_cnt)
{
static uint8_t buf[320];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_40_30_2(uint8_t *page_cnt)
{
static uint8_t buf[640];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_40_30_f(uint8_t *page_cnt)
{
static uint8_t buf[9600];
*page_cnt = 30;
return buf;
}
uint8_t *u8g2_m_4_1_1(uint8_t *page_cnt)
{
static uint8_t buf[32];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_4_1_2(uint8_t *page_cnt)
{
static uint8_t buf[64];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_4_1_f(uint8_t *page_cnt)
{
static uint8_t buf[32];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_1_1_1(uint8_t *page_cnt)
{
static uint8_t buf[8];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_1_1_2(uint8_t *page_cnt)
{
static uint8_t buf[16];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_1_1_f(uint8_t *page_cnt)
{
static uint8_t buf[8];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_48_30_1(uint8_t *page_cnt)
{
static uint8_t buf[384];
*page_cnt = 1;
return buf;
}
uint8_t *u8g2_m_48_30_2(uint8_t *page_cnt)
{
static uint8_t buf[768];
*page_cnt = 2;
return buf;
}
uint8_t *u8g2_m_48_30_f(uint8_t *page_cnt)
{
static uint8_t buf[11520];
*page_cnt = 30;
return buf;
}
/* end of generated code */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,267 @@
/*
u8g2_hvline.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Calltree
void u8g2_DrawHVLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
u8g2->cb->draw_l90
void u8g2_draw_hv_line_4dir(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
void u8g2_draw_hv_line_2dir(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
void u8g2_draw_pixel(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y)
*/
#include "u8g2.h"
#include <assert.h>
#ifdef U8G2_WITH_CLIPPING
/*
Description:
clip range from a (included) to b (excluded) agains c (included) to d (excluded)
Assumptions:
a <= b (violation is checked and handled correctly)
c <= d (this is not checked)
will return 0 if there is no intersection and if a > b
optimized clipping: c is set to 0
*/
//static uint8_t u8g2_clip_intersection(u8g2_uint_t *ap, u8g2_uint_t *bp, u8g2_uint_t c, u8g2_uint_t d)
static uint8_t u8g2_clip_intersection(u8g2_uint_t *ap, u8g2_uint_t *bp, u8g2_uint_t d)
{
u8g2_uint_t a = *ap;
u8g2_uint_t b = *bp;
/* handle the a>b case correctly. If code and time is critical, this could */
/* be removed completly (be aware about memory curruption for wrong */
/* arguments) or return 0 for a>b (will lead to skipped lines for wrong */
/* arguments) */
/* removing the following if clause completly may lead to memory corruption of a>b */
if ( a > b )
{
/* replacing this if with a simple "return 0;" will not handle the case with negative a */
if ( a < d )
{
b = d;
b--;
*bp = b;
}
else
{
a = 0;
*ap = a;
}
}
/* from now on, the asumption a <= b is ok */
if ( a >= d )
return 0;
if ( b <= 0 ) // was b <= c, could be replaced with b == 0
return 0;
//if ( a < c ) // never true with c == 0
// *ap = c;
if ( b > d )
*bp = d;
return 1;
}
/*
x,y Upper left position of the line within the pixel buffer
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
This function first adjusts the y position to the local buffer. Then it
will clip the line and call u8g2_draw_low_level_hv_line()
*/
static void u8g2_draw_hv_line_2dir(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t a;
register u8g2_uint_t w, h;
h = u8g2->pixel_buf_height; // this must be the real buffer height
w = u8g2->pixel_buf_width; // this could be replaced by u8g2->u8x8.display_info->pixel_width
if ( dir == 0 )
{
if ( y >= h )
return;
a = x;
a += len;
if ( u8g2_clip_intersection(&x, &a, w) == 0 )
return;
len = a;
len -= x;
}
else
{
if ( x >= w )
return;
a = y;
a += len;
if ( u8g2_clip_intersection(&y, &a, h) == 0 )
return;
len = a;
len -= y;
}
u8g2->ll_hvline(u8g2, x, y, len, dir);
}
#endif
/*
x,y Upper left position of the line (full screen coordinates)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
2: horizontal line (right to left)
3: vertical line (bottom to top)
This function will remove directions 2 and 3. Instead 0 and 1 are used.
*/
void u8g2_draw_hv_line_4dir(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
#ifdef U8G2_WITH_HVLINE_COUNT
u8g2->hv_cnt++;
#endif /* U8G2_WITH_HVLINE_COUNT */
/* transform to pixel buffer coordinates */
y -= u8g2->tile_curr_row*8;
/* additional optimization for one pixel draw */
/* requires about 60 bytes on the ATMega flash memory */
/* 20% improvement for single pixel draw test in FPS.ino */
#ifdef U8G2_WITH_ONE_PIXEL_OPTIMIZATION
if ( len == 1 )
{
if ( x < u8g2->pixel_buf_width && y < u8g2->pixel_buf_height )
u8g2->ll_hvline(u8g2, x, y, len, dir);
return;
}
#endif
if ( dir == 2 )
{
x -= len;
x++;
}
else if ( dir == 3 )
{
y -= len;
y++;
}
dir &= 1;
#ifdef U8G2_WITH_CLIPPING
u8g2_draw_hv_line_2dir(u8g2, x, y, len, dir);
#else
u8g2->ll_hvline(u8g2, x, y, len, dir);
#endif
}
/*
This is the toplevel function for the hv line draw procedures.
This function should be called by the user.
*/
void u8g2_DrawHVLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
/* Make a call to the callback function (e.g. u8g2_draw_l90_r0). */
/* The callback may rotate the hv line */
/* after rotation this will call u8g2_draw_hv_line_4dir() */
if ( len != 0 )
u8g2->cb->draw_l90(u8g2, x, y, len, dir);
}
void u8g2_DrawHLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len)
{
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+len, y+1) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
u8g2_DrawHVLine(u8g2, x, y, len, 0);
}
void u8g2_DrawVLine(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len)
{
#ifdef U8G2_WITH_INTERSECTION
if ( u8g2_IsIntersection(u8g2, x, y, x+1, y+len) == 0 )
return;
#endif /* U8G2_WITH_INTERSECTION */
u8g2_DrawHVLine(u8g2, x, y, len, 1);
}
void u8g2_DrawPixel(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y)
{
#ifdef U8G2_WITH_INTERSECTION
if ( y < u8g2->user_y0 )
return;
if ( y >= u8g2->user_y1 )
return;
if ( x < u8g2->user_x0 )
return;
if ( x >= u8g2->user_x1 )
return;
#endif /* U8G2_WITH_INTERSECTION */
u8g2_DrawHVLine(u8g2, x, y, 1, 0);
}
/*
Assign the draw color for all drawing functions.
color may be 0 or 1. The actual color is defined by the display.
With color = 1 the drawing function will set the display memory to 1.
For OLEDs this ususally means, that the pixel is enabled and the LED
at the pixel is turned on.
On an LCD it usually means that the LCD segment of the pixel is enabled,
which absorbs the light.
For eInk/ePaper it means black ink.
7 Jan 2017: Allow color value 2 for XOR operation.
*/
void u8g2_SetDrawColor(u8g2_t *u8g2, uint8_t color)
{
u8g2->draw_color = color; /* u8g2_SetDrawColor: just assign the argument */
if ( color >= 3 )
u8g2->draw_color = 1; /* u8g2_SetDrawColor: make color as one if arg is invalid */
}

View File

@ -0,0 +1,150 @@
/*
u8g2_input_value.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/*
return:
0: value is not changed (HOME/Break Button pressed)
1: value has been updated
*/
uint8_t u8g2_UserInterfaceInputValue(u8g2_t *u8g2, const char *title, const char *pre, uint8_t *value, uint8_t lo, uint8_t hi, uint8_t digits, const char *post)
{
uint8_t line_height;
uint8_t height;
u8g2_uint_t pixel_height;
u8g2_uint_t y, yy;
u8g2_uint_t pixel_width;
u8g2_uint_t x, xx;
uint8_t local_value = *value;
//uint8_t r; /* not used ??? */
uint8_t event;
/* only horizontal strings are supported, so force this here */
u8g2_SetFontDirection(u8g2, 0);
/* force baseline position */
u8g2_SetFontPosBaseline(u8g2);
/* calculate line height */
line_height = u8g2_GetAscent(u8g2);
line_height -= u8g2_GetDescent(u8g2);
/* calculate overall height of the input value box */
height = 1; /* value input line */
height += u8x8_GetStringLineCnt(title);
/* calculate the height in pixel */
pixel_height = height;
pixel_height *= line_height;
/* calculate offset from top */
y = 0;
if ( pixel_height < u8g2_GetDisplayHeight(u8g2) )
{
y = u8g2_GetDisplayHeight(u8g2);
y -= pixel_height;
y /= 2;
}
/* calculate offset from left for the label */
x = 0;
pixel_width = u8g2_GetUTF8Width(u8g2, pre);
pixel_width += u8g2_GetUTF8Width(u8g2, "0") * digits;
pixel_width += u8g2_GetUTF8Width(u8g2, post);
if ( pixel_width < u8g2_GetDisplayWidth(u8g2) )
{
x = u8g2_GetDisplayWidth(u8g2);
x -= pixel_width;
x /= 2;
}
/* event loop */
for(;;)
{
u8g2_FirstPage(u8g2);
do
{
/* render */
yy = y;
yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title);
xx = x;
xx += u8g2_DrawUTF8(u8g2, xx, yy, pre);
xx += u8g2_DrawUTF8(u8g2, xx, yy, u8x8_u8toa(local_value, digits));
u8g2_DrawUTF8(u8g2, xx, yy, post);
} while( u8g2_NextPage(u8g2) );
#ifdef U8G2_REF_MAN_PIC
return 0;
#endif
for(;;)
{
event = u8x8_GetMenuEvent(u8g2_GetU8x8(u8g2));
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
{
*value = local_value;
return 1;
}
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
{
return 0;
}
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_UP )
{
if ( local_value >= hi )
local_value = lo;
else
local_value++;
break;
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_DOWN )
{
if ( local_value <= lo )
local_value = hi;
else
local_value--;
break;
}
}
}
/* never reached */
//return r;
}

View File

@ -0,0 +1,176 @@
/*
u8g2_intersection.c
Intersection calculation, code taken from u8g_clip.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#ifdef __GNUC__
#define U8G2_ALWAYS_INLINE __inline__ __attribute__((always_inline))
#else
#define U8G2_ALWAYS_INLINE
#endif
#ifdef U8G2_WITH_INTERSECTION
#ifdef OLD_VERSION_WITH_SYMETRIC_BOUNDARIES
/*
intersection assumptions:
a1 <= a2 is always true
minimized version
---1----0 1 b1 <= a2 && b1 > b2
-----1--0 1 b2 >= a1 && b1 > b2
---1-1--- 1 b1 <= a2 && b2 >= a1
*/
/*
calculate the intersection between a0/a1 and v0/v1
The intersection check returns one if the range of a0/a1 has an intersection with v0/v1.
The intersection check includes the boundary values v1 and a1.
The following asserts will succeed:
assert( u8g2_is_intersection_decision_tree(4, 6, 7, 9) == 0 );
assert( u8g2_is_intersection_decision_tree(4, 6, 6, 9) != 0 );
assert( u8g2_is_intersection_decision_tree(6, 9, 4, 6) != 0 );
assert( u8g2_is_intersection_decision_tree(7, 9, 4, 6) == 0 );
*/
//static uint8_t U8G2_ALWAYS_INLINE u8g2_is_intersection_decision_tree(u8g_uint_t a0, u8g_uint_t a1, u8g_uint_t v0, u8g_uint_t v1)
static uint8_t u8g2_is_intersection_decision_tree(u8g2_uint_t a0, u8g2_uint_t a1, u8g2_uint_t v0, u8g2_uint_t v1)
{
if ( v0 <= a1 )
{
if ( v1 >= a0 )
{
return 1;
}
else
{
if ( v0 > v1 )
{
return 1;
}
else
{
return 0;
}
}
}
else
{
if ( v1 >= a0 )
{
if ( v0 > v1 )
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
#endif /* OLD_VERSION_WITH_SYMETRIC_BOUNDARIES */
/*
version with asymetric boundaries.
a1 and v1 are excluded
v0 == v1 is not support end return 1
*/
uint8_t u8g2_is_intersection_decision_tree(u8g2_uint_t a0, u8g2_uint_t a1, u8g2_uint_t v0, u8g2_uint_t v1)
{
if ( v0 < a1 ) // v0 <= a1
{
if ( v1 > a0 ) // v1 >= a0
{
return 1;
}
else
{
if ( v0 > v1 ) // v0 > v1
{
return 1;
}
else
{
return 0;
}
}
}
else
{
if ( v1 > a0 ) // v1 >= a0
{
if ( v0 > v1 ) // v0 > v1
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
/* upper limits are not included (asymetric boundaries) */
uint8_t u8g2_IsIntersection(u8g2_t *u8g2, u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t x1, u8g2_uint_t y1)
{
if ( u8g2_is_intersection_decision_tree(u8g2->user_y0, u8g2->user_y1, y0, y1) == 0 )
return 0;
return u8g2_is_intersection_decision_tree(u8g2->user_x0, u8g2->user_x1, x0, x1);
}
#endif /* U8G2_WITH_INTERSECTION */

View File

@ -0,0 +1,94 @@
/*
u8g2_kerning.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/* this function is used as "u8g2_get_kerning_cb" */
/*
uint8_t u8g2_GetNullKerning(u8g2_t *u8g2, uint16_t e1, uint16_t e2)
{
return 0;
}
*/
/* this function is used as "u8g2_get_kerning_cb" */
uint8_t u8g2_GetKerning(U8X8_UNUSED u8g2_t *u8g2, u8g2_kerning_t *kerning, uint16_t e1, uint16_t e2)
{
uint16_t i1, i2, cnt, end;
if ( kerning == NULL )
return 0;
/* search for the encoding in the first table */
cnt = kerning->first_table_cnt;
cnt--; /* ignore the last element of the table, which is 0x0ffff */
for( i1 = 0; i1 < cnt; i1++ )
{
if ( kerning->first_encoding_table[i1] == e1 )
break;
}
if ( i1 >= cnt )
return 0; /* e1 not part of the kerning table, return 0 */
/* get the upper index for i2 */
end = kerning->index_to_second_table[i1+1];
for( i2 = kerning->index_to_second_table[i1]; i2 < end; i2++ )
{
if ( kerning->second_encoding_table[i2] == e2 )
break;
}
if ( i2 >= end )
return 0; /* e2 not part of any pair with e1, return 0 */
return kerning->kerning_values[i2];
}
uint8_t u8g2_GetKerningByTable(U8X8_UNUSED u8g2_t *u8g2, const uint16_t *kt, uint16_t e1, uint16_t e2)
{
uint16_t i;
i = 0;
if ( kt == NULL )
return 0;
for(;;)
{
if ( kt[i] == 0x0ffff )
break;
if ( kt[i] == e1 && kt[i+1] == e2 )
return kt[i+2];
i+=3;
}
return 0;
}

View File

@ -0,0 +1,92 @@
/*
u8g2_box.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
void u8g2_DrawLine(u8g2_t *u8g2, u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, u8g2_uint_t y2)
{
u8g2_uint_t tmp;
u8g2_uint_t x,y;
u8g2_uint_t dx, dy;
u8g2_int_t err;
u8g2_int_t ystep;
uint8_t swapxy = 0;
/* no intersection check at the moment, should be added... */
if ( x1 > x2 ) dx = x1-x2; else dx = x2-x1;
if ( y1 > y2 ) dy = y1-y2; else dy = y2-y1;
if ( dy > dx )
{
swapxy = 1;
tmp = dx; dx =dy; dy = tmp;
tmp = x1; x1 =y1; y1 = tmp;
tmp = x2; x2 =y2; y2 = tmp;
}
if ( x1 > x2 )
{
tmp = x1; x1 =x2; x2 = tmp;
tmp = y1; y1 =y2; y2 = tmp;
}
err = dx >> 1;
if ( y2 > y1 ) ystep = 1; else ystep = -1;
y = y1;
#ifndef U8G2_16BIT
if ( x2 == 255 )
x2--;
#else
if ( x2 == 0xffff )
x2--;
#endif
for( x = x1; x <= x2; x++ )
{
if ( swapxy == 0 )
u8g2_DrawPixel(u8g2, x, y);
else
u8g2_DrawPixel(u8g2, y, x);
err -= (uint8_t)dy;
if ( err < 0 )
{
y += (u8g2_uint_t)ystep;
err += (u8g2_uint_t)dx;
}
}
}

View File

@ -0,0 +1,359 @@
/*
u8g2_ll_hvline.c
low level hvline
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*ptr |= or_mask
*ptr ^= xor_mask
color = 0: or_mask = 1, xor_mask = 1
color = 1: or_mask = 1, xor_mask = 0
color = 2: or_mask = 0, xor_mask = 1
if ( color <= 1 )
or_mask = mask;
if ( color != 1 )
xor_mask = mask;
*/
#include "u8g2.h"
#include <assert.h>
/*=================================================*/
/*
u8g2_ll_hvline_vertical_top_lsb
SSD13xx
UC1701
*/
#ifdef U8G2_HVLINE_SPEED_OPTIMIZATION
/*
x,y Upper left position of the line within the local buffer (not the display!)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
asumption:
all clipping done
*/
void u8g2_ll_hvline_vertical_top_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
uint16_t offset;
uint8_t *ptr;
uint8_t bit_pos, mask;
uint8_t or_mask, xor_mask;
//assert(x >= u8g2->buf_x0);
//assert(x < u8g2_GetU8x8(u8g2)->display_info->tile_width*8);
//assert(y >= u8g2->buf_y0);
//assert(y < u8g2_GetU8x8(u8g2)->display_info->tile_height*8);
/* bytes are vertical, lsb on top (y=0), msb at bottom (y=7) */
bit_pos = y; /* overflow truncate is ok here... */
bit_pos &= 7; /* ... because only the lowest 3 bits are needed */
mask = 1;
mask <<= bit_pos;
or_mask = 0;
xor_mask = 0;
if ( u8g2->draw_color <= 1 )
or_mask = mask;
if ( u8g2->draw_color != 1 )
xor_mask = mask;
offset = y; /* y might be 8 or 16 bit, but we need 16 bit, so use a 16 bit variable */
offset &= ~7;
offset *= u8g2_GetU8x8(u8g2)->display_info->tile_width;
ptr = u8g2->tile_buf_ptr;
ptr += offset;
ptr += x;
if ( dir == 0 )
{
do
{
*ptr |= or_mask;
*ptr ^= xor_mask;
ptr++;
len--;
} while( len != 0 );
}
else
{
do
{
*ptr |= or_mask;
*ptr ^= xor_mask;
bit_pos++;
bit_pos &= 7;
len--;
if ( bit_pos == 0 )
{
ptr+=u8g2->pixel_buf_width; /* 6 Jan 17: Changed u8g2->width to u8g2->pixel_buf_width, issue #148 */
if ( u8g2->draw_color <= 1 )
or_mask = 1;
if ( u8g2->draw_color != 1 )
xor_mask = 1;
}
else
{
or_mask <<= 1;
xor_mask <<= 1;
}
} while( len != 0 );
}
}
#else /* U8G2_HVLINE_SPEED_OPTIMIZATION */
/*
x,y position within the buffer
*/
static void u8g2_draw_pixel_vertical_top_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y)
{
uint16_t offset;
uint8_t *ptr;
uint8_t bit_pos, mask;
//assert(x >= u8g2->buf_x0);
//assert(x < u8g2_GetU8x8(u8g2)->display_info->tile_width*8);
//assert(y >= u8g2->buf_y0);
//assert(y < u8g2_GetU8x8(u8g2)->display_info->tile_height*8);
/* bytes are vertical, lsb on top (y=0), msb at bottom (y=7) */
bit_pos = y; /* overflow truncate is ok here... */
bit_pos &= 7; /* ... because only the lowest 3 bits are needed */
mask = 1;
mask <<= bit_pos;
offset = y; /* y might be 8 or 16 bit, but we need 16 bit, so use a 16 bit variable */
offset &= ~7;
offset *= u8g2_GetU8x8(u8g2)->display_info->tile_width;
ptr = u8g2->tile_buf_ptr;
ptr += offset;
ptr += x;
if ( u8g2->draw_color <= 1 )
*ptr |= mask;
if ( u8g2->draw_color != 1 )
*ptr ^= mask;
}
/*
x,y Upper left position of the line within the local buffer (not the display!)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
asumption:
all clipping done
*/
void u8g2_ll_hvline_vertical_top_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
if ( dir == 0 )
{
do
{
u8g2_draw_pixel_vertical_top_lsb(u8g2, x, y);
x++;
len--;
} while( len != 0 );
}
else
{
do
{
u8g2_draw_pixel_vertical_top_lsb(u8g2, x, y);
y++;
len--;
} while( len != 0 );
}
}
#endif /* U8G2_HVLINE_SPEED_OPTIMIZATION */
/*=================================================*/
/*
u8g2_ll_hvline_horizontal_right_lsb
ST7920
*/
#ifdef U8G2_HVLINE_SPEED_OPTIMIZATION
/*
x,y Upper left position of the line within the local buffer (not the display!)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
asumption:
all clipping done
*/
void u8g2_ll_hvline_horizontal_right_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
uint16_t offset;
uint8_t *ptr;
uint8_t bit_pos;
uint8_t mask;
uint8_t tile_width = u8g2_GetU8x8(u8g2)->display_info->tile_width;
bit_pos = x; /* overflow truncate is ok here... */
bit_pos &= 7; /* ... because only the lowest 3 bits are needed */
mask = 128;
mask >>= bit_pos;
offset = y; /* y might be 8 or 16 bit, but we need 16 bit, so use a 16 bit variable */
offset *= tile_width;
offset += x>>3;
ptr = u8g2->tile_buf_ptr;
ptr += offset;
if ( dir == 0 )
{
do
{
if ( u8g2->draw_color <= 1 )
*ptr |= mask;
if ( u8g2->draw_color != 1 )
*ptr ^= mask;
mask >>= 1;
if ( mask == 0 )
{
mask = 128;
ptr++;
}
//x++;
len--;
} while( len != 0 );
}
else
{
do
{
if ( u8g2->draw_color <= 1 )
*ptr |= mask;
if ( u8g2->draw_color != 1 )
*ptr ^= mask;
ptr += tile_width;
//y++;
len--;
} while( len != 0 );
}
}
#else /* U8G2_HVLINE_SPEED_OPTIMIZATION */
/*
x,y position within the buffer
*/
static void u8g2_draw_pixel_horizontal_right_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y)
{
uint16_t offset;
uint8_t *ptr;
uint8_t bit_pos, mask;
//assert(x >= u8g2->buf_x0);
//assert(x < u8g2_GetU8x8(u8g2)->display_info->tile_width*8);
//assert(y >= u8g2->buf_y0);
//assert(y < u8g2_GetU8x8(u8g2)->display_info->tile_height*8);
/* bytes are vertical, lsb on top (y=0), msb at bottom (y=7) */
bit_pos = x; /* overflow truncate is ok here... */
bit_pos &= 7; /* ... because only the lowest 3 bits are needed */
mask = 128;
mask >>= bit_pos;
x >>= 3;
offset = y; /* y might be 8 or 16 bit, but we need 16 bit, so use a 16 bit variable */
offset *= u8g2_GetU8x8(u8g2)->display_info->tile_width;
offset += x;
ptr = u8g2->tile_buf_ptr;
ptr += offset;
if ( u8g2->draw_color <= 1 )
*ptr |= mask;
if ( u8g2->draw_color != 1 )
*ptr ^= mask;
}
/*
x,y Upper left position of the line within the local buffer (not the display!)
len length of the line in pixel, len must not be 0
dir 0: horizontal line (left to right)
1: vertical line (top to bottom)
asumption:
all clipping done
*/
void u8g2_ll_hvline_horizontal_right_lsb(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
if ( dir == 0 )
{
do
{
u8g2_draw_pixel_horizontal_right_lsb(u8g2, x, y);
x++;
len--;
} while( len != 0 );
}
else
{
do
{
u8g2_draw_pixel_horizontal_right_lsb(u8g2, x, y);
y++;
len--;
} while( len != 0 );
}
}
#endif /* U8G2_HVLINE_SPEED_OPTIMIZATION */

View File

@ -0,0 +1,197 @@
/*
u8g2_message.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#define SPACE_BETWEEN_BUTTONS_IN_PIXEL 6
#define SPACE_BETWEEN_TEXT_AND_BUTTONS_IN_PIXEL 3
uint8_t u8g2_draw_button_line(u8g2_t *u8g2, u8g2_uint_t y, u8g2_uint_t w, uint8_t cursor, const char *s)
{
u8g2_uint_t button_line_width;
uint8_t i;
uint8_t cnt;
uint8_t is_invert;
u8g2_uint_t d;
u8g2_uint_t x;
cnt = u8x8_GetStringLineCnt(s);
/* calculate the width of the button line */
button_line_width = 0;
for( i = 0; i < cnt; i++ )
{
button_line_width += u8g2_GetUTF8Width(u8g2, u8x8_GetStringLineStart(i, s));
}
button_line_width += (cnt-1)*SPACE_BETWEEN_BUTTONS_IN_PIXEL; /* add some space between the buttons */
/* calculate the left offset */
d = 0;
if ( button_line_width < w )
{
d = w;
d -= button_line_width;
d /= 2;
}
/* draw the buttons */
x = d;
for( i = 0; i < cnt; i++ )
{
is_invert = 0;
if ( i == cursor )
is_invert = 1;
u8g2_DrawUTF8Line(u8g2, x, y, 0, u8x8_GetStringLineStart(i, s), 1, is_invert);
x += u8g2_GetUTF8Width(u8g2, u8x8_GetStringLineStart(i, s));
x += SPACE_BETWEEN_BUTTONS_IN_PIXEL;
}
/* return the number of buttons */
return cnt;
}
/*
title1: Multiple lines,separated by '\n'
title2: A single line/string which is terminated by '\0' or '\n' . "title2" accepts the return value from u8x8_GetStringLineStart()
title3: Multiple lines,separated by '\n'
buttons: one more more buttons separated by '\n' and terminated with '\0'
side effects:
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFontPosBaseline(u8g2);
*/
uint8_t u8g2_UserInterfaceMessage(u8g2_t *u8g2, const char *title1, const char *title2, const char *title3, const char *buttons)
{
uint8_t height;
uint8_t line_height;
u8g2_uint_t pixel_height;
u8g2_uint_t y, yy;
uint8_t cursor = 0;
uint8_t button_cnt;
uint8_t event;
/* only horizontal strings are supported, so force this here */
u8g2_SetFontDirection(u8g2, 0);
/* force baseline position */
u8g2_SetFontPosBaseline(u8g2);
/* calculate line height */
line_height = u8g2_GetAscent(u8g2);
line_height -= u8g2_GetDescent(u8g2);
/* calculate overall height of the message box in lines*/
height = 1; /* button line */
height += u8x8_GetStringLineCnt(title1);
if ( title2 != NULL )
height++;
height += u8x8_GetStringLineCnt(title3);
/* calculate the height in pixel */
pixel_height = height;
pixel_height *= line_height;
/* ... and add the space between the text and the buttons */
pixel_height +=SPACE_BETWEEN_TEXT_AND_BUTTONS_IN_PIXEL;
/* calculate offset from top */
y = 0;
if ( pixel_height < u8g2_GetDisplayHeight(u8g2) )
{
y = u8g2_GetDisplayHeight(u8g2);
y -= pixel_height;
y /= 2;
}
y += u8g2_GetAscent(u8g2);
for(;;)
{
u8g2_FirstPage(u8g2);
do
{
yy = y;
/* draw message box */
yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title1);
if ( title2 != NULL )
{
u8g2_DrawUTF8Line(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), title2, 0, 0);
yy+=line_height;
}
yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title3);
yy += SPACE_BETWEEN_TEXT_AND_BUTTONS_IN_PIXEL;
button_cnt = u8g2_draw_button_line(u8g2, yy, u8g2_GetDisplayWidth(u8g2), cursor, buttons);
} while( u8g2_NextPage(u8g2) );
#ifdef U8G2_REF_MAN_PIC
return 0;
#endif
for(;;)
{
event = u8x8_GetMenuEvent(u8g2_GetU8x8(u8g2));
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
return cursor+1;
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
return 0;
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_DOWN )
{
cursor++;
if ( cursor >= button_cnt )
cursor = 0;
break;
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_UP )
{
if ( cursor == 0 )
cursor = button_cnt;
cursor--;
break;
}
}
}
/* never reached */
//return 0;
}

View File

@ -0,0 +1,346 @@
/*
u8g22_polygon.c
*/
#include "u8g2.h"
/*===========================================*/
/* local definitions */
typedef int16_t pg_word_t;
struct pg_point_struct
{
pg_word_t x;
pg_word_t y;
};
typedef struct _pg_struct pg_struct; /* forward declaration */
struct pg_edge_struct
{
pg_word_t x_direction; /* 1, if x2 is greater than x1, -1 otherwise */
pg_word_t height;
pg_word_t current_x_offset;
pg_word_t error_offset;
/* --- line loop --- */
pg_word_t current_y;
pg_word_t max_y;
pg_word_t current_x;
pg_word_t error;
/* --- outer loop --- */
uint8_t (*next_idx_fn)(pg_struct *pg, uint8_t i);
uint8_t curr_idx;
};
/* maximum number of points in the polygon */
/* can be redefined, but highest possible value is 254 */
#define PG_MAX_POINTS 6
/* index numbers for the pge structures below */
#define PG_LEFT 0
#define PG_RIGHT 1
struct _pg_struct
{
struct pg_point_struct list[PG_MAX_POINTS];
uint8_t cnt;
uint8_t is_min_y_not_flat;
pg_word_t total_scan_line_cnt;
struct pg_edge_struct pge[2]; /* left and right line draw structures */
};
/*===========================================*/
/* procedures, which should not be inlined (save as much flash ROM as possible */
#define PG_NOINLINE U8G2_NOINLINE
static uint8_t pge_Next(struct pg_edge_struct *pge) PG_NOINLINE;
static uint8_t pg_inc(pg_struct *pg, uint8_t i) PG_NOINLINE;
static uint8_t pg_dec(pg_struct *pg, uint8_t i) PG_NOINLINE;
static void pg_expand_min_y(pg_struct *pg, pg_word_t min_y, uint8_t pge_idx) PG_NOINLINE;
static void pg_line_init(pg_struct * const pg, uint8_t pge_index) PG_NOINLINE;
/*===========================================*/
/* line draw algorithm */
static uint8_t pge_Next(struct pg_edge_struct *pge)
{
if ( pge->current_y >= pge->max_y )
return 0;
pge->current_x += pge->current_x_offset;
pge->error += pge->error_offset;
if ( pge->error > 0 )
{
pge->current_x += pge->x_direction;
pge->error -= pge->height;
}
pge->current_y++;
return 1;
}
/* assumes y2 > y1 */
static void pge_Init(struct pg_edge_struct *pge, pg_word_t x1, pg_word_t y1, pg_word_t x2, pg_word_t y2)
{
pg_word_t dx = x2 - x1;
pg_word_t width;
pge->height = y2 - y1;
pge->max_y = y2;
pge->current_y = y1;
pge->current_x = x1;
if ( dx >= 0 )
{
pge->x_direction = 1;
width = dx;
pge->error = 0;
}
else
{
pge->x_direction = -1;
width = -dx;
pge->error = 1 - pge->height;
}
pge->current_x_offset = dx / pge->height;
pge->error_offset = width % pge->height;
}
/*===========================================*/
/* convex polygon algorithm */
static uint8_t pg_inc(pg_struct *pg, uint8_t i)
{
i++;
if ( i >= pg->cnt )
i = 0;
return i;
}
static uint8_t pg_dec(pg_struct *pg, uint8_t i)
{
i--;
if ( i >= pg->cnt )
i = pg->cnt-1;
return i;
}
static void pg_expand_min_y(pg_struct *pg, pg_word_t min_y, uint8_t pge_idx)
{
uint8_t i = pg->pge[pge_idx].curr_idx;
for(;;)
{
i = pg->pge[pge_idx].next_idx_fn(pg, i);
if ( pg->list[i].y != min_y )
break;
pg->pge[pge_idx].curr_idx = i;
}
}
static uint8_t pg_prepare(pg_struct *pg)
{
pg_word_t max_y;
pg_word_t min_y;
uint8_t i;
/* setup the next index procedures */
pg->pge[PG_RIGHT].next_idx_fn = pg_inc;
pg->pge[PG_LEFT].next_idx_fn = pg_dec;
/* search for highest and lowest point */
max_y = pg->list[0].y;
min_y = pg->list[0].y;
pg->pge[PG_LEFT].curr_idx = 0;
for( i = 1; i < pg->cnt; i++ )
{
if ( max_y < pg->list[i].y )
{
max_y = pg->list[i].y;
}
if ( min_y > pg->list[i].y )
{
pg->pge[PG_LEFT].curr_idx = i;
min_y = pg->list[i].y;
}
}
/* calculate total number of scan lines */
pg->total_scan_line_cnt = max_y;
pg->total_scan_line_cnt -= min_y;
/* exit if polygon height is zero */
if ( pg->total_scan_line_cnt == 0 )
return 0;
/* if the minimum y side is flat, try to find the lowest and highest x points */
pg->pge[PG_RIGHT].curr_idx = pg->pge[PG_LEFT].curr_idx;
pg_expand_min_y(pg, min_y, PG_RIGHT);
pg_expand_min_y(pg, min_y, PG_LEFT);
/* check if the min side is really flat (depends on the x values) */
pg->is_min_y_not_flat = 1;
if ( pg->list[pg->pge[PG_LEFT].curr_idx].x != pg->list[pg->pge[PG_RIGHT].curr_idx].x )
{
pg->is_min_y_not_flat = 0;
}
else
{
pg->total_scan_line_cnt--;
if ( pg->total_scan_line_cnt == 0 )
return 0;
}
return 1;
}
static void pg_hline(pg_struct *pg, u8g2_t *u8g2)
{
pg_word_t x1, x2, y;
x1 = pg->pge[PG_LEFT].current_x;
x2 = pg->pge[PG_RIGHT].current_x;
y = pg->pge[PG_RIGHT].current_y;
if ( y < 0 )
return;
if ( y >= u8g2_GetDisplayHeight(u8g2) ) // does not work for 256x64 display???
return;
if ( x1 < x2 )
{
if ( x2 < 0 )
return;
if ( x1 >= u8g2_GetDisplayWidth(u8g2) )
return;
if ( x1 < 0 )
x1 = 0;
if ( x2 >= u8g2_GetDisplayWidth(u8g2) )
x2 = u8g2_GetDisplayWidth(u8g2);
u8g2_DrawHLine(u8g2, x1, y, x2 - x1);
}
else
{
if ( x1 < 0 )
return;
if ( x2 >= u8g2_GetDisplayWidth(u8g2) )
return;
if ( x2 < 0 )
x1 = 0;
if ( x1 >= u8g2_GetDisplayWidth(u8g2) )
x1 = u8g2_GetDisplayWidth(u8g2);
u8g2_DrawHLine(u8g2, x2, y, x1 - x2);
}
}
static void pg_line_init(pg_struct * const pg, uint8_t pge_index)
{
struct pg_edge_struct *pge = pg->pge+pge_index;
uint8_t idx;
pg_word_t x1;
pg_word_t y1;
pg_word_t x2;
pg_word_t y2;
idx = pge->curr_idx;
y1 = pg->list[idx].y;
x1 = pg->list[idx].x;
idx = pge->next_idx_fn(pg, idx);
y2 = pg->list[idx].y;
x2 = pg->list[idx].x;
pge->curr_idx = idx;
pge_Init(pge, x1, y1, x2, y2);
}
static void pg_exec(pg_struct *pg, u8g2_t *u8g2)
{
pg_word_t i = pg->total_scan_line_cnt;
/* first line is skipped if the min y line is not flat */
pg_line_init(pg, PG_LEFT);
pg_line_init(pg, PG_RIGHT);
if ( pg->is_min_y_not_flat != 0 )
{
pge_Next(&(pg->pge[PG_LEFT]));
pge_Next(&(pg->pge[PG_RIGHT]));
}
do
{
pg_hline(pg, u8g2);
while ( pge_Next(&(pg->pge[PG_LEFT])) == 0 )
{
pg_line_init(pg, PG_LEFT);
}
while ( pge_Next(&(pg->pge[PG_RIGHT])) == 0 )
{
pg_line_init(pg, PG_RIGHT);
}
i--;
} while( i > 0 );
}
/*===========================================*/
/* API procedures */
static void pg_ClearPolygonXY(pg_struct *pg)
{
pg->cnt = 0;
}
static void pg_AddPolygonXY(pg_struct *pg, int16_t x, int16_t y)
{
if ( pg->cnt < PG_MAX_POINTS )
{
pg->list[pg->cnt].x = x;
pg->list[pg->cnt].y = y;
pg->cnt++;
}
}
static void pg_DrawPolygon(pg_struct *pg, u8g2_t *u8g2)
{
if ( pg_prepare(pg) == 0 )
return;
pg_exec(pg, u8g2);
}
pg_struct u8g2_pg;
void u8g2_ClearPolygonXY(void)
{
pg_ClearPolygonXY(&u8g2_pg);
}
void u8g2_AddPolygonXY(U8X8_UNUSED u8g2_t *u8g2, int16_t x, int16_t y)
{
pg_AddPolygonXY(&u8g2_pg, x, y);
}
void u8g2_DrawPolygon(u8g2_t *u8g2)
{
pg_DrawPolygon(&u8g2_pg, u8g2);
}
void u8g2_DrawTriangle(u8g2_t *u8g2, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
{
u8g2_ClearPolygonXY();
u8g2_AddPolygonXY(u8g2, x0, y0);
u8g2_AddPolygonXY(u8g2, x1, y1);
u8g2_AddPolygonXY(u8g2, x2, y2);
u8g2_DrawPolygon(u8g2);
}

View File

@ -0,0 +1,284 @@
/*
u8g2_selection_list.c
selection list with scroll option
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#define MY_BORDER_SIZE 1
/*
Draw a string at x,y
Center string within w (left adjust if w < pixel len of s)
Side effects:
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFontPosBaseline(u8g2);
*/
void u8g2_DrawUTF8Line(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, const char *s, uint8_t border_size, uint8_t is_invert)
{
u8g2_uint_t d, str_width;
u8g2_uint_t fx, fy, fw, fh;
/* only horizontal strings are supported, so force this here */
u8g2_SetFontDirection(u8g2, 0);
/* revert y position back to baseline ref */
y += u8g2->font_calc_vref(u8g2);
/* calculate the width of the string in pixel */
str_width = u8g2_GetUTF8Width(u8g2, s);
/* calculate delta d within the box */
d = 0;
if ( str_width < w )
{
d = w;
d -=str_width;
d /= 2;
}
else
{
w = str_width;
}
/* caluclate text box */
fx = x;
fy = y - u8g2_GetAscent(u8g2) ;
fw = w;
fh = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2) ;
/* draw the box, if inverted */
u8g2_SetDrawColor(u8g2, 1);
if ( is_invert )
{
u8g2_DrawBox(u8g2, fx, fy, fw, fh);
}
/* draw the frame */
while( border_size > 0 )
{
fx--;
fy--;
fw +=2;
fh +=2;
u8g2_DrawFrame(u8g2, fx, fy, fw, fh );
border_size--;
}
if ( is_invert )
{
u8g2_SetDrawColor(u8g2, 0);
}
else
{
u8g2_SetDrawColor(u8g2, 1);
}
/* draw the text */
u8g2_DrawUTF8(u8g2, x+d, y, s);
/* revert draw color */
u8g2_SetDrawColor(u8g2, 1);
}
/*
draw several lines at position x,y.
lines are stored in s and must be separated with '\n'.
lines can be centered with respect to "w"
if s == NULL nothing is drawn and 0 is returned
returns the number of lines in s multiplied with line_height
*/
u8g2_uint_t u8g2_DrawUTF8Lines(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t line_height, const char *s)
{
uint8_t i;
uint8_t cnt;
u8g2_uint_t yy = 0;
cnt = u8x8_GetStringLineCnt(s);
//printf("str=%s\n", s);
//printf("cnt=%d, y=%d, line_height=%d\n", cnt, y, line_height);
for( i = 0; i < cnt; i++ )
{
//printf(" i=%d, y=%d, line_height=%d\n", i, y, line_height);
u8g2_DrawUTF8Line(u8g2, x, y, w, u8x8_GetStringLineStart(i, s), 0, 0);
y+=line_height;
yy+=line_height;
}
return yy;
}
/*
selection list with string line
returns line height
*/
static u8g2_uint_t u8g2_draw_selection_list_line(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, uint8_t idx, const char *s) U8G2_NOINLINE;
static u8g2_uint_t u8g2_draw_selection_list_line(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, uint8_t idx, const char *s)
{
u8g2_uint_t yy;
uint8_t border_size = 0;
uint8_t is_invert = 0;
u8g2_uint_t line_height = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2)+MY_BORDER_SIZE;
/* calculate offset from display upper border */
yy = idx;
yy -= u8sl->first_pos;
yy *= line_height;
yy += y;
/* check whether this is the current cursor line */
if ( idx == u8sl->current_pos )
{
border_size = MY_BORDER_SIZE;
is_invert = 1;
}
/* get the line from the array */
s = u8x8_GetStringLineStart(idx, s);
/* draw the line */
if ( s == NULL )
s = "";
u8g2_DrawUTF8Line(u8g2, MY_BORDER_SIZE, y, u8g2_GetDisplayWidth(u8g2)-2*MY_BORDER_SIZE, s, border_size, is_invert);
return line_height;
}
void u8g2_DrawSelectionList(u8g2_t *u8g2, u8sl_t *u8sl, u8g2_uint_t y, const char *s)
{
uint8_t i;
for( i = 0; i < u8sl->visible; i++ )
{
y += u8g2_draw_selection_list_line(u8g2, u8sl, y, i+u8sl->first_pos, s);
}
}
/*
title: NULL for no title, valid str for title line. Can contain mutliple lines, separated by '\n'
start_pos: default position for the cursor, first line is 1.
sl: string list (list of strings separated by \n)
returns 0 if user has pressed the home key
returns the selected line if user has pressed the select key
side effects:
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFontPosBaseline(u8g2);
*/
uint8_t u8g2_UserInterfaceSelectionList(u8g2_t *u8g2, const char *title, uint8_t start_pos, const char *sl)
{
u8sl_t u8sl;
u8g2_uint_t yy;
uint8_t event;
u8g2_uint_t line_height = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2)+MY_BORDER_SIZE;
uint8_t title_lines = u8x8_GetStringLineCnt(title);
uint8_t display_lines;
if ( start_pos > 0 ) /* issue 112 */
start_pos--; /* issue 112 */
if ( title_lines > 0 )
{
display_lines = (u8g2_GetDisplayHeight(u8g2)-3) / line_height;
u8sl.visible = display_lines;
u8sl.visible -= title_lines;
}
else
{
display_lines = u8g2_GetDisplayHeight(u8g2) / line_height;
u8sl.visible = display_lines;
}
u8sl.total = u8x8_GetStringLineCnt(sl);
u8sl.first_pos = 0;
u8sl.current_pos = start_pos;
if ( u8sl.current_pos >= u8sl.total )
u8sl.current_pos = u8sl.total-1;
if ( u8sl.first_pos+u8sl.visible <= u8sl.current_pos )
u8sl.first_pos = u8sl.current_pos-u8sl.visible+1;
u8g2_SetFontPosBaseline(u8g2);
for(;;)
{
u8g2_FirstPage(u8g2);
do
{
yy = u8g2_GetAscent(u8g2);
if ( title_lines > 0 )
{
yy += u8g2_DrawUTF8Lines(u8g2, 0, yy, u8g2_GetDisplayWidth(u8g2), line_height, title);
u8g2_DrawHLine(u8g2, 0, yy-line_height- u8g2_GetDescent(u8g2) + 1, u8g2_GetDisplayWidth(u8g2));
yy += 3;
}
u8g2_DrawSelectionList(u8g2, &u8sl, yy, sl);
} while( u8g2_NextPage(u8g2) );
#ifdef U8G2_REF_MAN_PIC
return 0;
#endif
for(;;)
{
event = u8x8_GetMenuEvent(u8g2_GetU8x8(u8g2));
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
return u8sl.current_pos+1; /* +1, issue 112 */
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
return 0; /* issue 112: return 0 instead of start_pos */
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_DOWN )
{
u8sl_Next(&u8sl);
break;
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_UP )
{
u8sl_Prev(&u8sl);
break;
}
}
}
}

View File

@ -0,0 +1,305 @@
/*
u8g2_setup.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
#include <string.h>
/*============================================*/
/*
This procedure is called after setting up the display (u8x8 structure).
--> This is the central init procedure for u8g2 object
*/
void u8g2_SetupBuffer(u8g2_t *u8g2, uint8_t *buf, uint8_t tile_buf_height, u8g2_draw_ll_hvline_cb ll_hvline_cb, const u8g2_cb_t *u8g2_cb)
{
u8g2->font = NULL;
//u8g2->kerning = NULL;
//u8g2->get_kerning_cb = u8g2_GetNullKerning;
//u8g2->ll_hvline = u8g2_ll_hvline_vertical_top_lsb;
u8g2->ll_hvline = ll_hvline_cb;
u8g2->tile_buf_ptr = buf;
u8g2->tile_buf_height = tile_buf_height;
u8g2->tile_curr_row = 0;
u8g2->font_decode.is_transparent = 0; /* issue 443 */
u8g2->bitmap_transparency = 0;
u8g2->draw_color = 1;
u8g2->is_auto_page_clear = 1;
u8g2->cb = u8g2_cb;
u8g2->cb->update(u8g2);
u8g2_SetFontPosBaseline(u8g2); /* issue 195 */
#ifdef U8G2_WITH_FONT_ROTATION
u8g2->font_decode.dir = 0;
#endif
}
/*
Usually the display rotation is set initially, but it could be done later also
u8g2_cb can be U8G2_R0..U8G2_R3
*/
void u8g2_SetDisplayRotation(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb)
{
u8g2->cb = u8g2_cb;
u8g2->cb->update(u8g2);
}
/*============================================*/
/*
update dimension:
calculate the following variables:
u8g2_uint_t buf_x0; left corner of the buffer
u8g2_uint_t buf_x1; right corner of the buffer (excluded)
u8g2_uint_t buf_y0;
u8g2_uint_t buf_y1;
*/
static void u8g2_update_dimension_common(u8g2_t *u8g2)
{
u8g2_uint_t t;
t = u8g2->tile_buf_height;
t *= 8;
u8g2->pixel_buf_height = t;
t = u8g2_GetU8x8(u8g2)->display_info->tile_width;
#ifndef U8G2_16BIT
if ( t >= 32 )
t = 31;
#endif
t *= 8;
u8g2->pixel_buf_width = t;
t = u8g2->tile_curr_row;
t *= 8;
u8g2->pixel_curr_row = t;
t = u8g2->tile_buf_height;
/* handle the case, where the buffer is larger than the (remaining) part of the display */
if ( t + u8g2->tile_curr_row > u8g2_GetU8x8(u8g2)->display_info->tile_height )
t = u8g2_GetU8x8(u8g2)->display_info->tile_height - u8g2->tile_curr_row;
t *= 8;
u8g2->buf_y0 = u8g2->pixel_curr_row;
u8g2->buf_y1 = u8g2->buf_y0;
u8g2->buf_y1 += t;
#ifdef U8G2_16BIT
u8g2->width = u8g2_GetU8x8(u8g2)->display_info->pixel_width;
u8g2->height = u8g2_GetU8x8(u8g2)->display_info->pixel_height;
#else
u8g2->width = 240;
if ( u8g2_GetU8x8(u8g2)->display_info->pixel_width <= 240 )
u8g2->width = u8g2_GetU8x8(u8g2)->display_info->pixel_width;
u8g2->height = u8g2_GetU8x8(u8g2)->display_info->pixel_height;
#endif
}
void u8g2_update_dimension_r0(u8g2_t *u8g2)
{
u8g2_update_dimension_common(u8g2);
u8g2->user_x0 = 0;
u8g2->user_x1 = u8g2->pixel_buf_width; /* pixel_buf_width replaced with width */
u8g2->user_y0 = u8g2->buf_y0;
u8g2->user_y1 = u8g2->buf_y1;
// printf("x0=%d x1=%d y0=%d y1=%d\n",
// u8g2->user_x0, u8g2->user_x1, u8g2->user_y0, u8g2->user_y1);
}
void u8g2_update_dimension_r1(u8g2_t *u8g2)
{
u8g2_update_dimension_common(u8g2);
u8g2->height = u8g2_GetU8x8(u8g2)->display_info->pixel_width;
u8g2->width = u8g2_GetU8x8(u8g2)->display_info->pixel_height;
u8g2->user_x0 = u8g2->buf_y0;
u8g2->user_x1 = u8g2->buf_y1;
u8g2->user_y0 = 0;
u8g2->user_y1 = u8g2->height; /* pixel_buf_width replaced with height (which is the real pixel width) */
//printf("x0=%d x1=%d y0=%d y1=%d\n",
// u8g2->user_x0, u8g2->user_x1, u8g2->user_y0, u8g2->user_y1);
}
void u8g2_update_dimension_r2(u8g2_t *u8g2)
{
u8g2_update_dimension_common(u8g2);
u8g2->user_x0 = 0;
u8g2->user_x1 = u8g2->width; /* pixel_buf_width replaced with width */
/* there are ases where the height is not a multiple of 8. */
/* in such a case u8g2->buf_y1 might be heigher than u8g2->height */
u8g2->user_y0 = 0;
if ( u8g2->height >= u8g2->buf_y1 )
u8g2->user_y0 = u8g2->height - u8g2->buf_y1;
u8g2->user_y1 = u8g2->height - u8g2->buf_y0;
// printf("x0=%d x1=%d y0=%d y1=%d\n",
// u8g2->user_x0, u8g2->user_x1, u8g2->user_y0, u8g2->user_y1);
}
void u8g2_update_dimension_r3(u8g2_t *u8g2)
{
u8g2_update_dimension_common(u8g2);
u8g2->height = u8g2_GetU8x8(u8g2)->display_info->pixel_width;
u8g2->width = u8g2_GetU8x8(u8g2)->display_info->pixel_height;
/* there are ases where the height is not a multiple of 8. */
/* in such a case u8g2->buf_y1 might be heigher than u8g2->width */
u8g2->user_x0 = 0;
if ( u8g2->width >= u8g2->buf_y1 )
u8g2->user_x0 = u8g2->width - u8g2->buf_y1;
u8g2->user_x1 = u8g2->width - u8g2->buf_y0;
u8g2->user_y0 = 0;
u8g2->user_y1 = u8g2->height; /* pixel_buf_width replaced with height (pixel_width) */
// printf("x0=%d x1=%d y0=%d y1=%d\n",
// u8g2->user_x0, u8g2->user_x1, u8g2->user_y0, u8g2->user_y1);
}
/*============================================*/
extern void u8g2_draw_hv_line_4dir(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir);
void u8g2_draw_l90_r0(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_draw_hv_line_4dir(u8g2, x, y, len, dir);
}
void u8g2_draw_l90_mirrorr_r0(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t xx;
xx = u8g2->width;
xx -= x;
if ( (dir & 1) == 0 )
{
xx -= len;
}
else
{
xx--;
}
u8g2_draw_hv_line_4dir(u8g2, xx, y, len, dir);
}
void u8g2_draw_l90_r1(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t xx, yy;
yy = x;
xx = u8g2->height;
xx -= y;
xx--;
dir ++;
dir &= 3;
u8g2_draw_hv_line_4dir(u8g2, xx, yy, len, dir);
}
void u8g2_draw_l90_r2(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t xx, yy;
yy = u8g2->height;
yy -= y;
yy--;
xx = u8g2->width;
xx -= x;
xx--;
dir +=2;
dir &= 3;
u8g2_draw_hv_line_4dir(u8g2, xx, yy, len, dir);
}
void u8g2_draw_l90_r3(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t len, uint8_t dir)
{
u8g2_uint_t xx, yy;
xx = y;
yy = u8g2->width;
yy -= x;
yy--;
dir +=3;
dir &= 3;
u8g2_draw_hv_line_4dir(u8g2, xx, yy, len, dir);
}
/*============================================*/
const u8g2_cb_t u8g2_cb_r0 = { u8g2_update_dimension_r0, u8g2_draw_l90_r0 };
const u8g2_cb_t u8g2_cb_r1 = { u8g2_update_dimension_r1, u8g2_draw_l90_r1 };
const u8g2_cb_t u8g2_cb_r2 = { u8g2_update_dimension_r2, u8g2_draw_l90_r2 };
const u8g2_cb_t u8g2_cb_r3 = { u8g2_update_dimension_r3, u8g2_draw_l90_r3 };
const u8g2_cb_t u8g2_cb_mirror = { u8g2_update_dimension_r0, u8g2_draw_l90_mirrorr_r0 };
/*============================================*/
/* setup for the null device */
/* setup for the null (empty) device */
void u8g2_Setup_null(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
static uint8_t buf[8];
u8g2_SetupDisplay(u8g2, u8x8_d_null_cb, u8x8_cad_empty, byte_cb, gpio_and_delay_cb);
u8g2_SetupBuffer(u8g2, buf, 1, u8g2_ll_hvline_vertical_top_lsb, rotation);
}

View File

@ -0,0 +1,260 @@
/*
u8log.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include <string.h>
#include "u8x8.h"
/*
static uint8_t u8log_is_on_screen(u8log_t *u8log, uint8_t x, uint8_t y)
{
if ( x >= u8log->width )
return 0;
if ( y >= u8log->height )
return 0;
return 1;
}
*/
static void u8log_clear_screen(u8log_t *u8log)
{
uint8_t *dest = u8log->screen_buffer;
uint16_t cnt = u8log->height;
cnt *= u8log->width;
do
{
*dest++ = ' ';
cnt--;
} while( cnt > 0 );
}
/* scroll the content of the complete buffer, set redraw_line to 255 */
static void u8log_scroll_up(u8log_t *u8log)
{
uint8_t *dest = u8log->screen_buffer;
uint8_t *src = dest+u8log->width;
uint16_t cnt = u8log->height;
cnt--;
cnt *= u8log->width;
do
{
*dest++ = *src++;
cnt--;
} while( cnt > 0 );
cnt = u8log->width;
do
{
*dest++ = ' ';
cnt--;
} while(cnt > 0);
if ( u8log->is_redraw_line_for_each_char )
u8log->is_redraw_all = 1;
else
u8log->is_redraw_all_required_for_next_nl = 1;
}
/*
Place the cursor on the screen. This will also scroll, if required
*/
static void u8log_cursor_on_screen(u8log_t *u8log)
{
//printf("u8log_cursor_on_screen, cursor_y=%d\n", u8log->cursor_y);
if ( u8log->cursor_x >= u8log->width )
{
u8log->cursor_x = 0;
u8log->cursor_y++;
}
while ( u8log->cursor_y >= u8log->height )
{
u8log_scroll_up(u8log);
u8log->cursor_y--;
}
}
/*
Write a printable, single char on the screen, do any kind of scrolling
*/
static void u8log_write_to_screen(u8log_t *u8log, uint8_t c)
{
u8log_cursor_on_screen(u8log);
u8log->screen_buffer[u8log->cursor_y * u8log->width + u8log->cursor_x] = c;
u8log->cursor_x++;
if ( u8log->is_redraw_line_for_each_char )
{
u8log->is_redraw_line = 1;
u8log->redraw_line = u8log->cursor_y;
}
}
/*
Handle control codes or write the char to the screen.
Supported control codes are:
\n 10 Goto first position of the next line. Line is marked for redraw.
\r 13 Goto first position in the same line. Line is marked for redraw.
\t 9 Jump to the next tab position
\f 12 Clear the screen and mark redraw for whole screen
any other char Write char to screen. Line redraw mark depends on
is_redraw_line_for_each_char flag.
*/
void u8log_write_char(u8log_t *u8log, uint8_t c)
{
switch(c)
{
case '\n': // 10
u8log->is_redraw_line = 1;
u8log->redraw_line = u8log->cursor_y;
if ( u8log->is_redraw_all_required_for_next_nl )
u8log->is_redraw_all = 1;
u8log->is_redraw_all_required_for_next_nl = 0;
u8log->cursor_y++;
u8log->cursor_x = 0;
break;
case '\r': // 13
u8log->is_redraw_line = 1;
u8log->redraw_line = u8log->cursor_y;
u8log->cursor_x = 0;
break;
case '\t': // 9
u8log->cursor_x = (u8log->cursor_x + 8) & 0xf8;
break;
case '\f': // 12
u8log_clear_screen(u8log);
u8log->is_redraw_all = 1;
u8log->cursor_x = 0;
u8log->cursor_y = 0;
break;
default:
u8log_write_to_screen(u8log, c);
break;
}
}
void u8log_Init(u8log_t *u8log, uint8_t width, uint8_t height, uint8_t *buf)
{
memset(u8log, 0, sizeof(u8log_t));
u8log->width = width;
u8log->height = height;
u8log->screen_buffer = buf;
u8log_clear_screen(u8log);
}
void u8log_SetCallback(u8log_t *u8log, u8log_cb cb, void *aux_data)
{
u8log->cb = cb;
u8log->aux_data = aux_data;
}
void u8log_SetRedrawMode(u8log_t *u8log, uint8_t is_redraw_line_for_each_char)
{
u8log->is_redraw_line_for_each_char = is_redraw_line_for_each_char;
}
/* offset can be negative or positive, it is 0 by default */
void u8log_SetLineHeightOffset(u8log_t *u8log, int8_t line_height_offset)
{
u8log->line_height_offset = line_height_offset;
}
void u8log_WriteChar(u8log_t *u8log, uint8_t c)
{
u8log_write_char(u8log, c);
if ( u8log->is_redraw_line || u8log->is_redraw_all )
{
if ( u8log->cb != 0 )
{
u8log->cb(u8log);
}
u8log->is_redraw_line = 0;
u8log->is_redraw_all = 0;
}
}
void u8log_WriteString(u8log_t *u8log, const char *s)
{
while( *s != '\0' )
{
u8log_WriteChar(u8log, *s);
s++;
}
}
static void u8log_WriteHexHalfByte(u8log_t *u8log, uint8_t b) U8X8_NOINLINE;
static void u8log_WriteHexHalfByte(u8log_t *u8log, uint8_t b)
{
b &= 0x0f;
if ( b < 10 )
u8log_WriteChar(u8log, b+'0');
else
u8log_WriteChar(u8log, b+'a'-10);
}
void u8log_WriteHex8(u8log_t *u8log, uint8_t b)
{
u8log_WriteHexHalfByte(u8log, b >> 4);
u8log_WriteHexHalfByte(u8log, b);
}
void u8log_WriteHex16(u8log_t *u8log, uint16_t v)
{
u8log_WriteHex8(u8log, v>>8);
u8log_WriteHex8(u8log, v);
}
void u8log_WriteHex32(u8log_t *u8log, uint32_t v)
{
u8log_WriteHex16(u8log, v>>16);
u8log_WriteHex16(u8log, v);
}
/* v = value, d = number of digits (1..3) */
void u8log_WriteDec8(u8log_t *u8log, uint8_t v, uint8_t d)
{
u8log_WriteString(u8log, u8x8_u8toa(v, d));
}
/* v = value, d = number of digits (1..5) */
void u8log_WriteDec16(u8log_t *u8log, uint16_t v, uint8_t d)
{
u8log_WriteString(u8log, u8x8_u16toa(v, d));
}

View File

@ -0,0 +1,98 @@
/*
u8log_u8g2.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8g2.h"
/*
Draw the u8log text at the specified x/y position.
x/y position is the reference position of the first char of the first line.
the line height is
u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2) + line_height_offset;
line_height_offset can be set with u8log_SetLineHeightOffset()
Use
u8g2_SetFontRefHeightText(u8g2_t *u8g2);
u8g2_SetFontRefHeightExtendedText(u8g2_t *u8g2);
u8g2_SetFontRefHeightAll(u8g2_t *u8g2);
to change the return values for u8g2_GetAscent and u8g2_GetDescent
*/
void u8g2_DrawLog(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8log_t *u8log)
{
u8g2_uint_t disp_x, disp_y;
uint8_t buf_x, buf_y;
uint8_t c;
disp_y = y;
u8g2_SetFontDirection(u8g2, 0);
for( buf_y = 0; buf_y < u8log->height; buf_y++ )
{
disp_x = x;
for( buf_x = 0; buf_x < u8log->width; buf_x++ )
{
c = u8log->screen_buffer[buf_y * u8log->width + buf_x];
disp_x += u8g2_DrawGlyph(u8g2, disp_x, disp_y, c);
}
disp_y += u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2);
disp_y += u8log->line_height_offset;
}
}
/*
u8lib callback for u8g2
Only font direction 0 is supported: u8g2_SetFontDirection(u8g2, 0)
Use
u8g2_SetFontRefHeightText(u8g2_t *u8g2);
u8g2_SetFontRefHeightExtendedText(u8g2_t *u8g2);
u8g2_SetFontRefHeightAll(u8g2_t *u8g2);
to change the top offset and the line height and
u8log_SetLineHeightOffset(u8log_t *u8log, int8_t line_height_offset)
to change the line height.
*/
void u8log_u8g2_cb(u8log_t * u8log)
{
u8g2_t *u8g2 = (u8g2_t *)(u8log->aux_data);
if ( u8log->is_redraw_line || u8log->is_redraw_all )
{
u8g2_FirstPage(u8g2);
do
{
u8g2_DrawLog( u8g2, 0, u8g2_GetAscent(u8g2), u8log);
}
while( u8g2_NextPage(u8g2) );
}
}

View File

@ -0,0 +1,75 @@
/*
u8log_u8x8.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static void u8x8_DrawLogLine(u8x8_t *u8x8, uint8_t disp_x, uint8_t disp_y, uint8_t buf_y, u8log_t *u8log) U8X8_NOINLINE;
static void u8x8_DrawLogLine(u8x8_t *u8x8, uint8_t disp_x, uint8_t disp_y, uint8_t buf_y, u8log_t *u8log)
{
uint8_t buf_x;
uint8_t c;
for( buf_x = 0; buf_x < u8log->width; buf_x++ )
{
c = u8log->screen_buffer[buf_y * u8log->width + buf_x];
u8x8_DrawGlyph(u8x8, disp_x, disp_y, c);
disp_x++;
}
}
void u8x8_DrawLog(u8x8_t *u8x8, uint8_t x, uint8_t y, u8log_t *u8log)
{
uint8_t buf_y;
for( buf_y = 0; buf_y < u8log->height; buf_y++ )
{
u8x8_DrawLogLine(u8x8, x, y, buf_y, u8log);
y++;
}
}
void u8log_u8x8_cb(u8log_t * u8log)
{
u8x8_t *u8x8 = (u8x8_t *)(u8log->aux_data);
if ( u8log->is_redraw_all )
{
u8x8_DrawLog(u8x8, 0, 0, u8log);
}
else if ( u8log->is_redraw_line )
{
u8x8_DrawLogLine(u8x8, 0, u8log->redraw_line, u8log->redraw_line, u8log);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,420 @@
/*
u8x8_8x8.c
font procedures, directly interfaces display procedures
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
#if defined(ESP8266)
uint8_t u8x8_pgm_read_esp(const uint8_t * addr)
{
uint32_t bytes;
bytes = *(uint32_t*)((uint32_t)addr & ~3);
return ((uint8_t*)&bytes)[(uint32_t)addr & 3];
}
#endif
void u8x8_SetFont(u8x8_t *u8x8, const uint8_t *font_8x8)
{
u8x8->font = font_8x8;
}
/*
Args:
u8x8: ptr to u8x8 structure
encoding: glyph for which the data is requested (must be between 0 and 255)
buf: pointer to 8 bytes
*/
static void u8x8_get_glyph_data(u8x8_t *u8x8, uint8_t encoding, uint8_t *buf) U8X8_NOINLINE;
static void u8x8_get_glyph_data(u8x8_t *u8x8, uint8_t encoding, uint8_t *buf)
{
uint8_t first, last, i;
uint16_t offset;
first = u8x8_pgm_read(u8x8->font+0);
last = u8x8_pgm_read(u8x8->font+1);
/* get the glyph bitmap from the font */
if ( first <= encoding && encoding <= last )
{
offset = encoding;
offset -= first;
offset *= 8;
offset +=2;
for( i = 0; i < 8; i++ )
{
buf[i] = u8x8_pgm_read(u8x8->font+offset);
offset++;
}
}
else
{
for( i = 0; i < 8; i++ )
{
buf[i] = 0;
}
}
/* invert the bitmap if required */
if ( u8x8->is_font_inverse_mode )
{
for( i = 0; i < 8; i++ )
{
buf[i] ^= 255;
}
}
}
void u8x8_DrawGlyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
{
uint8_t buf[8];
u8x8_get_glyph_data(u8x8, encoding, buf);
u8x8_DrawTile(u8x8, x, y, 1, buf);
}
/*
Source: http://graphics.stanford.edu/~seander/bithacks.html
Section: Interleave bits by Binary Magic Numbers
Original codes is here:
static const unsigned int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF};
static const unsigned int S[] = {1, 2, 4, 8};
unsigned int x; // Interleave lower 16 bits of x and y, so the bits of x
unsigned int y; // are in the even positions and bits from y in the odd;
unsigned int z; // z gets the resulting 32-bit Morton Number.
// x and y must initially be less than 65536.
x = (x | (x << S[3])) & B[3];
x = (x | (x << S[2])) & B[2];
x = (x | (x << S[1])) & B[1];
x = (x | (x << S[0])) & B[0];
y = (y | (y << S[3])) & B[3];
y = (y | (y << S[2])) & B[2];
y = (y | (y << S[1])) & B[1];
y = (y | (y << S[0])) & B[0];
z = x | (y << 1);
*/
uint16_t u8x8_upscale_byte(uint8_t x)
{
uint16_t y = x;
y |= (y << 4); // x = (x | (x << S[2])) & B[2];
y &= 0x0f0f;
y |= (y << 2); // x = (x | (x << S[1])) & B[1];
y &= 0x3333;
y |= (y << 1); // x = (x | (x << S[0])) & B[0];
y &= 0x5555;
y |= (y << 1); // z = x | (y << 1);
return y;
}
static void u8x8_upscale_buf(uint8_t *src, uint8_t *dest) U8X8_NOINLINE;
static void u8x8_upscale_buf(uint8_t *src, uint8_t *dest)
{
uint8_t i = 4;
do
{
*dest++ = *src;
*dest++ = *src++;
i--;
} while( i > 0 );
}
void u8x8_Draw2x2Glyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
{
uint8_t i;
uint16_t t;
uint8_t buf[8];
uint8_t buf1[8];
uint8_t buf2[8];
u8x8_get_glyph_data(u8x8, encoding, buf);
for( i = 0; i < 8; i ++ )
{
t = u8x8_upscale_byte(buf[i]);
buf1[i] = t >> 8;
buf2[i] = t & 255;
}
u8x8_upscale_buf(buf2, buf);
u8x8_DrawTile(u8x8, x, y, 1, buf);
u8x8_upscale_buf(buf2+4, buf);
u8x8_DrawTile(u8x8, x+1, y, 1, buf);
u8x8_upscale_buf(buf1, buf);
u8x8_DrawTile(u8x8, x, y+1, 1, buf);
u8x8_upscale_buf(buf1+4, buf);
u8x8_DrawTile(u8x8, x+1, y+1, 1, buf);
}
/* https://github.com/olikraus/u8g2/issues/474 */
void u8x8_Draw1x2Glyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
{
uint8_t i;
uint16_t t;
uint8_t buf[8];
uint8_t buf1[8];
uint8_t buf2[8];
u8x8_get_glyph_data(u8x8, encoding, buf);
for( i = 0; i < 8; i ++ )
{
t = u8x8_upscale_byte(buf[i]);
buf1[i] = t >> 8;
buf2[i] = t & 255;
}
u8x8_DrawTile(u8x8, x, y, 1, buf2);
u8x8_DrawTile(u8x8, x, y+1, 1, buf1);
}
/*
source: https://en.wikipedia.org/wiki/UTF-8
Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
7 U+0000 U+007F 1 0xxxxxxx
11 U+0080 U+07FF 2 110xxxxx 10xxxxxx
16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
26 U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
31 U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
/* reset the internal state machine */
void u8x8_utf8_init(u8x8_t *u8x8)
{
u8x8->utf8_state = 0; /* also reset during u8x8_SetupDefaults() */
}
uint16_t u8x8_ascii_next(U8X8_UNUSED u8x8_t *u8x8, uint8_t b)
{
if ( b == 0 || b == '\n' ) /* '\n' terminates the string to support the string list procedures */
return 0x0ffff; /* end of string detected*/
return b;
}
/*
pass a byte from an utf8 encoded string to the utf8 decoder state machine
returns
0x0fffe: no glyph, just continue
0x0ffff: end of string
anything else: The decoded encoding
*/
uint16_t u8x8_utf8_next(u8x8_t *u8x8, uint8_t b)
{
if ( b == 0 || b == '\n' ) /* '\n' terminates the string to support the string list procedures */
return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
if ( u8x8->utf8_state == 0 )
{
if ( b >= 0xfc ) /* 6 byte sequence */
{
u8x8->utf8_state = 5;
b &= 1;
}
else if ( b >= 0xf8 )
{
u8x8->utf8_state = 4;
b &= 3;
}
else if ( b >= 0xf0 )
{
u8x8->utf8_state = 3;
b &= 7;
}
else if ( b >= 0xe0 )
{
u8x8->utf8_state = 2;
b &= 15;
}
else if ( b >= 0xc0 )
{
u8x8->utf8_state = 1;
b &= 0x01f;
}
else
{
/* do nothing, just use the value as encoding */
return b;
}
u8x8->encoding = b;
return 0x0fffe;
}
else
{
u8x8->utf8_state--;
/* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
u8x8->encoding<<=6;
b &= 0x03f;
u8x8->encoding |= b;
if ( u8x8->utf8_state != 0 )
return 0x0fffe; /* nothing to do yet */
}
return u8x8->encoding;
}
static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
uint16_t e;
uint8_t cnt = 0;
u8x8_utf8_init(u8x8);
for(;;)
{
e = u8x8->next_cb(u8x8, (uint8_t)*s);
if ( e == 0x0ffff )
break;
s++;
if ( e != 0x0fffe )
{
u8x8_DrawGlyph(u8x8, x, y, e);
x++;
cnt++;
}
}
return cnt;
}
uint8_t u8x8_DrawString(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_ascii_next;
return u8x8_draw_string(u8x8, x, y, s);
}
uint8_t u8x8_DrawUTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_utf8_next;
return u8x8_draw_string(u8x8, x, y, s);
}
static uint8_t u8x8_draw_2x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
static uint8_t u8x8_draw_2x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
uint16_t e;
uint8_t cnt = 0;
u8x8_utf8_init(u8x8);
for(;;)
{
e = u8x8->next_cb(u8x8, (uint8_t)*s);
if ( e == 0x0ffff )
break;
s++;
if ( e != 0x0fffe )
{
u8x8_Draw2x2Glyph(u8x8, x, y, e);
x+=2;
cnt++;
}
}
return cnt;
}
uint8_t u8x8_Draw2x2String(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_ascii_next;
return u8x8_draw_2x2_string(u8x8, x, y, s);
}
uint8_t u8x8_Draw2x2UTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_utf8_next;
return u8x8_draw_2x2_string(u8x8, x, y, s);
}
static uint8_t u8x8_draw_1x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
static uint8_t u8x8_draw_1x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
uint16_t e;
uint8_t cnt = 0;
u8x8_utf8_init(u8x8);
for(;;)
{
e = u8x8->next_cb(u8x8, (uint8_t)*s);
if ( e == 0x0ffff )
break;
s++;
if ( e != 0x0fffe )
{
u8x8_Draw1x2Glyph(u8x8, x, y, e);
x++;
cnt++;
}
}
return cnt;
}
uint8_t u8x8_Draw1x2String(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_ascii_next;
return u8x8_draw_1x2_string(u8x8, x, y, s);
}
uint8_t u8x8_Draw1x2UTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
{
u8x8->next_cb = u8x8_utf8_next;
return u8x8_draw_1x2_string(u8x8, x, y, s);
}
uint8_t u8x8_GetUTF8Len(u8x8_t *u8x8, const char *s)
{
uint16_t e;
uint8_t cnt = 0;
u8x8_utf8_init(u8x8);
for(;;)
{
e = u8x8_utf8_next(u8x8, *s);
if ( e == 0x0ffff )
break;
s++;
if ( e != 0x0fffe )
cnt++;
}
return cnt;
}

View File

@ -0,0 +1,666 @@
/*
u8x8_byte.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
uint8_t u8x8_byte_SetDC(u8x8_t *u8x8, uint8_t dc)
{
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_SET_DC, dc, NULL);
}
uint8_t u8x8_byte_SendBytes(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
{
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_SEND, cnt, (void *)data);
}
uint8_t u8x8_byte_SendByte(u8x8_t *u8x8, uint8_t byte)
{
return u8x8_byte_SendBytes(u8x8, 1, &byte);
}
uint8_t u8x8_byte_StartTransfer(u8x8_t *u8x8)
{
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_START_TRANSFER, 0, NULL);
}
uint8_t u8x8_byte_EndTransfer(u8x8_t *u8x8)
{
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_END_TRANSFER, 0, NULL);
}
/*=========================================*/
uint8_t u8x8_byte_empty(U8X8_UNUSED u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
case U8X8_MSG_BYTE_INIT:
case U8X8_MSG_BYTE_SET_DC:
case U8X8_MSG_BYTE_START_TRANSFER:
case U8X8_MSG_BYTE_END_TRANSFER:
break; /* do nothing */
}
return 1; /* always succeed */
}
/*=========================================*/
/*
Uses:
u8x8->display_info->sda_setup_time_ns
u8x8->display_info->sck_pulse_width_ns
u8x8->display_info->spi_mode
u8x8->display_info->chip_disable_level
u8x8->display_info->chip_enable_level
u8x8->display_info->post_chip_enable_wait_ns
u8x8->display_info->pre_chip_disable_wait_ns
Calls to GPIO and DELAY:
U8X8_MSG_DELAY_NANO
U8X8_MSG_GPIO_DC
U8X8_MSG_GPIO_CS
U8X8_MSG_GPIO_CLOCK
U8X8_MSG_GPIO_DATA
Handles:
U8X8_MSG_BYTE_INIT
U8X8_MSG_BYTE_SEND
U8X8_MSG_BYTE_SET_DC
U8X8_MSG_BYTE_START_TRANSFER
U8X8_MSG_BYTE_END_TRANSFER
*/
uint8_t u8x8_byte_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
uint8_t not_takeover_edge = 1 - takeover_edge;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = 0; i < 8; i++ )
{
if ( b & 128 )
u8x8_gpio_SetSPIData(u8x8, 1);
else
u8x8_gpio_SetSPIData(u8x8, 0);
b <<= 1;
u8x8_gpio_SetSPIClock(u8x8, not_takeover_edge);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sda_setup_time_ns);
u8x8_gpio_SetSPIClock(u8x8, takeover_edge);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sck_pulse_width_ns);
}
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* no wait required here */
/* for SPI: setup correct level of the clock signal */
u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
uint8_t u8x8_byte_8bit_6800mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
{
u8x8_gpio_call(u8x8, i, b&1);
b >>= 1;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* ensure that the enable signal is high */
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_byte_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
{
u8x8_gpio_call(u8x8, i, b&1);
b >>= 1;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* ensure that the enable signal is high */
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
uint8_t u8x8_byte_3wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i;
uint8_t *data;
uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
uint8_t not_takeover_edge = 1 - takeover_edge;
uint16_t b;
static uint8_t last_dc;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
if ( last_dc != 0 )
b |= 256;
data++;
arg_int--;
for( i = 0; i < 9; i++ )
{
if ( b & 256 )
u8x8_gpio_SetSPIData(u8x8, 1);
else
u8x8_gpio_SetSPIData(u8x8, 0);
b <<= 1;
u8x8_gpio_SetSPIClock(u8x8, not_takeover_edge);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sda_setup_time_ns);
u8x8_gpio_SetSPIClock(u8x8, takeover_edge);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sck_pulse_width_ns);
}
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* no wait required here */
/* for SPI: setup correct level of the clock signal */
u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
break;
case U8X8_MSG_BYTE_SET_DC:
last_dc = arg_int;
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
void u8x8_byte_set_ks0108_cs(u8x8_t *u8x8, uint8_t arg)
{
u8x8_gpio_SetCS(u8x8, arg&1);
arg = arg >> 1;
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS1, arg&1);
arg = arg >> 1;
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS2, arg&1);
}
/* 6800 mode */
uint8_t u8x8_byte_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
{
u8x8_gpio_call(u8x8, i, b&1);
b >>= 1;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* ensure that the enable signal is low */
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
/* expects 3 bits in arg_int for the chip select lines */
u8x8_byte_set_ks0108_cs(u8x8, arg_int);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_byte_set_ks0108_cs(u8x8, arg_int);
break;
default:
return 0;
}
return 1;
}
/* sed1520 or sbn1661
U8X8_MSG_GPIO_E --> E1
U8X8_MSG_GPIO_CS --> E2
*/
uint8_t u8x8_byte_sed1520(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t i, b;
uint8_t *data;
static uint8_t enable_pin;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
b = *data;
data++;
arg_int--;
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
{
u8x8_gpio_call(u8x8, i, b&1);
b >>= 1;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
u8x8_gpio_call(u8x8, enable_pin, 1);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 200); /* KS0108 requires 450 ns, use 200 here */
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns); /* expect 250 here */
u8x8_gpio_call(u8x8, enable_pin, 0);
}
break;
case U8X8_MSG_BYTE_INIT:
/* disable chipselect */
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
/* ensure that the enable signals are low */
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS, 0);
enable_pin = U8X8_MSG_GPIO_E;
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
/* cs lines are not supported for the SED1520/SBN1661 */
/* instead, this will select the E1 or E2 line */
enable_pin = U8X8_MSG_GPIO_E;
if ( arg_int != 0 )
enable_pin = U8X8_MSG_GPIO_CS;
break;
case U8X8_MSG_BYTE_END_TRANSFER:
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
/*
software i2c,
ignores ACK response (which is anyway not provided by some displays)
also does not allow reading from the device
*/
static void i2c_delay(u8x8_t *u8x8) U8X8_NOINLINE;
static void i2c_delay(u8x8_t *u8x8)
{
//u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_10MICRO, u8x8->display_info->i2c_bus_clock_100kHz);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_I2C, u8x8->display_info->i2c_bus_clock_100kHz);
}
static void i2c_init(u8x8_t *u8x8)
{
u8x8_gpio_SetI2CClock(u8x8, 1);
u8x8_gpio_SetI2CData(u8x8, 1);
i2c_delay(u8x8);
}
/* actually, the scl line is not observed, so this procedure does not return a value */
static void i2c_read_scl_and_delay(u8x8_t *u8x8)
{
/* set as input (line will be high) */
u8x8_gpio_SetI2CClock(u8x8, 1);
i2c_delay(u8x8);
}
static void i2c_clear_scl(u8x8_t *u8x8)
{
u8x8_gpio_SetI2CClock(u8x8, 0);
}
static void i2c_read_sda(u8x8_t *u8x8)
{
/* set as input (line will be high) */
u8x8_gpio_SetI2CData(u8x8, 1);
}
static void i2c_clear_sda(u8x8_t *u8x8)
{
/* set open collector and drive low */
u8x8_gpio_SetI2CData(u8x8, 0);
}
static void i2c_start(u8x8_t *u8x8)
{
if ( u8x8->i2c_started != 0 )
{
/* if already started: do restart */
i2c_read_sda(u8x8); /* SDA = 1 */
i2c_delay(u8x8);
i2c_read_scl_and_delay(u8x8);
}
i2c_read_sda(u8x8);
/* send the start condition, both lines go from 1 to 0 */
i2c_clear_sda(u8x8);
i2c_delay(u8x8);
i2c_clear_scl(u8x8);
u8x8->i2c_started = 1;
}
static void i2c_stop(u8x8_t *u8x8)
{
/* set SDA to 0 */
i2c_clear_sda(u8x8);
i2c_delay(u8x8);
/* now release all lines */
i2c_read_scl_and_delay(u8x8);
/* set SDA to 1 */
i2c_read_sda(u8x8);
i2c_delay(u8x8);
u8x8->i2c_started = 0;
}
static void i2c_write_bit(u8x8_t *u8x8, uint8_t val)
{
if (val)
i2c_read_sda(u8x8);
else
i2c_clear_sda(u8x8);
i2c_delay(u8x8);
i2c_read_scl_and_delay(u8x8);
i2c_clear_scl(u8x8);
}
static void i2c_read_bit(u8x8_t *u8x8)
{
//uint8_t val;
/* do not drive SDA */
i2c_read_sda(u8x8);
i2c_delay(u8x8);
i2c_read_scl_and_delay(u8x8);
i2c_read_sda(u8x8);
i2c_delay(u8x8);
i2c_clear_scl(u8x8);
//return val;
}
static void i2c_write_byte(u8x8_t *u8x8, uint8_t b)
{
i2c_write_bit(u8x8, b & 128);
i2c_write_bit(u8x8, b & 64);
i2c_write_bit(u8x8, b & 32);
i2c_write_bit(u8x8, b & 16);
i2c_write_bit(u8x8, b & 8);
i2c_write_bit(u8x8, b & 4);
i2c_write_bit(u8x8, b & 2);
i2c_write_bit(u8x8, b & 1);
/* read ack from client */
/* 0: ack was given by client */
/* 1: nothing happend during ack cycle */
i2c_read_bit(u8x8);
}
uint8_t u8x8_byte_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
i2c_write_byte(u8x8, *data);
data++;
arg_int--;
}
break;
case U8X8_MSG_BYTE_INIT:
i2c_init(u8x8);
break;
case U8X8_MSG_BYTE_SET_DC:
break;
case U8X8_MSG_BYTE_START_TRANSFER:
i2c_start(u8x8);
i2c_write_byte(u8x8, u8x8_GetI2CAddress(u8x8));
//i2c_write_byte(u8x8, 0x078);
break;
case U8X8_MSG_BYTE_END_TRANSFER:
i2c_stop(u8x8);
break;
default:
return 0;
}
return 1;
}
/*=========================================*/
/* alternative i2c byte procedure */
#ifdef ALTERNATIVE_I2C_BYTE_PROCEDURE
void i2c_transfer(u8x8_t *u8x8, uint8_t adr, uint8_t cnt, uint8_t *data)
{
uint8_t i;
i2c_start(u8x8);
i2c_write_byte(u8x8, adr);
for( i = 0; i < cnt; i++ )
i2c_write_byte(u8x8, data[i]);
i2c_stop(u8x8);
}
uint8_t u8x8_byte_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t buffer[32]; /* u8g2/u8x8 will never send more than 32 bytes */
static uint8_t buf_idx;
uint8_t *data;
switch(msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 )
{
buffer[buf_idx++] = *data;
data++;
arg_int--;
}
break;
case U8X8_MSG_BYTE_INIT:
i2c_init(u8x8); /* init i2c communication */
break;
case U8X8_MSG_BYTE_SET_DC:
/* ignored for i2c */
break;
case U8X8_MSG_BYTE_START_TRANSFER:
buf_idx = 0;
break;
case U8X8_MSG_BYTE_END_TRANSFER:
i2c_transfer(u8x8, u8x8_GetI2CAddress(u8x8), buf_idx, buffer);
break;
default:
return 0;
}
return 1;
}
#endif

View File

@ -0,0 +1,643 @@
/*
u8x8_cad.c
"command arg data" interface to the graphics controller
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The following sequence must be used for any data, which is set to the display:
uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
any of the following calls
uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd)
uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg)
uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
*/
/*
uint8_t u8x8_cad_template(u8x8_t *u8x8, uint8_t msg, uint16_t arg_int, void *arg_ptr)
{
uint8_t i;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_mcd_byte_SetDC(mcd->next, 1);
u8x8_mcd_byte_Send(mcd->next, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_mcd_byte_SetDC(mcd->next, 1);
u8x8_mcd_byte_Send(mcd->next, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_mcd_byte_SetDC(mcd->next, 0);
for( i = 0; i < 8; i++ )
u8x8_mcd_byte_Send(mcd->next, ((uint8_t *)arg_ptr)[i]);
break;
case U8X8_MSG_CAD_RESET:
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_END_TRANSFER:
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
default:
break;
}
return 1;
}
*/
#include "u8x8.h"
uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_CMD, cmd, NULL);
}
uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL);
}
uint8_t u8x8_cad_SendMultipleArg(u8x8_t *u8x8, uint8_t cnt, uint8_t arg)
{
while( cnt > 0 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL);
cnt--;
}
return 1;
}
uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, cnt, data);
}
uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
}
uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
{
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
}
/*
21 c send command c
22 a send arg a
23 d send data d
24 CS on
25 CS off
254 milli delay by milliseconds
255 end of sequence
*/
void u8x8_cad_SendSequence(u8x8_t *u8x8, uint8_t const *data)
{
uint8_t cmd;
uint8_t v;
for(;;)
{
cmd = *data;
data++;
switch( cmd )
{
case U8X8_MSG_CAD_SEND_CMD:
case U8X8_MSG_CAD_SEND_ARG:
v = *data;
u8x8->cad_cb(u8x8, cmd, v, NULL);
data++;
break;
case U8X8_MSG_CAD_SEND_DATA:
v = *data;
u8x8_cad_SendData(u8x8, 1, &v);
data++;
break;
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
u8x8->cad_cb(u8x8, cmd, 0, NULL);
break;
case 0x0fe:
v = *data;
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, v);
data++;
break;
default:
return;
}
}
}
uint8_t u8x8_cad_empty(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/*
convert to bytes by using
dc = 1 for commands and args and
dc = 0 for data
*/
uint8_t u8x8_cad_110(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SetDC(u8x8, 1);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SetDC(u8x8, 1);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SetDC(u8x8, 0);
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
//break;
/* fall through */
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/*
convert to bytes by using
dc = 1 for commands and args and
dc = 0 for data
t6963
*/
uint8_t u8x8_cad_100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SetDC(u8x8, 1);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SetDC(u8x8, 0);
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
//break;
/* fall through */
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/*
convert to bytes by using
dc = 0 for commands and args and
dc = 1 for data
*/
uint8_t u8x8_cad_001(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SetDC(u8x8, 1);
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
//break;
/* fall through */
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/*
convert to bytes by using
dc = 0 for commands
dc = 1 for args and data
*/
uint8_t u8x8_cad_011(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SetDC(u8x8, 1);
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SetDC(u8x8, 1);
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
//break;
/* fall through */
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/* cad procedure for the ST7920 in SPI mode */
/* u8x8_byte_SetDC is not used */
uint8_t u8x8_cad_st7920_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *data;
uint8_t b;
uint8_t i;
static uint8_t buf[16];
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_SendByte(u8x8, 0x0f8);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
u8x8_byte_SendByte(u8x8, arg_int << 4);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SendByte(u8x8, 0x0f8);
u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
u8x8_byte_SendByte(u8x8, arg_int << 4);
break;
case U8X8_MSG_CAD_SEND_DATA:
u8x8_byte_SendByte(u8x8, 0x0fa);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
/* this loop should be optimized: multiple bytes should be sent */
/* u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); */
data = (uint8_t *)arg_ptr;
/* the following loop increases speed by 20% */
while( arg_int >= 8 )
{
i = 8;
ptr = buf;
do
{
b = *data++;
*ptr++= b & 0x0f0;
b <<= 4;
*ptr++= b;
i--;
} while( i > 0 );
arg_int -= 8;
u8x8_byte_SendBytes(u8x8, 16, buf);
}
while( arg_int > 0 )
{
b = *data;
u8x8_byte_SendByte(u8x8, b & 0x0f0);
u8x8_byte_SendByte(u8x8, b << 4);
data++;
arg_int--;
}
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
break;
case U8X8_MSG_CAD_INIT:
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
default:
return 0;
}
return 1;
}
/* cad procedure for the SSD13xx family in I2C mode */
/* this procedure is also used by the ST7588 */
/* u8x8_byte_SetDC is not used */
/* U8X8_MSG_BYTE_START_TRANSFER starts i2c transfer, U8X8_MSG_BYTE_END_TRANSFER stops transfer */
/* After transfer start, a full byte indicates command or data mode */
static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
{
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x040);
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, arg_ptr);
u8x8_byte_EndTransfer(u8x8);
}
uint8_t u8x8_cad_ssd13xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
case U8X8_MSG_CAD_SEND_ARG:
/* 7 Nov 2016: Can this be improved? */
//u8x8_byte_SetDC(u8x8, 0);
u8x8_byte_StartTransfer(u8x8);
//u8x8_byte_SendByte(u8x8, u8x8_GetI2CAddress(u8x8));
u8x8_byte_SendByte(u8x8, 0x000);
u8x8_byte_SendByte(u8x8, arg_int);
u8x8_byte_EndTransfer(u8x8);
break;
case U8X8_MSG_CAD_SEND_DATA:
//u8x8_byte_SetDC(u8x8, 1);
/* the FeatherWing OLED with the 32u4 transfer of long byte */
/* streams was not possible. This is broken down to */
/* smaller streams, 32 seems to be the limit... */
/* I guess this is related to the size of the Wire buffers in Arduino */
/* Unfortunately, this can not be handled in the byte level drivers, */
/* so this is done here. Even further, only 24 bytes will be sent, */
/* because there will be another byte (DC) required during the transfer */
p = arg_ptr;
while( arg_int > 24 )
{
u8x8_i2c_data_transfer(u8x8, 24, p);
arg_int-=24;
p+=24;
}
u8x8_i2c_data_transfer(u8x8, arg_int, p);
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x078;
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
/* cad transfer commands are ignored */
break;
default:
return 0;
}
return 1;
}
/* the st75256 i2c driver is a copy of the ssd13xx driver, but with arg=1 */
/* modified from cad001 (ssd13xx) to cad011 */
uint8_t u8x8_cad_st75256_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x000);
u8x8_byte_SendByte(u8x8, arg_int);
u8x8_byte_EndTransfer(u8x8);
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x040);
u8x8_byte_SendByte(u8x8, arg_int);
u8x8_byte_EndTransfer(u8x8);
break;
case U8X8_MSG_CAD_SEND_DATA:
/* see ssd13xx driver */
p = arg_ptr;
while( arg_int > 24 )
{
u8x8_i2c_data_transfer(u8x8, 24, p);
arg_int-=24;
p+=24;
}
u8x8_i2c_data_transfer(u8x8, arg_int, p);
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x078; /* ST75256, often this is 0x07e */
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
case U8X8_MSG_CAD_END_TRANSFER:
/* cad transfer commands are ignored */
break;
default:
return 0;
}
return 1;
}
/* cad i2c procedure for the ld7032 controller */
uint8_t u8x8_cad_ld7032_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t in_transfer = 0;
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, arg_int);
in_transfer = 1;
break;
case U8X8_MSG_CAD_SEND_ARG:
u8x8_byte_SendByte(u8x8, arg_int);
break;
case U8X8_MSG_CAD_SEND_DATA:
//u8x8_byte_SetDC(u8x8, 1);
/* the FeatherWing OLED with the 32u4 transfer of long byte */
/* streams was not possible. This is broken down to */
/* smaller streams, 32 seems to be the limit... */
/* I guess this is related to the size of the Wire buffers in Arduino */
/* Unfortunately, this can not be handled in the byte level drivers, */
/* so this is done here. Even further, only 24 bytes will be sent, */
/* because there will be another byte (DC) required during the transfer */
p = arg_ptr;
while( arg_int > 24 )
{
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
arg_int-=24;
p+=24;
u8x8_byte_EndTransfer(u8x8);
u8x8_byte_StartTransfer(u8x8);
u8x8_byte_SendByte(u8x8, 0x08); /* data write for LD7032 */
}
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x060;
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
in_transfer = 0;
break;
case U8X8_MSG_CAD_END_TRANSFER:
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/* cad procedure for the UC16xx family in I2C mode */
/* u8x8_byte_SetDC is not used */
/* DC bit is encoded into the adr byte */
uint8_t u8x8_cad_uc16xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
static uint8_t in_transfer = 0;
static uint8_t is_data = 0;
uint8_t *p;
switch(msg)
{
case U8X8_MSG_CAD_SEND_CMD:
case U8X8_MSG_CAD_SEND_ARG:
if ( in_transfer != 0 )
{
if ( is_data != 0 )
{
/* transfer mode is active, but data transfer */
u8x8_byte_EndTransfer(u8x8);
/* clear the lowest two bits of the adr */
u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
u8x8_byte_StartTransfer(u8x8);
}
}
else
{
/* clear the lowest two bits of the adr */
u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
u8x8_byte_StartTransfer(u8x8);
}
u8x8_byte_SendByte(u8x8, arg_int);
in_transfer = 1;
break;
case U8X8_MSG_CAD_SEND_DATA:
if ( in_transfer != 0 )
{
if ( is_data == 0 )
{
/* transfer mode is active, but data transfer */
u8x8_byte_EndTransfer(u8x8);
/* clear the lowest two bits of the adr */
u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
u8x8_byte_StartTransfer(u8x8);
}
}
else
{
/* clear the lowest two bits of the adr */
u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
u8x8_byte_StartTransfer(u8x8);
}
in_transfer = 1;
p = arg_ptr;
while( arg_int > 24 )
{
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
arg_int-=24;
p+=24;
u8x8_byte_EndTransfer(u8x8);
u8x8_byte_StartTransfer(u8x8);
}
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
break;
case U8X8_MSG_CAD_INIT:
/* apply default i2c adr if required so that the start transfer msg can use this */
if ( u8x8->i2c_address == 255 )
u8x8->i2c_address = 0x070;
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
case U8X8_MSG_CAD_START_TRANSFER:
in_transfer = 0;
/* actual start is delayed, because we do not whether this is data or cmd transfer */
break;
case U8X8_MSG_CAD_END_TRANSFER:
if ( in_transfer != 0 )
u8x8_byte_EndTransfer(u8x8);
in_transfer = 0;
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,182 @@
/*
u8x8_d_a2printer.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Use DC2 bitmap command of the A2 Micro panel termal printer
double stroke
*/
#include "u8x8.h"
#define LINE_MIN_DELAY_MS 15
/* higher values improve quality */
/* however if the value is too high (>=5) then form feed does not work any more */
#define LINE_EXTRA_8PIXEL_DELAY_MS 3
/* this must be a power of two and between 1 and 8 */
/* best quality only with 1 */
#define NO_OF_LINES_TO_SEND_WITHOUT_DELAY 1
/* calculates the delay, based on the number of black pixel */
/* actually only "none-zero" bytes are calculated which is, of course not so accurate, but should be good enough */
uint16_t get_delay_in_milliseconds(uint8_t cnt, uint8_t *data)
{
uint8_t i;
uint16_t time = LINE_MIN_DELAY_MS;
for ( i = 0; i < cnt; i++ )
if ( data[i] != 0 )
time += LINE_EXTRA_8PIXEL_DELAY_MS;
return time;
}
uint8_t u8x8_d_a2printer_common(u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, void *arg_ptr)
{
uint8_t c, i, j;
uint8_t *ptr;
uint16_t delay_in_milliseconds;
switch(msg)
{
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
/*
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
// no setup required
// u8x8_cad_SendSequence(u8x8, u8x8_d_a2printer_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
// no powersave
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 27); /* ESC */
u8x8_cad_SendCmd(u8x8, 55 ); /* parameter command */
/* increasing the "max printing dots" requires a good power supply, but LINE_EXTRA_8PIXEL_DELAY_MS could be reduced then */
u8x8_cad_SendCmd(u8x8, 0); /* Max printing dots,Unit(8dots),Default:7(64 dots) 8*(x+1) ... lower values improve, probably my current supply is not sufficient */
u8x8_cad_SendCmd(u8x8, 200); /* 3-255 Heating time,Unit(10us),Default:80(800us) */
u8x8_cad_SendCmd(u8x8, 2); /* 0-255 Heating interval,Unit(10us),Default:2(20us) ... does not have much influence */
//c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
c = u8x8->display_info->tile_width;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
u8x8_cad_SendCmd(u8x8, 18); /* DC2 */
u8x8_cad_SendCmd(u8x8, 42 ); /* * */
u8x8_cad_SendCmd(u8x8, 8 ); /* height */
u8x8_cad_SendCmd(u8x8, c ); /* c, u8x8->display_info->tile_width */
for( j = 0; j < 8 / NO_OF_LINES_TO_SEND_WITHOUT_DELAY; j ++ )
{
delay_in_milliseconds = 0;
for( i = 0; i < NO_OF_LINES_TO_SEND_WITHOUT_DELAY; i++ )
{
u8x8_cad_SendData(u8x8, c, ptr); /* c, note: SendData can not handle more than 255 bytes, send one line of data */
delay_in_milliseconds += get_delay_in_milliseconds(c, ptr);
ptr += c;
}
while( delay_in_milliseconds > 200 )
{
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_MILLI, 200, NULL);
delay_in_milliseconds -= 200;
}
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_MILLI, delay_in_milliseconds, NULL);
}
/* set parameters back to their default values */
u8x8_cad_SendCmd(u8x8, 27); /* ESC */
u8x8_cad_SendCmd(u8x8, 55 ); /* parameter command */
u8x8_cad_SendCmd(u8x8, 7); /* Max printing dots,Unit(8dots),Default:7(64 dots) 8*(x+1)*/
u8x8_cad_SendCmd(u8x8, 80); /* 3-255 Heating time,Unit(10us),Default:80(800us) */
u8x8_cad_SendCmd(u8x8, 2); /* 0-255 Heating interval,Unit(10us),Default:2(20us)*/
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_a2printer_384x240_display_info =
{
/* most of the settings are not required, because this is a serial RS232 printer */
/* chip_enable_level = */ 1,
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 5,
/* pre_chip_disable_wait_ns = */ 5,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0) */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 48,
/* tile_hight = */ 30,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 384,
/* pixel_height = */ 240
};
uint8_t u8x8_d_a2printer_384x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_a2printer_384x240_display_info);
break;
default:
return u8x8_d_a2printer_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}

View File

@ -0,0 +1,552 @@
/*
u8x8_d_il3820_296x128.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
il3820: 200x300x1
command
0x22: assign actions
0x20: execute actions
action for command 0x022 are (more or less guessed)
bit 7: Enable Clock
bit 6: Enable Charge Pump
bit 5: Load Temparture Value (???)
bit 4: Load LUT (???)
bit 3: Initial Display (???)
bit 2: Pattern Display --> Requires about 945ms with the LUT from below
bit 1: Disable Charge Pump
bit 0: Disable Clock
Disable Charge Pump and Clock require about 10ms
Enable Charge Pump and Clock require about 100 to 300ms
Notes:
- Introduced a refresh display message, which copies RAM to display
- Charge pump is always enabled. Charge pump can be enabled/disabled via power save message
- U8x8 will not really work because of the two buffers in the SSD1606, however U8g2 should be ok.
LUT for the 296x128 device (IL3820)
LUT (cmd: 0x032 has 30 bytes)
section 6.8 of the datasheet mentions 256 bits = 32 bytes for the LUT
chapter 7 tells 30 bytes
according to section 6.8:
20 bytes waveform
10 bytes timing
1 byte named as VSH/VSL
1 empty byte
according to the command table, the lut has 240 bits (=30 bytes * 8 bits)
LUT / Refresh time
total_refresh_time = (refresh_lines + dummy_lines*2)*TGate*TS_Sum/f_OSC
f_OSC=1MHz (according to the datasheets)
refreh_lines = 296 (for the waveshare display, 0x045 cmd)
dummy_lines = 22 (for the upcoming u8g2 code, 0x03a cmd)
TGate = 62 (POR default, 0x03b cmd)
TS_Sum: Sum of all TS entries of the second part of the LUT
f_OSC: 1MHz according to the datasheet.
so we have
total_refresh_time = 21080*TS_Sum/1000000 = 21ms * TS_Sum
This file includes two devices:
u8x8_d_il3820_296x128 --> includes LUT which is probably from the WaveShare 2.9 Vendor
u8x8_d_il3820_v2_296x128 --> includes LUT which was optimized for faster speed and lesser flicker
*/
/* Waveform part of the LUT (20 bytes) */
/* bit 7/6: 1 - 1 transition */
/* bit 5/4: 1 - 0 transition */
/* bit 3/2: 0 - 1 transition */
/* bit 1/0: 0 - 0 transition */
/* 00 VSS */
/* 01 VSH */
/* 10 VSL */
/* 11 NA */
#include "u8x8.h"
/*=================================================*/
/* common code for all devices */
static const uint8_t u8x8_d_il3820_296x128_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x22, 0xc0), /* enable clock and charge pump */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(200), /* according to my measures it may take up to 150ms */
U8X8_DLY(100), /* but it might take longer */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_il3820_296x128_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
/* disable clock and charge pump only, deep sleep is not entered, because we will loose RAM content */
U8X8_CA(0x22, 0x02), /* only disable charge pump, HW reset seems to be required if the clock is disabled */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(20),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
// static const uint8_t u8x8_d_il3820_296x128_flip0_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
// static const uint8_t u8x8_d_il3820_296x128_flip1_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
static const u8x8_display_info_t u8x8_il3820_296x128_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 120,
/* pre_chip_disable_wait_ns = */ 60,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100,
/* sda_setup_time_ns = */ 50, /* IL3820 */
/* sck_pulse_width_ns = */ 125, /* IL3820: 125ns, clock cycle = 250ns */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150,
/* tile_width = */ 37, /* 37*8 = 296 */
/* tile_hight = */ 16, /* 16*8 = 128 */
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 296,
/* pixel_height = */ 128
};
static uint8_t *u8x8_convert_tile_for_il3820(uint8_t *t)
{
uint8_t i;
static uint8_t buf[8];
uint8_t *pbuf = buf;
for( i = 0; i < 8; i++ )
{
*pbuf++ = ~(*t++);
}
return buf;
}
static void u8x8_d_il3820_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
static void u8x8_d_il3820_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
{
uint16_t x;
uint8_t c, page;
uint8_t *ptr;
u8x8_cad_StartTransfer(u8x8);
page = u8x8->display_info->tile_height;
page --;
page -= (((u8x8_tile_t *)arg_ptr)->y_pos);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
//u8x8_cad_SendCmd(u8x8, 0x011 ); /* cursor increment mode */
//u8x8_cad_SendArg(u8x8, 7);
u8x8_cad_SendCmd(u8x8, 0x04f ); /* set cursor column */
u8x8_cad_SendArg(u8x8, x&255);
u8x8_cad_SendArg(u8x8, x>>8);
u8x8_cad_SendCmd(u8x8, 0x04e ); /* set cursor row */
u8x8_cad_SendArg(u8x8, page);
u8x8_cad_SendCmd(u8x8, 0x024 );
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_il3820(ptr));
ptr += 8;
x += 8;
c--;
} while( c > 0 );
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
}
static const uint8_t u8x8_d_il3820_exec_1000dly_seq[] = {
// assumes, that the start transfer has happend
U8X8_CA(0x22, 0x04), /* display update seq. option: pattern display */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static void u8x8_d_il3820_first_init(u8x8_t *u8x8)
{
u8x8_ClearDisplay(u8x8);
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x032); // program update sequence
u8x8_cad_SendMultipleArg(u8x8, 8, 0x055); // all black
u8x8_cad_SendMultipleArg(u8x8, 12, 0x0aa); // all white
u8x8_cad_SendMultipleArg(u8x8, 10, 0x022); // 830ms
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_exec_1000dly_seq);
}
#ifdef OBSOLETE
static void u8x8_d_il3820_second_init(u8x8_t *u8x8)
{
u8x8_ClearDisplay(u8x8);
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x032); // program update sequence
u8x8_cad_SendMultipleArg(u8x8, 20, 0x000); // do nothing
u8x8_cad_SendMultipleArg(u8x8, 10, 0x011); // 414ms dly
/* reuse sequence from above, ok some time is wasted here, */
/* delay could be lesser */
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_exec_1000dly_seq);
}
#endif
/*=================================================*/
/* first version, LUT from WaveShare */
/* http://www.waveshare.com/wiki/File:2.9inch_e-Paper_Module_code.7z */
static const uint8_t u8x8_d_il3820_296x128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x10, 0x00), /* Deep Sleep mode Control: Disable */
U8X8_C(0x01),
U8X8_A(295 % 256), U8X8_A(295/256), U8X8_A(0),
U8X8_CA(0x03, 0x00), /* Gate Driving voltage: 15V (lowest value)*/
U8X8_CA(0x04, 0x0a), /* Source Driving voltage: 15V (mid value and POR)*/
//U8X8_CA(0x22, 0xc0), /* display update seq. option: enable clk, enable CP, .... todo: this is never activated */
//U8X8_CA(0x0b, 7), /* Set Delay of gate and source non overlap period, POR = 7 */
U8X8_CA(0x2c, 0xa8), /* write vcom value*/
U8X8_CA(0x3a, 0x16), /* dummy lines POR=22 (0x016) */
U8X8_CA(0x3b, 0x08), /* gate time POR=0x08*/
U8X8_CA(0x3c, 0x33), /* select boarder waveform */
//U8X8_CA(0x22, 0xc4), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
U8X8_CA(0x11, 0x07), /* Define data entry mode, x&y inc, x first*/
U8X8_CAA(0x44, 0, 29), /* RAM x start & end, 32*4=128 */
U8X8_CAAAA(0x45, 0, 0, 295&255, 295>>8), /* RAM y start & end, 0..295 */
//U8X8_CA(0x4e, 0), /* set x pos, 0..29? */
//U8X8_CAA(0x4f, 0, 0), /* set y pos, 0...320??? */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_il3820_to_display_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
/*
0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
measured 1582 ms
*/
U8X8_C(0x32), /* write LUT register*/
/* original values */
U8X8_A(0x50),
U8X8_A(0xaa),
U8X8_A(0x55),
U8X8_A(0xaa),
U8X8_A(0x11),
U8X8_A(0x11),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
/* Timing part of the LUT, 20 Phases with 4 bit each: 10 bytes */
U8X8_A(0xff),
U8X8_A(0xff),
U8X8_A(0x3f),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_CA(0x22, 0x04), /* display update seq. option: pattern display, assumes clk and charge pump are enabled */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(250), /* delay for 1620ms. The current sequence takes 1582ms */
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(120),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_il3820_296x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_il3820_296x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_init_seq);
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave0_seq);
u8x8_d_il3820_first_init(u8x8);
/* usually the DISPLAY_INIT message leaves the display in power save state */
/* however this is not done for e-paper devices, see: */
/* https://github.com/olikraus/u8g2/wiki/internal#powersave-mode */
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_d_il3820_draw_tile(u8x8, arg_int, arg_ptr);
break;
case U8X8_MSG_DISPLAY_REFRESH:
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_to_display_seq);
break;
default:
return 0;
}
return 1;
}
/*=================================================*/
/* second version for the IL3820 display */
/* http://www.waveshare.com/wiki/File:2.9inch_e-Paper_Module_code.7z */
static const uint8_t u8x8_d_il3820_v2_296x128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_CA(0x10, 0x00), /* Deep Sleep mode Control: POR: Normal mode */
U8X8_C(0x01),
U8X8_A(295 % 256), U8X8_A(295/256), U8X8_A(0),
/* the driving voltagesmust not be that high, in order to aviod level change after */
/* some seconds (which happens with 0xea */
U8X8_CA(0x03, 0x75), /* Gate Driving voltage: +/-15V =0x00 POR (+22/-20V) = 0x0ea*/
U8X8_CA(0x04, 0x0a), /* Source Driving voltage: (POR=0x0a=15V), max=0x0e*/
U8X8_CA(0x0b, 7), /* Set Delay of gate and source non overlap period, POR = 7 */
U8X8_CA(0x2c, 0xa8), /* write vcom value*/
U8X8_CA(0x3a, 0x16), /* dummy lines POR=22 (0x016) */
U8X8_CA(0x3b, 0x08), /* gate time POR=0x08*/
U8X8_CA(0x3c, 0x33), /* select boarder waveform */
U8X8_CA(0x11, 0x07), /* Define data entry mode, x&y inc, x first*/
U8X8_CAA(0x44, 0, 29), /* RAM x start & end, 32*4=128 */
U8X8_CAAAA(0x45, 0, 0, 295&255, 295>>8), /* RAM y start & end, 0..295 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_il3820_v2_to_display_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
/*
0xaa, 0x09, 0x09, 0x19, 0x19,
0x11, 0x11, 0x11, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x75, 0x77, 0x77, 0x77, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00
measured 1240 ms
*/
U8X8_C(0x32), /* write LUT register*/
/* https://github.com/olikraus/u8g2/issues/347 */
U8X8_A(0xaa),
U8X8_A(0x09),
U8X8_A(0x09),
U8X8_A(0x19),
U8X8_A(0x19),
U8X8_A(0x11),
U8X8_A(0x11),
U8X8_A(0x11),
U8X8_A(0x11),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
/* Timing part of the LUT, 20 Phases with 4 bit each: 10 bytes */
U8X8_A(0x75),
U8X8_A(0x77),
U8X8_A(0x77),
U8X8_A(0x77),
U8X8_A(0x07),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_CA(0x22, 0x04), /* display update seq. option: pattern display */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(250), /* delay for 1400ms. The current sequence takes 1240ms, it was reported, that longer delays are better */
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(150), /* extended, #318 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_il3820_v2_296x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_il3820_296x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_v2_296x128_init_seq);
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave0_seq);
u8x8_d_il3820_first_init(u8x8);
/* u8x8_d_il3820_second_init(u8x8); */ /* not required, u8g2.begin() will also clear the display once more */
/* usually the DISPLAY_INIT message leaves the display in power save state */
/* however this is not done for e-paper devices, see: */
/* https://github.com/olikraus/u8g2/wiki/internal#powersave-mode */
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_d_il3820_draw_tile(u8x8, arg_int, arg_ptr);
break;
case U8X8_MSG_DISPLAY_REFRESH:
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_v2_to_display_seq);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,200 @@
/*
u8x8_d_ist3020.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_ist3020_erc19264_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a4), /* all pixel off, issue 142 */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ist3020_erc19264_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ist3020_erc19264_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ist3020_erc19264_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_ist3020_erc19264_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 150, /* IST3020 datasheet, page 56 */
/* pre_chip_disable_wait_ns = */ 150, /* IST3020 datasheet, page 56 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 1,
/* sda_setup_time_ns = */ 100, /* IST3020 datasheet, page 56 */
/* sck_pulse_width_ns = */ 100, /* IST3020 datasheet, page 56 */
/* sck_clock_hz = */ 4000000UL, /* */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40, /* IST3020 datasheet, page 54 */
/* write_pulse_width_ns = */ 60, /* IST3020 datasheet, page 54 */
/* tile_width = */ 24, /* width of 24*8=192 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 64,
/* pixel_width = */ 192,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_ist3020_erc19264_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_C(0x0ab), /* build in osc on, used in ER code, but not mentioned in data sheet */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x0a0), /* ADC set to reverse */
U8X8_C(0x0c8), /* common output mode */
// Flipmode
//U8X8_C(0x0a0), /* ADC set to reverse */
//U8X8_C(0x0c8), /* common output mode */
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
U8X8_C(0x0a3), /* FIX: LCD bias 1/7, old value was 1/9 (0x0a2) */
U8X8_C(0x028|4), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x028|6), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x028|7), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x020), /* v0 voltage resistor ratio */
U8X8_CA(0x081, 0x019), /* set contrast, contrast value (from ER code: 45) */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ist3020_erc19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ist3020_erc19264_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,344 @@
/*
u8x8_d_ks0108.c
The classic 5V LCD
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_ks0108_init_seq[] = {
U8X8_C(0x0c0), /* satart at the top */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ks0108_powersave0_seq[] = {
U8X8_C(0x03f), /* display on */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ks0108_powersave1_seq[] = {
U8X8_C(0x03e), /* display off */
U8X8_END() /* end of sequence */
};
struct u8x8_ks0108_vars
{
uint8_t *ptr;
uint8_t x;
uint8_t c;
uint8_t arg_int;
};
static void u8x8_ks0108_out(u8x8_t *u8x8, struct u8x8_ks0108_vars *v, void *arg_ptr)
{
uint8_t cnt;
u8x8_cad_SendCmd(u8x8, 0x040 | ((v->x << 3) & 63) );
u8x8_cad_SendCmd(u8x8, 0x0b8 | (((u8x8_tile_t *)arg_ptr)->y_pos));
while( v->arg_int > 0 )
{
/* calculate tiles to next boundary (end or chip limit) */
cnt = v->x;
cnt += 8;
cnt &= 0x0f8;
cnt -= v->x;
if ( cnt > v->c )
cnt = v->c;
/* of cours we still could use cnt=1 here... */
/* but setting cnt to 1 is not very efficient */
//cnt = 1;
v->x +=cnt;
v->c-=cnt;
cnt<<=3;
u8x8_cad_SendData(u8x8, cnt, v->ptr); /* note: SendData can not handle more than 255 bytes */
v->ptr += cnt;
if ( v->c == 0 )
{
v->ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
v->c = ((u8x8_tile_t *)arg_ptr)->cnt;
v->arg_int--;
}
if ( ((v->x) & 7) == 0 )
break;
}
}
static const u8x8_display_info_t u8x8_ks0108_128x64_display_info =
{
/* chip_enable_level = */ 0, /* KS0108: Not used */
/* chip_disable_level = */ 1, /* KS0108: Not used */
/* post_chip_enable_wait_ns = */ 100,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6, /* could be faster for the KS0108 */
/* sda_setup_time_ns = */ 12,
/* sck_pulse_width_ns = */ 75, /* KS0108: Not used */
/* sck_clock_hz = */ 4000000UL, /* KS0108: Not used */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4, /* KS0108: Not used */
/* data_setup_time_ns = */ 200,
/* write_pulse_width_ns = */ 250, /* KS0108: actially 450 ns, but additional 200 ns are added by the byte transfer function */
/* tile_width = */ 16, /* width of 16*8=128 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
uint8_t u8x8_d_ks0108_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
struct u8x8_ks0108_vars v;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ks0108_128x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 2, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 2, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
}
else
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 2, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
}
break;
// The KS0108 can not mirror the cols and rows, use U8g2 for rotation
// case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
// break;
// The KS0108 has no internal contrast command
// case U8X8_MSG_DISPLAY_SET_CONTRAST:
// break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
v.ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
v.x = ((u8x8_tile_t *)arg_ptr)->x_pos;
v.c = ((u8x8_tile_t *)arg_ptr)->cnt;
v.arg_int = arg_int;
if ( v.x < 8 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
u8x8_ks0108_out(u8x8, &v, arg_ptr);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
}
if ( v.x < 16 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 2, NULL);
u8x8_ks0108_out(u8x8, &v, arg_ptr);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
}
//if ( v.x < 24 )
//{
//u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 4, NULL);
//u8x8_ks0108_out(u8x8, &v, arg_ptr);
//u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
//}
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ks0108_192x64_display_info =
{
/* chip_enable_level = */ 0, /* KS0108: Not used */
/* chip_disable_level = */ 1, /* KS0108: Not used */
/* post_chip_enable_wait_ns = */ 100,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6, /* could be faster for the KS0108 */
/* sda_setup_time_ns = */ 12,
/* sck_pulse_width_ns = */ 75, /* KS0108: Not used */
/* sck_clock_hz = */ 4000000UL, /* KS0108: Not used */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4, /* KS0108: Not used */
/* data_setup_time_ns = */ 200,
/* write_pulse_width_ns = */ 250, /* KS0108: actially 450 ns, but additional 200 ns are added by the byte transfer function */
/* tile_width = */ 24, /* width of 24*8=192 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 192,
/* pixel_height = */ 64
};
/* east rising (buydisplay.com) ERM19264 */
/* left: 011, middle: 101, right: 110, no chip select: 111 */
uint8_t u8x8_d_ks0108_erm19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
struct u8x8_ks0108_vars v;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ks0108_192x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 3, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 5, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 6, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 3, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 5, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 6, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
}
else
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 3, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 5, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 6, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
}
break;
// The KS0108 can not mirror the cols and rows, use U8g2 for rotation
// case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
// break;
// The KS0108 has no internal contrast command
// case U8X8_MSG_DISPLAY_SET_CONTRAST:
// break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
v.ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
v.x = ((u8x8_tile_t *)arg_ptr)->x_pos;
v.c = ((u8x8_tile_t *)arg_ptr)->cnt;
v.arg_int = arg_int;
/*
3-bit CS value:
In u8x8_byte_set_ks0108_cs(u8x8_t *u8x8, uint8_t arg) the lowest
bit is assigned to CS and highest bit if the 3-bit value to CS2
CS: left part of the display --> 6
CS1: middle part --> 5
CS2: right part of the display --> 3
Reference: https://github.com/olikraus/u8g2/issues/631
*/
if ( v.x < 8 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 6, NULL); // 3-->6, issue 631
u8x8_ks0108_out(u8x8, &v, arg_ptr);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
}
if ( v.x < 16 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 5, NULL);
u8x8_ks0108_out(u8x8, &v, arg_ptr);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
}
if ( v.x < 24 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 3, NULL); // 6-->3, // issue 631
u8x8_ks0108_out(u8x8, &v, arg_ptr);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
}
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,470 @@
/*
u8x8_d_lc7981.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* no powersave mode for the LC7981 */
// static const uint8_t u8x8_d_lc7981_powersave0_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
// static const uint8_t u8x8_d_lc7981_powersave1_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
/* no hardware flip for the LC7981 */
// static const uint8_t u8x8_d_lc7981_flip0_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
// static const uint8_t u8x8_d_lc7981_flip1_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
/* http://graphics.stanford.edu/~seander/bithacks.html */
static uint8_t reverse_byte(uint8_t v)
{
// if ( v != 0 && v != 255 ) does not help much
{
// swap odd and even bits
v = ((v >> 1) & 0x055) | ((v & 0x055) << 1);
// swap consecutive pairs
v = ((v >> 2) & 0x033) | ((v & 0x033) << 2);
// swap nibbles ...
v = ((v >> 4) & 0x00F) | ((v & 0x00F) << 4);
}
return v;
}
static uint8_t u8x8_d_lc7981_common(u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, void *arg_ptr)
{
uint8_t c, i, j;
uint16_t y;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y*=8;
y*= u8x8->display_info->tile_width;
/* x = ((u8x8_tile_t *)arg_ptr)->x_pos; x is ignored... no u8x8 support */
u8x8_cad_StartTransfer(u8x8);
/*
Tile structure is reused here for the t6963, however u8x8 is not supported
tile_ptr points to data which has cnt*8 bytes (same as SSD1306 tiles)
Buffer is expected to have 8 lines of code fitting to the t6963 internal memory
"cnt" includes the number of horizontal bytes. width is equal to cnt*8
x is assumed to be zero
TODO: Consider arg_int, however arg_int is not used by u8g2
*/
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
for( i = 0; i < 8; i++ )
{
u8x8_cad_SendCmd(u8x8, 0x0a ); /* display ram (cursor) address low byte */
u8x8_cad_SendArg(u8x8, y&255);
u8x8_cad_SendCmd(u8x8, 0x0b ); /* display ram (cursor) address high byte */
u8x8_cad_SendArg(u8x8, y>>8);
u8x8_cad_SendCmd(u8x8, 0x0c ); /* write start */
/*
The LC7981 has the MSB at the right position, which is exactly the opposite to the T6963.
Instead of writing a third hvline procedure for this device, we just revert the bytes before
transmit. This is slow because:
- the bit reverse itself
- the single byte transfer
The one byte is transmitted via SendArg, which is ok, because CAD = 100
*/
for( j = 0; j < c; j++ )
u8x8_cad_SendArg(u8x8, reverse_byte(*ptr++));
//u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes, send one line of data */
//ptr += u8x8->display_info->tile_width;
y += u8x8->display_info->tile_width;
}
u8x8_cad_EndTransfer(u8x8);
break;
/* handled in the calling procedure
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_128x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
break;
*/
/* power save is not there...
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_powersave1_seq);
break;
*/
/* hardware flip not is not available
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
*/
#ifdef U8X8_WITH_SET_CONTRAST
/* no contrast setting :-(
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int );
u8x8_cad_EndTransfer(u8x8);
break;
*/
#endif
default:
return 0;
}
return 1;
}
/*================================================*/
/* LC7981 160x80 LCD*/
static const u8x8_display_info_t u8x8_lc7981_160x80_display_info =
{
/* chip_enable_level = */ 0, /* LC7981 has a low active CS*/
/* chip_disable_level = */ 1,
/* from here... */
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 10,
/* sda_setup_time_ns = */ 30,
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* ... to here, values are ignored, because this is a parallel interface only */
/* data_setup_time_ns = */ 220,
/* write_pulse_width_ns = */ 20,
/* tile_width = */ 20, /* width of 20*8=160 pixel */
/* tile_hight = */ 10,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 160,
/* pixel_height = */ 80
};
static const uint8_t u8x8_d_lc7981_160x80_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(50),
U8X8_CA(0x00, 0x32), /* display on (bit 5), master mode on (bit 4), graphics mode on (bit 1) */
U8X8_CA(0x01, 0x07), /* character/bits per pixel pitch */
U8X8_CA(0x02, 160/8-1), /* number of chars/byte width of the screen */
U8X8_CA(0x03, 0x50), /* time division: 50 (1/80 duty cycle) */
U8X8_CA(0x08, 0x00), /* display start low */
U8X8_CA(0x09, 0x00), /* display start high */
U8X8_DLY(10),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_lc7981_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_lc7981_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_160x80_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_160x80_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/
/* LC7981 160x160 LCD*/
static const u8x8_display_info_t u8x8_lc7981_160x160_display_info =
{
/* chip_enable_level = */ 0, /* LC7981 has a low active CS*/
/* chip_disable_level = */ 1,
/* from here... */
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 10,
/* sda_setup_time_ns = */ 30,
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* ... to here, values are ignored, because this is a parallel interface only */
/* data_setup_time_ns = */ 220,
/* write_pulse_width_ns = */ 20,
/* tile_width = */ 20, /* width of 20*8=160 pixel */
/* tile_hight = */ 20,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 160,
/* pixel_height = */ 160
};
static const uint8_t u8x8_d_lc7981_160x160_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(50),
U8X8_CA(0x00, 0x32), /* display on (bit 5), master mode on (bit 4), graphics mode on (bit 1) */
U8X8_CA(0x01, 0x07), /* character/bits per pixel pitch */
U8X8_CA(0x02, 160/8-1), /* number of chars/byte width of the screen */
U8X8_CA(0x03, 159), /* time division */
U8X8_CA(0x08, 0x00), /* display start low */
U8X8_CA(0x09, 0x00), /* display start high */
U8X8_DLY(10),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_lc7981_160x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_lc7981_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_160x160_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_160x160_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/
/* LC7981 240x128 LCD*/
static const u8x8_display_info_t u8x8_lc7981_240x128_display_info =
{
/* chip_enable_level = */ 0, /* LC7981 has a low active CS*/
/* chip_disable_level = */ 1,
/* from here... */
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 10,
/* sda_setup_time_ns = */ 30,
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* ... to here, values are ignored, because this is a parallel interface only */
/* data_setup_time_ns = */ 220,
/* write_pulse_width_ns = */ 20,
/* tile_width = */ 30, /* width of 30*8=240 pixel */
/* tile_hight = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 240,
/* pixel_height = */ 128
};
static const uint8_t u8x8_d_lc7981_240x128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(50),
U8X8_CA(0x00, 0x32), /* display on (bit 5), master mode on (bit 4), graphics mode on (bit 1) */
U8X8_CA(0x01, 0x07), /* character/bits per pixel pitch */
U8X8_CA(0x02, 240/8-1), /* number of chars/byte width of the screen */
U8X8_CA(0x03, 0x7f), /* time division */
U8X8_CA(0x08, 0x00), /* display start low */
U8X8_CA(0x09, 0x00), /* display start high */
U8X8_DLY(10),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_lc7981_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_lc7981_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_240x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_240x128_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/
/* LC7981 240x64 LCD*/
/* https://github.com/olikraus/u8g2/issues/642 */
static const u8x8_display_info_t u8x8_lc7981_240x64_display_info =
{
/* chip_enable_level = */ 0, /* LC7981 has a low active CS*/
/* chip_disable_level = */ 1,
/* from here... */
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 10,
/* sda_setup_time_ns = */ 30,
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* ... to here, values are ignored, because this is a parallel interface only */
/* data_setup_time_ns = */ 220,
/* write_pulse_width_ns = */ 20,
/* tile_width = */ 30, /* width of 30*8=240 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 240,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_lc7981_240x64_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(50),
U8X8_CA(0x00, 0x32), /* display on (bit 5), master mode on (bit 4), graphics mode on (bit 1) */
U8X8_CA(0x01, 0x07), /* character/bits per pixel pitch */
U8X8_CA(0x02, 240/8-1), /* number of chars/byte width of the screen */
U8X8_CA(0x03, 0x7f), /* time division */
U8X8_CA(0x08, 0x00), /* display start low */
U8X8_CA(0x09, 0x00), /* display start high */
U8X8_DLY(10),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_lc7981_240x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_lc7981_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_240x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_240x64_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}

View File

@ -0,0 +1,207 @@
/*
u8x8_d_ld7032_60x32.c
Note: Flip Mode is NOT supported
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* testboard U8GLIB_LD7032_60x32 u8g(11, 12, 9, 10, 8); // SPI Com: SCK = 11, MOSI = 12, CS = 9, A0 = 10, RST = 8 (SW SPI Nano Board) */
/* http://www.seeedstudio.com/document/pdf/0.5OLED%20SPEC.pdf */
static const uint8_t u8x8_d_ld7032_60x32_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
//U8X8_CA(0x002, 0x001), /* Dot Matrix Display ON */
U8X8_CA(0x014, 0x000), /* Stand-by OFF */
U8X8_CA(0x01a, 0x004), /* Dot Matrix Frame Rate, special value for this OLED from manual*/
U8X8_CA(0x01d, 0x000), /* Graphics Memory Writing Direction: reset default (right down, horizontal) */
U8X8_CA(0x009, 0x000), /* Display Direction: reset default (x,y: min --> max) */
U8X8_CAA(0x030, 0x000, 0x03b), /* Display Size X, Column Start - End*/
U8X8_CAA(0x032, 0x000, 0x01f), /* Display Size Y, Row Start - End*/
U8X8_CA(0x010, 0x000), /* Peak Pulse Width Set: 0 SCLK */
U8X8_CA(0x016, 0x000), /* Peak Pulse Delay Set: 0 SCLK */
U8X8_CA(0x012, 0x040), /* Dot Matrix Current Level Set: 0x050 * 1 uA = 80 uA */
U8X8_CA(0x018, 0x003), /* Pre-Charge Pulse Width: 3 SCLK */
U8X8_CA(0x044, 0x002), /* Pre-Charge Mode: Every Time */
U8X8_CA(0x048, 0x003), /* Row overlap timing: Pre-Charge + Peak Delay + Peak boot Timing */
U8X8_CA(0x03f, 0x011), /* VCC_R_SEL: ??? */
U8X8_CA(0x03d, 0x000), /* VSS selection: 2.8V */
//U8X8_CA(0x002, 0x001), /* Dot Matrix Display ON */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ld7032_60x32_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x002, 0x001), /* Dot Matrix Display ON */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ld7032_60x32_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x002, 0x000), /* Dot Matrix Display ON */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ld7032_60x32_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x009, 0x000), /* Display Direction: reset default (x,y: min --> max) */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ld7032_60x32_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
//U8X8_CA(0x009, 0x002), /* Display Direction: reset default (x,y: min --> max) */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ld7032_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ld7032_60x32_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x012 );
if ( arg_int > 0x07f ) /* default is 0x040, limit to 0x07f to be on the safe side (hopefully) */
arg_int= 0x07f;
u8x8_cad_SendArg(u8x8, arg_int ); /* values from 0x00 to 0x0ff are allowed, bit will all values be safe??? */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x += u8x8->x_offset/8;
u8x8_cad_SendCmd(u8x8, 0x034 );
u8x8_cad_SendArg(u8x8, x );
u8x8_cad_SendCmd(u8x8, 0x035 );
u8x8_cad_SendArg(u8x8, 0x007 );
u8x8_cad_SendCmd(u8x8, 0x036 );
u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos)*8 );
u8x8_cad_SendCmd(u8x8, 0x037 );
u8x8_cad_SendArg(u8x8, 0x01f );
u8x8_cad_SendCmd(u8x8, 0x008 );
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ld7032_60x32_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 15,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100,
/* sda_setup_time_ns = */ 30, /* 20ns, but cycle time is 60ns, so use 60/2 */
/* sck_pulse_width_ns = */ 30, /* 20ns, but cycle time is 60ns, so use 60/2 */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 20,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 8,
/* tile_hight = */ 4,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 60,
/* pixel_height = */ 32
};
uint8_t u8x8_d_ld7032_60x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ld7032_60x32_display_info);
return 1;
}
return u8x8_d_ld7032_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,122 @@
/*
u8x8_d_ls013b7dh03.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The LS013B7DH02 is a simple display and controller
--> no support for contrast adjustment, flip and power down.
*/
#include "u8x8.h"
#define SWAP8(a) ((((a) & 0x80) >> 7) | (((a) & 0x40) >> 5) | (((a) & 0x20) >> 3) | (((a) & 0x10) >> 1) | (((a) & 0x08) << 1) | (((a) & 0x04) << 3) | (((a) & 0x02) << 5) | (((a) & 0x01) << 7))
#define LS013B7DH03_CMD_UPDATE (0x01)
#define LS013B7DH03_CMD_ALL_CLEAR (0x04)
#define LS013B7DH03_VAL_TRAILER (0x00)
static const u8x8_display_info_t u8x8_ls013b7dh03_128x128_display_info =
{
/* chip_enable_level = */ 1,
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 50,
/* pre_chip_disable_wait_ns = */ 50,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 227, /* 227 nsec according to the datasheet */
/* sck_pulse_width_ns = */ 255, /* 450 nsec according to the datasheet */
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 2, /* active low, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 100,
/* write_pulse_width_ns = */ 100,
/* tile_width = */ 16,
/* tile_hight = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 128
};
uint8_t u8x8_d_ls013b7dh03_128x128(u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, void *arg_ptr)
{
uint8_t y, c, i;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ls013b7dh03_128x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
/* clear screen */
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, SWAP8(LS013B7DH03_CMD_ALL_CLEAR) );
u8x8_cad_SendCmd(u8x8, LS013B7DH03_VAL_TRAILER);
u8x8_cad_EndTransfer(u8x8);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
/* not available for the ls013b7dh03 */
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
/* each tile is 8 lines, with the data starting at the left edge */
y = ((((u8x8_tile_t *)arg_ptr)->y_pos) * 8) + 1;
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
/* send data mode byte */
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, SWAP8(LS013B7DH03_CMD_UPDATE) );
/* send 8 lines of 16 bytes (=128 pixels) */
for( i = 0; i < 8; i++ )
{
u8x8_cad_SendCmd(u8x8, SWAP8(y + i) );
u8x8_cad_SendData(u8x8, c, ptr);
u8x8_cad_SendCmd(u8x8, LS013B7DH03_VAL_TRAILER);
ptr += c;
}
/* finish with a trailing byte */
u8x8_cad_SendCmd(u8x8, LS013B7DH03_VAL_TRAILER);
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,244 @@
/*
u8x8_d_max7219.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_max7219_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(15, 0), /* test mode off */
U8X8_CA(15, 0), /* test mode off */
U8X8_CA(15, 0), /* test mode off */
U8X8_CA(15, 0), /* test mode off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(12, 0), /* */
U8X8_CA(12, 0), /* */
U8X8_CA(12, 0), /* */
U8X8_CA(12, 0), /* */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(9, 0), /* decode mode: graphics */
U8X8_CA(9, 0), /* decode mode: graphics */
U8X8_CA(9, 0), /* decode mode: graphics */
U8X8_CA(9, 0), /* decode mode: graphics */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(10, 10), /* medium high intensity */
U8X8_CA(10, 10), /* medium high intensity */
U8X8_CA(10, 10), /* medium high intensity */
U8X8_CA(10, 10), /* medium high intensity */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(11, 7), /* scan limit: display all digits (assuming a 8x8 matrix) */
U8X8_CA(11, 7), /* scan limit: display all digits (assuming a 8x8 matrix) */
U8X8_CA(11, 7), /* scan limit: display all digits (assuming a 8x8 matrix) */
U8X8_CA(11, 7), /* scan limit: display all digits (assuming a 8x8 matrix) */
U8X8_END_TRANSFER(), /* disable chip */
//U8X8_CA(12, 0), /* shutdown */
//U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_max7219_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(12, 1), /* display on */
U8X8_CA(12, 1), /* display on */
U8X8_CA(12, 1), /* display on */
U8X8_CA(12, 1), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_max7219_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(12, 0), /* shutdown */
U8X8_CA(12, 0), /* shutdown */
U8X8_CA(12, 0), /* shutdown */
U8X8_CA(12, 0), /* shutdown */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_max7219_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t c, j, i;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_pcf8812_96x65_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_max7219_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_max7219_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_max7219_powersave1_seq);
break;
/* not supported by MAX7219
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
break;
*/
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 10 ); /* brightness */
u8x8_cad_SendArg(u8x8, (arg_int>>4) ); /* 0..15 for contrast */
u8x8_cad_SendCmd(u8x8, 10 ); /* brightness */
u8x8_cad_SendArg(u8x8, (arg_int>>4) ); /* 0..15 for contrast */
u8x8_cad_SendCmd(u8x8, 10 ); /* brightness */
u8x8_cad_SendArg(u8x8, (arg_int>>4) ); /* 0..15 for contrast */
u8x8_cad_SendCmd(u8x8, 10 ); /* brightness */
u8x8_cad_SendArg(u8x8, (arg_int>>4) ); /* 0..15 for contrast */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
/* transfer always has to start at x pos 0 (u8x8 is not supported) */
/* also y pos has to be 0 */
/* arg_int is ignored */
//x = ((u8x8_tile_t *)arg_ptr)->x_pos;
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
for( i = 0; i < 8; i++ )
{
u8x8_cad_StartTransfer(u8x8);
for( j = 0; j < c; j++ )
{
u8x8_cad_SendCmd(u8x8, i+1);
u8x8_cad_SendArg(u8x8, *ptr );
ptr++;
}
u8x8_cad_EndTransfer(u8x8);
}
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_max7219_32x8_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 100,
/* pre_chip_disable_wait_ns = */ 100,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100,
/* sda_setup_time_ns = */ 100,
/* sck_pulse_width_ns = */ 100,
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150,
/* tile_width = */ 4,
/* tile_hight = */ 1,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 32,
/* pixel_height = */ 8
};
uint8_t u8x8_d_max7219_32x8(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_max7219_32x8_display_info);
return 1;
}
return u8x8_d_max7219_generic(u8x8, msg, arg_int, arg_ptr);
}
/*==============================*/
static const u8x8_display_info_t u8x8_max7219_8x8_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 100,
/* pre_chip_disable_wait_ns = */ 100,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100,
/* sda_setup_time_ns = */ 100,
/* sck_pulse_width_ns = */ 100,
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150,
/* tile_width = */ 1,
/* tile_hight = */ 1,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 8,
/* pixel_height = */ 8
};
uint8_t u8x8_d_max7219_8x8(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_max7219_8x8_display_info);
return 1;
}
return u8x8_d_max7219_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,166 @@
/*
u8x8_d_pcd8544_84x48.c (so called "Nokia 5110" displays)
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_pcd8544_84x48_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x021), /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
U8X8_C(0x006), /* temp. control: b10 = 2 */
U8X8_C(0x013), /* bias system 1:48 */
U8X8_C(0x0c0), /* medium Vop */
U8X8_C(0x020), /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
U8X8_C(0x008), /* blank */
U8X8_C(0x024), /* power down (PD=1), horizontal increment (V=0), enter normal command set (H=0) */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_pcd8544_84x48_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x020), /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
U8X8_C(0x00c), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_pcd8544_84x48_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x020), /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
U8X8_C(0x008), /* blank */
U8X8_C(0x024), /* power down (PD=1), horizontal increment (V=0), enter normal command set (H=0) */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_pcd8544_84x48_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 5,
/* pre_chip_disable_wait_ns = */ 5,
/* reset_pulse_width_ms = */ 2,
/* post_reset_wait_ms = */ 2,
/* sda_setup_time_ns = */ 12,
/* sck_pulse_width_ns = */ 75, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 11, /* width of 11*8=88 pixel */
/* tile_hight = */ 6,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 84,
/* pixel_height = */ 48
};
uint8_t u8x8_d_pcd8544_84x48(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_pcd8544_84x48_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_pcd8544_84x48_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_pcd8544_84x48_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_pcd8544_84x48_powersave1_seq);
break;
// case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
// break; NOT SUPPORTED
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x021 ); /* command mode, extended function set */
u8x8_cad_SendCmd(u8x8, 0x080 | (arg_int >> 1) );
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x020 ); /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
u8x8_cad_SendCmd(u8x8, 0x080 | (x) ); /* set X address */
u8x8_cad_SendCmd(u8x8, 0x040 | (((u8x8_tile_t *)arg_ptr)->y_pos) ); /* set Y address */
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
do
{
if ( c + x > 84u )
{
if ( x >= 84u )
break;
c = 84u;
c -= x;
}
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
x += c;
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,193 @@
/*
u8x8_d_pcf8812.c
pcf8812: 65x102
pcf8814: 65x96
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_pcf8812_96x65_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x020), /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
U8X8_C(0x008), /* blank display */
U8X8_C(0x021), /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
U8X8_C(0x006), /* temp. control: b10 = 2 */
U8X8_C(0x013), /* bias system, 0x010..0x07 1:48 */
U8X8_C(0x09f), /* contrast setting, 0..127 */
//U8X8_CA(0x020 | 2, 0x080 | 0), /* contrast setting, pcf8814 */
U8X8_C(0x024), /* deactivate chip (PD=1), horizontal increment (V=0), enter normal command set (H=0) */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_pcf8812_96x65_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x020), /* power on */
U8X8_C(0x00c), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_pcf8812_96x65_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x020), /* power on */
U8X8_C(0x008), /* blank display */
U8X8_C(0x024), /* power down */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_pcf8812_96x65_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_pcf8812_96x65_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_powersave1_seq);
break;
/*
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
*/
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x021 ); /* command mode, extended function set */
u8x8_cad_SendArg(u8x8, (arg_int>>1)|0x80 ); /* 0..127 for contrast */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x020 ); /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
u8x8_cad_SendCmd(u8x8, 0x080 | x);
u8x8_cad_SendCmd(u8x8, 0x040 | ((u8x8_tile_t *)arg_ptr)->y_pos);
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
/*
do
{
u8x8_cad_SendData(u8x8, 8, ptr);
ptr += 8;
c--;
} while( c > 0 );
*/
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_pcf8812_96x65_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 100,
/* pre_chip_disable_wait_ns = */ 100,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100,
/* sda_setup_time_ns = */ 100,
/* sck_pulse_width_ns = */ 100,
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150,
/* tile_width = */ 12,
/* tile_hight = */ 9,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 96,
/* pixel_height = */ 65
};
uint8_t u8x8_d_pcf8812_96x65(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_pcf8812_96x65_display_info);
return 1;
}
return u8x8_d_pcf8812_96x65_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,198 @@
/*
u8x8_d_pcf8814_hc1230.c
pcf8814: 65x96
hx1230: 68x96
pcf8814 and hc1230 are almost identical.
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_hx1230_96x68_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x020), /* power off */
U8X8_C(0x080), /* contrast setting, 0..31, set to 0 */
U8X8_C(0x0a6), /* not inverted display */
U8X8_C(0x0a4), /* normal display mode */
U8X8_C(0x0a0), /* */
U8X8_C(0x0c0), /* */
U8X8_C(0x040), /* start at scanline 0 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_hx1230_96x68_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x02f), /* power on */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_hx1230_96x68_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a4), /* display off */
U8X8_C(0x020), /* power off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_hx1230_96x68_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* */
U8X8_C(0x0c0), /* */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_hx1230_96x68_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* */
U8X8_C(0x0c8), /* */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_hx1230_96x68_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_hx1230_96x68_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_hx1230_96x68_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_hx1230_96x68_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_hx1230_96x68_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_hx1230_96x68_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_hx1230_96x68_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, (arg_int>>3)|0x80 ); /* 0..31 for contrast */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, x&15);
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4));
u8x8_cad_SendCmd(u8x8, 0x0b0 | ((u8x8_tile_t *)arg_ptr)->y_pos);
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_hx1230_96x68_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 100,
/* pre_chip_disable_wait_ns = */ 100,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100,
/* sda_setup_time_ns = */ 100,
/* sck_pulse_width_ns = */ 100,
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150,
/* tile_width = */ 12,
/* tile_hight = */ 9,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 96,
/* pixel_height = */ 68
};
uint8_t u8x8_d_hx1230_96x68(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_hx1230_96x68_display_info);
return 1;
}
return u8x8_d_hx1230_96x68_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,217 @@
/*
u8x8_d_sbn1661.c
SED1520 / SBN1661 122x32 5V LCD
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_sbn1661_init_seq[] = {
U8X8_C(0x0c0), /* display start at line 0 */
U8X8_C(0x0a0), /* a0: ADC forward, a1: ADC reverse */
U8X8_C(0x0a4), /* a4: normal driving, a5: power save */
U8X8_C(0x0a9), /* a8: 1/16, a9: 1/32 duty */
//U8X8_C(0x0af), /* display on */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sbn1661_powersave0_seq[] = {
U8X8_C(0x0af), /* display on */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sbn1661_powersave1_seq[] = {
U8X8_C(0x0ae), /* display off */
U8X8_END() /* end of sequence */
};
struct u8x8_sbn1661_vars
{
uint8_t *ptr;
uint8_t x;
uint8_t c;
uint8_t arg_int;
};
#ifdef NOT_USED
static void u8x8_sbn1661_out(u8x8_t *u8x8, struct u8x8_sbn1661_vars *v, void *arg_ptr)
{
uint8_t cnt;
u8x8_cad_SendCmd(u8x8, 0x000 | ((v->x << 3) & 63) );
u8x8_cad_SendCmd(u8x8, 0x0b8 | (((u8x8_tile_t *)arg_ptr)->y_pos));
while( v->arg_int > 0 )
{
/* calculate tiles to next boundary (end or chip limit) */
cnt = v->x;
cnt += 8;
cnt &= 0x0f8;
cnt -= v->x;
if ( cnt > v->c )
cnt = v->c;
/* of course we still could use cnt=1 here... */
/* but setting cnt to 1 is not very efficient */
//cnt = 1;
v->x +=cnt;
v->c-=cnt;
cnt<<=3;
u8x8_cad_SendData(u8x8, cnt, v->ptr); /* note: SendData can not handle more than 255 bytes */
v->ptr += cnt;
if ( v->c == 0 )
{
v->ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
v->c = ((u8x8_tile_t *)arg_ptr)->cnt;
v->arg_int--;
}
if ( ((v->x) & 7) == 0 )
break;
}
}
#endif /* NOT_USED */
static const u8x8_display_info_t u8x8_sbn1661_122x32_display_info =
{
/* chip_enable_level = */ 0, /* sbn1661: Not used */
/* chip_disable_level = */ 1, /* sbn1661: Not used */
/* post_chip_enable_wait_ns = */ 100,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6, /* */
/* sda_setup_time_ns = */ 12,
/* sck_pulse_width_ns = */ 75, /* sbn1661: Not used */
/* sck_clock_hz = */ 4000000UL, /* sbn1661: Not used */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4, /* sbn1661: Not used */
/* data_setup_time_ns = */ 200,
/* write_pulse_width_ns = */ 200, /* */
/* tile_width = */ 16, /* width of 16*8=128 pixel */
/* tile_hight = */ 4,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 122,
/* pixel_height = */ 32
};
uint8_t u8x8_d_sbn1661_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *ptr;
//uint8_t x;
//uint8_t c;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sbn1661_122x32_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_init_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_init_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 1, NULL);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_powersave0_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_powersave0_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 1, NULL);
}
else
{
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_powersave1_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_powersave1_seq);
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 1, NULL);
}
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
// x and c are ignored (u8g2 only)
//x = ((u8x8_tile_t *)arg_ptr)->x_pos;
//c = ((u8x8_tile_t *)arg_ptr)->cnt;
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
u8x8_cad_SendCmd(u8x8, 0x000 | 0); // column 0
u8x8_cad_SendCmd(u8x8, 0x0b8 | (((u8x8_tile_t *)arg_ptr)->y_pos));
u8x8_cad_SendData(u8x8, 61, ptr); /* note: SendData can not handle more than 255 bytes */
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
ptr += 61;
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
u8x8_cad_SendCmd(u8x8, 0x000 | 0); // column 0
u8x8_cad_SendCmd(u8x8, 0x0b8 | (((u8x8_tile_t *)arg_ptr)->y_pos));
u8x8_cad_SendData(u8x8, 61, ptr); /* note: SendData can not handle more than 255 bytes */
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 1, NULL);
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_d_sed1520_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
return u8x8_d_sbn1661_122x32(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,351 @@
/*
u8x8_d_sed1330.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The device might also work with the RA8835, SED1335 and SED1336 controller.
The following devices might be compatible:
RA8835
SED1330
SED1335
S1D13700
*/
#include "u8x8.h"
static const uint8_t u8x8_d_sed1330_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x040, 0x030), /* sys init (0x040) with one arg, where 0x030 is a wild guess */
U8X8_CA(0x059, 0x004), /* send display on command (hex 0x059, see p37 ) */
/* display cmd has one arg: 01010100 should enable all three blocks, but disable the cursor*/
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sed1330_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x058, 0x000), /* send display off command (hex 0x059, see p37) and turn of all banks */
/* maybe send a sleep in cmd */
//U8X8_C(0x053) /* sleep in: 0x053 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_sed1330_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t c, i;
uint16_t y;
uint8_t *ptr;
switch(msg)
{
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
/*
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
break;
case U8X8_MSG_DISPLAY_INIT:
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y*=8;
y*= u8x8->display_info->tile_width;
u8x8_cad_StartTransfer(u8x8);
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
for( i = 0; i < 8; i++ )
{
u8x8_cad_SendCmd(u8x8, 0x046 ); /* CSRW command*/
u8x8_cad_SendArg(u8x8, y&255); /* CSRW low adr byte */
u8x8_cad_SendArg(u8x8, y>>8); /* CSRW high adr byte */
u8x8_cad_SendCmd(u8x8, 0x042 ); /* MWRITE */
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes, send one line of data */
ptr += u8x8->display_info->tile_width;
y += u8x8->display_info->tile_width;
}
/* sometimes the display switches off... so just sent a display on command */
u8x8_cad_SendCmd(u8x8, 0x059 ); /* display on */
u8x8_cad_SendArg(u8x8, 0x004); /* arg for display on */
u8x8_cad_EndTransfer(u8x8);
//u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
break;
default:
return 0;
}
return 1;
}
/*=============================================*/
static const u8x8_display_info_t u8x8_sed1330_240x128_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 30, /* G242CX Datasheet p5 */
/* pre_chip_disable_wait_ns = */ 10, /* G242CX Datasheet p5 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0,
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 120, /* G242CX Datasheet p5 */
/* write_pulse_width_ns = */ 220, /* G242CX Datasheet p5 */
/* tile_width = */ 0x01e,
/* tile_hight = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 240,
/* pixel_height = */ 128
};
/* 240x128 Seiko G242C */
static const uint8_t u8x8_d_sed1330_240x128_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(100),
/* system init command, see also u8x8_d_sed1330_powersave0_seq */
U8X8_CA(0x040, 0x030), /* sys init (0x040) with one arg, where 0x030 is a wild guess */
/* system init has total 8 parameters, so 7 more are here */
U8X8_A(0x087), /* no idea here... WF (topmost bit) is set to one because it is suggested in the datasheet, lowest 3 bits refer to text mode only */
U8X8_A(0x007), /* FY: height of a char+1, does not matter here (hopefully), because we use graphics mode only */
U8X8_A(0x01d), /* C/R: this could be the number of horizontal bytes - 1 (Value confirmed with app notes p41) */
U8X8_A(0x050), /* TC/R: According to app notes fOSC=6Mhz fFF=70Hz --> TC/R = 74d*/
U8X8_A(0x080), /* L/F: Lines per frame - 1, probably this is the height of the display - 1 (value confirmed with app notes p41)*/
U8X8_A(0x01e), /* Low byte of the virtual screen size. (Value confirmed with app notes p41) */
U8X8_A(0), /* High byte of the virtual screen size, see also section 9.1.2 */
U8X8_C(0x044), /* SCROLL */
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x080),
U8X8_A(0x000),
U8X8_A(0x040),
U8X8_A(0x080),
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_CA(0x05a, 0), /* HDOT SCR: Horizontal dotwise scroll... set to 0 */
U8X8_CA(0x05b, 0x0c), /* OVLAY: 2-layer, all graphics, OR between layer 1 and 2 */
U8X8_DLY(100),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_DLY(100),
};
/* RA8835 NHD-240128BZ */
static const uint8_t u8x8_d_rh8835_nhd_240128_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(100),
/* system init command, see also u8x8_d_sed1330_powersave0_seq */
U8X8_CA(0x040, 0x030), /* sys init (0x040) with one arg, where 0x030 is a wild guess */
/* system init has total 8 parameters, so 7 more are here */
U8X8_A(0x087), /* no idea here... WF (topmost bit) is set to one because it is suggested in the datasheet, lowest 3 bits refer to text mode only */
U8X8_A(0x007), /* FY: height of a char+1, does not matter here (hopefully), because we use graphics mode only */
U8X8_A(0x01d), /* C/R: this could be the number of horizontal bytes - 1 (Value confirmed with app notes p41) */
U8X8_A(0x050), /* TC/R: According to app notes fOSC=6Mhz fFF=70Hz --> TC/R = 74d*/
U8X8_A(0x080), /* L/F: Lines per frame - 1, probably this is the height of the display - 1 (value confirmed with app notes p41)*/
U8X8_A(0x01e), /* Low byte of the virtual screen size. (Value confirmed with app notes p41) */
U8X8_A(0), /* High byte of the virtual screen size, see also section 9.1.2 */
U8X8_C(0x044), /* SCROLL */
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x080),
U8X8_A(0x000),
U8X8_A(0x040),
U8X8_A(0x080),
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x000),
//U8X8_CA(0x05a, 0), /* HDOT SCR: Horizontal dotwise scroll... set to 0 */
U8X8_CA(0x05b, 0x0c), /* OVLAY: 2-layer, all graphics, OR between layer 1 and 2 */
//U8X8_CA(0x059, 0x04), /* send display on command (hex 0x059, see p37 ) */
U8X8_DLY(100),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_DLY(100),
};
uint8_t u8x8_d_sed1330_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sed1330_240x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_240x128_init_seq);
break;
default:
return u8x8_d_sed1330_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
uint8_t u8x8_d_ra8835_nhd_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sed1330_240x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_rh8835_nhd_240128_init_seq);
break;
default:
return u8x8_d_sed1330_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
/*=============================================*/
static const u8x8_display_info_t u8x8_sed1330_320x240_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 30, /* G242CX Datasheet p5 */
/* pre_chip_disable_wait_ns = */ 10, /* G242CX Datasheet p5 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0,
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 120, /* G242CX Datasheet p5 */
/* write_pulse_width_ns = */ 220, /* G242CX Datasheet p5 */
/* tile_width = */ 40,
/* tile_hight = */ 30,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 320,
/* pixel_height = */ 240
};
static const uint8_t u8x8_d_sed1330_320x240_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(100),
/* system init command, see also u8x8_d_sed1330_powersave0_seq */
U8X8_CA(0x040, 0x030), /* sys init (0x040) with one arg, where 0x030 is a wild guess */
/* system init has total 8 parameters, so 7 more are here */
U8X8_A(0x087), /* no idea here... WF (topmost bit) is set to one because it is suggested in the datasheet, lowest 3 bits refer to text mode only */
U8X8_A(0x007), /* FY: height of a char+1, does not matter here (hopefully), because we use graphics mode only */
U8X8_A(0x027), /* 40-1 */ /* C/R: this could be the number of horizontal bytes - 1 (Value confirmed with app notes p41) */
U8X8_A(0x039), /* TC/R: According to app notes fOSC=6Mhz fFF=70Hz --> TC/R = 74d*/
U8X8_A(0x0ef), /* L/F: Lines per frame - 1, probably this is the height of the display - 1 (value confirmed with app notes p41)*/
U8X8_A(0x028), /* Low byte of the virtual screen size. (Value confirmed with app notes p41) */
U8X8_A(0), /* High byte of the virtual screen size, see also section 9.1.2 */
U8X8_C(0x044), /* SCROLL */
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x0ef),
U8X8_A(0x0b0),
U8X8_A(0x004),
U8X8_A(0x0ef),
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_A(0x000),
U8X8_CA(0x05a, 0), /* HDOT SCR: Horizontal dotwise scroll... set to 0 */
U8X8_CA(0x05b, 0x0c), /* OVLAY: 2-layer, all graphics, OR between layer 1 and 2 */
U8X8_DLY(100),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_DLY(100),
};
uint8_t u8x8_d_ra8835_320x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sed1330_320x240_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_320x240_init_seq);
break;
default:
return u8x8_d_sed1330_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}

View File

@ -0,0 +1,215 @@
/*
u8x8_d_sh1106_64x32.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* issue 568 */
static const uint8_t u8x8_d_sh1106_64x32_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x01f), /* multiplex ratio, 0.42 OLED */
U8X8_CA(0x0d3, 0x000), /* display offset, 0.42 OLED */
U8X8_C(0x040), /* set display start line to 0, 0.42 OLED */
U8X8_CA(0xad, 0x8b), /* DC-DC ON/OFF Mode Set: Built-in DC-DC is used, Normal Display (POR = 0x8b) */
U8X8_C(0x33), /* set charge pump voltage 0x30 (POR) .. 0x33 */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1, 0.66 OLED */
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse, 0.66 OLED */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), 0.66 OLED */
U8X8_CA(0x081, 0x080), /* [2] set contrast control, 0.42 OLED datasheet: 0xcf */
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1, 0.42 OLED datasheet: 0x22 */
U8X8_CA(0x0db, 0x028), /* vcomh deselect level, 0.42 OLED datasheet: 0x00 */
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1106_64x32_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1106_64x32_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1106_64x32_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0d3, 0), /* display offset, 0.42 OLED */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1106_64x32_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0d3, 0), /* What is the correct offset in flip 1 mode? --> Issue 547 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_sh1106_64x32_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_64x32_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_64x32_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_64x32_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_64x32_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_64x32_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_64x32_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/* copied from SSD1306 */
static const u8x8_display_info_t u8x8_sh1106_64x32_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 8,
/* tile_hight = */ 4,
/* default_x_offset = */ 32,
/* flipmode_x_offset = */ 36,
/* pixel_width = */ 64,
/* pixel_height = */ 32
};
uint8_t u8x8_d_sh1106_64x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_64x32_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_64x32_init_seq);
return 1;
}
return u8x8_d_sh1106_64x32_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,216 @@
/*
u8x8_d_sh1106_72x40.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* WiseChip 0.42 OLED, issue 547 */
static const uint8_t u8x8_d_sh1106_72x40_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x027), /* multiplex ratio, 0.42 OLED */
U8X8_CA(0x0d3, 0x00c), /* display offset, 0.42 OLED */
U8X8_C(0x040), /* set display start line to 0, 0.42 OLED */
U8X8_CA(0xad, 0x8b), /* DC-DC ON/OFF Mode Set: Built-in DC-DC is used, Normal Display (POR = 0x8b) */
U8X8_C(0x33), /* set charge pump voltage 0x30 (POR) .. 0x33 */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1, 0.66 OLED */
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse, 0.66 OLED */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), 0.66 OLED */
U8X8_CA(0x081, 0x080), /* [2] set contrast control, 0.42 OLED datasheet: 0xcf */
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1, 0.42 OLED datasheet: 0x22 */
U8X8_CA(0x0db, 0x028), /* vcomh deselect level, 0.42 OLED datasheet: 0x00 */
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1106_72x40_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1106_72x40_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1106_72x40_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0d3, 12), /* display offset, 0.42 OLED */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1106_72x40_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0d3, 52), /* What is the correct offset in flip 1 mode? --> Issue 547 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_sh1106_72x40_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_72x40_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_72x40_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_72x40_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_72x40_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_72x40_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_72x40_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/* copied from SSD1306 */
static const u8x8_display_info_t u8x8_sh1106_72x40_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 9,
/* tile_hight = */ 5,
/* default_x_offset = */ 30,
/* flipmode_x_offset = */ 30,
/* pixel_width = */ 72,
/* pixel_height = */ 40
};
/* WiseChip 0.42" OLED */
uint8_t u8x8_d_sh1106_72x40_wise(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_72x40_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_72x40_init_seq);
return 1;
}
return u8x8_d_sh1106_72x40_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,399 @@
/*
u8x8_d_sh1107.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* code copyied from SSD1306 */
static const uint8_t u8x8_d_sh1107_64x128_noname_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1107_64x128_noname_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1107_64x128_noname_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1107_64x128_noname_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_sh1107_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1107_64x128_noname_display_info);
break;
*/
/* handled by the calling function
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* sh1107 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
//u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
// set column address
u8x8_cad_SendCmd(u8x8, 0x010 | (x >> 4));
u8x8_cad_SendCmd(u8x8, 0x000 | ((x & 15))); /* probably wrong, should be SendCmd */
// set page address
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos)); /* probably wrong, should be SendCmd */
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
/*
do
{
u8x8_cad_SendData(u8x8, 8, ptr);
ptr += 8;
c--;
} while( c > 0 );
*/
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*==================================================*/
/* QG-6428TSWKG01 */
static const uint8_t u8x8_d_sh1107_64x128_noname_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0dc, 0x000), /* start line */
U8X8_CA(0x081, 0x02f), /* [2] set contrast control */
U8X8_C(0x020), /* use page addressing mode */
// U8X8_C(0x0a1), /* segment remap a0/a1*/
// U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0a8, 0x7f), /* 0x03f) multiplex ratio */
U8X8_CA(0x0d3, 0x060), /* display offset */
U8X8_CA(0x0d5, 0x051), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x035), /* vcomh deselect level */
U8X8_C(0x0b0), /* set page address */
U8X8_CA(0x0da, 0x012), /* set com pins */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_sh1107_64x128_noname_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* sh1107: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* sh1107: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* sh1107: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* sh1107: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 8,
/* tile_height = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 64,
/* pixel_height = */ 128
};
uint8_t u8x8_d_sh1107_64x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_sh1107_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1107_64x128_noname_display_info);
break;
default:
return 0;
}
return 1;
}
/*==================================================*/
/* init sequence from Grove OLED 96x96 */
static const uint8_t u8x8_d_sh1107_seeed_96x96_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x050), /* clock divide ratio (0x00=1) and oscillator frequency (0x5) */
U8X8_C(0x020), /* use page addressing mode */
//U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
U8X8_CA(0x0d3, 0x000), /* display offset */
U8X8_CA(0x0dc, 0x000), /* start line */
//U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
//U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x080), /* [2] set contrast control */
U8X8_CA(0x0ad, 0x080), /* */
U8X8_CA(0x0d9, 0x01f), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x027), /* vcomh deselect level */
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
//U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_sh1107_seeed_96x96_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 100, /* cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 100, /* cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* sh1107: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 12,
/* tile_hight = */ 12,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 96,
/* pixel_height = */ 96
};
uint8_t u8x8_d_sh1107_seeed_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_sh1107_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_seeed_96x96_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1107_seeed_96x96_display_info);
break;
default:
return 0;
}
return 1;
}
/*==================================================*/
/* 128x128 OLED: this display has a very strange x offset */
/* sequence taken over from 64x128 sequence, because it seems to work mostly */
static const uint8_t u8x8_d_sh1107_128x128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0dc, 0x000), /* start line */
U8X8_CA(0x081, 0x02f), /* [2] set contrast control */
U8X8_C(0x020), /* use page addressing mode */
// U8X8_C(0x0a1), /* segment remap a0/a1*/
// U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0a8, 0x7f), /* 0x03f multiplex ratio */
//U8X8_CA(0x0d3, 0x060), /* display offset (removed, not in datasheet ) */
U8X8_CA(0x0d5, 0x050), /* clock divide ratio (0x00=1) and oscillator frequency (0x8), changed to 0x051, issue 501 */
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x035), /* vcomh deselect level */
U8X8_C(0x0b0), /* set page address */
U8X8_CA(0x0da, 0x012), /* set com pins */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_sh1107_128x128_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 100, /* cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 100, /* cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* sh1107: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,
/* tile_hight = */ 16,
/* default_x_offset = */ 96,
/* flipmode_x_offset = */ 96,
/* pixel_width = */ 128,
/* pixel_height = */ 128
};
uint8_t u8x8_d_sh1107_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_sh1107_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_128x128_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1107_128x128_display_info);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,225 @@
/*
u8x8_d_sh1108.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2018, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/*
code copyied from sh1107
SH1108: 160x160 controller from Sino Wealth
*/
static const uint8_t u8x8_d_sh1108_noname_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1108_noname_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1108_160x160_noname_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1108_160x160_noname_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_sh1108_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1108_64x128_noname_display_info);
break;
*/
/* handled by the calling function
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1108_64x128_noname_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1108_noname_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1108_noname_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1108_160x160_noname_powersave0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1108_160x160_noname_powersave1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* sh1108 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
//u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
// set column address
u8x8_cad_SendCmd(u8x8, 0x010 | (x >> 4));
u8x8_cad_SendCmd(u8x8, 0x000 | ((x & 15)));
// set page address
u8x8_cad_SendCmd(u8x8, 0x0b0 ); // page cmd is a two byte command
u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos));
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*==================================================*/
/* issue #619, 160x160 OLED */
static const uint8_t u8x8_d_sh1108_160x160_noname_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x060), /* clock divide ratio and oscillator frequency */
U8X8_CA(0x0a9, 0x003), /* set display resolution, 0=64x160, 1=96x160, 2=128x160, 3=160x160 */
U8X8_C(0x020), /* use page addressing mode */
U8X8_CA(0x081, 0x01f), /* set contrast control */
U8X8_CA(0x0ad, 0x80), /* DC/DC control 80=Use external Vpp, 89=Use internal DC/DC*/
U8X8_C(0x030), /* set discharge VSL level, 0x030..0x03f */
U8X8_CA(0x0d9, 0x028), /* pre-charge period */
U8X8_CA(0x0db, 0x035), /* vcomh deselect level */
U8X8_CA(0x0dc, 0x035), /* VSEGM Deselect Level */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_sh1108_160x160_noname_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 60,
/* pre_chip_disable_wait_ns = */ 120,
/* reset_pulse_width_ms = */ 100, /* sh1108: 3 us */
/* post_reset_wait_ms = */ 100, /* sometimes OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 100, /* sh1108: 100ns */
/* sck_pulse_width_ns = */ 100, /* sh1108: 100ns */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* sh1108: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 20,
/* tile_height = */ 20,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 160,
/* pixel_height = */ 160
};
uint8_t u8x8_d_sh1108_160x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_sh1108_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1108_160x160_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1108_160x160_noname_display_info);
break;
default:
return 0;
}
return 1;
}
/*==================================================*/

View File

@ -0,0 +1,287 @@
/*
u8x8_d_sh1122.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copied from sh1122 mostly because of the similar RAM architecture.
However: Commands are very different!
*/
#include "u8x8.h"
static const uint8_t u8x8_d_sh1122_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* sh1122: display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1122_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* sh1122: display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/*
input:
one tile (8 Bytes)
output:
Tile for SH1122 (32 Bytes)
*/
/*
static uint8_t u8x8_sh1122_to32_dest_buf[32];
static uint8_t *u8x8_sh1122_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
{
uint8_t v;
uint8_t a,b;
uint8_t i, j;
uint8_t *dest;
for( j = 0; j < 4; j++ )
{
dest = u8x8_sh1122_to32_dest_buf;
dest += j;
a =*ptr;
ptr++;
b = *ptr;
ptr++;
for( i = 0; i < 8; i++ )
{
v = 0;
if ( a&1 ) v |= 0xf0;
if ( b&1 ) v |= 0x0f;
*dest = v;
dest+=4;
a >>= 1;
b >>= 1;
}
}
return u8x8_sh1122_to32_dest_buf;
}
*/
static uint8_t u8x8_write_byte_to_16gr_device(u8x8_t *u8x8, uint8_t b)
{
static uint8_t buf[4];
static uint8_t map[4] = { 0, 0x00f, 0x0f0, 0x0ff };
buf [3] = map[b & 3];
b>>=2;
buf [2] = map[b & 3];
b>>=2;
buf [1] = map[b & 3];
b>>=2;
buf [0] = map[b & 3];
return u8x8_cad_SendData(u8x8, 4, buf);
}
uint8_t u8x8_d_sh1122_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x;
uint8_t y, c, i;
uint8_t *ptr;
switch(msg)
{
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
/*
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1122_256x64_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1122_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1122_powersave1_seq);
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* sh1122 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 2; // only every 4th col can be addressed
x += u8x8->x_offset;
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y *= 8;
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
for( i = 0; i < 8; i++ )
{
u8x8_cad_SendCmd(u8x8, 0x0b0 ); /* set row address */
u8x8_cad_SendArg(u8x8, y);
u8x8_cad_SendCmd(u8x8, x & 15 ); /* lower 4 bit*/
u8x8_cad_SendCmd(u8x8, 0x010 | (x >> 4) ); /* higher 3 bit */
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
while ( c > 0 )
{
u8x8_write_byte_to_16gr_device(u8x8, *ptr);
c--;
ptr++;
}
y++;
}
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*=========================================================*/
static const uint8_t u8x8_d_sh1122_256x64_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* remap */
U8X8_C(0x0c8), /* remap */
U8X8_C(0x060),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_sh1122_256x64_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* remap */
U8X8_C(0x0c0), /* remap */
U8X8_C(0x040),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_sh1122_256x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 10, /* sh1122: 10 us */
/* post_reset_wait_ms = */ 20, /* */
/* sda_setup_time_ns = */ 125, /* sh1122: cycle time is 250ns, so use 250/2 */
/* sck_pulse_width_ns = */ 125, /* sh1122: cycle time is 250ns, so use 250/2 */
/* sck_clock_hz = */ 40000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 10,
/* write_pulse_width_ns = */ 150, /* sh1122: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 32, /* 256 pixel, so we require 32 bytes for this */
/* tile_hight = */ 8,
/* default_x_offset = */ 0, /* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 256,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_sh1122_256x64_init_seq[] = {
U8X8_DLY(1),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(1),
U8X8_C(0xae), /* display off */
U8X8_C(0x40), /* display start line */
U8X8_C(0x0a0), /* remap */
U8X8_C(0x0c0), /* remap */
U8X8_CA(0x81, 0x80), /* set display contrast */
U8X8_CA(0xa8, 0x3f), /* multiplex ratio 1/64 Duty (0x0F~0x3F) */
U8X8_CA(0xad, 0x81), /* use buildin DC-DC with 0.6 * 500 kHz */
U8X8_CA(0xd5, 0x50), /* set display clock divide ratio (lower 4 bit)/oscillator frequency (upper 4 bit) */
U8X8_CA(0xd3, 0x00), /* display offset, shift mapping ram counter */
U8X8_CA(0xd9, 0x22), /* pre charge (lower 4 bit) and discharge(higher 4 bit) period */
U8X8_CA(0xdb, 0x35), /* VCOM deselect level */
U8X8_CA(0xdc, 0x35), /* Pre Charge output voltage */
U8X8_C(0x030), /* discharge level */
U8X8_DLY(1), /* delay */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_sh1122_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1122_256x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1122_256x64_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1122_256x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1122_256x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
default:
return u8x8_d_sh1122_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}

View File

@ -0,0 +1,323 @@
/*
u8x8_d_ssd1305.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_ssd1305_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1305_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1305_128x32_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0d3, 32), /* display offset to 32 */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1305_128x32_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0d3, 0), /* display offset to */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ssd1305_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendArg(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendArg(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos) );
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
/*
do
{
u8x8_cad_SendData(u8x8, 8, ptr);
ptr += 8;
c--;
} while( c > 0 );
*/
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_powersave1_seq);
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1305 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
default:
return 0;
}
return 1;
}
/* timing from SSD1306 */
static const u8x8_display_info_t u8x8_ssd1305_128x32_noname_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,
/* tile_hight = */ 4,
/* default_x_offset = */ 2,
/* flipmode_x_offset = */ 2,
/* pixel_width = */ 128,
/* pixel_height = */ 32
};
static const uint8_t u8x8_d_ssd1305_128x32_noname_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
U8X8_CA(0x0d3, 32), /* display offset to 32 */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control */
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1305_128x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1305_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1305_128x32_noname_display_info);
break;
default:
return 0;
}
return 1;
}
/*================================================*/
/* adafruit SSD1305 OLED */
/* timing from SSD1306 */
static const u8x8_display_info_t u8x8_ssd1305_128x64_adafruit_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 2,
/* flipmode_x_offset = */ 2,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_ssd1305_128x64_adafruit_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x0f0), /* clock divide ratio (0x00=1) and oscillator frequency */
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
U8X8_CA(0x0d3, 0x040), /* display offset to 32 */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x032), /* [2] set contrast control */
U8X8_CA(0x082, 0x080), /* set area brightness (reset=0x080) */
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1305_128x64_adafruit(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1305_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x64_adafruit_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1305_128x64_adafruit_display_info);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,214 @@
/*
u8x8_d_ssd1306_128x32.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* UG-2832HSWEG02 Datasheet, Section 4.4 */
static const uint8_t u8x8_d_ssd1306_128x32_univision_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x01f), /* multiplex ratio */
U8X8_CA(0x0d3, 0x000), /* display offset */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x002), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x08f), /* [2] set contrast control */
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x32_univision_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x32_univision_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x32_univision_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x32_univision_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ssd1306_128x32_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x32_univision_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
/*
do
{
u8x8_cad_SendData(u8x8, 8, ptr);
ptr += 8;
c--;
} while( c > 0 );
*/
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ssd1306_128x32_univision_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,
/* tile_hight = */ 4,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 32
};
uint8_t u8x8_d_ssd1306_128x32_univision(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x32_univision_display_info);
return 1;
}
return u8x8_d_ssd1306_128x32_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,465 @@
/*
u8x8_d_ssd1306_128x64_noname.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* more or less generic setup of all these small OLEDs */
static const uint8_t u8x8_d_ssd1306_128x64_noname_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
U8X8_CA(0x0d3, 0x000), /* display offset */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, SSD1306 only, should be removed for SH1106 */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control */
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* this setup maximizes the brightness range, that can be set with setContrast() */
/* Drawback: VCOMH deselect level is set to 0, which das not work so good with all OLEDs, issue #116 */
static const uint8_t u8x8_d_ssd1306_128x64_vcomh0_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
U8X8_CA(0x0d3, 0x000), /* display offset */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x0ef), /* [2] set contrast control, */
U8X8_CA(0x0d9, 0x0a1), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x000), /* vcomh deselect level 0x000 .. 0x070, low nibble always 0 */
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* same as u8x8_d_ssd1306_128x64_noname_init_seq, but 0x0da bit 4 is set to 0 */
/* this will disable the alternative COM configuration */
static const uint8_t u8x8_d_ssd1306_128x64_alt0_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
U8X8_CA(0x0d3, 0x000), /* display offset */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, SSD1306 only, should be removed for SH1106 */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x002), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control */
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* issue 316: a special sh1106 setup, https://www.mikrocontroller.net/topic/431371?goto=5087807#5087807 */
static const uint8_t u8x8_d_sh1106_128x64_winstar_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0xae), // Display OFF/ON: off (POR = 0xae)
U8X8_C(0xa4), // Set Entire Display OFF/ON: off (POR = 0xa4)
U8X8_CA(0xd5, 0x50), // Divide Ratio/Oscillator FrequencyData Set: divide ratio = 1 (POR = 1), Oscillator Frequency = +/- 0% (POR = +/- 0%)
U8X8_CA(0xa8, 0x3f), // Multiplex Ratio Data Set: 64 (POR = 0x3f, 64)
U8X8_CA(0xd3, 0x00), // Display OffsetData Set: 0 (POR = 0x00)
U8X8_C(0x40), // Set Display Start Line: 0
U8X8_CA(0xad, 0x8b), // DC-DC ON/OFF Mode Set: Built-in DC-DC is used, Normal Display (POR = 0x8b)
U8X8_CA(0xd9, 0x22), // Dis-charge/Pre-charge PeriodData Set: pre-charge 2 DCLKs, dis-charge 2 DCLKs (POR = 0x22, pre-charge 2 DCLKs, dis-charge 2 DCLKs)
U8X8_CA(0xdb, 0x35), // VCOM Deselect LevelData Set: 0,770V (POR = 0x35, 0,770 V)
U8X8_C(0x32), // Set Pump voltage value: 8,0 V (POR = 0x32, 8,0 V)
U8X8_CA(0x81, 0xff), // Contrast Data Register Set: 255 (large) (POR = 0x80)
U8X8_C(0x0a6), // Set Normal/Reverse Display: normal (POR = 0xa6)
U8X8_CA(0x0da, 0x012), // com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5)
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x64_noname_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x64_noname_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x64_noname_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_128x64_noname_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ssd1306_sh1106_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
break;
*/
/* handled by the calling function
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendArg(u8x8, 0x000 | ((x&15))); /* probably wrong, should be SendCmd */
u8x8_cad_SendArg(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos)); /* probably wrong, should be SendCmd */
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
/*
do
{
u8x8_cad_SendData(u8x8, 8, ptr);
ptr += 8;
c--;
} while( c > 0 );
*/
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ssd1306_128x64_noname_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* ==> i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
uint8_t u8x8_d_ssd1306_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_d_ssd1306_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_vcomh0_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_d_ssd1306_128x64_alt0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_alt0_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_sh1106_128x64_noname_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
/* spi_mode = */ 3, /* active low (clock is high by default), rising edge, this seems to be a difference to the ssd1306 */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 2,
/* flipmode_x_offset = */ 2,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
uint8_t u8x8_d_sh1106_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
/* maybe use a better init sequence */
/* https://www.mikrocontroller.net/topic/431371 */
/* the new sequence is added in the winstar constructor (see below), this is kept untouched */
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_128x64_noname_display_info);
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_d_sh1106_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_vcomh0_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_128x64_noname_display_info);
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_d_sh1106_128x64_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_128x64_winstar_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_128x64_noname_display_info);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,215 @@
/*
u8x8_d_ssd1306_48x64_winstar.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* Winstar 0.71 OLED */
static const uint8_t u8x8_d_ssd1306_48x64_winstar_init_seq[] =
{
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio, 0.71 OLED: changed from 0x2f to 0x3f */
U8X8_CA(0x0d3, 0x000), /* display offset, 0.71 OLED */
U8X8_C(0x040), /* set display start line to 0, 0.71 OLED */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, 0.71 OLED 0x14*/
/// according to the datasheet, 0x00 is NOT page addressing mode, but horizontal addressing mode;
/// so it looks like u8g2 expects horizontal addressing (and the inline comment is wrong) while the Winstar example
/// actually uses page addressing (which is the reset default)
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1, 0.71 OLED */
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse, 0.71 OLED */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), 0.71 OLED */
U8X8_CA(0x081, 0x07f), /* [2] set contrast control, 0.71 OLED datasheet: 0x7f */
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1, 0.71 OLED datasheet: 0x22 */
U8X8_CA(0x0db, 0x040), /* vcomh deselect level, 0.71 OLED datasheet: 0x40 */
// U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_48x64_powersave0_seq[] =
{
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_48x64_powersave1_seq[] =
{
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_48x64_flip0_seq[] =
{
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_48x64_flip1_seq[] =
{
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ssd1306_48x64_generic(u8x8_t *u8x8, uint8_t msg,
uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch (msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_48x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_48x64_winstar_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if (arg_int == 0)
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_48x64_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_48x64_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if (arg_int == 0)
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_48x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_48x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081);
u8x8_cad_SendArg(u8x8, arg_int); /* ssd1306 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *) arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x >> 4));
u8x8_cad_SendCmd(u8x8, 0x000 | ((x & 15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *) arg_ptr)->y_pos));
do
{
c = ((u8x8_tile_t *) arg_ptr)->cnt;
ptr = ((u8x8_tile_t *) arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c * 8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while (arg_int > 0);
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ssd1306_48x64_display_info =
{
/* chip_enable_level = */0,
/* chip_disable_level = */1,
/* post_chip_enable_wait_ns = */20,
/* pre_chip_disable_wait_ns = */10,
/* reset_pulse_width_ms = */100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
/* spi_mode = */0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */4,
/* data_setup_time_ns = */40,
/* write_pulse_width_ns = */150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */6,
/* tile_height = */8,
/* default_x_offset = */40,
/* flipmode_x_offset = */40,
/* pixel_width = */48,
/* pixel_height = */64 };
/* Winstar 0.71" OLED */
uint8_t u8x8_d_ssd1306_48x64_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
void *arg_ptr)
{
if (msg == U8X8_MSG_DISPLAY_SETUP_MEMORY)
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_48x64_display_info);
return 1;
}
else if (msg == U8X8_MSG_DISPLAY_INIT)
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_48x64_winstar_init_seq);
return 1;
}
return u8x8_d_ssd1306_48x64_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,258 @@
/*
u8x8_d_ssd1306_64x32.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_ssd1306_64x32_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_64x32_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_64x32_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_64x32_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ssd1306_64x32_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x32_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_noname_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*======================================================*/
static const u8x8_display_info_t u8x8_ssd1306_64x32_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 8,
/* tile_hight = */ 4,
/* default_x_offset = */ 32,
/* flipmode_x_offset = */ 32,
/* pixel_width = */ 64,
/* pixel_height = */ 32
};
/*======================================================*/
static const uint8_t u8x8_d_ssd1306_64x32_noname_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x02f), /* multiplex ratio: changed from 0x1f to 0x2f */
U8X8_CA(0x0d3, 0x000), /* display offset */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1 */
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control datasheet: 0xcf */
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1 */
U8X8_CA(0x0db, 0x000), /* vcomh deselect level */
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1306_64x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x32_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_noname_init_seq);
return 1;
}
return u8x8_d_ssd1306_64x32_generic(u8x8, msg, arg_int, arg_ptr);
}
/*======================================================*/
static const uint8_t u8x8_d_ssd1306_64x32_1f_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x01f), /* multiplex ratio: changed from 0x1f to 0x2f, 23 Sep 17: changed back to 1f */
U8X8_CA(0x0d3, 0x000), /* display offset */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1 */
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control datasheet: 0xcf */
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1 */
U8X8_CA(0x0db, 0x000), /* vcomh deselect level */
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1306_64x32_1f(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x32_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_1f_init_seq);
return 1;
}
return u8x8_d_ssd1306_64x32_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,213 @@
/*
u8x8_d_ssd1306_64x48.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* EastRising 0.66 OLED */
static const uint8_t u8x8_d_ssd1306_64x48_er_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x02f), /* multiplex ratio, 0.66 OLED: changed from 0x1f to 0x2f */
U8X8_CA(0x0d3, 0x000), /* display offset, 0.66 OLED */
U8X8_C(0x040), /* set display start line to 0, 0.66 OLED */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, 0.66 OLED 0x14*/
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1, 0.66 OLED */
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse, 0.66 OLED */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), 0.66 OLED */
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control, 0.66 OLED datasheet: 0xcf */
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1, 0.66 OLED datasheet: 0x22 */
U8X8_CA(0x0db, 0x000), /* vcomh deselect level, 0.66 OLED datasheet: 0x00 */
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_64x48_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_64x48_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_64x48_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_64x48_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ssd1306_64x48_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x48_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_er_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ssd1306_64x48_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 8,
/* tile_hight = */ 6,
/* default_x_offset = */ 32,
/* flipmode_x_offset = */ 32,
/* pixel_width = */ 64,
/* pixel_height = */ 48
};
/* East Rising 0.66" OLED */
uint8_t u8x8_d_ssd1306_64x48_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x48_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_er_init_seq);
return 1;
}
return u8x8_d_ssd1306_64x48_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,213 @@
/*
u8x8_d_ssd1306_96x16.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* EastRising 0.69 OLED */
static const uint8_t u8x8_d_ssd1306_96x16_er_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
U8X8_CA(0x0a8, 0x00f), /* multiplex ratio, 0.69 OLED: 0x0f */
U8X8_CA(0x0d3, 0x000), /* display offset, 0.69 OLED */
U8X8_C(0x040), /* set display start line to 0, 0.69 OLED */
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, 0.66 OLED 0x14*/
U8X8_CA(0x020, 0x000), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1, 0.66 OLED */
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse, 0.66 OLED */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x002), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), 0.66 OLED */
U8X8_CA(0x081, 0x0af), /* [2] set contrast control, 0.69 OLED datasheet: 0xaf */
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x0f1, 0.69 OLED datasheet: 0xf1 */
U8X8_CA(0x0db, 0x020), /* vcomh deselect level, 0.69 OLED datasheet: 0x20 */
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_96x16_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_96x16_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_96x16_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1306_96x16_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ssd1306_96x16_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_96x16_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_er_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ssd1306_96x16_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 12,
/* tile_hight = */ 2,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 32,
/* pixel_width = */ 96,
/* pixel_height = */ 16
};
/* East Rising 0.69" OLED */
uint8_t u8x8_d_ssd1306_96x16_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_96x16_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_er_init_seq);
return 1;
}
return u8x8_d_ssd1306_96x16_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,287 @@
/*
u8x8_d_ssd1309.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_ssd1309_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1309_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1309_128x64_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1309_128x64_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_ssd1309_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendArg(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendArg(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos) );
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
/*
do
{
u8x8_cad_SendData(u8x8, 8, ptr);
ptr += 8;
c--;
} while( c > 0 );
*/
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_powersave1_seq);
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1309 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
default:
return 0;
}
return 1;
}
/*=================================================*/
/* offset 2 version */
/* timing from SSD1306 */
static const u8x8_display_info_t u8x8_ssd1309_128x64_noname2_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 2,
/* flipmode_x_offset = */ 2,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_ssd1309_128x64_noname_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0d5, 0x0a0), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
//U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_CA(0x020, 0x002), /* page addressing mode */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
// Flipmode
// U8X8_C(0x0a0), /* segment remap a0/a1*/
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
U8X8_CA(0x081, 0x06f), /* [2] set contrast control */
U8X8_CA(0x0d9, 0x0d3), /* [2] pre-charge period 0x022/f1*/
U8X8_CA(0x0db, 0x020), /* vcomh deselect level */
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
U8X8_C(0x02e), /* Deactivate scroll */
U8X8_C(0x0a4), /* output ram to display */
U8X8_C(0x0a6), /* none inverted normal display mode */
//U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1309_128x64_noname2(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1309_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1309_128x64_noname2_display_info);
break;
default:
return 0;
}
return 1;
}
/*=================================================*/
/* offset 0 version */
/* timing from SSD1306 */
static const u8x8_display_info_t u8x8_ssd1309_128x64_noname0_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
uint8_t u8x8_d_ssd1309_128x64_noname0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1309_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
switch(msg)
{
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1309_128x64_noname0_display_info);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,530 @@
/*
u8x8_d_ssd1322.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_ssd1322_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* ssd1322: display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1322_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* ssd1322: display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* interpret b as a monochrome bit pattern, write value 15 for high bit and value 0 for a low bit */
/* topbit (msb) is sent last */
/* example: b = 0x083 will send 0xff, 0x00, 0x00, 0xf0 */
/* 4 Jan 2017: I think this procedure not required any more. Delete? */
/*
static uint8_t u8x8_write_byte_to_16gr_device(u8x8_t *u8x8, uint8_t b)
{
static uint8_t buf[4];
static uint8_t map[4] = { 0, 0x00f, 0x0f0, 0x0ff };
buf [3] = map[b & 3];
b>>=2;
buf [2] = map[b & 3];
b>>=2;
buf [1] = map[b & 3];
b>>=2;
buf [0] = map[b & 3];
return u8x8_cad_SendData(u8x8, 4, buf);
}
*/
/*
input:
one tile (8 Bytes)
output:
Tile for SSD1325 (32 Bytes)
*/
static uint8_t u8x8_ssd1322_to32_dest_buf[32];
static uint8_t *u8x8_ssd1322_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
{
uint8_t v;
uint8_t a,b;
uint8_t i, j;
uint8_t *dest;
for( j = 0; j < 4; j++ )
{
dest = u8x8_ssd1322_to32_dest_buf;
dest += j;
a =*ptr;
ptr++;
b = *ptr;
ptr++;
for( i = 0; i < 8; i++ )
{
v = 0;
if ( a&1 ) v |= 0xf0;
if ( b&1 ) v |= 0x0f;
*dest = v;
dest+=4;
a >>= 1;
b >>= 1;
}
}
return u8x8_ssd1322_to32_dest_buf;
}
static uint8_t *u8x8_ssd1322_4to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
{
uint8_t v;
uint8_t a;
uint8_t i, j;
uint8_t *dest;
for( j = 0; j < 4; j++ )
{
dest = u8x8_ssd1322_to32_dest_buf;
dest += j;
a =*ptr;
ptr++;
for( i = 0; i < 8; i++ )
{
v = 0;
if ( a&1 ) v = 0xff;
*dest = v;
dest+=4;
a >>= 1;
}
}
return u8x8_ssd1322_to32_dest_buf;
}
uint8_t u8x8_d_ssd1322_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x;
uint8_t y, c;
uint8_t *ptr;
switch(msg)
{
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
/*
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_powersave1_seq);
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x0C1 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1322 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 2; // only every 4th col can be addressed
x += u8x8->x_offset;
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y *= 8;
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address, moved out of the loop (issue 302) */
u8x8_cad_SendArg(u8x8, y);
u8x8_cad_SendArg(u8x8, y+7);
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
u8x8_cad_SendArg(u8x8, x ); /* start */
u8x8_cad_SendArg(u8x8, x+1 ); /* end */
u8x8_cad_SendCmd(u8x8, 0x05c ); /* write to ram */
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1322_8to32(u8x8, ptr));
ptr += 8;
x += 2;
c--;
} while( c > 0 );
//x += 2;
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*=========================================================*/
static const uint8_t u8x8_d_ssd1322_256x64_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CAA(0x0a0, 0x006, 0x011), /* remap */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1322_256x64_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CAA(0x0a0, 0x014, 0x011), /* remap */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_ssd1322_256x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1322: 2 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1322: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1322: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 10000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215), 10 MHz (issue 301) */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 10,
/* write_pulse_width_ns = */ 150, /* SSD1322: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 32, /* 256 pixel, so we require 32 bytes for this */
/* tile_hight = */ 8,
/* default_x_offset = */ 0x01c, /* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
/* flipmode_x_offset = */ 0x01c,
/* pixel_width = */ 256,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_ssd1322_256x64_init_seq[] = {
U8X8_DLY(1),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(1),
U8X8_CA(0xfd, 0x12), /* unlock */
U8X8_C(0xae), /* display off */
U8X8_CA(0xb3, 0x91), /* set display clock divide ratio/oscillator frequency (set clock as 80 frames/sec) */
U8X8_CA(0xca, 0x3f), /* multiplex ratio 1/64 Duty (0x0F~0x3F) */
U8X8_CA(0xa2, 0x00), /* display offset, shift mapping ram counter */
U8X8_CA(0xa1, 0x00), /* display start line */
//U8X8_CAA(0xa0, 0x14, 0x11), /* Set Re-Map / Dual COM Line Mode */
U8X8_CAA(0xa0, 0x06, 0x011), /* Set Re-Map / Dual COM Line Mode */
U8X8_CA(0xab, 0x01), /* Enable Internal VDD Regulator */
U8X8_CAA(0xb4, 0xa0, 0x005|0x0fd), /* Display Enhancement A */
U8X8_CA(0xc1, 0x9f), /* contrast */
U8X8_CA(0xc7, 0x0f), /* Set Scale Factor of Segment Output Current Control */
U8X8_C(0xb9), /* linear grayscale */
U8X8_CA(0xb1, 0xe2), /* Phase 1 (Reset) & Phase 2 (Pre-Charge) Period Adjustment */
U8X8_CAA(0xd1, 0x082|0x020, 0x020), /* Display Enhancement B */
U8X8_CA(0xbb, 0x1f), /* precharge voltage */
U8X8_CA(0xb6, 0x08), /* precharge period */
U8X8_CA(0xbe, 0x07), /* vcomh */
U8X8_C(0xa6), /* normal display */
U8X8_C(0xa9), /* exit partial display */
U8X8_DLY(1), /* delay 2ms */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1322_nhd_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1322_256x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
default:
return u8x8_d_ssd1322_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
/*=========================================================*/
/*
NHD-2.7-12864WDW3-M
http://www.newhavendisplay.com/nhd2712864wdw3m-p-9546.html
http://www.newhavendisplay.com/specs/NHD-2.7-12864WDW3-M.pdf
It looks like that only every second pixel is connected to the OLED
*/
uint8_t u8x8_d_ssd1322_common2(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x;
uint8_t y, c;
uint8_t *ptr;
switch(msg)
{
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
/*
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_powersave1_seq);
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x0C1 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1322 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 2; // only every 4th col can be addressed
x *= 2; // only every second pixel is used in the 128x64 NHD OLED
x += u8x8->x_offset;
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y *= 8;
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address, moved out of the loop (issue 302) */
u8x8_cad_SendArg(u8x8, y);
u8x8_cad_SendArg(u8x8, y+7);
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
u8x8_cad_SendArg(u8x8, x ); /* start */
u8x8_cad_SendArg(u8x8, x+1 ); /* end */
u8x8_cad_SendCmd(u8x8, 0x05c ); /* write to ram */
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1322_4to32(u8x8, ptr));
ptr += 4;
x += 2;
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
u8x8_cad_SendArg(u8x8, x ); /* start */
u8x8_cad_SendArg(u8x8, x+1 ); /* end */
u8x8_cad_SendCmd(u8x8, 0x05c ); /* write to ram */
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1322_4to32(u8x8, ptr));
ptr += 4;
x += 2;
c--;
} while( c > 0 );
//x += 2;
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const uint8_t u8x8_d_ssd1322_128x64_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CAA(0x0a0, 0x016, 0x011), /* remap */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1322_128x64_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CAA(0x0a0, 0x004, 0x011), /* remap */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_ssd1322_128x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100, /* SSD1322: 2 us */
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
/* sda_setup_time_ns = */ 50, /* SSD1322: 15ns, but cycle time is 100ns, so use 100/2 */
/* sck_pulse_width_ns = */ 50, /* SSD1322: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 10000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215), 10 MHz (issue 301) */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 10,
/* write_pulse_width_ns = */ 150, /* SSD1322: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16, /* 128 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 28, /* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
/* flipmode_x_offset = */ 28,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_ssd1322_128x64_init_seq[] = {
U8X8_DLY(1),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(1),
U8X8_CA(0xfd, 0x12), /* unlock */
U8X8_C(0xae), /* display off */
U8X8_CA(0xb3, 0x91), /* set display clock divide ratio/oscillator frequency (set clock as 80 frames/sec) */
U8X8_CA(0xca, 0x3f), /* multiplex ratio 1/64 Duty (0x0F~0x3F) */
U8X8_CA(0xa2, 0x00), /* display offset, shift mapping ram counter */
U8X8_CA(0xa1, 0x00), /* display start line */
U8X8_CA(0xab, 0x01), /* Enable Internal VDD Regulator */
//U8X8_CAA(0xa0, 0x14, 0x11), /* Set Re-Map / Dual COM Line Mode */
//U8X8_CAA(0xa0, 0x06, 0x011), /* Set Re-Map / Dual COM Line Mode */
U8X8_CAA(0xa0, 0x16, 0x011), /* Set Re-Map / Dual COM Line Mode (NHD-2.7-12864WDW3-M datasheet) */
U8X8_CA(0xc7, 0x0f), /* Set Scale Factor of Segment Output Current Control */
U8X8_CA(0xc1, 0x9f), /* contrast */
//U8X8_CA(0xb1, 0xe2), /* Phase 1 (Reset) & Phase 2 (Pre-Charge) Period Adjustment */
U8X8_CA(0xb1, 0xf2), /* Phase 1 (Reset) & Phase 2 (Pre-Charge) Period Adjustment (NHD-2.7-12864WDW3-M datasheet) */
U8X8_CA(0xbb, 0x1f), /* precharge voltage */
//U8X8_CAA(0xb4, 0xa0, 0x005|0x0fd), /* Display Enhancement A */
U8X8_CAA(0xb4, 0xa0, 0x0fd), /* Display Enhancement A (NHD-2.7-12864WDW3-M datasheet) */
U8X8_CA(0xbe, 0x04), /* vcomh (NHD-2.7-12864WDW3-M datasheet) */
U8X8_C(0xb9), /* linear grayscale */
//U8X8_CAA(0xd1, 0x082|0x020, 0x020), /* Display Enhancement B */
//U8X8_CA(0xb6, 0x08), /* precharge period */
U8X8_C(0xa6), /* normal display */
U8X8_C(0xa9), /* exit partial display */
U8X8_DLY(1), /* delay 2ms */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1322_nhd_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1322_128x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_128x64_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_128x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_128x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
default:
return u8x8_d_ssd1322_common2(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}

View File

@ -0,0 +1,287 @@
/*
u8x8_d_ssd1325.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* http://www.newhavendisplay.com/app_notes/OLED_2_7_12864.txt */
static const uint8_t u8x8_d_ssd1325_128x64_nhd_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio: 0x03f * 1/64 duty */
U8X8_CA(0x0a2, 0x04c), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a1, 0x000), /* display start line */
U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
U8X8_CA(0x0a0, 0x052), /* remap configuration, horizontal address increment (bit 2 = 0), enable nibble remap (upper nibble is left, bit 1 = 1) */
U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
U8X8_C(0x0b8), /* set gray scale table */
U8X8_A(0x001), /* */
U8X8_A(0x011), /* */
U8X8_A(0x022), /* */
U8X8_A(0x032), /* */
U8X8_A(0x043), /* */
U8X8_A(0x054), /* */
U8X8_A(0x065), /* */
U8X8_A(0x076), /* */
U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128, Newhaven: 0x040 */
U8X8_CA(0x0b2, 0x051), /* frame frequency (row period) */
U8X8_CA(0x0b1, 0x055), /* phase length */
U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
U8X8_CA(0x0b4, 0x002), /* set pre-charge compensation level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
U8X8_CA(0x0b0, 0x028), /* enable pre-charge compensation (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
U8X8_CA(0x0bf, 0x002|0x00d), /* VSL voltage level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
U8X8_C(0x0a4), /* normal display mode */
U8X8_CA(0x023, 0x003), /* graphics accelleration: fill pixel */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1325_128x64_nhd_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1325_128x64_nhd_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1325_128x64_nhd_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a0, 0x052), /* remap */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1325_128x64_nhd_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a0, 0x041), /* remap */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/*
input:
one tile (8 Bytes)
output:
Tile for SSD1325 (32 Bytes)
*/
static uint8_t u8x8_ssd1325_8to32_dest_buf[32];
static uint8_t *u8x8_ssd1325_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
{
uint8_t v;
uint8_t a,b;
uint8_t i, j;
uint8_t *dest;
for( j = 0; j < 4; j++ )
{
dest = u8x8_ssd1325_8to32_dest_buf;
dest += j;
a =*ptr;
ptr++;
b = *ptr;
ptr++;
for( i = 0; i < 8; i++ )
{
v = 0;
if ( a&1 ) v |= 0xf0;
if ( b&1 ) v |= 0x0f;
*dest = v;
dest+=4;
a >>= 1;
b >>= 1;
}
}
return u8x8_ssd1325_8to32_dest_buf;
}
static uint8_t u8x8_d_ssd1325_128x64_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1325_128x64_nhd_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1325 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 4;
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y *= 8;
y += u8x8->x_offset; /* x_offset is used as y offset for the SSD1325 */
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address */
u8x8_cad_SendArg(u8x8, y);
u8x8_cad_SendArg(u8x8, y+7);
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
if ( ptr[0] | ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5] | ptr[6] | ptr[7] )
{
/* draw the tile if pattern is not zero for all bytes */
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
u8x8_cad_SendArg(u8x8, x ); /* start */
u8x8_cad_SendArg(u8x8, x+3 ); /* end */
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1325_8to32(u8x8, ptr));
}
else
{
/* tile is empty, use the graphics acceleration command */
u8x8_cad_SendCmd(u8x8, 0x024 ); // draw rectangle
u8x8_cad_SendArg(u8x8, x );
u8x8_cad_SendArg(u8x8, y );
u8x8_cad_SendArg(u8x8, x+3 );
u8x8_cad_SendArg(u8x8, y+7 );
u8x8_cad_SendArg(u8x8, 0 ); // clear
}
ptr += 8;
x += 4;
c--;
} while( c > 0 );
//x += 4;
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_nhd_ssd1325_128x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100, /**/
/* sda_setup_time_ns = */ 100, /* SSD1325 */
/* sck_pulse_width_ns = */ 100, /* SSD1325 */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 60, /* SSD1325 */
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 0, /* x_offset is used as y offset for the SSD1325 */
/* flipmode_x_offset = */ 8, /* x_offset is used as y offset for the SSD1325 */
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
uint8_t u8x8_d_ssd1325_nhd_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_nhd_ssd1325_128x64_display_info);
return 1;
}
return u8x8_d_ssd1325_128x64_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,277 @@
/*
u8x8_d_ssd1326.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* ER OLED */
static const uint8_t u8x8_d_ssd1326_er_256x32_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0fd, 0x012), /* unlock (not required, this is default by reset) */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0a8, 0x01f), /* multiplex ratio: 0x03f * 1/64 duty - changed by CREESOO, acc. to datasheet, 100317*/
U8X8_CA(0x0a1, 0x000), /* display start line */
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
/*
a0 command: 0x0a0 ***abcde
a: 1: mono mode
b: 0: horizontal (1: vertical) address increment
c: 1: enable bit remap
d: 1: COM remap
e: 1: Column remap
*/
U8X8_CA(0x0a0, 0x006), /* remap configuration, see above */
U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
U8X8_C(0x0b7), /* set default gray scale table */
U8X8_CA(0x081, 0x027), /* contrast, brightness, 0..128 */
U8X8_CA(0x0b1, 0x071), /* phase length */
//U8X8_CA(0x0b2, 0x051), /* frame frequency (row period) */
U8X8_CA(0x0b3, 0x0f0), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
//U8X8_CA(0x0b4, 0x002), /* set pre-charge compensation level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
//U8X8_CA(0x0b0, 0x028), /* enable pre-charge compensation (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
U8X8_CAA(0x0bb, 0x035, 0x0ff), /* set precharge */
U8X8_CA(0x0bc, 0x01f), /* pre-charge voltage level */
U8X8_CA(0x0be, 0x00f), /* VCOMH voltage */
U8X8_CA(0x0bf, 0x002|0x00d), /* VSL voltage level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
U8X8_C(0x0a4), /* normal display mode */
//U8X8_CA(0x023, 0x003), /* graphics accelleration: fill pixel */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1326_256x32_nhd_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1326_256x32_nhd_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1326_256x32_nhd_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a0, 0x006), /* remap 00110 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1326_256x32_nhd_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
//U8X8_CA(0x0a0, 0x005), /* remap 00101 */
U8X8_CA(0x0a0, 0x001), /* remap 00001 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/*
input:
one tile (8 Bytes)
output:
Tile for ssd1326 (32 Bytes)
*/
static uint8_t u8x8_ssd1326_8to32_dest_buf[32];
static uint8_t *u8x8_ssd1326_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
{
uint8_t v;
uint8_t a,b;
uint8_t i, j;
uint8_t *dest;
for( j = 0; j < 4; j++ )
{
dest = u8x8_ssd1326_8to32_dest_buf;
dest += j;
a =*ptr;
ptr++;
b = *ptr;
ptr++;
for( i = 0; i < 8; i++ )
{
v = 0;
if ( a&1 ) v |= 0xf0;
if ( b&1 ) v |= 0x0f;
*dest = v;
dest+=4;
a >>= 1;
b >>= 1;
}
}
return u8x8_ssd1326_8to32_dest_buf;
}
static uint8_t u8x8_d_ssd1326_256x32_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1326_256x32_nhd_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_er_256x32_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_256x32_nhd_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_256x32_nhd_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_256x32_nhd_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_256x32_nhd_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1326 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 4;
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y *= 8;
y += u8x8->x_offset; /* x_offset is used as y offset for the ssd1326 */
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
u8x8_cad_SendArg(u8x8, x ); /* start */
u8x8_cad_SendArg(u8x8, x+3 ); /* end */
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address */
u8x8_cad_SendArg(u8x8, y);
u8x8_cad_SendArg(u8x8, y+7);
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1326_8to32(u8x8, ptr));
ptr += 8;
x += 4;
c--;
} while( c > 0 );
//x += 4;
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ssd1326_256x32_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 15,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100, /**/
/* sda_setup_time_ns = */ 100, /* ssd1326 */
/* sck_pulse_width_ns = */ 100, /* ssd1326 */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 60, /* ssd1326 */
/* tile_width = */ 32,
/* tile_hight = */ 4,
/* default_x_offset = */ 0, /* x_offset is used as y offset for the ssd1326 */
/* flipmode_x_offset = */ 0, /* x_offset is used as y offset for the ssd1326 */
/* pixel_width = */ 256,
/* pixel_height = */ 32
};
uint8_t u8x8_d_ssd1326_er_256x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1326_256x32_display_info);
return 1;
}
return u8x8_d_ssd1326_256x32_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,571 @@
/*
u8x8_d_ssd1327.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_ssd1327_96x96_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1327_96x96_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/*
input:
one tile (8 Bytes)
output:
Tile for ssd1327 (32 Bytes)
*/
static uint8_t u8x8_ssd1327_8to32_dest_buf[32];
static uint8_t *u8x8_ssd1327_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
{
uint8_t v;
uint8_t a,b;
uint8_t i, j;
uint8_t *dest;
for( j = 0; j < 4; j++ )
{
dest = u8x8_ssd1327_8to32_dest_buf;
dest += j;
a =*ptr;
ptr++;
b = *ptr;
ptr++;
for( i = 0; i < 8; i++ )
{
v = 0;
if ( a&1 ) v |= 0xf0;
if ( b&1 ) v |= 0x0f;
*dest = v;
dest+=4;
a >>= 1;
b >>= 1;
}
}
return u8x8_ssd1327_8to32_dest_buf;
}
static uint8_t u8x8_d_ssd1327_96x96_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1327_96x96_display_info);
break;
*/
/* handled by the calling function
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_96x96_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_96x96_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_96x96_powersave1_seq);
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1327 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 4;
x+=u8x8->x_offset/2;
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y *= 8;
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address, moved out of the loop (issue 302) */
u8x8_cad_SendArg(u8x8, y);
u8x8_cad_SendArg(u8x8, y+7);
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
u8x8_cad_SendArg(u8x8, x ); /* start */
u8x8_cad_SendArg(u8x8, x+3 ); /* end */
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1327_8to32(u8x8, ptr));
ptr += 8;
x += 4;
c--;
} while( c > 0 );
//x += 4;
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*=============================================*/
/* Seeedstudio Grove OLED 96x96 */
static const u8x8_display_info_t u8x8_ssd1327_96x96_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100, /**/
/* sda_setup_time_ns = */ 100, /* */
/* sck_pulse_width_ns = */ 100, /* */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 1, /* use 1 instead of 4, because the SSD1327 seems to be very slow */
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 60,
/* tile_width = */ 12,
/* tile_hight = */ 12,
/* default_x_offset = */ 16,
/* flipmode_x_offset = */ 16,
/* pixel_width = */ 96,
/* pixel_height = */ 96
};
/* https://github.com/SeeedDocument/Grove_OLED_1.12/raw/master/resources/LY120-096096.pdf */
/* http://www.seeedstudio.com/wiki/index.php?title=Twig_-_OLED_96x96 */
/* values from u8glib */
/*
Re-map setting in Graphic Display Data RAM, command 0x0a0
Bit 0: Column Address Re-map
Bit 1: Nibble Re-map
Bit 2: Horizontal/Vertical Address Increment
Bit 3: Not used, must be 0
Bit 4: COM Re-map
Bit 5: Not used, must be 0
Bit 6: COM Split Odd Even
Bit 7: Not used, must be 0
*/
static const uint8_t u8x8_d_ssd1327_96x96_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0fd, 0x012), /* unlock display, usually not required because the display is unlocked after reset */
U8X8_C(0x0ae), /* display off */
//U8X8_CA(0x0a8, 0x03f), /* multiplex ratio: 0x03f * 1/64 duty */
U8X8_CA(0x0a8, 0x05f), /* multiplex ratio: 0x05f * 1/64 duty */
U8X8_CA(0x0a1, 0x000), /* display start line */
//U8X8_CA(0x0a2, 0x04c), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a2, 0x020), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x051), /* remap configuration */
U8X8_CA(0x0ab, 0x001), /* Enable internal VDD regulator (RESET) */
//U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128 */
U8X8_CA(0x081, 0x053), /* contrast, brightness, 0..128 */
//U8X8_CA(0x0b1, 0x055), /* phase length */
U8X8_CA(0x0b1, 0x051), /* phase length */
//U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
U8X8_CA(0x0b3, 0x001), /* set display clock divide ratio/oscillator frequency */
//? U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
//? U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
U8X8_C(0x0b9), /* use linear lookup table */
//U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
U8X8_CA(0x0bc, 0x008), /* pre-charge voltage level */
//U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
U8X8_CA(0x0be, 0x007), /* VCOMH voltage */
U8X8_CA(0x0b6, 0x001), /* second precharge */
U8X8_CA(0x0d5, 0x062), /* enable second precharge, internal vsl (bit0 = 0) */
U8X8_C(0x0a4), /* normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1327_seeed_96x96_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a2, 0x020), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x051), /* remap configuration */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1327_seeed_96x96_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a2, 0x060), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x042), /* remap configuration */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1327_seeed_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1327_96x96_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1327_96x96_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_96x96_init_seq);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
{
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_seeed_96x96_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_seeed_96x96_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
return 1;
}
return 0;
}
/*=============================================*/
/* EA W128128 round OLED 128x128 */
/* issue #641 */
/* https://www.lcd-module.de/fileadmin/eng/pdf/grafik/W128128-XR.pdf */
static const u8x8_display_info_t u8x8_ssd1327_ea_w128128_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100, /**/
/* sda_setup_time_ns = */ 100, /* */
/* sck_pulse_width_ns = */ 100, /* */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 1, /* use 1 instead of 4, because the SSD1327 seems to be very slow */
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 60,
/* tile_width = */ 16,
/* tile_hight = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 128
};
/* this is a copy of the init sequence for the seeed 96x96 oled */
static const uint8_t u8x8_d_ssd1327_ea_w128128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0fd, 0x012), /* unlock display, usually not required because the display is unlocked after reset */
U8X8_C(0x0ae), /* display off */
//U8X8_CA(0x0a8, 0x03f), /* multiplex ratio: 0x03f * 1/64 duty */
U8X8_CA(0x0a8, 0x05f), /* multiplex ratio: 0x05f * 1/64 duty */
U8X8_CA(0x0a1, 0x000), /* display start line */
//U8X8_CA(0x0a2, 0x04c), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a2, 0x010), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x051), /* remap configuration */
U8X8_CA(0x0ab, 0x001), /* Enable internal VDD regulator (RESET) */
//U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128 */
U8X8_CA(0x081, 0x053), /* contrast, brightness, 0..128 */
//U8X8_CA(0x0b1, 0x055), /* phase length */
U8X8_CA(0x0b1, 0x051), /* phase length */
//U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
U8X8_CA(0x0b3, 0x001), /* set display clock divide ratio/oscillator frequency */
//? U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
//? U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
U8X8_C(0x0b9), /* use linear lookup table */
//U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
U8X8_CA(0x0bc, 0x008), /* pre-charge voltage level */
//U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
U8X8_CA(0x0be, 0x007), /* VCOMH voltage */
U8X8_CA(0x0b6, 0x001), /* second precharge */
U8X8_CA(0x0d5, 0x062), /* enable second precharge, internal vsl (bit0 = 0) */
U8X8_C(0x0a4), /* normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1327_ea_w128128_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x051), /* remap configuration */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1327_ea_w128128_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x042), /* remap configuration */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1327_ea_w128128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_ssd1327_96x96_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1327_ea_w128128_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_ea_w128128_init_seq);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
{
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_ea_w128128_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_ea_w128128_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
return 1;
}
return 0;
}
/*=============================================*/
/* MIDAS MCOT128128C1V-YM 128x128 Module */
static const u8x8_display_info_t u8x8_ssd1327_128x128_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 10,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100, /**/
/* sda_setup_time_ns = */ 100, /* */
/* sck_pulse_width_ns = */ 100, /* */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 1, /* use 1 instead of 4, because the SSD1327 seems to be very slow */
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 60,
/* tile_width = */ 16,
/* tile_hight = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 128
};
/* https://github.com/SeeedDocument/Grove_OLED_1.12/raw/master/resources/LY120-096096.pdf */
/* http://www.seeedstudio.com/wiki/index.php?title=Twig_-_OLED_96x96 */
/* values from u8glib */
/*
Re-map setting in Graphic Display Data RAM, command 0x0a0
Bit 0: Column Address Re-map
Bit 1: Nibble Re-map
Bit 2: Horizontal/Vertical Address Increment
Bit 3: Not used, must be 0
Bit 4: COM Re-map
Bit 5: Not used, must be 0
Bit 6: COM Split Odd Even
Bit 7: Not used, must be 0
*/
static const uint8_t u8x8_d_ssd1327_128x128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0fd, 0x012), /* unlock display, usually not required because the display is unlocked after reset */
U8X8_C(0x0ae), /* display off */
//U8X8_CA(0x0a8, 0x03f), /* multiplex ratio: 0x03f * 1/64 duty */
//U8X8_CA(0x0a8, 0x05f), /* multiplex ratio: 0x05f * 1/64 duty */
U8X8_CA(0x0a8, 0x07f), /* multiplex ratio: 0x05f * 1/128duty */
U8X8_CA(0x0a1, 0x000), /* display start line */
//U8X8_CA(0x0a2, 0x04c), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x051), /* remap configuration */
U8X8_CA(0x0ab, 0x001), /* Enable internal VDD regulator (RESET) */
//U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128 */
U8X8_CA(0x081, 0x053), /* contrast, brightness, 0..128 */
//U8X8_CA(0x0b1, 0x055), /* phase length */
U8X8_CA(0x0b1, 0x051), /* phase length */
//U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
U8X8_CA(0x0b3, 0x001), /* set display clock divide ratio/oscillator frequency */
//? U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
//? U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
U8X8_C(0x0b9), /* use linear lookup table */
//U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
U8X8_CA(0x0bc, 0x008), /* pre-charge voltage level */
//U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
U8X8_CA(0x0be, 0x007), /* VCOMH voltage */
U8X8_CA(0x0b6, 0x001), /* second precharge */
U8X8_CA(0x0d5, 0x062), /* enable second precharge, internal vsl (bit0 = 0) */
U8X8_C(0x0a4), /* normal display mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1327_128x128_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x051), /* remap configuration */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1327_128x128_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a0, 0x042), /* remap configuration */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1327_midas_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call the 96x96 procedure at the moment */
if ( u8x8_d_ssd1327_96x96_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1327_128x128_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_128x128_init_seq);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
{
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_128x128_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_128x128_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
return 1;
}
return 0;
}

View File

@ -0,0 +1,298 @@
/*
u8x8_d_ssd1329.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_ssd1329_128x96_noname_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
U8X8_CA(0x0a8, 0x05f), /* multiplex ratio: 0x03f * 1/64 duty - changed by CREESOO, acc. to datasheet, 100317*/
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
U8X8_CA(0x0a1, 0x000), /* display start line */
U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
U8X8_CA(0x0a0, 0x052), /* remap configuration, horizontal address increment (bit 2 = 0), enable nibble remap (upper nibble is left, bit 1 = 1) */
U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
#ifdef removed
U8X8_C(0x0b8), /* set gray scale table */
U8X8_A(1), /* */
U8X8_A(5), /* */
U8X8_A(10), /* */
U8X8_A(14), /* */
U8X8_A(19), /* */
U8X8_A(23), /* */
U8X8_A(28), /* */
U8X8_A(32), /* */
U8X8_A(37), /* */
U8X8_A(41), /* */
U8X8_A(46), /* */
U8X8_A(50), /* */
U8X8_A(55), /* */
U8X8_A(59), /* */
U8X8_A(63), /* */
#endif
U8X8_C(0x0b7), /* set default gray scale table */
U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128 */
U8X8_CA(0x0b2, 0x051), /* frame frequency (row period) */
U8X8_CA(0x0b1, 0x055), /* phase length */
U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
U8X8_CA(0x0b4, 0x002), /* set pre-charge compensation level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
U8X8_CA(0x0b0, 0x028), /* enable pre-charge compensation (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
U8X8_CA(0x0bf, 0x002|0x00d), /* VSL voltage level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
U8X8_C(0x0a4), /* normal display mode */
U8X8_CA(0x023, 0x003), /* graphics accelleration: fill pixel */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1329_128x96_nhd_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1329_128x96_nhd_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1329_128x96_nhd_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a0, 0x052), /* remap */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1329_128x96_nhd_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0a0, 0x041), /* remap */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/*
input:
one tile (8 Bytes)
output:
Tile for ssd1329 (32 Bytes)
*/
static uint8_t u8x8_ssd1329_8to32_dest_buf[32];
static uint8_t *u8x8_ssd1329_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
{
uint8_t v;
uint8_t a,b;
uint8_t i, j;
uint8_t *dest;
for( j = 0; j < 4; j++ )
{
dest = u8x8_ssd1329_8to32_dest_buf;
dest += j;
a =*ptr;
ptr++;
b = *ptr;
ptr++;
for( i = 0; i < 8; i++ )
{
v = 0;
if ( a&1 ) v |= 0xf0;
if ( b&1 ) v |= 0x0f;
*dest = v;
dest+=4;
a >>= 1;
b >>= 1;
}
}
return u8x8_ssd1329_8to32_dest_buf;
}
static uint8_t u8x8_d_ssd1329_128x96_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1329_128x96_nhd_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_noname_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_nhd_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_nhd_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_nhd_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_nhd_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1329 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 4;
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y *= 8;
y += u8x8->x_offset; /* x_offset is used as y offset for the ssd1329 */
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
if ( ptr[0] | ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5] | ptr[6] | ptr[7] )
{
/* draw the tile if pattern is not zero for all bytes */
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
u8x8_cad_SendArg(u8x8, x ); /* start */
u8x8_cad_SendArg(u8x8, x+3 ); /* end */
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address */
u8x8_cad_SendArg(u8x8, y);
u8x8_cad_SendArg(u8x8, y+7);
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1329_8to32(u8x8, ptr));
}
else
{
/* tile is empty, use the graphics acceleration command */
/* are this really available on the SSD1329??? */
u8x8_cad_SendCmd(u8x8, 0x024 ); // draw rectangle
u8x8_cad_SendArg(u8x8, x );
u8x8_cad_SendArg(u8x8, y );
u8x8_cad_SendArg(u8x8, x+3 );
u8x8_cad_SendArg(u8x8, y+7 );
u8x8_cad_SendArg(u8x8, 0 ); // clear
}
ptr += 8;
x += 4;
c--;
} while( c > 0 );
//x += 4;
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ssd1329_128x96_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 15,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100, /**/
/* sda_setup_time_ns = */ 100, /* ssd1329 */
/* sck_pulse_width_ns = */ 100, /* ssd1329 */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 60, /* ssd1329 */
/* tile_width = */ 16,
/* tile_hight = */ 12,
/* default_x_offset = */ 0, /* x_offset is used as y offset for the ssd1329 */
/* flipmode_x_offset = */ 0, /* x_offset is used as y offset for the ssd1329 */
/* pixel_width = */ 128,
/* pixel_height = */ 96
};
uint8_t u8x8_d_ssd1329_128x96_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1329_128x96_display_info);
return 1;
}
return u8x8_d_ssd1329_128x96_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,394 @@
/*
u8x8_d_ssd1606_172x72.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
SSD1606: 128x180x2
two-bit, four graylevels
command
0x22: assign actions
0x20: execute actions
action for command 0x022 are (more or less guessed)
bit 7: Enable Clock
bit 6: Enable Charge Pump
bit 5: Load Temparture Value (???)
bit 4: Load LUT (???)
bit 3: Initial Display (???)
bit 2: Pattern Display --> Requires about 945ms with the LUT from below
bit 1: Disable Charge Pump
bit 0: Disable Clock
Disable Charge Pump and Clock require about 267ms
Enable Charge Pump and Clock require about 10ms
Notes:
- Introduced a refresh display message, which copies RAM to display
- Charge pump and clock are only enabled for the transfer RAM to display
- U8x8 will not really work because of the two buffers in the SSD1606, however U8g2 should be ok.
*/
#include "u8x8.h"
#define L(a,b,c,d) (((a)<<6)|((b)<<4)|((c)<<2)|(d))
/* GDE021A1, 2.1" EPD */
static const uint8_t u8x8_d_ssd1606_172x72_gde021a1_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x10, 0x00), /* Deep Sleep mode Control: Disable */
U8X8_CA(0x11, 0x03), /* Define data entry mode, x&y inc, x first */
U8X8_CAA(0x44, 0, 31), /* RAM x start & end, each byte has 4 pixel, 32*4=128 */
U8X8_CAA(0x45, 0, 179), /* RAM y start & end, 179 MAX */
U8X8_CA(0x4e, 0), /* set x pos, 0..31 */
U8X8_CA(0x4f, 0), /* set y pos, 0...179 */
U8X8_CA(0xf0, 0x1f), /* set booster feedback to internal */
U8X8_CA(0x22, 0xc0), /* display update seq. option: enable clk, enable CP, .... todo: this is never activated */
U8X8_C(0x32), /* write LUT register*/
#ifdef ORIGINAL_LUT
/* wavefrom part of the LUT: absolute LUT... this will always force the destination color */
U8X8_A4(0x00,0x00,0x00,0x55), /* step 0 */
U8X8_A4(0x00,0x00,0x55,0x55), /* step 1 */
U8X8_A4(0x00,0x55,0x55,0x55),
U8X8_A4(0xAA,0xAA,0xAA,0xAA),
U8X8_A4(0x15,0x15,0x15,0x15),
U8X8_A4(0x05,0x05,0x05,0x05),
U8X8_A4(0x01,0x01,0x01,0x01),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00), /* step 19 */
/* timing part of the LUT */
U8X8_A8(0x22,0xFB,0x22,0x1B,0x00,0x00,0x00,0x00),
U8X8_A(0x00),U8X8_A(0x00),
#else
/* the following LUT will not change anything if the old and the new values are the same */
/* 03 02 01 00 13 12 11 10 23 22 21 20 33 32 31 30 original */
U8X8_A4(L(0, 0, 0, 0), L(0, 0, 0, 0), L(0, 0, 0, 0), L(0, 1, 1, 1)), // 0x00,0x00,0x00,0x55, step 0
U8X8_A4(L(0, 0, 0, 0), L(0, 0, 0, 0), L(1, 0, 1, 1), L(0, 1, 1, 1)), // 0x00,0x00,0x55,0x55, step 1
U8X8_A4(L(0, 0, 0, 0), L(1, 1, 0, 1), L(1, 0, 1, 1), L(0, 1, 1, 1)), // 0x00,0x55,0x55,0x55, step 2
U8X8_A4(L(2, 2, 2, 0), L(2, 2, 0, 2), L(2, 0, 2, 2), L(0, 2, 2, 2)), // 0xAA,0xAA,0xAA,0xAA, step 3
U8X8_A4(L(0, 1, 1, 0), L(0, 1, 0, 1), L(0, 0, 1, 1), L(0, 1, 1, 1)), // 0x15,0x15,0x15,0x15, step 4
U8X8_A4(L(0, 0, 1, 0), L(0, 0, 0, 1), L(0, 0, 1, 1), L(0, 0, 1, 1)), // 0x05,0x05,0x05,0x05, step 5
U8X8_A4(L(0, 0, 0, 0), L(0, 0, 0, 1), L(0, 0, 0, 1), L(0, 0, 0, 1)), // 0x01,0x01,0x01,0x01, step 6
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00),
U8X8_A4(0x00,0x00,0x00,0x00), /* step 19 */
/* timing part of the LUT */
U8X8_A8(0x22,0xFB,0x22,0x1B,0x00,0x00,0x00,0x00),
U8X8_A(0x00),U8X8_A(0x00),
#endif
U8X8_CA(0x2c, 0xa0), /* write vcom value*/
U8X8_CA(0x3c, 0x63), /* select boarder waveform */
U8X8_CA(0x22, 0xc4), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
/* 0x0c4 is mentioned in chapter 9.2 of the GDE021A1 data sheet */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1606_to_display_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
//U8X8_CA(0x22, 0xc0), /* display update seq. option: Enable clock and charge pump */
//U8X8_C(0x20), /* execute sequence */
//U8X8_DLY(10),
/* strange, splitting 0x0c0 does not work reliable */
U8X8_CA(0x22, 0xc4), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(250), /* the sequence above requires about 970ms */
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(230),
U8X8_CA(0x22, 0x03), /* disable clock and charge pump */
U8X8_DLY(200), /* this requres about 270ms */
U8X8_DLY(90),
//U8X8_CA(0x10, 0x01), /* deep sleep mode */
//U8X8_C(0x20), /* execute sequence */
U8X8_DLY(50),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
// static const uint8_t u8x8_d_ssd1606_172x72_powersave0_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
// static const uint8_t u8x8_d_ssd1606_172x72_powersave1_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
// static const uint8_t u8x8_d_ssd1606_172x72_flip0_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
// static const uint8_t u8x8_d_ssd1606_172x72_flip1_seq[] = {
// U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
// U8X8_END_TRANSFER(), /* disable chip */
// U8X8_END() /* end of sequence */
// };
static uint8_t *u8x8_convert_tile_for_ssd1606(uint8_t *t)
{
uint8_t i;
uint16_t r;
static uint8_t buf[16];
uint8_t *pbuf = buf;
for( i = 0; i < 8; i++ )
{
r = u8x8_upscale_byte(~(*t++));
*pbuf++ = (r>>8) & 255;
*pbuf++ = r & 255;
}
return buf;
}
static void u8x8_d_ssd1606_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
static void u8x8_d_ssd1606_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c, page;
uint8_t *ptr;
u8x8_cad_StartTransfer(u8x8);
page = u8x8->display_info->tile_height;
page --;
page -= (((u8x8_tile_t *)arg_ptr)->y_pos);
page *= 2;
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x00f ); /* scan start */
u8x8_cad_SendArg(u8x8, 0);
u8x8_cad_SendCmd(u8x8, 0x011 ); /* cursor increment mode */
u8x8_cad_SendArg(u8x8, 3);
u8x8_cad_SendCmd(u8x8, 0x045 ); /* window start column */
u8x8_cad_SendArg(u8x8, 0);
u8x8_cad_SendArg(u8x8, 179); /* end of display */
u8x8_cad_SendCmd(u8x8, 0x044 ); /* window end page */
u8x8_cad_SendArg(u8x8, page);
u8x8_cad_SendArg(u8x8, page+1);
u8x8_cad_SendCmd(u8x8, 0x04f ); /* window column */
u8x8_cad_SendArg(u8x8, x);
u8x8_cad_SendCmd(u8x8, 0x04e ); /* window row */
u8x8_cad_SendArg(u8x8, page);
u8x8_cad_SendCmd(u8x8, 0x024 );
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, 16, u8x8_convert_tile_for_ssd1606(ptr));
ptr += 8;
x += 8;
c--;
} while( c > 0 );
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
}
static uint8_t u8x8_d_ssd1606_172x72_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1606_172x72_display_info);
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_gde021a1_init_seq);
/* special code for the SSD1606... */
/* ensure that the initial buffer is clear and all eInk is set to white */
/* this is done here, because the LUT will be of that kind, that it uses the previous color */
/* make everything black */
u8x8_FillDisplay(u8x8);
/* write content to the display */
u8x8_RefreshDisplay(u8x8);
/* now make everything clear */
u8x8_FillDisplay(u8x8);
/* write content to the display */
u8x8_RefreshDisplay(u8x8);
/* now make everything clear */
u8x8_ClearDisplay(u8x8);
/* write content to the display */
u8x8_RefreshDisplay(u8x8);
u8x8_ClearDisplay(u8x8);
/* write content to the display */
u8x8_RefreshDisplay(u8x8);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
/*
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_powersave1_seq);
*/
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
/*
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
*/
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
/*
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_EndTransfer(u8x8);
*/
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_d_ssd1606_draw_tile(u8x8, arg_int, arg_ptr);
break;
case U8X8_MSG_DISPLAY_REFRESH:
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_to_display_seq);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_ssd1606_172x72_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 120,
/* pre_chip_disable_wait_ns = */ 60,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100,
/* sda_setup_time_ns = */ 50, /* SSD1606: */
/* sck_pulse_width_ns = */ 100, /* SSD1606: 100ns */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150,
/* tile_width = */ 22, /* 22*8 = 176 */
/* tile_hight = */ 9, /* 9*8 = 72 */
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 172,
/* pixel_height = */ 72
};
uint8_t u8x8_d_ssd1606_172x72(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1606_172x72_display_info);
return 1;
}
return u8x8_d_ssd1606_172x72_generic(u8x8, msg, arg_int, arg_ptr);
}

View File

@ -0,0 +1,597 @@
/*
u8x8_d_ssd1607_200x200.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
SSD1607: 200x300x1
command
0x22: assign actions
0x20: execute actions
action for command 0x022 are (more or less guessed)
bit 7: Enable Clock
bit 6: Enable Charge Pump
bit 5: Load Temparture Value (???)
bit 4: Load LUT (???)
bit 3: Initial Display (???)
bit 2: Pattern Display --> Requires about 945ms with the LUT from below
bit 1: Disable Charge Pump
bit 0: Disable Clock
Disable Charge Pump and Clock require about 267ms
Enable Charge Pump and Clock require about 10ms
Notes:
- Introduced a refresh display message, which copies RAM to display
- Charge pump and clock are only enabled for the transfer RAM to display
- U8x8 will not really work because of the two buffers in the SSD1606, however U8g2 should be ok.
*/
#include "u8x8.h"
/*=================================================*/
static const u8x8_display_info_t u8x8_ssd1607_200x200_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* values from SSD1606 */
/* post_chip_enable_wait_ns = */ 120,
/* pre_chip_disable_wait_ns = */ 60,
/* reset_pulse_width_ms = */ 100,
/* post_reset_wait_ms = */ 100,
/* sda_setup_time_ns = */ 50, /* SSD1606: */
/* sck_pulse_width_ns = */ 100, /* SSD1606: 100ns */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 2, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150,
/* tile_width = */ 25, /* 25*8 = 200 */
/* tile_hight = */ 25,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 200,
/* pixel_height = */ 200
};
static const uint8_t u8x8_d_ssd1607_200x200_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x22, 0xc0), /* enable clock and charge pump */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(200), /* according to my measures it may take up to 150ms */
U8X8_DLY(100), /* but it might take longer */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1607_200x200_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
/* disable clock and charge pump only, deep sleep is not entered, because we will loose RAM content */
U8X8_CA(0x22, 0x02), /* only disable charge pump, HW reset seems to be required if the clock is disabled */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(20),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1607_200x200_exec_1000dly_seq[] = {
// assumes, that the start transfer has happend
U8X8_CA(0x22, 0x04), /* display update seq. option: pattern display */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static void u8x8_d_ssd1607_200x200_first_init(u8x8_t *u8x8)
{
u8x8_ClearDisplay(u8x8);
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x032); // program update sequence
u8x8_cad_SendMultipleArg(u8x8, 8, 0x055); // all black
u8x8_cad_SendMultipleArg(u8x8, 12, 0x0aa); // all white
u8x8_cad_SendMultipleArg(u8x8, 10, 0x022); // 830ms
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_exec_1000dly_seq);
}
static uint8_t *u8x8_convert_tile_for_ssd1607(uint8_t *t)
{
uint8_t i;
static uint8_t buf[8];
uint8_t *pbuf = buf;
for( i = 0; i < 8; i++ )
{
*pbuf++ = ~(*t++);
}
return buf;
}
static void u8x8_d_ssd1607_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
static void u8x8_d_ssd1607_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
{
uint16_t x;
uint8_t c, page;
uint8_t *ptr;
u8x8_cad_StartTransfer(u8x8);
page = u8x8->display_info->tile_height;
page --;
page -= (((u8x8_tile_t *)arg_ptr)->y_pos);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x045 ); /* window start column */
u8x8_cad_SendArg(u8x8, 0);
u8x8_cad_SendArg(u8x8, 0);
u8x8_cad_SendArg(u8x8, 199); /* end of display */
u8x8_cad_SendArg(u8x8, 0);
u8x8_cad_SendCmd(u8x8, 0x044 ); /* window end page */
u8x8_cad_SendArg(u8x8, page);
u8x8_cad_SendArg(u8x8, page);
u8x8_cad_SendCmd(u8x8, 0x04f ); /* window column */
u8x8_cad_SendArg(u8x8, x&255);
u8x8_cad_SendArg(u8x8, x>>8);
u8x8_cad_SendCmd(u8x8, 0x04e ); /* window row */
u8x8_cad_SendArg(u8x8, page);
u8x8_cad_SendCmd(u8x8, 0x024 );
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_ssd1607(ptr));
ptr += 8;
x += 8;
c--;
} while( c > 0 );
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
}
/*=================================================*/
#define L(a,b,c,d) (((a)<<6)|((b)<<4)|((c)<<2)|(d))
/* https://github.com/embeddedadventures/SSD1607/blob/master/SSD1607.cpp */
static const uint8_t u8x8_d_ssd1607_200x200_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
//U8X8_CA(0x10, 0x00), /* Deep Sleep mode Control: Disable */
U8X8_C(0x01),
U8X8_A(199),U8X8_A(0),U8X8_A(0),
U8X8_CA(0x03, 0x00), /* Gate Driving voltage: 15V (lowest value)*/
U8X8_CA(0x04, 0x0a), /* Source Driving voltage: 15V (mid value and POR)*/
U8X8_CA(0x0f, 0x00), /* scan start ? */
U8X8_CA(0xf0, 0x1f), /* set booster feedback to internal */
U8X8_CA(0x2c, 0xa8), /* write vcom value*/
U8X8_CA(0x3a, 0x1a), /* dummy lines */
U8X8_CA(0x3b, 0x08), /* gate time */
U8X8_CA(0x3c, 0x33), /* select boarder waveform */
U8X8_CA(0x11, 0x03), /* cursor increment mode */
U8X8_CAA(0x44, 0, 24), /* RAM x start & end, each byte has 8 pixel, 25*4=200 */
U8X8_CAAAA(0x45, 0, 0, 299&255, 299>>8), /* RAM y start & end, 0..299 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_ssd1607_to_display_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x32), /* write LUT register*/
/* according to the command table, the lut has 240 bits (=30 bytes * 8 bits) */
/* Waveform part of the LUT (20 bytes) */
/* bit 7/6: 1 - 1 transition */
/* bit 5/4: 1 - 0 transition */
/* bit 3/2: 0 - 1 transition */
/* bit 1/0: 0 - 0 transition */
/* 00 VSS */
/* 01 VSH */
/* 10 VSL */
/* 11 NA */
/* original values */
/*
U8X8_A(0x02),
U8X8_A(0x02),
U8X8_A(0x01),
U8X8_A(0x11),
U8X8_A(0x12),
U8X8_A(0x12),
U8X8_A(0x22),
U8X8_A(0x22),
U8X8_A(0x66),
U8X8_A(0x69),
U8X8_A(0x69),
U8X8_A(0x59),
U8X8_A(0x58),
U8X8_A(0x99),
U8X8_A(0x99),
U8X8_A(0x88),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
*/
/* original values, L-macro */
U8X8_A(L(0,0,0,2)), // 0x02
U8X8_A(L(0,0,0,2)), // 0x02
U8X8_A(L(0,0,0,1)), // 0x01
U8X8_A(L(0,1,0,1)), // 0x11
U8X8_A(L(0,1,0,2)), // 0x12
U8X8_A(L(0,1,0,2)), // 0x12
U8X8_A(L(0,2,0,2)), // 0x22
U8X8_A(L(0,2,0,2)), // 0x22
U8X8_A(L(1,2,1,2)), // 0x66
U8X8_A(L(1,2,2,1)), // 0x69
U8X8_A(L(1,2,2,1)), // 0x69
U8X8_A(L(1,1,2,1)), // 0x59
U8X8_A(L(1,1,2,0)), // 0x58
U8X8_A(L(2,1,2,1)), // 0x99
U8X8_A(L(2,1,2,1)), // 0x99
U8X8_A(L(2,0,2,0)), // 0x88
U8X8_A(L(0,0,0,0)), // 0x00
U8X8_A(L(0,0,0,0)), // 0x00
U8X8_A(L(0,0,0,0)), // 0x00
U8X8_A(L(0,0,0,0)), // 0x00
/* orginal values without 0-0 and 1-1 transition */
/*
U8X8_A(L(3,0,0,3)), // 0x02
U8X8_A(L(3,0,0,3)), // 0x02
U8X8_A(L(3,0,0,3)), // 0x01
U8X8_A(L(3,1,0,3)), // 0x11
U8X8_A(L(3,1,0,3)), // 0x12
U8X8_A(L(3,1,0,3)), // 0x12
U8X8_A(L(3,2,0,3)), // 0x22
U8X8_A(L(3,2,0,3)), // 0x22
U8X8_A(L(3,2,1,3)), // 0x66
U8X8_A(L(3,2,2,3)), // 0x69
U8X8_A(L(3,2,2,3)), // 0x69
U8X8_A(L(3,1,2,3)), // 0x59
U8X8_A(L(3,1,2,3)), // 0x58
U8X8_A(L(3,1,2,3)), // 0x99
U8X8_A(L(3,1,2,3)), // 0x99
U8X8_A(L(3,0,2,3)), // 0x88
U8X8_A(L(3,0,0,3)), // 0x00
U8X8_A(L(3,0,0,3)), // 0x00
U8X8_A(L(3,0,0,3)), // 0x00
U8X8_A(L(3,0,0,3)), // 0x00
*/
/* Timing part of the LUT, 20 Phases with 4 bit each: 10 bytes */
U8X8_A(0xF8),
U8X8_A(0xB4),
U8X8_A(0x13),
U8X8_A(0x51),
U8X8_A(0x35),
U8X8_A(0x51),
U8X8_A(0x51),
U8X8_A(0x19),
U8X8_A(0x01),
U8X8_A(0x00),
U8X8_CA(0x22, 0x04), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(250), /* the sequence above requires about 1200ms for the 200x200 display*/
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1607_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1607_200x200_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_init_seq);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
u8x8_d_ssd1607_200x200_first_init(u8x8);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_d_ssd1607_draw_tile(u8x8, arg_int, arg_ptr);
break;
case U8X8_MSG_DISPLAY_REFRESH:
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_to_display_seq);
break;
default:
return 0;
}
return 1;
}
/*=================================================*/
/* there is no improvement possible... so i consider the v2 version as obsolete */
static const uint8_t u8x8_d_ssd1607_v2_to_display_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
/*
0xaa, 0x09, 0x09, 0x19, 0x19,
0x11, 0x11, 0x11, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x75, 0x77, 0x77, 0x77, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00
measured 1240 ms with IL3830 196x128
0x02, 0x02, 0x01, 0x11, 0x12,
0x12, 0x12, 0x22, 0x22, 0x66,
0x69, 0x59, 0x58, 0x99, 0x99,
0x88, 0x00, 0x00, 0x00, 0x00,
0xf8, 0xb4, 0x13, 0x51, 0x35,
0x51, 0x51, 0xe9, 0x04, 0x00
*/
U8X8_C(0x32), /* write LUT register*/
/* https://github.com/olikraus/u8g2/issues/347 */
U8X8_A(0x02),
U8X8_A(0x02),
U8X8_A(0x01),
U8X8_A(0x11),
U8X8_A(0x12),
U8X8_A(0x12),
U8X8_A(0x22),
U8X8_A(0x22),
U8X8_A(0x66),
U8X8_A(0x69),
U8X8_A(0x69),
U8X8_A(0x59),
U8X8_A(0x58),
U8X8_A(0x99),
U8X8_A(0x99),
U8X8_A(0x88),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
U8X8_A(0x00),
/* Timing part of the LUT, 20 Phases with 4 bit each: 10 bytes */
U8X8_A(0xF8),
U8X8_A(0xB4),
U8X8_A(0x13),
U8X8_A(0x51),
U8X8_A(0x35),
U8X8_A(0x51),
U8X8_A(0x51),
U8X8_A(0xe9),
U8X8_A(0x04),
U8X8_A(0x00),
U8X8_CA(0x22, 0x04), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(250), /* delay for 1500ms. The current sequence takes 1300ms */
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1607_v2_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1607_200x200_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_init_seq);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
u8x8_d_ssd1607_200x200_first_init(u8x8);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_d_ssd1607_draw_tile(u8x8, arg_int, arg_ptr);
break;
case U8X8_MSG_DISPLAY_REFRESH:
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_v2_to_display_seq);
break;
default:
return 0;
}
return 1;
}
/*=================================================*/
/* GDEP015OC1 */
/* https://github.com/olikraus/u8g2/issues/454 */
static const uint8_t u8x8_d_ssd1607_gd_to_display_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
/*
0xaa, 0x09, 0x09, 0x19, 0x19,
0x11, 0x11, 0x11, 0x11, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x75, 0x77, 0x77, 0x77, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00
measured 1240 ms with IL3830 196x128
0x02, 0x02, 0x01, 0x11, 0x12,
0x12, 0x12, 0x22, 0x22, 0x66,
0x69, 0x59, 0x58, 0x99, 0x99,
0x88, 0x00, 0x00, 0x00, 0x00,
0xf8, 0xb4, 0x13, 0x51, 0x35,
0x51, 0x51, 0xe9, 0x04, 0x00
*/
U8X8_C(0x32), /* write LUT register*/
U8X8_A(0x50), U8X8_A(0xAA), U8X8_A(0x55), U8X8_A(0xAA), U8X8_A(0x11),
U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00),
U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00),
U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00),
U8X8_A(0xFF), U8X8_A(0xFF), U8X8_A(0x1F), U8X8_A(0x00), U8X8_A(0x00),
U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00), U8X8_A(0x00),
U8X8_CA(0x22, 0x04), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
U8X8_C(0x20), /* execute sequence */
U8X8_DLY(250), /* delay for 1500ms. The current sequence takes 1300ms */
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_DLY(250),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_ssd1607_gd_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1607_200x200_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_init_seq);
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
u8x8_d_ssd1607_200x200_first_init(u8x8);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_d_ssd1607_draw_tile(u8x8, arg_int, arg_ptr);
break;
case U8X8_MSG_DISPLAY_REFRESH:
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_gd_to_display_seq);
break;
default:
return 0;
}
return 1;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,574 @@
/*
u8x8_d_st7567.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_st7567_132x64_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a4), /* all pixel off, issue 142 */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7567_132x64_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7567_132x64_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7567_132x64_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7567_n_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7567_n_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/*=====================================================*/
static const u8x8_display_info_t u8x8_st7567_132x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 150, /* */
/* pre_chip_disable_wait_ns = */ 50, /* */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 1,
/* sda_setup_time_ns = */ 50, /* */
/* sck_pulse_width_ns = */ 120, /* */
/* sck_clock_hz = */ 4000000UL, /* */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40, /* */
/* write_pulse_width_ns = */ 80, /* */
/* tile_width = */ 17, /* width of 17*8=136 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 132,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_st7567_132x64_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x0a1), /* ADC set to reverse */
U8X8_C(0x0c0), /* common output mode */
// Flipmode
//U8X8_C(0x0a0), /* ADC set to reverse */
//U8X8_C(0x0c8), /* common output mode */
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
U8X8_C(0x0a3), /* LCD bias 1/7 */
/* power on sequence from paxinstruments */
U8X8_C(0x028|4), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x028|6), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x028|7), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x026), /* v0 voltage resistor ratio */
U8X8_CA(0x081, 0x027), /* set contrast, contrast value*/
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* pax instruments 132x64 display */
uint8_t u8x8_d_st7567_pi_132x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_132x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
/*
The following if condition checks the hardware limits of the st7567
controller: It is not allowed to write beyond the display limits.
This is in fact an issue within flip mode.
*/
if ( c + x > 132u )
{
c = 132u;
c -= x;
}
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*=====================================================*/
static const u8x8_display_info_t u8x8_st7567_jlx12864_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 150, /* */
/* pre_chip_disable_wait_ns = */ 50, /* */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 1,
/* sda_setup_time_ns = */ 50, /* */
/* sck_pulse_width_ns = */ 120, /* */
/* sck_clock_hz = */ 4000000UL, /* */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40, /* */
/* write_pulse_width_ns = */ 80, /* */
/* tile_width = */ 16, /* width of 16*8=128 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 4,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
static const uint8_t u8x8_st7567_jlx12864_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x0a1), /* ADC set to reverse */
U8X8_C(0x0c0), /* common output mode */
// Flipmode
//U8X8_C(0x0a0), /* ADC set to reverse */
//U8X8_C(0x0c8), /* common output mode */
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
U8X8_C(0x0a3), /* LCD bias 1/7 */
/* power on sequence from paxinstruments */
U8X8_C(0x028|4), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x028|6), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x028|7), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x023), /* v0 voltage resistor ratio */
U8X8_CA(0x081, 42>>2), /* set contrast, contrast value*/
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* JLX12864 display */
uint8_t u8x8_d_st7567_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_jlx12864_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_st7567_jlx12864_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
/*
The following if condition checks the hardware limits of the st7567
controller: It is not allowed to write beyond the display limits.
This is in fact an issue within flip mode.
*/
if ( c + x > 132u )
{
c = 132u;
c -= x;
}
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*=====================================================*/
static const u8x8_display_info_t u8x8_st7567_enh_dg128064_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 150, /* */
/* pre_chip_disable_wait_ns = */ 50, /* */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 1,
/* sda_setup_time_ns = */ 50, /* */
/* sck_pulse_width_ns = */ 120, /* */
/* sck_clock_hz = */ 4000000UL, /* */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40, /* */
/* write_pulse_width_ns = */ 80, /* */
/* tile_width = */ 16, /* width of 16*8=128 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 4,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
static const u8x8_display_info_t u8x8_st7567_enh_dg128064i_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 150, /* */
/* pre_chip_disable_wait_ns = */ 50, /* */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 1,
/* sda_setup_time_ns = */ 50, /* */
/* sck_pulse_width_ns = */ 120, /* */
/* sck_clock_hz = */ 4000000UL, /* */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 40, /* */
/* write_pulse_width_ns = */ 80, /* */
/* tile_width = */ 16, /* width of 16*8=128 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 4,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
static const uint8_t u8x8_st7567_enh_dg128064_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x0a1), /* ADC set to reverse */
U8X8_C(0x0c0), /* common output mode */
// Flipmode
//U8X8_C(0x0a0), /* ADC set to reverse */
//U8X8_C(0x0c8), /* common output mode */
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
U8X8_C(0x0a2), /* LCD bias 1/9 */
/* power on sequence from paxinstruments */
U8X8_C(0x028|4), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x028|6), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x028|7), /* all power control circuits on */
U8X8_DLY(50),
U8X8_C(0x023), /* v0 voltage resistor ratio */
U8X8_CA(0x081, 200>>2), /* set contrast, contrast value*/
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* ENH-DG128064 transparent display */
static uint8_t u8x8_d_st7567_enh_dg128064_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_enh_dg128064_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_st7567_enh_dg128064_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
/*
The following if condition checks the hardware limits of the st7567
controller: It is not allowed to write beyond the display limits.
This is in fact an issue within flip mode.
*/
if ( c + x > 132u )
{
c = 132u;
c -= x;
}
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
uint8_t u8x8_d_st7567_enh_dg128064(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_enh_dg128064_display_info);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_n_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_n_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
default:
return u8x8_d_st7567_enh_dg128064_generic(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
uint8_t u8x8_d_st7567_enh_dg128064i(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_enh_dg128064i_display_info);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
default:
return u8x8_d_st7567_enh_dg128064_generic(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}

View File

@ -0,0 +1,256 @@
/*
u8x8_d_st7588.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ST7588
- has 4 different I2C addresses
- I2C protocol is identical to SSD13xx
*/
#include "u8x8.h"
/* function set, bit 2: power down, bit 3: MY, bit 4: MX, bit 5: must be 1 */
#define FS (0x020)
/* not a real power down for the ST7588... just a display off */
static const uint8_t u8x8_d_st7588_128x64_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C( FS | 0x00 ), /* select 00 commands */
//U8X8_C( 0x08 ), /* display off */
U8X8_C( 0x0c ), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7588_128x64_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C( FS | 0x00 ), /* select 00 commands */
U8X8_C( 0x08 ), /* display off */
//U8X8_C( 0x0c ), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static uint8_t u8x8_d_st7588_128x64_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
/* handled by the calling function
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7588_128x64_display_info);
break;
*/
/* handled by the calling function
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_st7588_128x64_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_st7588_128x64_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_st7588_128x64_powersave1_seq);
/* restore orientation */
if ( u8x8->x_offset == 0 )
u8x8_cad_SendCmd(u8x8, FS ); /* select 00 commands */
else
u8x8_cad_SendCmd(u8x8, FS ^ 0x018 ); /* select 00 commands */
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, FS );
u8x8_cad_SendArg(u8x8, 4 | (arg_int>>7) );
u8x8_cad_SendCmd(u8x8, FS | 1);
u8x8_cad_SendArg(u8x8, 0x080 | arg_int );
/* restore orientation */
if ( u8x8->x_offset == 0 )
u8x8_cad_SendCmd(u8x8, FS ); /* select 00 commands */
else
u8x8_cad_SendCmd(u8x8, FS ^ 0x018 ); /* select 00 commands */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
if ( u8x8->x_offset == 0 )
u8x8_cad_SendCmd(u8x8, FS ); /* select 00 commands */
else
u8x8_cad_SendCmd(u8x8, FS ^ 0x018 ); /* select 00 commands */
u8x8_cad_SendCmd(u8x8, 0x040 | (((u8x8_tile_t *)arg_ptr)->y_pos));
u8x8_cad_SendCmd(u8x8, 0x0e0 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0f0 | (x>>4) );
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
/*=============================================*/
static const u8x8_display_info_t u8x8_st7588_128x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 150,
/* pre_chip_disable_wait_ns = */ 30,
/* reset_pulse_width_ms = */ 5,
/* post_reset_wait_ms = */ 5, /**/
/* sda_setup_time_ns = */ 60, /* */
/* sck_pulse_width_ns = */ 60, /* */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
/* data_setup_time_ns = */ 80,
/* write_pulse_width_ns = */ 50,
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 0, /* must be 0, because this is checked also for normal mode */
/* flipmode_x_offset = */ 4,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_st7588_128x64_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C( FS | 0x03 ), /* select 11 commands */
U8X8_C( 0x03 ), /* software reset */
U8X8_C( FS | 0x00 ), /* select 00 commands */
U8X8_C( 0x08 ), /* display off */
//U8X8_C( 0x0c ), /* display on */
U8X8_C( FS | 0x01 ), /* select 01 commands */
U8X8_C( 0x08 ), /* display confguration */
U8X8_C( 0x12 ), /* bias 1/9 */
U8X8_C( 0x8f ), /* Vop, lower 7 bits */
U8X8_C( FS | 0x00 ), /* select 00 commands */
U8X8_C( 0x05), /* Bit 0 contains high/low range for Vop */
U8X8_C( FS | 0x03 ), /* select 11 commands */
U8X8_C( 0x0b), /* Frame Rate: 73 Hz */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7588_jlx12864_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C( FS ), /* normal mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7588_jlx12864_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C( FS ^ 0x018 ), /* normal mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_st7588_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
if ( u8x8_d_st7588_128x64_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
return 1;
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
{
u8x8_SetI2CAddress(u8x8, 0x07e); /* the JLX12864 has 0x07e as a default address for I2C */
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7588_128x64_display_info);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_INIT )
{
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_st7588_128x64_init_seq);
return 1;
}
else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
{
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7588_jlx12864_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_st7588_jlx12864_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
return 1;
}
return 0;
}

View File

@ -0,0 +1,233 @@
/*
u8x8_d_st7920.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The ST7920 controller does not support hardware graphics flip.
Contrast adjustment is done by an external resistor --> no support for contrast adjustment
*/
#include "u8x8.h"
static const uint8_t u8x8_d_st7920_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(10),
U8X8_C(0x038), /* 8 Bit interface (DL=1), basic instruction set (RE=0) */
U8X8_C(0x008), /* display on, cursor & blink off; 0x08: all off */
U8X8_C(0x006), /* Entry mode: Cursor move to right ,DDRAM address counter (AC) plus 1, no shift */
U8X8_C(0x002), /* disable scroll, enable CGRAM adress */
U8X8_C(0x001), /* clear RAM, needs 1.6 ms */
U8X8_DLY(4), /* delay 2ms */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7920_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x038), /* 8 Bit interface (DL=1), basic instruction set (RE=0) */
U8X8_C(0x00c), /* display on, cursor & blink off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_st7920_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x038), /* 8 Bit interface (DL=1), basic instruction set (RE=0) */
U8X8_C(0x008), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_st7920_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c, i;
uint8_t *ptr;
switch(msg)
{
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
/*
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
break;
*/
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_st7920_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_st7920_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_st7920_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y*=8;
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x /= 2; /* not sure whether this is a clever idea, problem is, the ST7920 can address only every second tile */
if ( y >= 32 ) /* this is the adjustment for 128x64 displays */
{
y-=32;
x+=8;
}
u8x8_cad_StartTransfer(u8x8);
/*
Tile structure is reused here for the ST7920, however u8x8 is not supported
tile_ptr points to data which has cnt*8 bytes (same as SSD1306 tiles)
Buffer is expected to have 8 lines of code fitting to the ST7920 internal memory
"cnt" includes the number of horizontal bytes. width is equal to cnt*8
Also important: Width must be a multiple of 16 (ST7920 requirement), so cnt must be even.
TODO: Consider arg_int, however arg_int is not used by u8g2
*/
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
/* The following byte is sent to allow the ST7920 to sync up with the data */
/* it solves some issues with garbage data */
u8x8_cad_SendCmd(u8x8, 0x03e ); /* enable extended mode */
u8x8_cad_SendCmd(u8x8, 0x03e ); /* enable extended mode, issue 487 */
for( i = 0; i < 8; i++ )
{
//u8x8_cad_SendCmd(u8x8, 0x03e ); /* enable extended mode */
u8x8_cad_SendCmd(u8x8, 0x080 | (y+i) ); /* y pos */
u8x8_cad_SendCmd(u8x8, 0x080 | x ); /* set x pos */
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
//u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes, send one line of data */
ptr += c;
//u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
}
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}
static const u8x8_display_info_t u8x8_st7920_192x32_display_info =
{
/* chip_enable_level = */ 1,
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 5,
/* pre_chip_disable_wait_ns = */ 5,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140, /* datasheet ST7920 */
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 3, /* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0), 18 Aug 16: changed from 1 to 3 which works for 101 */
/* Arduino mode 3: aktive low clock, but use rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 24,
/* tile_hight = */ 4,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 192,
/* pixel_height = */ 32
};
static const u8x8_display_info_t u8x8_st7920_128x64_display_info =
{
/* chip_enable_level = */ 1,
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 5,
/* pre_chip_disable_wait_ns = */ 5,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140, /* datasheet ST7920 */
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* ST7920+Due work with 1MHz but not with 2MHz, ST7920+Uno works with 2MHz */
/* spi_mode = */ 3, /* active high, rising edge, 18 Aug 16: changed from 1 to 3 which works for 101 */
/* in theory mode 3 should be correct */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
uint8_t u8x8_d_st7920_192x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_192x32_display_info);
break;
default:
return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
uint8_t u8x8_d_st7920_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_128x64_display_info);
break;
default:
return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}

View File

@ -0,0 +1,546 @@
/*
u8x8_d_t6963.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The t6963 controller does not support hardware graphics flip.
Contrast adjustment is done by an external resistor --> no support for contrast adjustment
*/
#include "u8x8.h"
static const uint8_t u8x8_d_t6963_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x098), /* mode register: Display Mode, Graphics on, Text off, Cursor off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_t6963_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x090), /* All Off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_t6963_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t c, i;
uint16_t y;
uint8_t *ptr;
switch(msg)
{
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
/*
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
break;
case U8X8_MSG_DISPLAY_INIT:
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_t6963_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_t6963_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_DRAW_TILE:
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
y*=8;
y*= u8x8->display_info->tile_width;
/* x = ((u8x8_tile_t *)arg_ptr)->x_pos; x is ignored... no u8x8 support */
//u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
u8x8_cad_StartTransfer(u8x8);
//u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
/*
Tile structure is reused here for the t6963, however u8x8 is not supported
tile_ptr points to data which has cnt*8 bytes (same as SSD1306 tiles)
Buffer is expected to have 8 lines of code fitting to the t6963 internal memory
"cnt" includes the number of horizontal bytes. width is equal to cnt*8
TODO: Consider arg_int, however arg_int is not used by u8g2
*/
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
for( i = 0; i < 8; i++ )
{
u8x8_cad_SendArg(u8x8, y&255);
u8x8_cad_SendArg(u8x8, y>>8);
u8x8_cad_SendCmd(u8x8, 0x024 ); /* set adr */
u8x8_cad_SendCmd(u8x8, 0x0b0 ); /* auto write start */
//c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes, send one line of data */
u8x8_cad_SendCmd(u8x8, 0x0b2 ); /* auto write reset */
ptr += u8x8->display_info->tile_width;
y += u8x8->display_info->tile_width;
}
u8x8_cad_EndTransfer(u8x8);
//u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
break;
default:
return 0;
}
return 1;
}
/*=============================================*/
static const u8x8_display_info_t u8x8_t6963_240x128_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 110, /* T6963 Datasheet p30 */
/* pre_chip_disable_wait_ns = */ 100, /* T6963 Datasheet p30 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0,
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 80,
/* write_pulse_width_ns = */ 80,
/* tile_width = */ 30,
/* tile_hight = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 240,
/* pixel_height = */ 128
};
/* 240x128 */
static const uint8_t u8x8_d_t6963_240x128_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(100),
U8X8_AAC(0x00,0x00,0x021), /* low, high, set cursor pos */
U8X8_AAC(0x00,0x00,0x022), /* low, high, set offset */
U8X8_AAC(0x00,0x00,0x040), /* low, high, set text home */
U8X8_AAC(240/8,0x00,0x041), /* low, high, set text columns */
U8X8_AAC(0x00,0x00,0x042), /* low, high, graphics home */
U8X8_AAC(240/8,0x00,0x043), /* low, high, graphics columns */
U8X8_DLY(2), /* delay 2ms */
// mode set
// 0x080: Internal CG, OR Mode
// 0x081: Internal CG, EXOR Mode
// 0x083: Internal CG, AND Mode
// 0x088: External CG, OR Mode
// 0x089: External CG, EXOR Mode
// 0x08B: External CG, AND Mode
U8X8_C(0x080), /* mode register: OR Mode, Internal Character Mode */
// display mode
// 0x090: Display off
// 0x094: Graphic off, text on, cursor off, blink off
// 0x096: Graphic off, text on, cursor on, blink off
// 0x097: Graphic off, text on, cursor on, blink on
// 0x098: Graphic on, text off, cursor off, blink off
// 0x09a: Graphic on, text off, cursor on, blink off
// ...
// 0x09c: Graphic on, text on, cursor off, blink off
// 0x09f: Graphic on, text on, cursor on, blink on
U8X8_C(0x090), /* All Off */
U8X8_AAC(0x00,0x00,0x024), /* low, high, set adr pointer */
U8X8_DLY(100),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_DLY(100),
};
uint8_t u8x8_d_t6963_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_t6963_240x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_t6963_240x128_init_seq);
break;
default:
return u8x8_d_t6963_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
/*=============================================*/
static const u8x8_display_info_t u8x8_t6963_240x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 110, /* T6963 Datasheet p30 */
/* pre_chip_disable_wait_ns = */ 100, /* T6963 Datasheet p30 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0,
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 80,
/* write_pulse_width_ns = */ 80,
/* tile_width = */ 30,
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 240,
/* pixel_height = */ 64
};
/* 240x64 */
static const uint8_t u8x8_d_t6963_240x64_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(100),
U8X8_AAC(0x00,0x00,0x021), /* low, high, set cursor pos */
U8X8_AAC(0x00,0x00,0x022), /* low, high, set offset */
U8X8_AAC(0x00,0x00,0x040), /* low, high, set text home */
U8X8_AAC(240/8,0x00,0x041), /* low, high, set text columns */
U8X8_AAC(0x00,0x00,0x042), /* low, high, graphics home */
U8X8_AAC(240/8,0x00,0x043), /* low, high, graphics columns */
U8X8_DLY(2), /* delay 2ms */
// mode set
// 0x080: Internal CG, OR Mode
// 0x081: Internal CG, EXOR Mode
// 0x083: Internal CG, AND Mode
// 0x088: External CG, OR Mode
// 0x089: External CG, EXOR Mode
// 0x08B: External CG, AND Mode
U8X8_C(0x080), /* mode register: OR Mode, Internal Character Mode */
// display mode
// 0x090: Display off
// 0x094: Graphic off, text on, cursor off, blink off
// 0x096: Graphic off, text on, cursor on, blink off
// 0x097: Graphic off, text on, cursor on, blink on
// 0x098: Graphic on, text off, cursor off, blink off
// 0x09a: Graphic on, text off, cursor on, blink off
// ...
// 0x09c: Graphic on, text on, cursor off, blink off
// 0x09f: Graphic on, text on, cursor on, blink on
U8X8_C(0x090), /* All Off */
U8X8_AAC(0x00,0x00,0x024), /* low, high, set adr pointer */
U8X8_DLY(100),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_DLY(100),
};
uint8_t u8x8_d_t6963_240x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_t6963_240x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_t6963_240x64_init_seq);
break;
default:
return u8x8_d_t6963_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
/*=============================================*/
static const u8x8_display_info_t u8x8_t6963_256x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 110, /* T6963 Datasheet p30 */
/* pre_chip_disable_wait_ns = */ 100, /* T6963 Datasheet p30 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0,
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 80,
/* write_pulse_width_ns = */ 80,
/* tile_width = */ 32,
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 256,
/* pixel_height = */ 64
};
/* 256x64 */
static const uint8_t u8x8_d_t6963_256x64_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(100),
U8X8_AAC(0x00,0x00,0x021), /* low, high, set cursor pos */
U8X8_AAC(0x00,0x00,0x022), /* low, high, set offset */
U8X8_AAC(0x00,0x00,0x040), /* low, high, set text home */
U8X8_AAC(256/8,0x00,0x041), /* low, high, set text columns */
U8X8_AAC(0x00,0x00,0x042), /* low, high, graphics home */
U8X8_AAC(256/8,0x00,0x043), /* low, high, graphics columns */
U8X8_DLY(2), /* delay 2ms */
// mode set
// 0x080: Internal CG, OR Mode
// 0x081: Internal CG, EXOR Mode
// 0x083: Internal CG, AND Mode
// 0x088: External CG, OR Mode
// 0x089: External CG, EXOR Mode
// 0x08B: External CG, AND Mode
U8X8_C(0x080), /* mode register: OR Mode, Internal Character Mode */
// display mode
// 0x090: Display off
// 0x094: Graphic off, text on, cursor off, blink off
// 0x096: Graphic off, text on, cursor on, blink off
// 0x097: Graphic off, text on, cursor on, blink on
// 0x098: Graphic on, text off, cursor off, blink off
// 0x09a: Graphic on, text off, cursor on, blink off
// ...
// 0x09c: Graphic on, text on, cursor off, blink off
// 0x09f: Graphic on, text on, cursor on, blink on
U8X8_C(0x090), /* All Off */
U8X8_AAC(0x00,0x00,0x024), /* low, high, set adr pointer */
U8X8_DLY(100),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_DLY(100),
};
uint8_t u8x8_d_t6963_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_t6963_256x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_t6963_256x64_init_seq);
break;
default:
return u8x8_d_t6963_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
/*=============================================*/
static const u8x8_display_info_t u8x8_t6963_128x64_display_info =
{
/* chip_enable_level = */ 1,
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 10, /* T6963 Datasheet p30 */
/* pre_chip_disable_wait_ns = */ 100, /* T6963 Datasheet p30 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0,
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 80,
/* write_pulse_width_ns = */ 80,
/* tile_width = */ 16,
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
/* 128x64 */
static const uint8_t u8x8_d_t6963_128x64_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(100),
U8X8_AAC(0x00,0x00,0x021), /* low, high, set cursor pos */
U8X8_AAC(0x00,0x00,0x022), /* low, high, set offset */
U8X8_AAC(0x00,0x00,0x040), /* low, high, set text home */
U8X8_AAC(128/8,0x00,0x041), /* low, high, set text columns */
U8X8_AAC(0x00,0x00,0x042), /* low, high, graphics home */
U8X8_AAC(128/8,0x00,0x043), /* low, high, graphics columns */
U8X8_DLY(2), /* delay 2ms */
// mode set
// 0x080: Internal CG, OR Mode
// 0x081: Internal CG, EXOR Mode
// 0x083: Internal CG, AND Mode
// 0x088: External CG, OR Mode
// 0x089: External CG, EXOR Mode
// 0x08B: External CG, AND Mode
U8X8_C(0x080), /* mode register: OR Mode, Internal Character Mode */
// display mode
// 0x090: Display off
// 0x094: Graphic off, text on, cursor off, blink off
// 0x096: Graphic off, text on, cursor on, blink off
// 0x097: Graphic off, text on, cursor on, blink on
// 0x098: Graphic on, text off, cursor off, blink off
// 0x09a: Graphic on, text off, cursor on, blink off
// ...
// 0x09c: Graphic on, text on, cursor off, blink off
// 0x09f: Graphic on, text on, cursor on, blink on
U8X8_C(0x090), /* All Off */
U8X8_AAC(0x00,0x00,0x024), /* low, high, set adr pointer */
U8X8_DLY(100),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_DLY(100),
};
uint8_t u8x8_d_t6963_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_t6963_128x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_t6963_128x64_init_seq);
break;
default:
return u8x8_d_t6963_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}
/*=============================================*/
static const u8x8_display_info_t u8x8_t6963_160x80_display_info =
{
/* chip_enable_level = */ 1,
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 10, /* T6963 Datasheet p30 */
/* pre_chip_disable_wait_ns = */ 100, /* T6963 Datasheet p30 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 20,
/* sck_pulse_width_ns = */ 140,
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0,
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 80,
/* write_pulse_width_ns = */ 80,
/* tile_width = */ 20,
/* tile_hight = */ 10,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 160,
/* pixel_height = */ 80
};
/* 128x64 */
static const uint8_t u8x8_d_t6963_160x80_init_seq[] = {
U8X8_DLY(100),
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(100),
U8X8_AAC(0x00,0x00,0x021), /* low, high, set cursor pos */
U8X8_AAC(0x00,0x00,0x022), /* low, high, set offset */
U8X8_AAC(0x00,0x00,0x040), /* low, high, set text home */
U8X8_AAC(160/8,0x00,0x041), /* low, high, set text columns */
U8X8_AAC(0x00,0x00,0x042), /* low, high, graphics home */
U8X8_AAC(160/8,0x00,0x043), /* low, high, graphics columns */
U8X8_DLY(2), /* delay 2ms */
// mode set
// 0x080: Internal CG, OR Mode
// 0x081: Internal CG, EXOR Mode
// 0x083: Internal CG, AND Mode
// 0x088: External CG, OR Mode
// 0x089: External CG, EXOR Mode
// 0x08B: External CG, AND Mode
U8X8_C(0x080), /* mode register: OR Mode, Internal Character Mode */
// display mode
// 0x090: Display off
// 0x094: Graphic off, text on, cursor off, blink off
// 0x096: Graphic off, text on, cursor on, blink off
// 0x097: Graphic off, text on, cursor on, blink on
// 0x098: Graphic on, text off, cursor off, blink off
// 0x09a: Graphic on, text off, cursor on, blink off
// ...
// 0x09c: Graphic on, text on, cursor off, blink off
// 0x09f: Graphic on, text on, cursor on, blink on
U8X8_C(0x090), /* All Off */
U8X8_AAC(0x00,0x00,0x024), /* low, high, set adr pointer */
U8X8_DLY(100),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_DLY(100),
};
uint8_t u8x8_d_t6963_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_t6963_160x80_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_t6963_160x80_init_seq);
break;
default:
return u8x8_d_t6963_common(u8x8, msg, arg_int, arg_ptr);
}
return 1;
}

View File

@ -0,0 +1,188 @@
/*
u8x8_d_uc1601.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This is for the uc1601s controller
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1601_128x32_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1601_128x32_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1601_128x32_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c4), /* bit 1: MX, bit 2: MY */
U8X8_C(0x060), /* set display start line to 32 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1601_128x32_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c2), /* bit 1: MX, bit 2: MY */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_uc1601_128x32_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 1, /* uc1601 datasheet, page 46 */
/* pre_chip_disable_wait_ns = */ 5, /* uc1601 datasheet, page 46 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 12, /* uc1601 datasheet, page 44 */
/* sck_pulse_width_ns = */ 15, /* uc1601 datasheet, page 44 */
/* sck_clock_hz = */ 2000000UL, /* */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 1,
/* data_setup_time_ns = */ 60, /* uc1601 datasheet, page 43 */
/* write_pulse_width_ns = */ 80, /* uc1601 datasheet, page 43 */
/* tile_width = */ 16,
/* tile_hight = */ 4,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 4,
/* pixel_width = */ 128,
/* pixel_height = */ 32
};
static const uint8_t u8x8_d_uc1601_128x32_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_C(0x0eb), /* LCD Bias: 0xe8: 6, 0xe9: 7, 0xea: 8, 0xeb: 9 */
//U8X8_C(0x023), /* 0x020...0x023 only for UC1601, not for UC1601s */
//U8X8_C(0x02e), /* LCD Load + Internal Charge Pump (default: 0x2e) */
U8X8_C(0x024), /* Temperature Compenstation, default: 0x24 */
U8X8_C(0x089), /* RAM address ctrl, default: 0x89 */
U8X8_C(0x0c4), /* RAM mapping ctrl */
U8X8_C(0x0a0), /* Frame Rate, 0x0a0 or 0x0a1 */
U8X8_CA(0x081, 0x0df), /* set contrast */
U8X8_C(0x02e), /* LCD Load + Internal Charge Pump (default: 0x2e) */
U8X8_C(0x060), /* set display start line to 32 */
U8X8_C(0x0a6), /* normal display */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1601_128x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1601_128x32_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1601_128x32_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1601_128x32_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1601_128x32_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1601_128x32_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1601_128x32_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* uc1601 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,240 @@
/*
u8x8_d_uc1604.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1604_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_DLY(20),
U8X8_C(0x0af), /* display on */
U8X8_DLY(20), /* during setup, it seems that the startup is more reliable when sending this cmd twice */
U8X8_C(0x0af), /* display on */
U8X8_DLY(50), /* startup takes some time */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1604_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off, enter sleep mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1604_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c4), /* LCD Mapping */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1604_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c2), /* LCD Mapping */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1604_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
y = ((u8x8_tile_t *)arg_ptr)->y_pos;
y += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x0b0 | (y&15));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
/* handled in the calling procedure
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1604_128x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1604_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1604_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1604_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1604_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* uc1604 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
default:
return 0;
}
return 1;
}
/*================================================*/
/* JLX19264 */
/*
timings from uc1608
UC1604 has two chip select inputs (CS0 and CS1).
CS0 is low active, CS1 is high active. It will depend on the display
module whether the display has a is low or high active chip select.
*/
static const u8x8_display_info_t u8x8_uc1604_192x64_display_info =
{
/* chip_enable_level = */ 0, /* JLX19264G uses CS0, which is low active CS*/
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 20,
/* pre_chip_disable_wait_ns = */ 20,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 10,
/* sda_setup_time_ns = */ 30,
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 35,
/* tile_width = */ 24, /* width of 24*8=192 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0, /* reused as y page offset */
/* flipmode_x_offset = */ 0, /* reused as y page offset */
/* pixel_width = */ 192,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_uc1604_jlx19264_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_DLY(200),
U8X8_DLY(200),
U8X8_C(0x02f), /* power on, Bit 2 PC2=1 (internal charge pump), Bits 0/1: cap of panel */
U8X8_DLY(200),
U8X8_DLY(200),
U8X8_CA(0x081, 0x052), /* set contrast, JLX19264G suggestion: 0x045 */
U8X8_C(0x0eb), /* LCD bias Bits 0/1: 00=6 01=7, 10=8, 11=9 */
//U8X8_C(0x023), /* Bit 0/1: Temp compenstation, Bit 2: Multiplex Rate 0=96, 1=128 */
//U8X8_C(0x027), /* Bit 0/1: Temp compenstation, Bit 2: Multiplex Rate 0=96, 1=128 */
U8X8_C(0x0c4), /* Map control, Bit 2: MY=1, Bit 1: MX=0 */
U8X8_C(0x0a0), /* 0xa0: 76Hz FPS, controller default: 0x0a1: 95Hz FPS */
U8X8_C(0x040), /* set scroll line to 0 */
U8X8_C(0x089), /* RAM access control (controller default: 0x089)*/
U8X8_C(0x000), /* column low nibble */
U8X8_C(0x010), /* column high nibble */
U8X8_C(0x0b0), /* page adr */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1604_jlx19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_uc1604_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1604_192x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1604_jlx19264_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}

View File

@ -0,0 +1,393 @@
/*
u8x8_d_uc1608.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1608_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1608_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off, enter sleep mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1608_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c8), /* LCD Mapping */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1608_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c4), /* LCD Mapping */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1608_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
y = ((u8x8_tile_t *)arg_ptr)->y_pos;
y += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x0b0 | (y&15));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
/* handled in the calling procedure
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1608_128x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1608_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1608_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1608_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1608_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* uc1608 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
default:
return 0;
}
return 1;
}
/*================================================*/
/* ERC24064-1 */
/*
The UC1608 has only one high active chip select input.
UC1604, UC1610 and UC1611 have two chip select inputs.
*/
static const u8x8_display_info_t u8x8_uc1608_240x64_display_info =
{
/* chip_enable_level = */ 1, /* uc1608 has high active CS */
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 10, /* uc1608 datasheet, page 39, actually 0 */
/* pre_chip_disable_wait_ns = */ 20, /* uc1608 datasheet, page 39 */
/* reset_pulse_width_ms = */ 1, /* uc1608 datasheet, page 42 */
/* post_reset_wait_ms = */ 10,
/* sda_setup_time_ns = */ 30, /* uc1608 datasheet, page 41 */
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30, /* uc1608 datasheet, page 39 */
/* write_pulse_width_ns = */ 35, /* uc1608 datasheet, page 39 */
/* tile_width = */ 30, /* width of 30*8=240 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0, /* reused as y page offset */
/* flipmode_x_offset = */ 4, /* reused as y page offset */
/* pixel_width = */ 240,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_uc1608_erc24064_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_DLY(200),
U8X8_C(0x023), /* Bit 0/1: Temp compenstation, Bit 2: Multiplex Rate 0=96, 1=128 */
//U8X8_C(0x027), /* Bit 0/1: Temp compenstation, Bit 2: Multiplex Rate 0=96, 1=128 */
U8X8_C(0x0c8), /* Map control, Bit 3: MY=1, Bit 2: MX=0, Bit 0: MSF =0 */
U8X8_C(0x0e8), /* LCD bias Bits 0/1: 00=10.7 01=10.3, 10=12.0, 11=12.7 */
U8X8_C(0x02f), /* power on, Bit 2 PC2=1 (internal charge pump), Bits 0/1: cap of panel */
U8X8_DLY(50),
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x090), /* no fixed lines */
U8X8_C(0x089), /* RAM access control */
U8X8_CA(0x081, 0x014), /* set contrast, ERC24064-1 default: 0x040 */
U8X8_C(0x000), /* column low nibble */
U8X8_C(0x010), /* column high nibble */
U8X8_C(0x0b0), /* page adr */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1608_erc24064(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_uc1608_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1608_240x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1608_erc24064_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/
/* experimental implementation for the uc1608 240x128, not referenced in codebuild */
static const u8x8_display_info_t u8x8_uc1608_240x128_display_info =
{
/* chip_enable_level = */ 1, /* uc1608 has high active CS */
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 10, /* uc1608 datasheet, page 39, actually 0 */
/* pre_chip_disable_wait_ns = */ 20, /* uc1608 datasheet, page 39 */
/* reset_pulse_width_ms = */ 1, /* uc1608 datasheet, page 42 */
/* post_reset_wait_ms = */ 10,
/* sda_setup_time_ns = */ 30, /* uc1608 datasheet, page 41 */
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30, /* uc1608 datasheet, page 39 */
/* write_pulse_width_ns = */ 35, /* uc1608 datasheet, page 39 */
/* tile_width = */ 30, /* width of 30*8=240 pixel */
/* tile_hight = */ 16,
/* default_x_offset = */ 0, /* reused as y page offset */
/* flipmode_x_offset = */ 0, /* reused as y page offset */
/* pixel_width = */ 240,
/* pixel_height = */ 128
};
static const uint8_t u8x8_d_uc1608_240x128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_DLY(200),
//U8X8_C(0x023), /* Bit 0/1: Temp compenstation, Bit 2: Multiplex Rate 0=96, 1=128 */
U8X8_C(0x026), /* Bit 0/1: Temp compenstation, Bit 2: Multiplex Rate 0=96, 1=128 */
U8X8_C(0x0c8), /* Map control, Bit 3: MY=1, Bit 2: MX=0, Bit 0: MSF =0 */
U8X8_C(0x0ea), /* LCD bias Bits 0/1: 00=10.7 01=10.3, 10=12.0, 11=12.7 */
/* maybe 0x0eb??? */
U8X8_C(0x02f), /* power on, Bit 2 PC2=1 (internal charge pump), Bits 0/1: cap of panel */
U8X8_DLY(50),
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x090), /* no fixed lines */
U8X8_C(0x089), /* RAM access control */
U8X8_CA(0x081, 0x072), /* set contrast */
U8X8_C(0x000), /* column low nibble */
U8X8_C(0x010), /* column high nibble */
U8X8_C(0x0b0), /* page adr */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1608_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_uc1608_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1608_240x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1608_240x128_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/
/* experimental implementation for the uc1608 erc240x120 */
static const u8x8_display_info_t u8x8_uc1608_erc240120_display_info =
{
/* chip_enable_level = */ 1, /* uc1608 has high active CS */
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 10, /* uc1608 datasheet, page 39, actually 0 */
/* pre_chip_disable_wait_ns = */ 20, /* uc1608 datasheet, page 39 */
/* reset_pulse_width_ms = */ 1, /* uc1608 datasheet, page 42 */
/* post_reset_wait_ms = */ 10,
/* sda_setup_time_ns = */ 30, /* uc1608 datasheet, page 41 */
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30, /* uc1608 datasheet, page 39 */
/* write_pulse_width_ns = */ 35, /* uc1608 datasheet, page 39 */
/* tile_width = */ 30, /* width of 30*8=240 pixel */
/* tile_hight = */ 15,
/* default_x_offset = */ 1, /* reused as y page offset */
/* flipmode_x_offset = */ 0, /* reused as y page offset */
/* pixel_width = */ 240,
/* pixel_height = */ 120
};
/* http://www.buydisplay.com/download/democode/ERC240120-1_DemoCode.txt */
static const uint8_t u8x8_d_uc1608_erc240120_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_DLY(200),
//U8X8_C(0x023), /* Bit 0/1: Temp compenstation, Bit 2: Multiplex Rate 0=96, 1=128 */
U8X8_C(0x026), /* Bit 0/1: Temp compenstation, Bit 2: Multiplex Rate 0=96, 1=128 */
U8X8_C(0x0c8), /* Map control, Bit 3: MY=1, Bit 2: MX=0, Bit 0: MSF =0 */
U8X8_C(0x0ea), /* LCD bias Bits 0/1: 00=10.7 01=10.3, 10=12.0, 11=12.7 */
/* according to DemoCode.txt */
U8X8_C(0x02f), /* power on, Bit 2 PC2=1 (internal charge pump), Bits 0/1: cap of panel */
U8X8_DLY(50),
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x090), /* no fixed lines */
U8X8_C(0x089), /* RAM access control */
//U8X8_CA(0x081, 46), /* set contrast, 46 according to DemoCode.txt */
U8X8_CA(0x081, 80), /* */
U8X8_C(0x000), /* column low nibble */
U8X8_C(0x010), /* column high nibble */
U8X8_C(0x0b0), /* page adr */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1608_erc240120(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_uc1608_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1608_erc240120_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1608_erc240120_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/

View File

@ -0,0 +1,304 @@
/*
u8x8_d_uc1610.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cad001
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1610_dogxl160_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0f1, 0x067), /* set COM end (display height-1) */
U8X8_C(0x0c0), /* SEG & COM normal */
U8X8_C(0x040), /* set scroll line lsb to zero */
U8X8_C(0x050), /* set scroll line msb to zero */
U8X8_C(0x02b), /* set panelloading */
U8X8_C(0x0eb), /* set bias 1/2 */
U8X8_CA(0x081, 0x05f), /* set contrast */
/*
AC0: 0: stop at boundary, 1: increment by one
AC1: 0: first column then page, 1: first page, then column increment
AC2: 0: increment page adr, 1: decrement page adr.
*/
U8X8_C(0x08b), /* set auto increment, low bits are AC2 AC1 AC0 */
/*
LC0: 0
MX: Mirror X
MY: Mirror Y
*/
U8X8_C(0x0c0), /* low bits are MY, MX, LC0 */
U8X8_C(0x0f8), // window mode off
U8X8_C(0x010), // col high
U8X8_C(0x000), // col low
U8X8_C(0x0b0), // page
U8X8_C(0x0a6), /* set normal pixel mode (not inverse) */
U8X8_C(0x0a4), /* set normal pixel mode (not all on) */
/* test code
U8X8_C(0x0af), // display on
U8X8_C(0x0f8), // window mode off
U8X8_CA(0x0f4, 0), // set window
U8X8_CA(0x0f5, 0),
U8X8_CA(0x0f6, 4),
U8X8_CA(0x0f7, 1),
U8X8_C(0x0f9), // window mode on
U8X8_D1(0x03),
U8X8_D1(0x0c0),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
*/
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1610_dogxl160_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on, UC1610 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1610_dogxl160_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off, UC1610 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1610_dogxl160_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
/*
LC0: 0
MX: Mirror X
MY: Mirror Y
*/
U8X8_C(0x0c0), /* low bits are MY, MX, LC0 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1610_dogxl160_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
/*
LC0: 0
MX: Mirror X
MY: Mirror Y
*/
U8X8_C(0x0c6), /* low bits are MY, MX, LC0 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/*
UC1610 has two chip select inputs (CS0 and CS1).
CS0 is low active, CS1 is high active. It will depend on the display
module whether the display has a is low or high active chip select.
*/
static const u8x8_display_info_t u8x8_uc1610_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 15,
/* pre_chip_disable_wait_ns = */ 15,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 30,
/* sck_pulse_width_ns = */ 63, /* half of cycle time (125ns cycle time according to datasheet) --> 8MHz clock */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 20,
/* tile_hight = */ 13, /* height of 13*8=104 pixel */
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 160,
/* pixel_height = */ 104
};
/*
RAM Organization:
D0 Pix0
D1
D2 Pix1
D3
D4 Pix2
D5
D6 Pix3
D7
D0 Pix4
D1
D2 Pix5
D3
D4 Pix6
D5
D6 Pix7
D7
*/
static uint8_t *u8x8_convert_tile_for_uc1610(uint8_t *t)
{
uint8_t i;
uint16_t r;
static uint8_t buf[16];
uint8_t *pbuf = buf;
for( i = 0; i < 8; i++ )
{
r = u8x8_upscale_byte(*t++);
*pbuf++ = r & 255;
r >>= 8;
*pbuf++ = r;
}
return buf;
}
uint8_t u8x8_d_uc1610_ea_dogxl160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c, page;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1610_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1610_dogxl160_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1610_dogxl160_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1610_dogxl160_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1610_dogxl160_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1610_dogxl160_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* uc1610 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
page = (((u8x8_tile_t *)arg_ptr)->y_pos);
page *= 2;
u8x8_cad_SendCmd(u8x8, 0x0f8 ); /* window disable */
//u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
//u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
//u8x8_cad_SendCmd(u8x8, 0x0b0 | page);
u8x8_cad_SendCmd(u8x8, 0x0f4 ); /* window start column */
u8x8_cad_SendArg(u8x8, x);
u8x8_cad_SendCmd(u8x8, 0x0f5 ); /* window start page */
u8x8_cad_SendArg(u8x8, page);
u8x8_cad_SendCmd(u8x8, 0x0f6 ); /* window end column */
u8x8_cad_SendArg(u8x8, 159); /* end of display */
u8x8_cad_SendCmd(u8x8, 0x0f7 ); /* window end page */
u8x8_cad_SendArg(u8x8, page+1);
u8x8_cad_SendCmd(u8x8, 0x0f9 ); /* window enable */
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, 16, u8x8_convert_tile_for_uc1610(ptr));
ptr += 8;
x += 8;
c--;
} while( c > 0 );
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,502 @@
/*
u8x8_d_uc1611.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6 Nov 2016: Not yet finished
There are two controller:
UC1611s 160x256
UC1611 160x240
Differences:
UC1611 0xa8 cmd: enables 80 display rows
UC1611s 0xa8 cmd: controlls graylevels
UC1611 0xc0 cmd: single byte command for LCD mapping control
UC1611s 0xc0 cmd: double byte command for LCD mapping control
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1611s_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a9), /* display on, UC1611s */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1611s_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a8), /* display off, enter sleep mode, UC1611s */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1611s_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1611s_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0c0, 0x002), /* LCD Mapping */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1611_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
y = ((u8x8_tile_t *)arg_ptr)->y_pos;
u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
/* handled in the calling procedure
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_128x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
break;
*/
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* uc1611 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
default:
return 0;
}
return 1;
}
/*================================================*/
/* EA DOGM240 */
/*
UC1611 has two chip select inputs (CS0 and CS1).
CS0 is low active, CS1 is high active. It will depend on the display
module whether the display has a is low or high active chip select.
*/
static const u8x8_display_info_t u8x8_uc1611_240x64_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
/* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
/* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
/* sck_pulse_width_ns = */ 60, /* half of cycle time */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
/* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
/* tile_width = */ 30, /* width of 30*8=240 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 240,
/* pixel_height = */ 64
};
static const uint8_t u8x8_d_uc1611_ea_dogm240_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x02f), /* internal pump control */
U8X8_CA(0x0f1, 63), /* set COM end */
U8X8_CA(0x0f2, 0x000), /* display line start */
U8X8_CA(0x0f3, 63), /* display line end */
U8X8_C(0x0a3), /* line rate */
U8X8_CA(0x081, 0x0a4), /* set contrast, EA default: 0x0b7 */
//U8X8_C(0x0a9), /* display enable */
U8X8_C(0x0d1), /* display pattern */
U8X8_C(0x089), /* auto increment */
U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
U8X8_C(0x000), /* column low nibble */
U8X8_C(0x010), /* column high nibble */
U8X8_C(0x060), /* page adr low */
U8X8_C(0x070), /* page adr high */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* UC1611s 240x64 display */
uint8_t u8x8_d_uc1611_ea_dogm240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_uc1611_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_240x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ea_dogm240_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/
/* EA DOGXL240 */
static const uint8_t u8x8_d_uc1611_ea_dogxl240_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x02f), /* internal pump control */
U8X8_CA(0x0f1, 0x07f), /* set COM end */
U8X8_CA(0x0f2, 0x000), /* display line start */
U8X8_CA(0x0f3, 127), /* display line end */
U8X8_C(0x0a3), /* line rate */
U8X8_CA(0x081, 0x08f), /* set contrast */
//U8X8_C(0x0a9), /* display enable */
U8X8_C(0x0d1), /* display pattern */
U8X8_C(0x089), /* auto increment */
U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
U8X8_C(0x000), /* column low nibble */
U8X8_C(0x010), /* column high nibble */
U8X8_C(0x060), /* page adr low */
U8X8_C(0x070), /* page adr high */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_uc1611_240x128_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
/* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
/* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
/* sck_pulse_width_ns = */ 60, /* half of cycle time */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
/* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
/* tile_width = */ 30, /* width of 30*8=240 pixel */
/* tile_hight = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 240,
/* pixel_height = */ 128
};
/* UC1611s 240x128 display */
uint8_t u8x8_d_uc1611_ea_dogxl240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_uc1611_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_240x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ea_dogxl240_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/
/* EMERGING DISPLAY, EW50850FLWP 240x160 */
/* active high CS (CS1), UC1611 display */
static const uint8_t u8x8_d_uc1611_ew50850_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x02f), /* internal pump control */
U8X8_CA(0x0f1, 159), /* set COM end */
U8X8_CA(0x0f2, 0), /* display line start */
U8X8_CA(0x0f3, 159), /* display line end */
U8X8_C(0x0a3), /* line rate */
U8X8_CA(0x081, 75), /* set contrast */
//U8X8_C(0x0a9), /* display enable */
U8X8_C(0x0d2), /* gray level mode: 16 gray shades */
U8X8_C(0x089), /* auto increment */
U8X8_C(0x0c0), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
U8X8_C(0x000), /* column low nibble */
U8X8_C(0x010), /* column high nibble */
U8X8_C(0x060), /* page adr low */
U8X8_C(0x070), /* page adr high */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_uc1611_ew50850_display_info =
{
/* chip_enable_level = */ 1, /* active high */
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
/* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
/* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
/* sck_pulse_width_ns = */ 60, /* half of cycle time */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
/* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
/* tile_width = */ 30, /* width of 30*8=240 pixel */
/* tile_hight = */ 20, /* height: 160 pixel */
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 240,
/* pixel_height = */ 160
};
static const uint8_t u8x8_d_uc1611_alt_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c0), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1611_alt_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c6), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1611_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0af), /* display on, UC1611 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1611_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a8), /* display off, enter sleep mode, UC1611 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
/* EW50850, 240x160 */
uint8_t u8x8_d_uc1611_ew50850(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c, i, v, m0, m1, ai;
uint8_t *ptr;
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
y = ((u8x8_tile_t *)arg_ptr)->y_pos;
y*=4;
m0 = 1;
m1 = 2;
for( i = 0; i < 4; i++ )
{
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
ai = arg_int;
do
{
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
while( c > 0 )
{
v = 0;
if ( *ptr & m0 )
v|= 0x0f;
if ( *ptr & m1 )
v|= 0xf0;
u8x8_cad_SendData(u8x8, 1, &v); /* note: SendData can not handle more than 255 bytes */
c--;
ptr++;
}
ai--;
} while( ai > 0 );
m0 <<= 2;
m1 <<= 2;
y++;
}
u8x8_cad_EndTransfer(u8x8);
break;
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_ew50850_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ew50850_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_alt_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_alt_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* uc1611 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
default:
return 0; /* msg unknown */
}
return 1;
}

View File

@ -0,0 +1,241 @@
/*
u8x8_d_uc1617.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2017, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1617_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ad), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1617_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ac), /* display off, enter sleep mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1617_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c4), /* LCD Mapping */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1617_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c2), /* LCD Mapping */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1617_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
y = ((u8x8_tile_t *)arg_ptr)->y_pos;
u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* uc1617 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
default:
return 0;
}
return 1;
}
/*================================================*/
/* JLX128128 */
static const uint8_t u8x8_d_uc1617_jlx128128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* reset */
U8X8_DLY(10),
//U8X8_D1(0x0ff),
U8X8_C(0x027), /* temperature compensation */
U8X8_C(0x02b), /* panel loading: 13-18nF */
U8X8_C(0x02f), /* internal pump control */
U8X8_C(0x0eb), /* bias=1/11 */
U8X8_CA(0x081, 0x066), /* set contrast */
//U8X8_C(0x0a9), /* used in display datasheet, but cmd not described in controller datasheet */
U8X8_CA(0x0f1, 0x07f), /* set COM end */
U8X8_CA(0x0f2, 0x000), /* display line start */
U8X8_CA(0x0f3, 127), /* display line end */
U8X8_C(0x0a3), /* line rate */
U8X8_C(0x0d3), /* */
U8X8_C(0x0d7), /* */
U8X8_C(0x0ad), /* display enable BW Mode*/
//U8X8_C(0x0af), /* display enable GS Mode*/
//U8X8_C(0x0a5), /* all pixel on */
//U8X8_C(0x0d1), /* display pattern */
U8X8_C(0x089), /* auto increment */
U8X8_C(0x0c4), /* LCD Mapping */
U8X8_C(0x000), /* column */
U8X8_C(0x060), /* page adr low */
U8X8_C(0x070), /* page adr high */
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_D1(0x0ff),
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_uc1617_128x128_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 10, /* uc1617 datasheet, page 54, actually 5 */
/* pre_chip_disable_wait_ns = */ 10, /* uc1617 datasheet, page 54, actually 5 */
/* reset_pulse_width_ms = */ 10,
/* post_reset_wait_ms = */ 20, /* uc1617 datasheet, page 56 */
/* sda_setup_time_ns = */ 24, /* uc1617 datasheet, page 54 */
/* sck_pulse_width_ns = */ 45, /* half of cycle time uc1617 datasheet, page 54*/
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30, /* uc1617 datasheet, page 52 */
/* write_pulse_width_ns = */ 65, /* uc1617 datasheet, page 52 */
/* tile_width = */ 16, /* width of 16*8=128 pixel */
/* tile_hight = */ 16,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 128,
/* pixel_height = */ 128
};
uint8_t u8x8_d_uc1617_jlx128128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_uc1617_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1617_128x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1617_jlx128128_init_seq);
for(;;)
;
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}

View File

@ -0,0 +1,223 @@
/*
u8x8_d_uc1638.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1638_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0c9, 0x0ad), /* display on */ /* UC1638 B/W mode */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1638_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0c9, 0x0ac), /* display off */ /* UC1638 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1638_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c4), /* LCD Mapping */ /* UC1638*/
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1638_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0c2), /* LCD Mapping */ /* UC1638*/
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1638_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, y, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
u8x8_cad_SendCmd(u8x8, 0x004); /* UC1638 */
u8x8_cad_SendArg(u8x8, x);
y = ((u8x8_tile_t *)arg_ptr)->y_pos;
y += u8x8->x_offset;
y *= 2; /* for B/W mode, use only every second page */
u8x8_cad_SendCmd(u8x8, 0x060 | (y&15)); /* UC1638 */
u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4)); /* UC1638 */
u8x8_cad_SendCmd(u8x8, 0x001); /* UC1638 */
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
/* handled in the calling procedure
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1638_128x64_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
break;
*/
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1638_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1638_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1638_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1638_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int ); /* uc1638 has range from 0 to 255 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
default:
return 0;
}
return 1;
}
/*================================================*/
/* uc1638 160x128 */
/* values taken from uc1608 */
static const u8x8_display_info_t u8x8_uc1638_160x128_display_info =
{
/* chip_enable_level = */ 1, /* uc1638 has high active CS */
/* chip_disable_level = */ 0,
/* post_chip_enable_wait_ns = */ 10, /* */
/* pre_chip_disable_wait_ns = */ 20, /* */
/* reset_pulse_width_ms = */ 5, /* */
/* post_reset_wait_ms = */ 150,
/* sda_setup_time_ns = */ 30, /* */
/* sck_pulse_width_ns = */ 65, /* */
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 3, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30, /* */
/* write_pulse_width_ns = */ 35, /* */
/* tile_width = */ 20, /* width of 20*8=160 pixel */
/* tile_hight = */ 16,
/* default_x_offset = */ 0, /* */
/* flipmode_x_offset = */ 0, /* */
/* pixel_width = */ 160,
/* pixel_height = */ 128
};
static const uint8_t u8x8_d_uc1638_160x128_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_CA(0x0e1, 0x0e2), /* software reset */ /* UC1638*/
U8X8_DLY(5), /* 5 ms */
U8X8_C(0x024), /* set temp comp*/
U8X8_C(0x0c0), /* mirror y and mirror x */ /* WAS: c2 */
U8X8_C(0x0a2), /* line rate */
U8X8_C(0x0d6), /* gray scale 2 */
U8X8_C(0x0eb), /* set bias*/
U8X8_C(0x095), /* set 1 bit per pixel, pattern 0*/
U8X8_C(0x089), /* set auto increment, low bits are AC2 AC1 AC0 */ /* WAS 89 */
U8X8_CA(0x081, 0x0a0), /* set contrast */ /* UC1638*/
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
uint8_t u8x8_d_uc1638_160x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* call common procedure first and handle messages there */
if ( u8x8_d_uc1638_common(u8x8, msg, arg_int, arg_ptr) == 0 )
{
/* msg not handled, then try here */
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1638_160x128_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1638_160x128_init_seq);
break;
default:
return 0; /* msg unknown */
}
}
return 1;
}
/*================================================*/

View File

@ -0,0 +1,203 @@
/*
u8x8_d_uc1701_dogs102.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1701_dogs102_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x0a1), /* ADC set to reverse */
U8X8_C(0x0c0), /* common output mode */
// Flipmode
//U8X8_C(0x0a0), /* ADC set to reverse */
//U8X8_C(0x0c8), /* common output mode */
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
U8X8_C(0x0a2), /* LCD bias 1/9 */
U8X8_C(0x02f), /* all power control circuits on */
U8X8_C(0x027), /* regulator, booster and follower */
U8X8_CA(0x081, 0x00e), /* set contrast, contrast value, EA default: 0x010, previous value for S102: 0x0e */
U8X8_C(0x0fa), /* Set Temp compensation */
U8X8_C(0x090), /* 0.11 deg/c WP Off WC Off*/
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1701_dogs102_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a4), /* all pixel off, issue 142 */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1701_dogs102_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1701_dogs102_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1701_dogs102_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_uc1701_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 5,
/* pre_chip_disable_wait_ns = */ 5,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 12,
/* sck_pulse_width_ns = */ 75, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 13, /* width of 13*8=104 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 30,
/* pixel_width = */ 102,
/* pixel_height = */ 64
};
uint8_t u8x8_d_uc1701_ea_dogs102(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1701_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* uc1701 has range from 0 to 63 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
/*
The following if condition checks the hardware limits of the uc1701
controller: It is not allowed to write beyond the display limits.
This is in fact an issue within flip mode.
*/
if ( c + x > 132u )
{
c = 132u;
c -= x;
}
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,205 @@
/*
u8x8_d_uc1701_mini12864.c (dealextreme, displays from ebay MP3 players)
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const uint8_t u8x8_d_uc1701_mini12864_init_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0e2), /* soft reset */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x040), /* set display start line to 0 */
U8X8_C(0x0a0), /* ADC set to reverse */
U8X8_C(0x0c8), /* common output mode */
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
U8X8_C(0x0a2), /* LCD bias 1/9 */
U8X8_C(0x02f), /* all power control circuits on */
U8X8_C(0x0f8), /* set booster ratio to */
U8X8_C(0x000), /* 4x */
U8X8_C(0x023), /* set V0 voltage resistor ratio to large */
U8X8_C(0x081), /* set contrast */
U8X8_C(0x027), /* contrast value */
U8X8_C(0x0ac), /* indicator */
// 0x000, /* disable */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1701_mini12864_powersave0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a4), /* all pixel off, issue 142 */
U8X8_C(0x0af), /* display on */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1701_mini12864_powersave1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0ae), /* display off */
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1701_mini12864_flip0_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a0), /* segment remap a0/a1*/
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const uint8_t u8x8_d_uc1701_mini12864_flip1_seq[] = {
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
U8X8_C(0x0a1), /* segment remap a0/a1*/
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
U8X8_END_TRANSFER(), /* disable chip */
U8X8_END() /* end of sequence */
};
static const u8x8_display_info_t u8x8_uc1701_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 5,
/* pre_chip_disable_wait_ns = */ 5,
/* reset_pulse_width_ms = */ 1,
/* post_reset_wait_ms = */ 6,
/* sda_setup_time_ns = */ 12,
/* sck_pulse_width_ns = */ 75, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 30,
/* write_pulse_width_ns = */ 40,
/* tile_width = */ 16, /* width of 16*8=128 pixel */
/* tile_hight = */ 8,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 4,
/* pixel_width = */ 128,
/* pixel_height = */ 64
};
uint8_t u8x8_d_uc1701_mini12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t x, c;
uint8_t *ptr;
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1701_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_mini12864_init_seq);
break;
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
if ( arg_int == 0 )
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_mini12864_powersave0_seq);
else
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_mini12864_powersave1_seq);
break;
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
if ( arg_int == 0 )
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_mini12864_flip0_seq);
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
else
{
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_mini12864_flip1_seq);
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
}
break;
#ifdef U8X8_WITH_SET_CONTRAST
case U8X8_MSG_DISPLAY_SET_CONTRAST:
u8x8_cad_StartTransfer(u8x8);
u8x8_cad_SendCmd(u8x8, 0x081 );
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* uc1701 has range from 0 to 63 */
u8x8_cad_EndTransfer(u8x8);
break;
#endif
case U8X8_MSG_DISPLAY_DRAW_TILE:
u8x8_cad_StartTransfer(u8x8);
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
x *= 8;
x += u8x8->x_offset;
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
c = ((u8x8_tile_t *)arg_ptr)->cnt;
c *= 8;
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
/*
The following if condition checks the hardware limits of the uc1701
controller: It is not allowed to write beyond the display limits.
This is in fact an issue within flip mode.
bug: this check should be inside the while loop, see u8x8_d_pcd8544_84x48.c
*/
if ( c + x > 132u )
{
c = 132u;
c -= x;
}
do
{
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
arg_int--;
} while( arg_int > 0 );
u8x8_cad_EndTransfer(u8x8);
break;
default:
return 0;
}
return 1;
}

View File

@ -0,0 +1,205 @@
/*
u8x8_debounce.c
Key/button simple debounce algorithm (Addon for u8x8)
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static uint8_t u8x8_read_pin_state(u8x8_t *u8x8)
{
uint8_t i;
uint8_t pin_state;
pin_state = 255; /* be compatible with the setup of the default pin setup, which is 255 */
for( i = 0; i < U8X8_PIN_INPUT_CNT; i++ )
{
pin_state <<= 1;
/* the callback function should put the return value into this variable */
u8x8->gpio_result = 1;
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO(i+U8X8_PIN_OUTPUT_CNT), 0);
pin_state |= u8x8->gpio_result & 1;
}
return pin_state;
}
/*
return 0 to U8X8_PIN_INPUT_CNT-1 if there is a difference
return U8X8_PIN_INPUT_CNT if there is no difference
*/
static uint8_t u8x8_find_first_diff(uint8_t a, uint8_t b)
{
uint8_t mask;
uint8_t i;
mask = 1;
i = U8X8_PIN_INPUT_CNT;
do
{
i--;
if ( (a & mask) != (b & mask) )
return i;
mask <<= 1;
} while( i > 0 );
return U8X8_PIN_INPUT_CNT;
}
/*
State A:
u8x8->debounce_last_pin_state == current_state
--> State A
u8x8->debounce_last_pin_state != current_state
--> u8x8->debounce_last_pin_state = current_state
--> State B + cnt
State B + cnt
--> state--
State B
u8x8->debounce_last_pin_state == current_state
--> keypress detected
--> State C
u8x8->debounce_last_pin_state != current_state
--> State A
State C
u8x8->debounce_last_pin_state == current_state
--> State C
u8x8->debounce_last_pin_state != current_state
--> State A
*/
#ifdef __unix__xxxxxx_THIS_IS_DISABLED
#include <stdio.h>
#include <stdlib.h>
uint8_t u8x8_GetMenuEvent(u8x8_t *u8x8)
{
int c;
c = getc(stdin);
switch(c)
{
case 'n':
return U8X8_MSG_GPIO_MENU_NEXT;
case 'p':
return U8X8_MSG_GPIO_MENU_PREV;
case 's':
return U8X8_MSG_GPIO_MENU_SELECT;
case 'h':
return U8X8_MSG_GPIO_MENU_HOME;
case 'x':
exit(0);
default:
puts("press n, p, s, h or x");
break;
}
return 0;
}
#else /* __unix__ */
#define U8X8_DEBOUNCE_WAIT 2
/* do debounce and return a GPIO msg which indicates the event */
/* returns 0, if there is no event */
#if defined(__GNUC__) && !defined(__CYGWIN__)
# pragma weak u8x8_GetMenuEvent
#endif
uint8_t u8x8_GetMenuEvent(u8x8_t *u8x8)
{
uint8_t pin_state;
uint8_t result_msg = 0; /* invalid message, no event */
pin_state = u8x8_read_pin_state(u8x8);
/* States A, B, C & D are encoded in the upper 4 bit*/
switch(u8x8->debounce_state)
{
case 0x00: /* State A, default state */
if ( u8x8->debounce_default_pin_state != pin_state )
{
//u8x8->debounce_last_pin_state = pin_state;
u8x8->debounce_state = 0x010 + U8X8_DEBOUNCE_WAIT;
}
break;
case 0x10: /* State B */
//if ( u8x8->debounce_last_pin_state != pin_state )
if ( u8x8->debounce_default_pin_state == pin_state )
{
u8x8->debounce_state = 0x00; /* back to state A */
}
else
{
/* keypress detected */
u8x8->debounce_last_pin_state = pin_state;
//result_msg = U8X8_MSG_GPIO_MENU_NEXT;
u8x8->debounce_state = 0x020 + U8X8_DEBOUNCE_WAIT; /* got to state C */
}
break;
case 0x20: /* State C */
if ( u8x8->debounce_last_pin_state != pin_state )
{
u8x8->debounce_state = 0x00; /* back to state A */
}
else
{
u8x8->debounce_state = 0x030; /* got to state D */
}
break;
case 0x30: /* State D */
/* wait until key release */
if ( u8x8->debounce_default_pin_state == pin_state )
{
u8x8->debounce_state = 0x00; /* back to state A */
result_msg = U8X8_MSG_GPIO(u8x8_find_first_diff(u8x8->debounce_default_pin_state, u8x8->debounce_last_pin_state)+U8X8_PIN_OUTPUT_CNT);
}
else
{
//result_msg = U8X8_MSG_GPIO_MENU_NEXT;
// maybe implement autorepeat here
}
break;
default:
u8x8->debounce_state--; /* count down, until there is a valid state */
break;
}
return result_msg;
}
#endif /* __unix__ */

View File

@ -0,0 +1,165 @@
/*
u8x8_display.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Abstraction layer for the graphics controller.
Main goal is the placement of a 8x8 pixel block (tile) on the display.
*/
#include "u8x8.h"
/*==========================================*/
/* internal library function */
/*
this is a helper function for the U8X8_MSG_DISPLAY_SETUP_MEMORY function.
It can be called within the display callback function to carry out the usual standard tasks.
*/
void u8x8_d_helper_display_setup_memory(u8x8_t *u8x8, const u8x8_display_info_t *display_info)
{
/* 1) set display info struct */
u8x8->display_info = display_info;
u8x8->x_offset = u8x8->display_info->default_x_offset;
}
/*
this is a helper function for the U8X8_MSG_DISPLAY_INIT function.
It can be called within the display callback function to carry out the usual standard tasks.
*/
void u8x8_d_helper_display_init(u8x8_t *u8x8)
{
/* 2) apply port directions to the GPIO lines and apply default values for the IO lines*/
u8x8_gpio_Init(u8x8);
u8x8_cad_Init(u8x8);
/* 3) do reset */
u8x8_gpio_SetReset(u8x8, 1);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, u8x8->display_info->reset_pulse_width_ms);
u8x8_gpio_SetReset(u8x8, 0);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, u8x8->display_info->reset_pulse_width_ms);
u8x8_gpio_SetReset(u8x8, 1);
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, u8x8->display_info->post_reset_wait_ms);
}
/*==========================================*/
/* official functions */
uint8_t u8x8_DrawTile(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr)
{
u8x8_tile_t tile;
tile.x_pos = x;
tile.y_pos = y;
tile.cnt = cnt;
tile.tile_ptr = tile_ptr;
return u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_DRAW_TILE, 1, (void *)&tile);
}
/* should be implemented as macro */
void u8x8_SetupMemory(u8x8_t *u8x8)
{
u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_SETUP_MEMORY, 0, NULL);
}
void u8x8_InitDisplay(u8x8_t *u8x8)
{
u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_INIT, 0, NULL);
}
void u8x8_SetPowerSave(u8x8_t *u8x8, uint8_t is_enable)
{
u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_SET_POWER_SAVE, is_enable, NULL);
}
void u8x8_SetFlipMode(u8x8_t *u8x8, uint8_t mode)
{
u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_SET_FLIP_MODE, mode, NULL);
}
void u8x8_SetContrast(u8x8_t *u8x8, uint8_t value)
{
u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_SET_CONTRAST, value, NULL);
}
void u8x8_RefreshDisplay(u8x8_t *u8x8)
{
u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_REFRESH, 0, NULL);
}
void u8x8_ClearDisplayWithTile(u8x8_t *u8x8, const uint8_t *buf)
{
u8x8_tile_t tile;
uint8_t h;
tile.x_pos = 0;
tile.cnt = 1;
tile.tile_ptr = (uint8_t *)buf; /* tile_ptr should be const, but isn't */
h = u8x8->display_info->tile_height;
tile.y_pos = 0;
do
{
u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_DRAW_TILE, u8x8->display_info->tile_width, (void *)&tile);
tile.y_pos++;
} while( tile.y_pos < h );
}
void u8x8_ClearDisplay(u8x8_t *u8x8)
{
uint8_t buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
u8x8_ClearDisplayWithTile(u8x8, buf);
}
void u8x8_FillDisplay(u8x8_t *u8x8)
{
uint8_t buf[8] = { 255, 255, 255, 255, 255, 255, 255, 255 };
u8x8_ClearDisplayWithTile(u8x8, buf);
}
void u8x8_ClearLine(u8x8_t *u8x8, uint8_t line)
{
uint8_t buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
u8x8_tile_t tile;
if ( line < u8x8->display_info->tile_height )
{
tile.x_pos = 0;
tile.y_pos = line;
tile.cnt = 1;
tile.tile_ptr = (uint8_t *)buf; /* tile_ptr should be const, but isn't */
u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_DRAW_TILE, u8x8->display_info->tile_width, (void *)&tile);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
/*
u8x8_gpio.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
void u8x8_gpio_call(u8x8_t *u8x8, uint8_t msg, uint8_t arg)
{
u8x8->gpio_and_delay_cb(u8x8, msg, arg, NULL);
}
/*
void u8x8_gpio_Delay(u8x8_t *u8x8, uint8_t msg, uint8_t dly)
{
u8x8->gpio_and_delay_cb(u8x8, msg, dly, NULL);
}
*/

View File

@ -0,0 +1,123 @@
/*
u8x8_input_value.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/*
return:
0: value is not changed (HOME/Break Button pressed)
1: value has been updated
*/
uint8_t u8x8_UserInterfaceInputValue(u8x8_t *u8x8, const char *title, const char *pre, uint8_t *value, uint8_t lo, uint8_t hi, uint8_t digits, const char *post)
{
uint8_t height;
uint8_t y;
uint8_t width;
uint8_t x;
uint8_t local_value = *value;
uint8_t r;
uint8_t event;
/* calculate overall height of the input value box */
height = 1; /* button line */
height += u8x8_GetStringLineCnt(title);
/* calculate offset from top */
y = 0;
if ( height < u8x8_GetRows(u8x8) )
{
y = u8x8_GetRows(u8x8);
y -= height;
y /= 2;
}
/* calculate offset from left for the label */
x = 0;
width = u8x8_GetUTF8Len(u8x8, pre);
width += digits;
width += u8x8_GetUTF8Len(u8x8, post);
if ( width < u8x8_GetCols(u8x8) )
{
x = u8x8_GetCols(u8x8);
x -= width;
x /= 2;
}
/* render */
u8x8_ClearDisplay(u8x8); /* required, because not everything is filled */
u8x8_SetInverseFont(u8x8, 0);
y += u8x8_DrawUTF8Lines(u8x8, 0, y, u8x8_GetCols(u8x8), title);
x += u8x8_DrawUTF8(u8x8, x, y, pre);
u8x8_DrawUTF8(u8x8, x+digits, y, post);
u8x8_SetInverseFont(u8x8, 1);
/* event loop */
u8x8_DrawUTF8(u8x8, x, y, u8x8_u8toa(local_value, digits));
for(;;)
{
event = u8x8_GetMenuEvent(u8x8);
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
{
*value = local_value;
r = 1;
break;
}
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
{
r = 0;
break;
}
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_UP )
{
if ( local_value >= hi )
local_value = lo;
else
local_value++;
u8x8_DrawUTF8(u8x8, x, y, u8x8_u8toa(local_value, digits));
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_DOWN )
{
if ( local_value <= lo )
local_value = hi;
else
local_value--;
u8x8_DrawUTF8(u8x8, x, y, u8x8_u8toa(local_value, digits));
}
}
u8x8_SetInverseFont(u8x8, 0);
return r;
}

View File

@ -0,0 +1,152 @@
/*
u8x8_message.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
uint8_t u8x8_draw_button_line(u8x8_t *u8x8, uint8_t y, uint8_t w, uint8_t cursor, const char *s)
{
uint8_t i;
uint8_t cnt;
uint8_t total;
uint8_t d;
uint8_t x;
cnt = u8x8_GetStringLineCnt(s);
/* calculate the width of the button */
total = 0;
for( i = 0; i < cnt; i++ )
{
total += u8x8_GetUTF8Len(u8x8, u8x8_GetStringLineStart(i, s));
}
total += (cnt-1); /* had one space between the buttons */
/* calculate the left offset */
d = 0;
if ( total < w )
{
d = w;
d -= total;
d /= 2;
}
/* draw the buttons */
x = d;
u8x8_SetInverseFont(u8x8, 0);
for( i = 0; i < cnt; i++ )
{
if ( i == cursor )
u8x8_SetInverseFont(u8x8, 1);
x+=u8x8_DrawUTF8(u8x8, x, y, u8x8_GetStringLineStart(i, s));
u8x8_SetInverseFont(u8x8, 0);
x+=u8x8_DrawUTF8(u8x8, x, y, " ");
}
/* return the number of buttons */
return cnt;
}
/*
title1: Multiple lines,separated by '\n'
title2: A single line/string which is terminated by '\0' or '\n' . "title2" accepts the return value from u8x8_GetStringLineStart()
title3: Multiple lines,separated by '\n'
buttons: one more more buttons separated by '\n' and terminated with '\0'
*/
uint8_t u8x8_UserInterfaceMessage(u8x8_t *u8x8, const char *title1, const char *title2, const char *title3, const char *buttons)
{
uint8_t height;
uint8_t y;
uint8_t cursor = 0;
uint8_t button_cnt;
uint8_t event;
u8x8_SetInverseFont(u8x8, 0);
/* calculate overall height of the message box */
height = 1; /* button line */
height += u8x8_GetStringLineCnt(title1);
if ( title2 != NULL )
height ++;
height += u8x8_GetStringLineCnt(title3);
/* calculate offset from top */
y = 0;
if ( height < u8x8_GetRows(u8x8) )
{
y = u8x8_GetRows(u8x8);
y -= height;
y /= 2;
}
/* draw message box */
u8x8_ClearDisplay(u8x8); /* required, because not everything is filled */
y += u8x8_DrawUTF8Lines(u8x8, 0, y, u8x8_GetCols(u8x8), title1);
if ( title2 != NULL )
{
u8x8_DrawUTF8Line(u8x8, 0, y, u8x8_GetCols(u8x8), title2);
y++;
}
y += u8x8_DrawUTF8Lines(u8x8, 0, y, u8x8_GetCols(u8x8), title3);
button_cnt = u8x8_draw_button_line(u8x8, y, u8x8_GetCols(u8x8), cursor, buttons);
for(;;)
{
event = u8x8_GetMenuEvent(u8x8);
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
return cursor+1;
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
break;
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_UP )
{
cursor++;
if ( cursor >= button_cnt )
cursor = 0;
u8x8_draw_button_line(u8x8, y, u8x8_GetCols(u8x8), cursor, buttons);
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_DOWN )
{
if ( cursor == 0 )
cursor = button_cnt;
cursor--;
u8x8_draw_button_line(u8x8, y, u8x8_GetCols(u8x8), cursor, buttons);
}
}
return 0;
}

View File

@ -0,0 +1,173 @@
/*
u8x8_selection_list.c
selection list with scroll option
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/*
increase the cursor position
*/
void u8sl_Next(u8sl_t *u8sl)
{
u8sl->current_pos++;
if ( u8sl->current_pos >= u8sl->total )
{
u8sl->current_pos = 0;
u8sl->first_pos = 0;
}
else
{
if ( u8sl->first_pos + u8sl->visible <= u8sl->current_pos + 1 )
{
u8sl->first_pos = u8sl->current_pos - u8sl->visible + 1;
}
}
}
void u8sl_Prev(u8sl_t *u8sl)
{
if ( u8sl->current_pos == 0 )
{
u8sl->current_pos = u8sl->total - 1;
u8sl->first_pos = 0;
if ( u8sl->total > u8sl->visible )
u8sl->first_pos = u8sl->total - u8sl->visible;
}
else
{
u8sl->current_pos--;
if ( u8sl->first_pos > u8sl->current_pos )
u8sl->first_pos = u8sl->current_pos;
}
}
void u8x8_DrawSelectionList(u8x8_t *u8x8, u8sl_t *u8sl, u8x8_sl_cb sl_cb, const void *aux)
{
uint8_t i;
for( i = 0; i < u8sl->visible; i++ )
{
sl_cb(u8x8, u8sl, i+u8sl->first_pos, aux);
}
}
/* selection list with string line */
void u8x8_sl_string_line_cb(u8x8_t *u8x8, u8sl_t *u8sl, uint8_t idx, const void *aux)
{
const char *s;
uint8_t row;
/* calculate offset from display upper border */
row = u8sl->y;
/* calculate target pos */
row += idx;
row -= u8sl->first_pos;
/* check whether this is the current cursor line */
if ( idx == u8sl->current_pos )
u8x8_SetInverseFont(u8x8, 1);
else
u8x8_SetInverseFont(u8x8, 0);
/* get the line from the array */
s = u8x8_GetStringLineStart(idx, (const char *)aux);
/* draw the line */
if ( s == NULL )
s = "";
u8x8_DrawUTF8Line(u8x8, u8sl->x, row, u8x8_GetCols(u8x8), s);
u8x8_SetInverseFont(u8x8, 0);
}
/*
title: NULL for no title, valid str for title line. Can contain mutliple lines, separated by '\n'
start_pos: default position for the cursor (starts with 1)
sl: string list (list of strings separated by \n)
returns 0 if user has pressed the home key
returns the selected line+1 if user has pressed the select key (e.g. 1 for the first line)
*/
uint8_t u8x8_UserInterfaceSelectionList(u8x8_t *u8x8, const char *title, uint8_t start_pos, const char *sl)
{
u8sl_t u8sl;
uint8_t event;
uint8_t title_lines;
if ( start_pos > 0 )
start_pos--;
u8sl.visible = u8x8_GetRows(u8x8);
u8sl.total = u8x8_GetStringLineCnt(sl);
u8sl.first_pos = 0;
u8sl.current_pos = start_pos;
u8sl.x = 0;
u8sl.y = 0;
//u8x8_ClearDisplay(u8x8); /* not required because all is 100% filled */
u8x8_SetInverseFont(u8x8, 0);
if ( title != NULL )
{
title_lines = u8x8_DrawUTF8Lines(u8x8, u8sl.x, u8sl.y, u8x8_GetCols(u8x8), title);
u8sl.y+=title_lines;
u8sl.visible-=title_lines;
}
if ( u8sl.current_pos >= u8sl.total )
u8sl.current_pos = u8sl.total-1;
u8x8_DrawSelectionList(u8x8, &u8sl, u8x8_sl_string_line_cb, sl);
for(;;)
{
event = u8x8_GetMenuEvent(u8x8);
if ( event == U8X8_MSG_GPIO_MENU_SELECT )
return u8sl.current_pos+1;
else if ( event == U8X8_MSG_GPIO_MENU_HOME )
return 0;
else if ( event == U8X8_MSG_GPIO_MENU_NEXT || event == U8X8_MSG_GPIO_MENU_DOWN )
{
u8sl_Next(&u8sl);
u8x8_DrawSelectionList(u8x8, &u8sl, u8x8_sl_string_line_cb, sl);
}
else if ( event == U8X8_MSG_GPIO_MENU_PREV || event == U8X8_MSG_GPIO_MENU_UP )
{
u8sl_Prev(&u8sl);
u8x8_DrawSelectionList(u8x8, &u8sl, u8x8_sl_string_line_cb, sl);
}
}
}

View File

@ -0,0 +1,146 @@
/*
u8x8_setup.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
/* universal dummy callback, which will be default for all callbacks */
uint8_t u8x8_dummy_cb(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
/* the dummy callback will not handle any message and will fail for all messages */
return 0;
}
static const u8x8_display_info_t u8x8_null_display_info =
{
/* chip_enable_level = */ 0,
/* chip_disable_level = */ 1,
/* post_chip_enable_wait_ns = */ 0,
/* pre_chip_disable_wait_ns = */ 0,
/* reset_pulse_width_ms = */ 0,
/* post_reset_wait_ms = */ 0,
/* sda_setup_time_ns = */ 0,
/* sck_pulse_width_ns = */ 0, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* i2c_bus_clock_100kHz = */ 4,
/* data_setup_time_ns = */ 0,
/* write_pulse_width_ns = */ 0,
/* tile_width = */ 1, /* 8x8 */
/* tile_hight = */ 1,
/* default_x_offset = */ 0,
/* flipmode_x_offset = */ 0,
/* pixel_width = */ 8,
/* pixel_height = */ 8
};
/* a special null device */
uint8_t u8x8_d_null_cb(u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
switch(msg)
{
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_null_display_info);
break;
case U8X8_MSG_DISPLAY_INIT:
u8x8_d_helper_display_init(u8x8);
break;
}
/* the null device callback will succeed for all messages */
return 1;
}
/*
Description:
Setup u8x8
Args:
u8x8 An empty u8x8 structure
*/
void u8x8_SetupDefaults(u8x8_t *u8x8)
{
u8x8->display_info = NULL;
u8x8->display_cb = u8x8_dummy_cb;
u8x8->cad_cb = u8x8_dummy_cb;
u8x8->byte_cb = u8x8_dummy_cb;
u8x8->gpio_and_delay_cb = u8x8_dummy_cb;
u8x8->is_font_inverse_mode = 0;
u8x8->device_address = 0;
u8x8->utf8_state = 0; /* also reset by u8x8_utf8_init */
u8x8->i2c_address = 255;
u8x8->debounce_default_pin_state = 255; /* assume all low active buttons */
#ifdef U8X8_USE_PINS
{
uint8_t i;
for( i = 0; i < U8X8_PIN_CNT; i++ )
u8x8->pins[i] = U8X8_PIN_NONE;
}
#endif
}
/*
Description:
Setup u8x8 and assign the callback function. The dummy
callback "u8x8_dummy_cb" can be used, if no callback is required.
This setup will not communicate with the display itself.
Use u8x8_InitDisplay() to send the startup code to the Display.
Args:
u8x8 An empty u8x8 structure
display_cb Display/controller specific callback function
cad_cb Display controller specific communication callback function
byte_cb Display controller/communication specific callback funtion
gpio_and_delay_cb Environment specific callback function
*/
void u8x8_Setup(u8x8_t *u8x8, u8x8_msg_cb display_cb, u8x8_msg_cb cad_cb, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb)
{
/* setup defaults and reset pins to U8X8_PIN_NONE */
u8x8_SetupDefaults(u8x8);
/* setup specific callbacks */
u8x8->display_cb = display_cb;
u8x8->cad_cb = cad_cb;
u8x8->byte_cb = byte_cb;
u8x8->gpio_and_delay_cb = gpio_and_delay_cb;
/* setup display info */
u8x8_SetupMemory(u8x8);
}

View File

@ -0,0 +1,170 @@
/*
u8x8_string.c
string line procedures
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
uint8_t u8x8_GetStringLineCnt(const char *str)
{
char e;
uint8_t line_cnt = 1;
if ( str == NULL )
return 0;
for(;;)
{
e = *str;
if ( e == '\0' )
break;
str++;
if ( e == '\n' )
line_cnt++;
}
return line_cnt;
}
/*
Assumes strings, separated by '\n' in "str".
Returns the string at index "line_idx". First strng has line_idx = 0
Example:
Returns "xyz" for line_idx = 1 with str = "abc\nxyz"
Support both UTF8 and normal strings.
*/
const char *u8x8_GetStringLineStart(uint8_t line_idx, const char *str )
{
char e;
uint8_t line_cnt = 1;
if ( line_idx == 0 )
return str;
for(;;)
{
e = *str;
if ( e == '\0' )
break;
str++;
if ( e == '\n' )
{
if ( line_cnt == line_idx )
return str;
line_cnt++;
}
}
return NULL; /* line not found */
}
/* copy until first '\n' or '\0' in str */
/* Important: There is no string overflow check, ensure */
/* that the destination buffer is large enough */
void u8x8_CopyStringLine(char *dest, uint8_t line_idx, const char *str)
{
if ( dest == NULL )
return;
str = u8x8_GetStringLineStart( line_idx, str );
if ( str != NULL )
{
for(;;)
{
if ( *str == '\n' || *str == '\0' )
break;
*dest = *str;
dest++;
str++;
}
}
*dest = '\0';
}
/*
Draw a string
Extend the string to size "w"
Center the string within "w"
return the size of the string
*/
uint8_t u8x8_DrawUTF8Line(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t w, const char *s)
{
uint8_t d, lw;
uint8_t cx, dx;
d = 0;
lw = u8x8_GetUTF8Len(u8x8, s);
if ( lw < w )
{
d = w;
d -=lw;
d /= 2;
}
cx = x;
dx = cx + d;
while( cx < dx )
{
u8x8_DrawUTF8(u8x8, cx, y, " ");
cx++;
}
cx += u8x8_DrawUTF8(u8x8, cx, y, s);
dx = x + w;
while( cx < dx )
{
u8x8_DrawUTF8(u8x8, cx, y, " ");
cx++;
}
cx -= x;
return cx;
}
/*
draw several lines at position x,y.
lines are stored in s and must be separated with '\n'.
lines can be centered with respect to "w"
if s == NULL nothing is drawn and 0 is returned
returns the number of lines in s
*/
uint8_t u8x8_DrawUTF8Lines(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t w, const char *s)
{
uint8_t i;
uint8_t cnt;
cnt = u8x8_GetStringLineCnt(s);
for( i = 0; i < cnt; i++ )
{
u8x8_DrawUTF8Line(u8x8, x, y, w, u8x8_GetStringLineStart(i, s));
y++;
}
return cnt;
}

View File

@ -0,0 +1,68 @@
/*
u8x8_u16toa.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
const char *u8x8_u16toap(char * dest, uint16_t v)
{
uint8_t pos;
uint8_t d;
uint16_t c;
c = 10000;
for( pos = 0; pos < 5; pos++ )
{
d = '0';
while( v >= c )
{
v -= c;
d++;
}
dest[pos] = d;
c /= 10;
}
dest[5] = '\0';
return dest;
}
/* v = value, d = number of digits */
const char *u8x8_u16toa(uint16_t v, uint8_t d)
{
static char buf[6];
d = 5-d;
return u8x8_u16toap(buf, v) + d;
}

View File

@ -0,0 +1,67 @@
/*
u8x8_u8toa.c
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "u8x8.h"
static const unsigned char u8x8_u8toa_tab[3] = { 100, 10, 1 } ;
const char *u8x8_u8toap(char * dest, uint8_t v)
{
uint8_t pos;
uint8_t d;
uint8_t c;
for( pos = 0; pos < 3; pos++ )
{
d = '0';
c = *(u8x8_u8toa_tab+pos);
while( v >= c )
{
v -= c;
d++;
}
dest[pos] = d;
}
dest[3] = '\0';
return dest;
}
/* v = value, d = number of digits */
const char *u8x8_u8toa(uint8_t v, uint8_t d)
{
static char buf[4];
d = 3-d;
return u8x8_u8toap(buf, v) + d;
}

View File

@ -1,162 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 Matthijs Kooijman
*
* Permission is hereby granted, free of charge, to anyone
* obtaining a copy of this document and accompanying files,
* to do whatever they want with them without any restriction,
* including, but not limited to, copying, modification and redistribution.
* NO WARRANTY OF ANY KIND IS PROVIDED.
*
* This example transmits data on hardcoded channel and receives data
* when not transmitting. Running this sketch on two nodes should allow
* them to communicate.
*******************************************************************************/
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#if !defined(DISABLE_INVERT_IQ_ON_RX)
#error This example requires DISABLE_INVERT_IQ_ON_RX to be set. Update \
config.h in the lmic library to set it.
#endif
// How often to send a packet. Note that this sketch bypasses the normal
// LMIC duty cycle limiting, so when you change anything in this sketch
// (payload length, frequency, spreading factor), be sure to check if
// this interval should not also be increased.
// See this spreadsheet for an easy airtime and duty cycle calculator:
// https://docs.google.com/spreadsheets/d/1voGAtQAjC1qBmaVuP1ApNKs1ekgUjavHuVQIXyYSvNc
#define TX_INTERVAL 2000
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = 6,
.rxtx = LMIC_UNUSED_PIN,
.rst = 5,
.dio = {2, 3, 4},
};
// These callbacks are only used in over-the-air activation, so they are
// left empty here (we cannot leave them out completely unless
// DISABLE_JOIN is set in config.h, otherwise the linker will complain).
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }
void onEvent (ev_t ev) {
}
osjob_t txjob;
osjob_t timeoutjob;
static void tx_func (osjob_t* job);
// Transmit the given string and call the given function afterwards
void tx(const char *str, osjobcb_t func) {
os_radio(RADIO_RST); // Stop RX first
delay(1); // Wait a bit, without this os_radio below asserts, apparently because the state hasn't changed yet
LMIC.dataLen = 0;
while (*str)
LMIC.frame[LMIC.dataLen++] = *str++;
LMIC.osjob.func = func;
os_radio(RADIO_TX);
Serial.println("TX");
}
// Enable rx mode and call func when a packet is received
void rx(osjobcb_t func) {
LMIC.osjob.func = func;
LMIC.rxtime = os_getTime(); // RX _now_
// Enable "continuous" RX (e.g. without a timeout, still stops after
// receiving a packet)
os_radio(RADIO_RXON);
Serial.println("RX");
}
static void rxtimeout_func(osjob_t *job) {
digitalWrite(LED_BUILTIN, LOW); // off
}
static void rx_func (osjob_t* job) {
// Blink once to confirm reception and then keep the led on
digitalWrite(LED_BUILTIN, LOW); // off
delay(10);
digitalWrite(LED_BUILTIN, HIGH); // on
// Timeout RX (i.e. update led status) after 3 periods without RX
os_setTimedCallback(&timeoutjob, os_getTime() + ms2osticks(3*TX_INTERVAL), rxtimeout_func);
// Reschedule TX so that it should not collide with the other side's
// next TX
os_setTimedCallback(&txjob, os_getTime() + ms2osticks(TX_INTERVAL/2), tx_func);
Serial.print("Got ");
Serial.print(LMIC.dataLen);
Serial.println(" bytes");
Serial.write(LMIC.frame, LMIC.dataLen);
Serial.println();
// Restart RX
rx(rx_func);
}
static void txdone_func (osjob_t* job) {
rx(rx_func);
}
// log text to USART and toggle LED
static void tx_func (osjob_t* job) {
// say hello
tx("Hello, world!", txdone_func);
// reschedule job every TX_INTERVAL (plus a bit of random to prevent
// systematic collisions), unless packets are received, then rx_func
// will reschedule at half this time.
os_setTimedCallback(job, os_getTime() + ms2osticks(TX_INTERVAL + random(500)), tx_func);
}
// application entry point
void setup() {
Serial.begin(115200);
Serial.println("Starting");
#ifdef VCC_ENABLE
// For Pinoccio Scout boards
pinMode(VCC_ENABLE, OUTPUT);
digitalWrite(VCC_ENABLE, HIGH);
delay(1000);
#endif
pinMode(LED_BUILTIN, OUTPUT);
// initialize runtime env
os_init();
// Set up these settings once, and use them for both TX and RX
#if defined(CFG_eu868)
// Use a frequency in the g3 which allows 10% duty cycling.
LMIC.freq = 869525000;
#elif defined(CFG_us915)
LMIC.freq = 902300000;
#endif
// Maximum TX power
LMIC.txpow = 27;
// Use a medium spread factor. This can be increased up to SF12 for
// better range, but then the interval should be (significantly)
// lowered to comply with duty cycle limits as well.
LMIC.datarate = DR_SF9;
// This sets CR 4/5, BW125 (except for DR_SF7B, which uses BW250)
LMIC.rps = updr2rps(LMIC.datarate);
Serial.println("Started");
Serial.flush();
// setup initial job
os_setCallback(&txjob, tx_func);
}
void loop() {
// execute scheduled jobs and events
os_runloop_once();
}

View File

@ -1,226 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
*
* Permission is hereby granted, free of charge, to anyone
* obtaining a copy of this document and accompanying files,
* to do whatever they want with them without any restriction,
* including, but not limited to, copying, modification and redistribution.
* NO WARRANTY OF ANY KIND IS PROVIDED.
*
* This example sends a valid LoRaWAN packet with payload "Hello,
* world!", using frequency and encryption settings matching those of
* the The Things Network.
*
* This uses ABP (Activation-by-personalisation), where a DevAddr and
* Session keys are preconfigured (unlike OTAA, where a DevEUI and
* application key is configured, while the DevAddr and session keys are
* assigned/generated in the over-the-air-activation procedure).
*
* Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
* g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
* violated by this sketch when left running for longer)!
*
* To use this sketch, first register your application and device with
* the things network, to set or generate a DevAddr, NwkSKey and
* AppSKey. Each device should have their own unique values for these
* fields.
*
* Do not forget to define the radio type correctly in config.h.
*
*******************************************************************************/
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
// LoRaWAN NwkSKey, network session key
// This is the default Semtech key, which is used by the early prototype TTN
// network.
static const PROGMEM u1_t NWKSKEY[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };
// LoRaWAN AppSKey, application session key
// This is the default Semtech key, which is used by the early prototype TTN
// network.
static const u1_t PROGMEM APPSKEY[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };
// LoRaWAN end-device address (DevAddr)
static const u4_t DEVADDR = 0x03FF0001 ; // <-- Change this address for every node!
// These callbacks are only used in over-the-air activation, so they are
// left empty here (we cannot leave them out completely unless
// DISABLE_JOIN is set in config.h, otherwise the linker will complain).
void os_getArtEui (u1_t* buf) { }
void os_getDevEui (u1_t* buf) { }
void os_getDevKey (u1_t* buf) { }
static uint8_t mydata[] = "Hello, world!";
static osjob_t sendjob;
// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 60;
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = 6,
.rxtx = LMIC_UNUSED_PIN,
.rst = 5,
.dio = {2, 3, 4},
};
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
switch(ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
break;
case EV_JOINED:
Serial.println(F("EV_JOINED"));
break;
case EV_RFU1:
Serial.println(F("EV_RFU1"));
break;
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen) {
Serial.println(F("Received "));
Serial.println(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
default:
Serial.println(F("Unknown event"));
break;
}
}
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
void setup() {
Serial.begin(115200);
Serial.println(F("Starting"));
#ifdef VCC_ENABLE
// For Pinoccio Scout boards
pinMode(VCC_ENABLE, OUTPUT);
digitalWrite(VCC_ENABLE, HIGH);
delay(1000);
#endif
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
// Set static session parameters. Instead of dynamically establishing a session
// by joining the network, precomputed session parameters are be provided.
#ifdef PROGMEM
// On AVR, these values are stored in flash and only copied to RAM
// once. Copy them to a temporary buffer here, LMIC_setSession will
// copy them into a buffer of its own again.
uint8_t appskey[sizeof(APPSKEY)];
uint8_t nwkskey[sizeof(NWKSKEY)];
memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
LMIC_setSession (0x1, DEVADDR, nwkskey, appskey);
#else
// If not running an AVR with PROGMEM, just use the arrays directly
LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY);
#endif
#if defined(CFG_eu868)
// Set up the channels used by the Things Network, which corresponds
// to the defaults of most gateways. Without this, only three base
// channels from the LoRaWAN specification are used, which certainly
// works, so it is good for debugging, but can overload those
// frequencies, so be sure to configure the full frequency range of
// your network here (unless your network autoconfigures them).
// Setting up channels should happen after LMIC_setSession, as that
// configures the minimal channel set.
// NA-US channels 0-71 are configured automatically
LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band
LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band
// TTN defines an additional channel at 869.525Mhz using SF9 for class B
// devices' ping slots. LMIC does not have an easy way to define set this
// frequency and support for class B is spotty and untested, so this
// frequency is not configured here.
#elif defined(CFG_us915)
// NA-US channels 0-71 are configured automatically
// but only one group of 8 should (a subband) should be active
// TTN recommends the second sub band, 1 in a zero based count.
// https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json
LMIC_selectSubBand(1);
#endif
// Disable link check validation
LMIC_setLinkCheckMode(0);
// TTN uses SF9 for its RX2 window.
LMIC.dn2Dr = DR_SF9;
// Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library)
LMIC_setDrTxpow(DR_SF7,14);
// Start job
do_send(&sendjob);
}
void loop() {
os_runloop_once();
}

View File

@ -1,173 +0,0 @@
/*******************************************************************************
* Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman
*
* Permission is hereby granted, free of charge, to anyone
* obtaining a copy of this document and accompanying files,
* to do whatever they want with them without any restriction,
* including, but not limited to, copying, modification and redistribution.
* NO WARRANTY OF ANY KIND IS PROVIDED.
*
* This example sends a valid LoRaWAN packet with payload "Hello,
* world!", using frequency and encryption settings matching those of
* the The Things Network.
*
* This uses OTAA (Over-the-air activation), where where a DevEUI and
* application key is configured, which are used in an over-the-air
* activation procedure where a DevAddr and session keys are
* assigned/generated for use with all further communication.
*
* Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in
* g1, 0.1% in g2), but not the TTN fair usage policy (which is probably
* violated by this sketch when left running for longer)!
* To use this sketch, first register your application and device with
* the things network, to set or generate an AppEUI, DevEUI and AppKey.
* Multiple devices can use the same AppEUI, but each device has its own
* DevEUI and AppKey.
*
* Do not forget to define the radio type correctly in config.h.
*
*******************************************************************************/
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
// This EUI must be in little-endian format, so least-significant-byte
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8]={ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
// The key shown here is the semtech default key.
static const u1_t PROGMEM APPKEY[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
static uint8_t mydata[] = "Hello, world!";
static osjob_t sendjob;
// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 60;
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = 6,
.rxtx = LMIC_UNUSED_PIN,
.rst = 5,
.dio = {2, 3, 4},
};
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
switch(ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
break;
case EV_JOINED:
Serial.println(F("EV_JOINED"));
// Disable link check validation (automatically enabled
// during join, but not supported by TTN at this time).
LMIC_setLinkCheckMode(0);
break;
case EV_RFU1:
Serial.println(F("EV_RFU1"));
break;
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen) {
Serial.println(F("Received "));
Serial.println(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
default:
Serial.println(F("Unknown event"));
break;
}
}
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
void setup() {
Serial.begin(9600);
Serial.println(F("Starting"));
#ifdef VCC_ENABLE
// For Pinoccio Scout boards
pinMode(VCC_ENABLE, OUTPUT);
digitalWrite(VCC_ENABLE, HIGH);
delay(1000);
#endif
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
}
void loop() {
os_runloop_once();
}

Some files were not shown because too many files have changed in this diff Show More