First Commit

This commit is contained in:
MindCreeper03
2025-02-27 19:31:50 +01:00
parent bcbb6aff9a
commit e490df1715
2470 changed files with 1479965 additions and 0 deletions

Binary file not shown.

View File

@@ -0,0 +1,2 @@
LCDAssistant free tool is written by Radoslaw Kwiecien.
Please, visit original site http://en.radzio.dxp.pl/bitmap_converter/

View File

@@ -0,0 +1,26 @@
@rem MIT License
@rem
@rem Copyright (c) 2018, Alexey Dynda
@rem
@rem Permission is hereby granted, free of charge, to any person obtaining a copy
@rem of this software and associated documentation files (the "Software"), to deal
@rem in the Software without restriction, including without limitation the rights
@rem to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@rem copies of the Software, and to permit persons to whom the Software is
@rem furnished to do so, subject to the following conditions:
@rem
@rem The above copyright notice and this permission notice shall be included in all
@rem copies or substantial portions of the Software.
@rem
@rem THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
@rem IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@rem FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@rem AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
@rem LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
@rem OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
@rem SOFTWARE.
@rem
"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-nm.exe" --size-sort -C -r %1 >elfdump.txt
"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-objdump.exe" -C -d %1 >elfdisasm.txt
"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-size.exe" -C %1 > elfsize.txt

View File

@@ -0,0 +1,34 @@
#!/bin/sh
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
if [ "$1" = "" ]; then
echo "Usage: avrparse.sh file.out"
exit 1
fi
avr-nm --size-sort -C -r $1 >elfdump.txt
avr-objdump -C -d $1 >elfdisasm.txt
avr-size -C $1 > elfsize.txt
cat elfsize.txt

View File

@@ -0,0 +1,46 @@
@rem MIT License
@rem
@rem Copyright (c) 2018, Alexey Dynda
@rem
@rem Permission is hereby granted, free of charge, to any person obtaining a copy
@rem of this software and associated documentation files (the "Software"), to deal
@rem in the Software without restriction, including without limitation the rights
@rem to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@rem copies of the Software, and to permit persons to whom the Software is
@rem furnished to do so, subject to the following conditions:
@rem
@rem The above copyright notice and this permission notice shall be included in all
@rem copies or substantial portions of the Software.
@rem
@rem THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
@rem IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@rem FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@rem AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
@rem LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
@rem OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
@rem SOFTWARE.
@rem
@if "%1" == "" goto error
set project=%1
@rem remove quotes and replace backslash
@set sketch_path=%project:"=%
@set sketch_path=%sketch_path:/=\%
@rem mkdir ..\bld\
@mkdir ..\bld\%sketch_path%
@copy /Y sdl\SDL2.dll ..\bld\%sketch_path%\..\
mingw32-make.exe -C ../examples -f Makefile.mingw32 EXTRA_CCFLAGS=%2 SDL_EMULATION=y PROJECT=%project% flash %3
@exit /0
:error
@echo "Usage: build_and_run.bat <project_name> ["flags"] [option]"
@echo " flags:"
@echo " -DARKANOID_SSD1331 to run in SSD1331 RGB color mode"
@echo " -DSDL_NO_BORDER to not draw border around oled display emulator"
@echo " option:"
@echo " "ADAFRUIT=y" to enable Adafruit support"
@echo -
@echo "Example: build_and_run.bat "games/arkanoid" "-DARKANOID_SSD1331 -DSDL_NO_BORDER""

View File

@@ -0,0 +1,87 @@
#!/bin/sh
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# avrdude -c avrisp -p ATtiny85 -P /dev/ttyS6 -b 19200 -U flash:w:../bld/demo.hex
platform=avr
extra_args=
mcu=
flash_target=
print_help_and_exit()
{
echo "Usage: ./build_and_run.sh [options] example [add_build_opts]"
echo "options:"
echo " -p platform to compile for: avr, linux, esp32, stm32"
echo " -m mcu to compiler for: atmega328p, attiny85, etc.."
echo " -f flash controller after build or run executable for Linux"
echo " -e start OLED emulation mode with SDL (Linux only)"
echo " OLED emulation allows to run simple demo without OLED hardware"
echo " OLED emulation mode requires installed libsdl2-dev package"
echo "add_build_opts: (additional options)"
echo " FREQUENCY=<num> frequency in Hz, passed as -DF_CPU=<num> to gcc/g++"
echo " ADAFRUIT=y add Adafruit GFX support to ssd1306 library"
echo ""
echo "# example: run demo on linux with emulator"
echo " ./build_and_run.sh -p linux -e -f demos/ssd1306_demo"
echo "# example: run demo on linux with real ssd1306 oled display"
echo " ./build_and_run.sh -p linux -f demos/ssd1306_demo"
echo "# example: build demo and flash for AVR controller"
echo " ./build_and_run.sh -p avr -m attiny85 -f demos/ssd1306_demo"
echo "# example: build demo for ESP32 controller"
echo " ./build_and_run.sh -p esp32 demos/ssd1306_demo"
exit 1
}
while getopts "fep:m:" opt; do
# echo $opt, $OPTARG
case $opt in
p) platform=$OPTARG;;
m) mcu=$OPTARG;;
f) flash_target=flash;;
e) extra_args="$extra_args SDL_EMULATION=y";;
\?)
echo "Invalid option: -$OPTARG" >&2
print_help_and_exit
;;
:)
echo "Option -$OPTARG requires an argument." >&2
print_help_and_exit
;;
esac
done
shift $((OPTIND-1))
if [ $# = 0 ]; then
print_help_and_exit
fi
project=$1
shift
if [ "$mcu" != "" ]; then
extra_args="MCU=$mcu $extra_args"
fi
make -C ../examples -f Makefile.${platform} PROJECT=${project} ${extra_args} ${flash_target} $@

View File

@@ -0,0 +1,44 @@
============================ SQUIX FORMAT:
WIDTH|HEIGHT|FIRSTCHAR|COUNT|
--- JUMP TABLE:
OFFSET(MSB)|OFFSET(LSB)|BYTES|WIDTH|
--- FONT DATA:
============================ FIXED FONT FORMAT
TYPE|WIDTH|HEIGHT|FIRSTCHAR|
FIRSTUNICODE(MSB)|FIRSTUNICODE(LSB)|COUNT|
--- FONT DATA:
* [COUNT*WIDTH*((HEIGHT+7)/8)]
where:
- TYPE is 0 or 1
- type 0 fonts support only ascii chars with codes 0 - 127, and extended chars with codes 128 - 255.
These fonts can be generated with LCD font generator ONLY.
- type 1 fonts are fixed size, but support unicode tables
These fonts can be generated with fontgenerator.py script in tools folder:
./fontgenerator.py --ttf consola.ttf -s 8 -g 0 127 -f old -d > output.cpp
- WIDTH is fixed width of the font char
- HEIGH is fixed height of the font char
- FIRSTCHAR has meaning only for fonts of type 0 - it is first ascii char code in the glyph table
============================ FREE FONT FORMAT
TYPE|WIDTH|HEIGHT|FIRSTCHAR|
FIRSTUNICODE(MSB)|FIRSTUNICODE(LSB)|COUNT|
--- JUMP TABLE:
OFFSET(MSB)|OFFSET(LSB)|WIDTH|HEIGHT|
--- FONT DATA:
where:
- TYPE is 2 (mandatory)
- WIDTH has no meaning
- HEIGHT is fixed height of the font char
- FIRSTCHAR has no meaning
Free font can be generated with the following command:
Fixed width:
./fontgenerator.py --ttf consola.ttf -s 8 -fw -g 0 127 -f new -d > output.cpp
Variable width:
./fontgenerator.py --ttf consola.ttf -s 8 -g 0 127 -f new -d > output.cpp

View File

@@ -0,0 +1,188 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# MIT License
#
# Copyright (c) 2018-2020, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
###################################################################################
# Linux:
# Fixing pip
# curl https://bootstrap.pypa.io/get-pip.py | python2
# sudo pip install freetype-py
# Win32:
# pip install freetype_py-2.0.0.post6-py2.py3-none-win32.whl
#
# Get fonts
# wget https://ftp.gnu.org/gnu/freefont/freefont-ttf-20120503.zip
import re
import sys
import codecs
from modules import glcdsource
from modules import fontgenerator
def print_help_and_exit():
print("Usage: ttf_fonts.py [args] > outputFile")
print("args:")
print(" --ttf S use ttf name as source")
print(" --glcd S use glcd file as as source")
print(" -s <N> font size (this is not pixels!) ")
print(" -SB <N> limit size in pixels to value (pixels will be cut)")
print(" -fh fixed height")
print(" -fw fixed width")
print(" -g <S> <E> add chars group to the font")
print(" where <S> - first char hex or binary code, or char symbol")
print(" <E> - chars count minus 1 (integer), or char symbol")
print(" -f old old format 1.7.6 and below")
print(" -f new new format 1.7.8 and above")
print(" -d Print demo text to console")
print(" -t text Use text as demo text")
print(" --demo-only Prints demo text to console and exits")
print("Examples:")
print(" [convert ttf font to old format]")
print(" ttf_fonts.py --ttf FreeSans.ttf -s 8 -f old > font.h")
print(" [convert ttf font to new format with demo text and print to console]")
print(" ttf_fonts.py --ttf FreeSans.ttf -d -f new")
print(" [convert GLCD font generated file to new format]")
print(" ttf_fonts.py --glcd font.c -f new > font.h")
exit(1)
if len(sys.argv) < 2:
print_help_and_exit()
fsize = 8
fold = False
flimit_bottom = 0
fwidth = False
fheight = False
fname = ""
fgroups = []
TTF = False
GLCD = False
demo_text = False
demo_text_ = "World!q01"
generate_font = True
source = None
# parse args
idx = 1
while idx < len(sys.argv):
opt = sys.argv[idx]
if opt == "--ttf":
TTF = True
idx += 1
fname = sys.argv[idx]
elif opt == "--glcd":
GLCD = True
idx += 1
fname = sys.argv[idx]
elif opt == "-s":
idx += 1
fsize = int(sys.argv[idx])
elif opt == "-SB":
idx +=1
flimit_bottom = int(sys.argv[idx])
elif opt == "-fh":
fheight = True
elif opt == "-fw":
fwidth = True
elif opt == "-f":
idx += 1
if sys.argv[idx] == "old":
fold = True
elif opt == "-g":
idx += 1
_start_char = sys.argv[idx]
if re.search(r'0x\d*', _start_char) is not None:
code = int(_start_char, 16)
_start_char = unichr(code)
elif _start_char.isdigit() and len(_start_char) > 1:
if sys.version_info < (3, 0):
_start_char = unichr(int(_start_char))
else:
_start_char = chr(int(_start_char))
else:
if sys.version_info < (3, 0):
_start_char = _start_char.decode("utf-8")
idx += 1
_end_char = sys.argv[idx]
if _end_char.isdigit():
if sys.version_info < (3, 0):
_end_char = unichr(ord(_start_char) + int(_end_char))
else:
_end_char = chr(ord(_start_char) + int(_end_char))
else:
if sys.version_info < (3, 0):
_end_char = _end_char.decode("utf-8")
fgroups.append( (_start_char, _end_char ) )
elif opt == "-d":
demo_text = True
elif opt == "-t":
idx += 1
demo_text_ = sys.argv[idx]
elif opt == "--demo-only":
generate_font = False
demo_text = True
else:
print("Unknown option: {0}".format(opt))
print_help_and_exit()
idx += 1
if TTF:
from modules import ttfsource
source = ttfsource.TTFSource(fname, fsize)
if len(fgroups) == 0:
fgroups.append((' ', unichr(127)))
for g in fgroups:
source.add_chars(g[0], g[1])
if GLCD:
source = glcdsource.GLCDSource(fname, fsize, "utf8")
if source is None:
print_help_and_exit()
if fwidth:
source.expand_chars_h()
if fheight:
source.expand_chars_v()
if flimit_bottom > 0:
source.deflate_chars_bottom( flimit_bottom )
font = fontgenerator.Generator( source )
if fold:
source.expand_chars()
if demo_text:
if sys.version_info < (3, 0):
source.printString(demo_text_.decode("utf-8"))
else:
source.printString(demo_text_)
if generate_font:
font.generate_fixed_old()
else:
if demo_text:
if sys.version_info < (3, 0):
source.printString(demo_text_.decode("utf-8"))
else:
source.printString(demo_text_)
if generate_font:
font.generate_new_format()

View File

@@ -0,0 +1,4 @@
#!/bin/sh
cd .. && doxygen doxygen.cfg -w html

View File

@@ -0,0 +1,22 @@
ifndef KERNELDIR
KERNELDIR := /lib/modules/$(shell uname -r)/build
endif
include $(PWD)/src/Makefile.src
obj-m += ssd1306.o
ssd1306-objs := ssd1306_main.o $(OBJS_C)
EXTRA_CFLAGS += -I$(PWD)/../../src -std=gnu99 -Wno-declaration-after-statement
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
/sbin/depmod -ae

View File

@@ -0,0 +1,3 @@
#!/bin/sh
rsync -ru ../../src ./ && make

View File

@@ -0,0 +1,246 @@
/*
MIT License
Copyright (C) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/string.h>
#include "ssd1306.h"
#include "intf/ssd1306_interface.h"
#include "intf/i2c/ssd1306_i2c.h"
#include "font6x8.h"
#define DEVICE_CLASS_NAME "ssd1306_lcd"
static int bus = 1;
static int addr = 0x3C;
static struct i2c_client *s_client = NULL;
static struct ssd1306_data *s_data = NULL;
//static struct class *ssd1306_class = NULL;
module_param(bus, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
module_param(addr, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MODULE_PARM_DESC(bus, " I2C Bus number, default 1");
MODULE_PARM_DESC(addr, " I2C device address, default 0x3C");
struct ssd1306_data {
struct mutex lock;
u8 index;
/// According to https://www.kernel.org/doc/Documentation/i2c/dev-interface
/// block buffers need not be longer than 32 bytes
u8 data[24];
};
static void ssd1306_smbus_end(void);
static void ssd1306_smbus_start(void) {
s_data->index = 0;
}
static void ssd1306_smbus_send(u8 data) {
if (s_data->index >= sizeof(s_data->data)) {
ssd1306_smbus_end();
ssd1306_smbus_start();
s_data->data[0] = 0x40;
s_data->index++;
}
s_data->data[s_data->index] = data;
s_data->index++;
}
static void ssd1306_smbus_send_bytes(const u8 *buffer, u16 size)
{
while (size--) {
ssd1306_smbus_send(*buffer);
buffer++;
}
}
static void ssd1306_smbus_end(void) {
if (s_data->index) {
i2c_smbus_write_i2c_block_data(s_client, s_data->data[0], s_data->index - 1, &s_data->data[1]);
s_data->index=0;
}
}
static void ssd1306_smbus_close(void) {
}
static ssize_t show_commands(struct device *dev,
struct device_attribute *attr, char *buf)
{
// struct ssd1306_data *data = i2c_get_clientdata(to_i2c_client(dev));
return sprintf(buf, "clear\n"
"pixel x,y\n"
);
}
static ssize_t execute_command(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
char cmd[16];
s_client = to_i2c_client(dev);
s_data = i2c_get_clientdata(s_client);
mutex_lock(&s_data->lock);
sscanf(buf, "%15s", cmd);
if (!strcmp(cmd, "clear"))
ssd1306_clearScreen();
else if (!strcmp(cmd, "pixel")) {
int x, y;
sscanf(&buf[strlen(cmd) + 1], "%d,%d", &x, &y);
ssd1306_putPixel(x,y);
}
mutex_unlock(&s_data->lock);
return count;
}
static DEVICE_ATTR(command, S_IWUSR | S_IWGRP | S_IRUGO, show_commands, execute_command);
static struct attribute *ssd1306_attributes[] = {
&dev_attr_command.attr,
NULL
};
static const struct attribute_group ssd1306_attr_group = {
.attrs = ssd1306_attributes,
};
static int ssd1306_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct ssd1306_data *data;
int err;
data = devm_kzalloc(&client->dev, sizeof(struct ssd1306_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
s_data = data;
ssd1306_startTransmission = ssd1306_smbus_start;
ssd1306_endTransmission = ssd1306_smbus_end;
ssd1306_sendByte = ssd1306_smbus_send;
ssd1306_sendBytes = ssd1306_smbus_send_bytes;
ssd1306_closeInterface = ssd1306_smbus_close;
mutex_lock(&data->lock);
s_client = client;
ssd1306_128x64_init();
ssd1306_fillScreen(0x00);
ssd1306_setFixedFont(ssd1306xled_font6x8);
ssd1306_printFixed (0, 8, "Line 1. text", 0); // STYLE_NORMAL
mutex_unlock(&data->lock);
// ssd1306_class = class_create(THIS_MODULE, DEVICE_CLASS_NAME);
/* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj, &ssd1306_attr_group);
if (err)
return err;
return 0;
}
static int ssd1306_remove(struct i2c_client *client)
{
// struct ssd1306_data *data = i2c_get_clientdata(client);
sysfs_remove_group(&client->dev.kobj, &ssd1306_attr_group);
return 0;
}
static const struct i2c_device_id ssd1306_device_id[] = {
{ "ssd1306", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ssd1306_device_id);
static struct i2c_driver ssd1306_driver = {
.probe = ssd1306_probe,
.remove = ssd1306_remove,
.id_table = ssd1306_device_id,
.driver = {
.owner = THIS_MODULE,
.name = "ssd1306"
},
};
static int __init ssd1306_driver_init(void)
{
int ret;
struct i2c_adapter *adapter;
struct i2c_board_info board_info = {
.type = "ssd1306",
.addr = addr,
};
adapter = i2c_get_adapter(bus);
if (!adapter)
return -EINVAL;
s_client = i2c_new_device(adapter, &board_info);
if (!s_client) {
i2c_put_adapter(adapter);
return -EINVAL;
}
ret = i2c_add_driver(&ssd1306_driver);
if (ret) {
i2c_put_adapter(adapter);
return ret;
}
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
i2c_put_adapter(adapter);
dev_err(&s_client->dev, "i2c bus error\n");
return -ENODEV;
}
i2c_put_adapter(adapter);
dev_info(&s_client->dev, "registered ssd1306\n");
return ret;
}
static void __exit ssd1306_driver_exit(void)
{
if (s_client)
i2c_unregister_device(s_client);
i2c_del_driver(&ssd1306_driver);
}
MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Aleksei Dynda <alexey.dynda@gmail.com>");
MODULE_DESCRIPTION("ssd1306 oled control driver");
module_init(ssd1306_driver_init);
module_exit(ssd1306_driver_exit);

View File

@@ -0,0 +1,253 @@
# -*- coding: UTF-8 -*-
# MIT License
#
# Copyright (c) 2018-2019, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
###################################################################################
import sys
class FontContainer:
width = 0
height = 0
# First char is for old format compatibility only
first_char = None
name = " "
face = None
# Char list is for compatibility with old format
_groups = []
def __init__(self, name, size):
self.width = 0
self.height = 0
self.size = size
self._origin_name = name
self.name = name
def get_group_chars(self, group_index = -1):
if group_index < 0:
chars = []
for i in range(len(self._groups)):
chars.extend( self.get_group_chars(i) )
return chars
return map(lambda x: x['char'], self._groups[group_index])
# Adds new group and returns its index
def add_group(self):
self._groups.append([])
return len(self._groups) - 1
def add_char(self, group, char, source, bitmap, width=-1, height=-1, left=-1, top=-1):
self._groups[group].append({})
index = len(self._groups[group]) - 1
if width < 0:
width = len(bitmap[0])
if height < 0:
height = len(bitmap)
if left < 0:
left = 0
if top < 0:
top = height
self._groups[group][index]['char'] = char
self._groups[group][index]['width'] = width
self._groups[group][index]['used_width'] = width
self._groups[group][index]['height'] = height
self._groups[group][index]['source_data'] = source
self._groups[group][index]['left'] = left
self._groups[group][index]['top'] = top
self._groups[group][index]['bitmap'] = bitmap
def groups_count(self):
return len(self._groups)
def printChar(self, ch):
data = self._find_char_data(ch)
if data is None:
return
# print(ch)
# print(data)
# print(data['source_data'])
for row in data['bitmap']:
print("".join('-' if x == 0 else '@' for x in row))
def printString(self, s):
for y in range(self.height):
row = ""
for ch in s:
data = self._find_char_data(ch)
if data is None:
continue
index = y - self.baseline + data['top']
if index < 0 or index >= data['height']:
row += "".join(['-'] * (data['width'] + 1))
continue
row += "".join('-' if x == 0 else '@' for x in data['bitmap'][index])
row += "-"
print("// {0}".format(row))
def charBitmap(self, ch):
data = self._find_char_data(ch)
if data is None:
return None
return data['bitmap']
def rows(self):
return int((self.height + 7) / 8)
def _find_char_data(self, ch):
res = []
for g in self._groups:
res = filter(lambda x: x['char'] == ch, g)
if sys.version_info >= (3, 0):
res = list(res)
if len(res) > 0:
break
return None if len(res) == 0 else res[0]
# Function calculates
# * baseline for the font (the line, where all chars are attached to)
# * width for the font (the width of most wide character)
# * height for the font (the height of most tall character)
def _commit_updates(self):
top = 0
bottom = 0
left = 0
right = 0
for g in self._groups:
for c in g:
top = min([top, 0 - c['top']])
bottom = max([bottom, c['height'] - c['top']])
left = min([left, 0 - c['left']])
right = max([right, c['width'] - c['left']])
self.width = right - left
self.height = bottom - top
self.baseline = -top
self.baseline_h = -left
self.name = self._origin_name + str(self.width) + "x" + str(self.height)
# Function expands character bitmap vertically to top boundary
def __expand_char_top(self, data):
# expand top
for y in range(0, self.baseline - data['top']):
data['bitmap'].insert(0, [0] * data['width'])
data['top'] = self.baseline
data['height'] = len(data['bitmap'])
# Function expands character bitmap vertically to match the tallest char
def __expand_char_v(self, data):
# expand top
for y in range(0, self.baseline - data['top']):
data['bitmap'].insert(0, [0] * data['width'])
for y in range(0, self.height - self.baseline - (data['height'] - data['top'])):
data['bitmap'].append( [0] * data['width'])
data['top'] = self.baseline
data['height'] = self.height
# Function expands character bitmap horizontally to match the widest char
def __expand_char_h(self, data):
# expand top
if self.baseline_h == 0:
before = int((self.width - data['width']) / 2)
after = self.width - data['width'] - before
else:
before = self.baseline_h - data['left']
after = self.width - self.baseline_h - (data['width'] - data['left'])
if before > 0:
for d in data['bitmap']:
for n in range(before):
d.insert(0, 0)
if after > 0:
for d in data['bitmap']: d += [0]*after
data['left'] = self.baseline_h
data['width'] = self.width
# Function expans all chars horizontally to match the widest char
def expand_chars_h(self):
for g in self._groups:
for c in g:
self.__expand_char_h( c )
# Function deflates character bitmap horizontally by left pixels
# from left side and right pixels from right side
def __deflate_char_h(self, data, left=0, right=0):
for d in data['bitmap']:
d = d[left:len(d)-right]
data['width'] -= (left + right)
data['left'] -= left
if data['left'] < 0:
data['left'] = 0
def __deflate_char_v(self, data, top=0, bottom=0):
if top < 0:
data['bitmap'] = [ ([0] * data['width']) for x in range(-top) ] + data['bitmap']
data['height'] -= top
data['top'] -= top
top = 0
if bottom < 0:
data['bitmap'].extend( [ ([0] * data['width']) for x in range(-bottom) ] )
data['height'] -= bottom
bottom = 0
data['bitmap'] = data['bitmap'][top:len(data['bitmap'])-bottom]
data['height'] -= (top + bottom)
data['top'] -= top
if data['top'] < 0:
data['top'] = 0
# Function expands all chars vertically to match the tallest char
def expand_chars_top(self):
for g in self._groups:
for c in g:
self.__expand_char_top( c )
# Function expands all chars vertically to match the tallest char
def expand_chars_v(self):
for g in self._groups:
for c in g:
self.__expand_char_v( c )
# Function expands all char and makes them fixed width and fixed height
def expand_chars(self):
self.expand_chars_v()
self.expand_chars_h()
def deflate_chars(self, left=0, top=0, right=0, bottom=0):
# Calculate maximum parts according to requested change
left_part = self.baseline_h - left
right_part = self.width - self.baseline_h - right
top_part = self.baseline - top
bottom_part = self.height - self.baseline - bottom
for g in self._groups:
for c in g:
# Deflate char only if it is out of font size
left_p = max([c['left'] - left_part, 0])
right_p = max([c['width'] - c['left'] - right_part, 0])
self.__deflate_char_h( c, left_p, right_p )
top_p = max([c['top'] - top_part, 0])
# bottom_p = max([c['height'] - c['top'] - bottom_part, 0])
bottom_p = c['height'] - c['top'] - bottom_part
self.__deflate_char_v( c, top_p, bottom_p )
self._commit_updates()
# Deflate chars from bottom side to specified height
def deflate_chars_bottom(self, height):
bottom = self.height - height
self.deflate_chars(bottom = bottom)

View File

@@ -0,0 +1,149 @@
# -*- coding: UTF-8 -*-
# MIT License
#
# Copyright (c) 2018-2020, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
###################################################################################
# Fixing pip
# curl https://bootstrap.pypa.io/get-pip.py | python2
# sudo pip install freetype-py
#
# Get fonts
# wget https://ftp.gnu.org/gnu/freefont/freefont-ttf-20120503.zip
from __future__ import print_function
import sys
class Generator:
source = None
def __init__(self, source):
self.source = source
def generate_fixed_old(self):
self.source.expand_chars()
print("extern const uint8_t {0}[] PROGMEM;".format(self.source.name))
print("const uint8_t {0}[] PROGMEM =".format(self.source.name))
print("{")
print("#ifdef CONFIG_SSD1306_UNICODE_ENABLE")
print("// type|width|height|first char")
print(" 0x%02X, 0x%02X, 0x%02X, 0x%02X," % (1, self.source.width, self.source.height, self.source.first_char))
print("// unicode(2B)|count")
print(" 0x%02X, 0x%02X, 0x%02X, // unicode record" % \
((self.source.first_char >> 8) & 0xFF, self.source.first_char & 0xFF, \
len(self.source.get_group_chars()) & 0xFF))
print("#else")
print("// type|width|height|first char")
print(" 0x%02X, 0x%02X, 0x%02X, 0x%02X," % (0, self.source.width, self.source.height, self.source.first_char))
print("#endif")
char_code = self.source.first_char
for char in self.source.get_group_chars():
print(" ", end='')
for row in range(self.source.rows()):
for x in range(self.source.width):
data = 0
for i in range(8):
y = row * 8 + i
if y >= self.source.height:
break
data |= (self.source.charBitmap(char)[y][x] << i)
print("0x%02X," % data, end=' ')
if sys.version_info < (3, 0):
print("// char '%s' (0x%04X/%d)" % (char.encode("utf-8"), char_code, char_code))
else:
print("// char '%s' (0x%04X/%d)" % (char, char_code, char_code))
char_code = char_code + 1
print("#ifdef CONFIG_SSD1306_UNICODE_ENABLE")
print(" 0x00, 0x00, 0x00, // end of unicode tables")
print("#endif")
print("};")
def generate_new_format(self):
total_size = 4
self.source.expand_chars_top()
print("extern const uint8_t %s[] PROGMEM;" % ("free_" + self.source.name))
print("const uint8_t %s[] PROGMEM =" % ("free_" + self.source.name))
print("{")
print("// type|width|height|first char")
print(" 0x%02X, 0x%02X, 0x%02X, 0x%02X," % (2, self.source.width, self.source.height, 0x00))
for group in range(self.source.groups_count()):
chars = self.source.get_group_chars(group)
total_size += 3
if sys.version_info < (3, 0):
print("// GROUP first '%s' total %d chars" % (chars[0].encode("utf-8"), len(chars)))
else:
chars = list(chars)
print("// GROUP first '%s' total %d chars" % (chars[0], len(chars)))
print("// unicode(LSB,MSB)|count")
print(" 0x%02X, 0x%02X, 0x%02X, // unicode record" % \
((ord(chars[0]) >> 8) & 0xFF, ord(chars[0]) & 0xFF, len(chars) & 0xFF))
# jump table
offset = 0
heights = []
sizes = []
for char in chars:
bitmap = self.source.charBitmap(char)
print(" ", end = '')
width = len(bitmap[0])
height = len(bitmap)
while (height > 0) and (sum(bitmap[height -1]) == 0):
height -= 1
heights.append( height )
size = int((height + 7) / 8) * width
sizes.append( size )
total_size += 4
print("0x%02X, 0x%02X, 0x%02X, 0x%02X," % (offset >> 8, offset & 0xFF, width, height), end = '')
if sys.version_info < (3, 0):
print("// char '%s' (0x%04X/%d)" % (char.encode("utf-8"), ord(char), ord(char)))
else:
print("// char '%s' (0x%04X/%d)" % (char, ord(char), ord(char)))
offset += size
total_size += 2
print(" 0x%02X, 0x%02X," % (offset >> 8, offset & 0xFF))
# char data
for index in range(len(chars)):
char = chars[index]
bitmap = self.source.charBitmap(char)
print (" ", end='')
size = 0
for row in range(int((heights[index] + 7) / 8)):
for x in range(len(bitmap[0])):
data = 0
for i in range(8):
y = row * 8 + i
if y >= len(bitmap):
break
data |= (self.source.charBitmap(char)[y][x] << i)
total_size += 1
size += 1
print("0x%02X," % data, end=' ')
if sys.version_info < (3, 0):
print("// char '%s' (0x%04X/%d)" % (char.encode("utf-8"), ord(char), ord(char)))
else:
print("// char '%s' (0x%04X/%d)" % (char, ord(char), ord(char)))
if size != sizes[index]:
print("ERROR!!!!")
exit(1)
total_size += 3
print(" 0x00, 0x00, 0x00, // end of unicode tables")
print(" // FONT REQUIRES %d BYTES" % (total_size))
print("};")

View File

@@ -0,0 +1,85 @@
# -*- coding: UTF-8 -*-
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
###################################################################################
#
import os
import sys
import re
import codecs
from . import fontcontainer
class GLCDSource(fontcontainer.FontContainer):
def __init__(self, filename, size, enc):
fontcontainer.FontContainer.__init__(self, filename, size)
if enc is None:
with open(filename) as f:
content = f.readlines()
else:
with codecs.open(filename,'r',encoding=enc) as f:
content = f.readlines()
self.add_group()
for line in content:
bytes_str = line.split(', ')
m = re.search(r'(const unsigned short)\s+(.+?)(\d+)x(\d+)', line)
if m is not None:
width = int(m.group(3))
height = int(m.group(4))
self.first_char = 32
self._origin_name = "%s" % (m.group(2))
elif len(bytes_str) >= 3:
# convert line with data
bytes = []
for e in bytes_str:
if e.find("//") < 0:
bytes.append( int(e, 16) )
else:
if re.search(r'0x\d{2}', e) is not None:
bytes.append( int(e[:4], 16) )
m = re.search(r'char\s(.\w*)', e)
if m is not None:
char = m.group(1)
if char == "BackSlash":
char = "\\"
if len(self.get_group_chars()) == 0:
self.first_char = ord(char[0])
else:
print("Parsing error")
exit(1)
# Cast bitmap from parsed data
bitmap=[]
for y in range(height):
bitmap.append( [] )
for x in range(width):
row = y / 8 + x * ((height + 7) / 8) + 1
bit = y % 8
bitmap[y].append( (bytes[row] >> bit) & 0x01 )
# Add new char
self.add_char(0, char, source=bytes,\
bitmap=bitmap,\
width=width,\
height=height)
self._commit_updates()

View File

@@ -0,0 +1,79 @@
# -*- coding: UTF-8 -*-
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
###################################################################################
# Fixing pip
# curl https://bootstrap.pypa.io/get-pip.py | python2
# sudo pip install freetype-py
#
# Get fonts
# wget https://ftp.gnu.org/gnu/freefont/freefont-ttf-20120503.zip
from . import fontcontainer
import os
import sys
import freetype
class TTFSource(fontcontainer.FontContainer):
face = None
# filename - name of TTF font file (full path is supported)
# size - size of font (not pixels)
def __init__(self, filename, size):
fontname = os.path.basename(os.path.splitext(filename)[0])
fontcontainer.FontContainer.__init__(self, fontname, size)
self.face = freetype.Face( filename )
self.face.set_char_size( width=0, height=(size << 6), hres=96, vres=96 )
def add_chars(self, first, last):
index = self.add_group()
if self.first_char is None:
self.first_char = ord(first)
for code in range(ord(first), ord(last) + 1):
if sys.version_info < (3, 0):
ch = unichr( code )
else:
ch = chr( code )
self.__add_char(index, ch)
self._commit_updates()
def __add_char(self, group_index, ch):
self.face.load_char(ch, freetype.FT_LOAD_MONOCHROME | freetype.FT_LOAD_RENDER )
bitmap = self.face.glyph.bitmap
print(bitmap.buffer)
bitmap_data = []
for y in range( bitmap.rows ):
bitmap_data.append( [] )
for x in range( bitmap.width ):
b_index = y * bitmap.pitch + int(x / 8)
bit = 7 - int(x % 8)
bit_data = (bitmap.buffer[ b_index ] >> bit) & 1
bitmap_data[y].append( bit_data )
self.add_char(group_index, ch,\
source=bitmap.buffer,\
bitmap=bitmap_data,\
width=bitmap.width,\
height=bitmap.rows,\
left=self.face.glyph.bitmap_left,\
top=self.face.glyph.bitmap_top)

View File

@@ -0,0 +1,34 @@
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#################################################################
# Makefile to build ssd1306 examples for Linux
#
# Accept the following parameters:
# CC
# CXX
# STRIP
# AR
# MCU
# FREQUENCY
include Makefile.linux

View File

@@ -0,0 +1,95 @@
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#################################################################
# Makefile to build ssd1306 examples for different platforms
#
# Accept the following parameters:
# CC
# CXX
# STRIP
# AR
#
default: all
DESTDIR ?=
BLD ?= ../../bld
BACKSLASH?=/
OUTFILE?=oled_cli
MKDIR?=mkdir -p
convert=$(subst /,$(BACKSLASH),$1)
.SUFFIXES: .bin .out .hex .srec
$(BLD)/%.o: %.c
-$(MKDIR) $(call convert,$(dir $@))
$(CC) -std=gnu11 $(CCFLAGS) $(CCFLAGS-$@) $(CCFLAGS-$(basename $(notdir $@))) -c $< -o $@
$(BLD)/%.o: %.ino
-$(MKDIR) $(call convert,$(dir $@))
$(CXX) -std=c++11 $(CCFLAGS) $(CXXFLAGS) -x c++ -c $< -o $@
$(BLD)/%.o: %.cpp
-$(MKDIR) $(call convert,$(dir $@))
$(CXX) -std=c++11 $(CCFLAGS) $(CXXFLAGS) $(CCFLAGS-$(basename $(notdir $@))) -c $< -o $@
# ************* Common defines ********************
INCLUDES += \
-I. \
-I../../src
CXXFLAGS += -fno-rtti
CCFLAGS += -MD -g -Os -w -ffreestanding $(INCLUDES) -Wall -Werror \
-Wl,--gc-sections -ffunction-sections -fdata-sections \
$(EXTRA_CCFLAGS)
.PHONY: clean ssd1306 all help
SRCS += main.cpp \
OBJS = $(addprefix $(BLD)/, $(addsuffix .o, $(basename $(SRCS))))
LDFLAGS += -L$(BLD) -lssd1306
####################### Compiling library #########################
ssd1306:
$(MAKE) -C ../../src -f Makefile.$(platform)
all: $(OUTFILE)
$(OUTFILE): $(OBJS) ssd1306
-$(MKDIR) $(call convert,$(dir $@))
$(CC) -o $(OUTFILE) $(CCFLAGS) $(OBJS) $(LDFLAGS)
clean:
rm -rf $(BLD)
rm -f *~ *.out *.bin *.hex *.srec *.s *.o *.pdf *core
help:
@echo "Makefile accepts the following targets:"
@echo " all Build oled_cli tool"
-include $(OBJS:%.o=%.d)

View File

@@ -0,0 +1,40 @@
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#################################################################
# Makefile to build ssd1306 examples for Linux
#
# Accept the following parameters:
# CC
# CXX
# STRIP
# AR
# MCU
# FREQUENCY
default: all
platform?=linux
CCFLAGS += -g -Os -w -ffreestanding
include Makefile.common

View File

@@ -0,0 +1,21 @@
# OLED CLI
## Introduction
oled_cli tool allows to use oled display, connected to raspberry pi, directly from command line.
## Compilation
compile oled_cli tool on your raspberry pi with the command
> make
## Running
example of running oled_cli tool for i2c display
> sudo modprobe i2c-dev<br>
> ./oled_cli i2c 1 0x3c ssd1306_128x64
now you're able to send commands to oled display from command line
> rect 10,10,20,30

View File

@@ -0,0 +1,184 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "ssd1306.h"
#include "intf/ssd1306_interface.h"
#include "intf/i2c/ssd1306_i2c.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int init_interface(char *intf, char *bus, char *devId)
{
if (!strcmp(intf, "spi"))
{
ssd1306_platform_spiInit(bus[0] - '0', strtol(devId, NULL, 16), -1);
}
else if (!strcmp(intf, "i2c"))
{
ssd1306_platform_i2cInit(bus[0] - '0', strtol(devId, NULL, 16), -1);
// ssd1306_i2cInitEx(bus[0] - '0', bus[0] - '0', strtol(devId, NULL, 16));
}
else
{
return -1;
}
return 0;
}
int init_driver(char *driver)
{
if (!strcmp(driver, "ssd1306_128x64")) ssd1306_128x64_init();
else return -1;
ssd1306_fillScreen(0x00);
ssd1306_setFixedFont(ssd1306xled_font6x8);
ssd1306_printFixed (0, 8, "ssd1306 library", STYLE_NORMAL);
return 0;
}
int get_args_list(char *str, char* argv[])
{
int argc = 0;
*argv = str;
argv++;
while (*str)
{
if (*str == '\n') *str = '\0';
if (*str == '\r') *str = '\0';
if ((*str == ' ') || (*str == ','))
{
do
{
*str = '\0';
str++;
}
while (*str == ' ');
if (*str)
{
argc++;
*argv = str;
argv++;
}
}
str++;
}
argc++;
return argc;
}
int atoi_(char *str)
{
return strtol(str, NULL, 10);
}
int atoi_h(char *str)
{
return strtol(str, NULL, 16);
}
int hex2int(char ch)
{
if (ch >= '0' && ch <= '9')
return ch - '0';
if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
return -1;
}
uint8_t *atoi_b(char *str)
{
static uint8_t buffer[4096];
uint8_t *ptr = buffer;
while (*str)
{
uint8_t data = hex2int(*str) << 4;
str++;
if (*str == '\0') break;
data |= hex2int(*str);
*ptr = data;
ptr++;
str++;
}
return buffer;
}
int execute_mono_cmd(int argc, char *argv[])
{
if (!strcmp(argv[0], "quit")) return -1;
else if (!strcmp(argv[0], "clear"))
argc > 1 ? ssd1306_fillScreen(atoi_h(argv[1])) : ssd1306_clearScreen();
else if (!strcmp(argv[0], "rect"))
ssd1306_drawRect(atoi_(argv[1]), atoi_(argv[2]), atoi_(argv[3]), atoi_(argv[4]));
else if (!strcmp(argv[0], "line"))
ssd1306_drawLine(atoi_(argv[1]), atoi_(argv[2]), atoi_(argv[3]), atoi_(argv[4]));
else if (!strcmp(argv[0], "bitmap"))
gfx_drawMonoBitmap(atoi_(argv[1]), atoi_(argv[2]), atoi_(argv[3]), atoi_(argv[4]), atoi_b(argv[5]));
else if (argv[0][0] != '\0')
fprintf(stderr, "commands:\nclear [pattern]\nrect x1,y1,x2,y2\n"
"line x1,y1,x2,y2\n"
"bitmap x1,y1,width,height,bitmap_hex\n");
return 0;
}
int main(int argc, char *argv[])
{
if (argc < 5)
{
fprintf(stderr, "Usage: oled_cli [interface] [bus] [devId] [oled_driver]\n");
fprintf(stderr, " interface - spi, i2c\n");
fprintf(stderr, " bus - i2c-bus number or spidev bus number\n");
fprintf(stderr, " devId - i2c-bus device address or spi device number in hex\n");
fprintf(stderr, " oled_driver - Oled driver name\n");
fprintf(stderr, "Example: oled_cli i2c 1 0x3c ssd1306_128x64\n");
return 1;
}
if (init_interface(argv[1], argv[2], argv[3]) < 0)
{
fprintf(stderr, "Error\n");
return 1;
}
if (init_driver(argv[4]) < 0)
{
fprintf(stderr, "Error2\n");
return 1;
}
fprintf(stderr, "Enter command\n");
char str[16384];
while (fgets(str, sizeof str, stdin))
{
char* arg_list[128];
if (execute_mono_cmd(get_args_list(str, &arg_list[0]), arg_list) < 0)
{
break;
}
}
ssd1306_intf.close();
return 0;
}

View File

@@ -0,0 +1,66 @@
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
###################################################################################
# Fixed font converter for GLCD Creator fonts to internal ssd1306 format
#
import os
import sys
import re
# if len(sys.argv) < 2:
# print "Usage: glcd2ssd1306.py inputFile > outputFile"
# print "Examples:"
# print " glcd2ssd1306.py glcdfont.c > ssd1306font.c"
# exit(1)
# filename = sys.argv[1]
filename = "../examples/games/lode_runner/sprites.cpp"
with open(filename) as f:
content = f.read()
index = 0
#pattern = re.compile(r'(0x[0-9a-fA-F]{1,})')
#name_pattern = re.compile(r'(.*)')
name_pattern = re.compile(r'([\w\d_]+)\s*(PROGMEM\s*){0,1}(\[\s*[\w\d_]*?\s*\]|)*\s*=\s*\{(.*?)\};', re.DOTALL)
#name_pattern = re.compile(r'([\w\d_]+)\s*(PROGMEM\s*){0,1}(\[\s*[\w\d_]*?\s*\]|)*\s*=\s*\{([.\/\w\s\,{}]*?)\};')
pattern = re.compile(r'\{(\s*(0x[0-9a-fA-F]+|0B\d+)\s*,{0,1}\s*)*?\}')
#pattern = re.compile(r'\{(\s*0B\d+\s*,{0,1}\s*)*\}')
all = name_pattern.findall(content)
print all
exit(1)
n = name_pattern.search(content, re.MULTILINE)
print n.start(), n.end()
print n.group(1), n.group(4)
m = pattern.search(content, n.start(), n.end())
print m
print m.group(0)

View File

@@ -0,0 +1,67 @@
# MIT License
#
# Copyright (c) 2018-2019, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#################################################################
# Makefile containing common logic for all systems
default: all
DESTDIR ?=
BLD ?= ../../bld
# ************* Common defines ********************
CPPFLAGS += -I.
CPPFLAGS += -g -Os -Wall -Werror -ffunction-sections -fdata-sections \
-fno-exceptions -Wno-error=deprecated-declarations \
$(EXTRA_CPPFLAGS)
CFLAGS += -std=c99
.PHONY: clean ssd1306_sdl all
OBJS = \
sdl_core.o \
sdl_graphics.o \
sdl_ssd1306.o \
sdl_ssd1325.o \
sdl_ssd1331.o \
sdl_ssd1351.o \
sdl_il9163.o \
sdl_ili9341.o \
sdl_pcd8544.o \
####################### Compiling library #########################
$(BLD)/libssd1306_sdl.a: $(OBJS)
$(AR) rcs $@ $(OBJS)
ssd1306_sdl: $(BLD)/libssd1306_sdl.a
all: ssd1306_sdl
clean:
rm -rf $(BLD)
rm -rf $(OBJS)
rm -rf $(OBJS:%.o=%.d)
rm -rf $(OBJS:.o=.gcno) $(OBJS:.o=.gcda)

View File

@@ -0,0 +1,36 @@
# MIT License
#
# Copyright (c) 2018, Alexey Dynda
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#################################################################
# Makefile containing common logic for all systems
#
# Accepts the following parameters:
# CC
# CXX
# STRIP
# AR
CC=gcc
MKDIR=mkdir
BACKSLASH=\\
include Makefile.linux

Binary file not shown.

View File

@@ -0,0 +1,60 @@
#!/bin/sh
prefix=/usr/local/i686-w64-mingw32
exec_prefix=${prefix}
exec_prefix_set=no
libdir=${exec_prefix}/lib
#usage="\
#Usage: $0 [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs]"
usage="\
Usage: $0 [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs] [--static-libs]"
if test $# -eq 0; then
echo "${usage}" 1>&2
exit 1
fi
while test $# -gt 0; do
case "$1" in
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) optarg= ;;
esac
case $1 in
--prefix=*)
prefix=$optarg
if test $exec_prefix_set = no ; then
exec_prefix=$optarg
fi
;;
--prefix)
echo $prefix
;;
--exec-prefix=*)
exec_prefix=$optarg
exec_prefix_set=yes
;;
--exec-prefix)
echo $exec_prefix
;;
--version)
echo 2.0.7
;;
--cflags)
echo -I${prefix}/include/SDL2 -Dmain=SDL_main
;;
--libs)
echo -L${exec_prefix}/lib -lmingw32 -lSDL2main -lSDL2 -mwindows
;;
--static-libs)
# --libs|--static-libs)
echo -L${exec_prefix}/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -static-libgcc
;;
*)
echo "${usage}" 1>&2
exit 1
;;
esac
shift
done

View File

@@ -0,0 +1,276 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_core.h"
#include "sdl_graphics.h"
#include "sdl_oled_basic.h"
#include "sdl_ssd1306.h"
#include "sdl_ssd1325.h"
#include "sdl_ssd1331.h"
#include "sdl_ssd1351.h"
#include "sdl_il9163.h"
#include "sdl_ili9341.h"
#include "sdl_pcd8544.h"
#include <unistd.h>
#include <SDL2/SDL.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define CANVAS_REFRESH_RATE 60
enum
{
SDL_AUTODETECT,
SDL_DETECTED,
};
static int s_analogInput[128];
static int s_digitalPins[128];
static int s_dcPin = -1;
static uint8_t s_gpioKeys[6] = {0};
static sdl_oled_info *p_oled_db[128] = { NULL };
static sdl_oled_info *p_active_driver = NULL;
int s_commandId = SSD_COMMAND_NONE;
int s_cmdArgIndex;
static int s_ssdMode = SSD_MODE_NONE;
static sdl_data_mode s_active_data_mode = SDM_COMMAND_ARG;
static int s_oled = SDL_AUTODETECT;
static void register_oled(sdl_oled_info *oled_info)
{
sdl_oled_info **p = p_oled_db;
while (*p) (p++);
*p = oled_info;
if ( oled_info->reset )
{
oled_info->reset();
}
}
static void unregister_oleds(void)
{
memset( p_oled_db, 0, sizeof( p_oled_db ) );
p_active_driver = NULL;
}
void sdl_core_init(void)
{
s_commandId = SSD_COMMAND_NONE;
s_ssdMode = SSD_MODE_NONE;
s_active_data_mode = SDM_COMMAND_ARG;
s_oled = SDL_AUTODETECT;
s_dcPin = -1;
memset(s_gpioKeys, 0, sizeof(s_gpioKeys));
register_oled( &sdl_ssd1306 );
register_oled( &sdl_ssd1325 );
register_oled( &sdl_ssd1331x8 );
register_oled( &sdl_ssd1331x16 );
register_oled( &sdl_ssd1351 );
register_oled( &sdl_il9163 );
register_oled( &sdl_ili9341 );
register_oled( &sdl_pcd8544 );
sdl_graphics_init();
}
static void sdl_poll_event(void)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT) exit(0);
switch (event.type)
{
case SDL_KEYDOWN:
if (event.key.keysym.scancode == SDL_SCANCODE_DOWN) { s_analogInput[0] = 300; s_digitalPins[s_gpioKeys[0]] = 1; }
if (event.key.keysym.scancode == SDL_SCANCODE_UP) { s_analogInput[0] = 150; s_digitalPins[s_gpioKeys[3]] = 1; }
if (event.key.keysym.scancode == SDL_SCANCODE_LEFT) { s_analogInput[0] = 500; s_digitalPins[s_gpioKeys[1]] = 1; }
if (event.key.keysym.scancode == SDL_SCANCODE_RIGHT) { s_analogInput[0] = 50; s_digitalPins[s_gpioKeys[2]] = 1; }
if (event.key.keysym.scancode == SDL_SCANCODE_SPACE) { s_analogInput[0] = 700; s_digitalPins[s_gpioKeys[4]] = 1; }
if (event.key.keysym.scancode == SDL_SCANCODE_Z) { s_analogInput[0] = 700; s_digitalPins[s_gpioKeys[4]] = 1; }
if (event.key.keysym.scancode == SDL_SCANCODE_X) { s_digitalPins[s_gpioKeys[5]] = 1; }
break;
case SDL_KEYUP:
if (event.key.keysym.scancode == SDL_SCANCODE_DOWN) { s_analogInput[0] = 1023; s_digitalPins[s_gpioKeys[0]] = 0; }
if (event.key.keysym.scancode == SDL_SCANCODE_UP) { s_analogInput[0] = 1023; s_digitalPins[s_gpioKeys[3]] = 0; }
if (event.key.keysym.scancode == SDL_SCANCODE_LEFT) { s_analogInput[0] = 1023; s_digitalPins[s_gpioKeys[1]] = 0; }
if (event.key.keysym.scancode == SDL_SCANCODE_RIGHT) { s_analogInput[0] = 1023; s_digitalPins[s_gpioKeys[2]] = 0; }
if (event.key.keysym.scancode == SDL_SCANCODE_SPACE) { s_analogInput[0] = 1023; s_digitalPins[s_gpioKeys[4]] = 0; }
if (event.key.keysym.scancode == SDL_SCANCODE_Z) { s_analogInput[0] = 1023; s_digitalPins[s_gpioKeys[4]] = 0; }
if (event.key.keysym.scancode == SDL_SCANCODE_X) { s_digitalPins[s_gpioKeys[5]] = 0; }
break;
default:
break;
};
}
}
void sdl_set_dc_pin(int pin)
{
s_dcPin = pin;
}
void sdl_set_gpio_keys(const uint8_t * pins)
{
memcpy(s_gpioKeys, pins, sizeof(s_gpioKeys));
}
int sdl_read_analog(int pin)
{
sdl_poll_event();
return s_analogInput[pin];
}
void sdl_write_digital(int pin, int value)
{
s_digitalPins[pin] = value;
}
int sdl_read_digital(int pin)
{
return s_digitalPins[pin];
}
void sdl_core_close(void)
{
sdl_graphics_close();
SDL_Quit();
unregister_oleds();
}
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
void sdl_send_init()
{
s_active_data_mode = SDM_COMMAND_ARG;
s_ssdMode = SSD_MODE_NONE;
// s_commandId = SSD_COMMAND_NONE;
}
static void sdl_send_command_or_arg(uint8_t data)
{
if (s_commandId == SSD_COMMAND_NONE)
{
s_commandId = data;
s_cmdArgIndex = -1; // no argument
}
else
{
s_cmdArgIndex++;
}
if (p_active_driver)
{
p_active_driver->run_cmd( data );
}
}
static void sdl_write_data(uint8_t data)
{
if (p_active_driver)
{
p_active_driver->run_data( data );
}
}
void sdl_send_byte(uint8_t data)
{
if (s_dcPin>=0)
{
// for spi
s_ssdMode = s_digitalPins[s_dcPin] ? SSD_MODE_DATA : SSD_MODE_COMMAND;
}
else if (s_ssdMode == SSD_MODE_NONE)
{
// for i2c
s_ssdMode = data == 0x00 ? SSD_MODE_COMMAND : SSD_MODE_DATA;
return;
}
if (s_ssdMode == SSD_MODE_COMMAND)
{
if (s_oled == SDL_AUTODETECT)
{
sdl_oled_info **p = p_oled_db;
while (*p)
{
if ((*p)->detect(data))
{
p_active_driver = *p;
s_oled = SDL_DETECTED;
s_commandId = SSD_COMMAND_NONE;
sdl_graphics_set_oled_params(
p_active_driver->width,
p_active_driver->height,
p_active_driver->bpp,
p_active_driver->pixfmt);
break;
}
p++;
}
}
else
{
sdl_send_command_or_arg( data );
}
}
else
{
if (p_active_driver)
{
if (p_active_driver->dataMode == SDMS_AUTO)
{
s_active_data_mode = SDM_WRITE_DATA;
}
switch ( s_active_data_mode )
{
case SDM_COMMAND_ARG:
sdl_send_command_or_arg( data );
break;
case SDM_WRITE_DATA:
sdl_write_data( data );
break;
default:
break;
}
}
}
}
void sdl_send_stop()
{
sdl_poll_event();
sdl_graphics_refresh();
s_ssdMode = -1;
}
void sdl_set_data_mode(sdl_data_mode mode)
{
s_active_data_mode = mode;
}

View File

@@ -0,0 +1,83 @@
/*
MIT License
Copyright (c) 2018-2019, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_CORE_H_
#define _SDL_CORE_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
enum
{
SDL_LCD_TEMPLATE,
SDL_LCD_SSD1306,
SDL_LCD_SH1106,
SDL_LCD_PCD8544,
SDL_LCD_SSD1325,
SDL_LCD_SSD1327,
SDL_LCD_SSD1331_X8,
SDL_LCD_SSD1331_X16,
SDL_LCD_SSD1351,
SDL_LCD_IL9163,
SDL_LCD_ST7735,
SDL_LCD_ILI9341,
};
/** ssd1325 / ssd1327 types */
enum
{
SDL_LCD_SSD1325_GENERIC,
SDL_LCD_SSD1327_GENERIC,
SDL_LCD_SSD1327_NO_COM_SPLIT,
};
extern void sdl_core_init(void);
extern void sdl_core_draw(void);
extern void sdl_set_dc_pin(int pin);
// Accepts pointer to six-elements array
extern void sdl_set_gpio_keys(const uint8_t * pins);
extern void sdl_send_init();
extern void sdl_send_byte(uint8_t data);
extern void sdl_send_stop();
extern int sdl_read_analog(int pin);
extern void sdl_write_digital(int pin, int value);
extern int sdl_read_digital(int pin);
/** Allocates buffer, returns number of bytes allocated */
extern void sdl_core_get_pixels_data( uint8_t *pixels, uint8_t target_bpp );
/** Returns length in bytes, required to hold the data */
extern int sdl_core_get_pixels_len( uint8_t target_bpp );
extern void sdl_core_set_unittest_mode(void);
extern void sdl_core_close(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,326 @@
/*
MIT License
Copyright (c) 2018-2019, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_graphics.h"
#include "sdl_oled_basic.h"
#include <unistd.h>
#include <SDL2/SDL.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define CANVAS_REFRESH_RATE 60
static SDL_Window *g_window = NULL;
static SDL_Renderer *g_renderer = NULL;
static SDL_Texture *g_texture = NULL;
void *g_pixels = NULL;
static int s_width = 128;
static int s_height = 64;
static int s_bpp = 16;
static uint32_t s_pixfmt = SDL_PIXELFORMAT_RGB565;
static bool s_unittest_mode = false;
static int windowWidth() { return s_width * PIXEL_SIZE + BORDER_SIZE * 2; };
static int windowHeight() { return s_height * PIXEL_SIZE + BORDER_SIZE * 2 + TOP_HEADER; };
void sdl_graphics_init(void)
{
if ((g_window != NULL) && (g_renderer != NULL))
{
/* SDL engine is already initialize */
return;
}
if ( s_unittest_mode )
{
SDL_Init(0);
return;
}
SDL_Init(SDL_INIT_EVERYTHING);
g_window = SDL_CreateWindow
(
"AVR SIMULATOR", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
windowWidth(),
windowHeight(),
SDL_WINDOW_SHOWN
);
g_renderer = SDL_CreateRenderer( g_window, -1, SDL_RENDERER_ACCELERATED );
// Set render color to black ( background will be rendered in this color )
SDL_SetRenderDrawColor( g_renderer, 20, 20, 20, 255 );
// Clear window
SDL_RenderClear( g_renderer );
// Render the rect to the screen
SDL_RenderPresent(g_renderer);
SDL_Rect r;
r.x = 0;
r.y = 0;
r.w = windowWidth();
r.h = windowHeight();
SDL_RenderFillRect( g_renderer, &r );
}
static void sdl_draw_oled_frame(void)
{
SDL_Rect r;
SDL_SetRenderDrawColor( g_renderer, 60, 128, 192, 255 );
r.x = 0; r.y = 0;
r.w = windowWidth();
r.h = TOP_HEADER + BORDER_SIZE - RECT_THICKNESS;
SDL_RenderFillRect( g_renderer, &r );
r.x = 0; r.y = TOP_HEADER + BORDER_SIZE - RECT_THICKNESS;
r.w = BORDER_SIZE - RECT_THICKNESS;
r.h = windowHeight() - ((BORDER_SIZE - RECT_THICKNESS)*2 + TOP_HEADER);
SDL_RenderFillRect( g_renderer, &r );
r.x = windowWidth() - (BORDER_SIZE - RECT_THICKNESS); r.y = TOP_HEADER + BORDER_SIZE - RECT_THICKNESS;
r.w = BORDER_SIZE - RECT_THICKNESS;
r.h = windowHeight() - ((BORDER_SIZE - RECT_THICKNESS)*2 + TOP_HEADER);
SDL_RenderFillRect( g_renderer, &r );
r.x = 0; r.y = windowHeight() - ((BORDER_SIZE - RECT_THICKNESS));
r.w = windowWidth();
r.h = BORDER_SIZE - RECT_THICKNESS;
SDL_RenderFillRect( g_renderer, &r );
SDL_SetRenderDrawColor( g_renderer, 0, 0, 0, 255 );
for (int i=0; i<RECT_THICKNESS; i++)
{
r.x = BORDER_SIZE - RECT_THICKNESS + i;
r.y = BORDER_SIZE - RECT_THICKNESS + TOP_HEADER + i;
r.w = windowWidth() - (BORDER_SIZE - RECT_THICKNESS + i)*2;
r.h = windowHeight() - ((BORDER_SIZE - RECT_THICKNESS + i)*2 + TOP_HEADER);
SDL_RenderDrawRect( g_renderer, &r );
}
#if !defined(SDL_NO_BORDER)
SDL_SetRenderDrawColor( g_renderer, 200, 200, 200, 255 );
r.x = 4;
r.y = 4;
r.w = 16;
r.h = 12;
SDL_RenderFillRect( g_renderer, &r );
r.x = windowWidth() - 4 - 16;
r.y = 4;
r.w = 16;
r.h = 12;
SDL_RenderFillRect( g_renderer, &r );
#endif
}
void sdl_graphics_refresh(void)
{
if ( s_unittest_mode )
{
return;
}
sdl_draw_oled_frame();
if (g_texture)
{
SDL_Rect r;
void * l_pixels;
int pitch;
if (SDL_LockTexture(g_texture, NULL, &l_pixels, &pitch) == 0)
{
if (pitch != s_width * (s_bpp/8))
{
fprintf(stderr, "Warning, pitch %d is not expected\n", pitch);
}
memcpy(l_pixels, g_pixels, s_width * s_height * (s_bpp/8));
SDL_UnlockTexture(g_texture);
}
else
{
fprintf(stderr, "Something bad happened to SDL texture\n");
exit(1);
}
r.x = BORDER_SIZE;
r.y = BORDER_SIZE + TOP_HEADER;
r.w = windowWidth() - BORDER_SIZE * 2;
r.h = windowHeight() - BORDER_SIZE * 2 - TOP_HEADER;
SDL_RenderCopy(g_renderer, g_texture, NULL, &r);
}
SDL_RenderPresent(g_renderer);
}
void sdl_graphics_set_oled_params(int width, int height, int bpp, uint32_t pixfmt)
{
SDL_Rect r;
s_bpp = bpp;
s_pixfmt = pixfmt;
s_width = width;
s_height = height;
if (g_texture)
{
SDL_DestroyTexture( g_texture );
g_texture = NULL;
free(g_pixels);
g_pixels = NULL;
}
g_pixels = malloc(s_width * s_height * (s_bpp / 8));
if ( s_unittest_mode )
{
return;
}
g_texture = SDL_CreateTexture( g_renderer, s_pixfmt,
SDL_TEXTUREACCESS_STREAMING,
width, height );
if (g_texture == NULL)
{
fprintf(stderr, "Error creating back buffer: %s\n", SDL_GetError());
exit(1);
}
SDL_SetWindowSize(g_window, windowWidth(), windowHeight());
SDL_SetRenderDrawColor( g_renderer, 20, 20, 20, 255 );
r.x = RECT_THICKNESS;
r.y = RECT_THICKNESS;
r.w = windowWidth() - RECT_THICKNESS*2;
r.h = windowHeight() - RECT_THICKNESS*2;
SDL_RenderFillRect( g_renderer, &r );
sdl_draw_oled_frame();
}
void sdl_put_pixel(int x, int y, uint32_t color)
{
while (x >= s_width) x-= s_width;
while (y >= s_height) y-= s_height;
if (x<0) x = 0;
if (y<0) y = 0;
if (g_pixels)
{
int index = x + y * s_width;
switch (s_bpp)
{
case 8:
((uint8_t *)g_pixels)[ index ] = color;
break;
case 16:
((uint16_t *)g_pixels)[ index ] = color;
break;
case 32:
((uint32_t *)g_pixels)[ index ] = color;
break;
default:
break;
}
}
}
uint32_t sdl_get_pixel(int x, int y)
{
uint32_t pixel = 0;
while (x >= s_width) x-= s_width;
while (y >= s_height) y-= s_height;
if (x<0) x = 0;
if (y<0) y = 0;
if (g_pixels)
{
int index = x + y * s_width;
switch (s_bpp)
{
case 8:
pixel = ((uint8_t *)g_pixels)[ index ];
break;
case 16:
pixel = ((uint16_t *)g_pixels)[ index ];
break;
case 32:
pixel = ((uint32_t *)g_pixels)[ index ];
break;
default:
break;
}
}
return pixel;
}
void sdl_graphics_close(void)
{
if ( s_unittest_mode )
{
return;
}
SDL_DestroyWindow(g_window);
}
static uint32_t convert_pixel( uint32_t value, uint8_t target_bpp )
{
uint32_t pixel;
switch ( s_pixfmt )
{
case SDL_PIXELFORMAT_RGB332: pixel = ((value & 0xE0) << 24) | ((value & 0x1C) << 19) | ((value & 0x03) << 14) | ( 0xFF ); break;
case SDL_PIXELFORMAT_RGB565: pixel = ((value & 0xF800) << 16) | ((value & 0x07E0) << 13) | ((value & 0x001F) << 11) | ( 0xFF ); break;
case SDL_PIXELFORMAT_RGBX8888: pixel = value;
default: pixel = 0; break;
}
switch ( target_bpp )
{
case 1: pixel = (pixel & 0xFFFFFF00) ? 1 : 0; break;
case 4: pixel = (pixel & 0x000000F0) >> 4; break;
case 8: pixel = ((pixel & 0xE0000000) >> 24) | ((pixel & 0x00E00000) >> 19) | ((pixel & 0x0000C000) >> 14); break;
case 16: pixel = ((pixel & 0xF8000000) >> 16) | ((pixel & 0x00FC0000) >> 13) | ((pixel & 0x0000F800) >> 11); break;
case 32: break;
default: break;
}
return pixel;
}
void sdl_core_get_pixels_data( uint8_t *pixels, uint8_t target_bpp )
{
for (int x = 0; x < s_width; x++)
for (int y = 0; y < s_height; y++)
{
uint32_t pixel = sdl_get_pixel( x, y );
pixel = convert_pixel( pixel, target_bpp );
switch ( target_bpp )
{
case 1: ((uint8_t *)pixels)[x + (y / 8)*s_width] |= (pixel << (y & 0x7)); break;
case 4: ((uint8_t *)pixels)[x / 2 + y * s_width / 2] |= (pixel << ((x & 1) * 4)); break;
case 8: ((uint8_t *)pixels)[x + y * s_width] = pixel; break;
case 16: ((uint16_t *)pixels)[x + y * s_width] = pixel; break;
case 32: ((uint32_t *)pixels)[x + y * s_width] = pixel; break;
default: break;
}
}
}
int sdl_core_get_pixels_len( uint8_t target_bpp )
{
int size = s_width * s_height * target_bpp / 8;
return size;
}
void sdl_core_set_unittest_mode(void)
{
s_unittest_mode = true;
}

View File

@@ -0,0 +1,47 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_GRAPHICS_H_
#define _SDL_GRAPHICS_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void sdl_graphics_init(void);
extern void sdl_graphics_refresh(void);
extern void sdl_graphics_close(void);
extern void sdl_graphics_set_oled_params(int width, int height, int bpp, uint32_t pixfmt);
extern void sdl_put_pixel(int x, int y, uint32_t color);
extern uint32_t sdl_get_pixel(int x, int y);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,261 @@
/*
MIT License
Copyright (c) 2018-2019, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_il9163.h"
#include "sdl_oled_basic.h"
#include "sdl_graphics.h"
#include "sdl_core.h"
static int s_activeColumn = 0;
static int s_activePage = 0;
static int s_columnStart = 0;
static int s_columnEnd = 127;
static int s_pageStart = 0;
static int s_pageEnd = 7;
static uint8_t detected = 0;
static uint8_t s_lcd_type;
static void sdl_il9163_reset(void)
{
detected = 0;
}
static int sdl_il9163_detect(uint8_t data)
{
if (detected)
{
switch (data)
{
case 0b00000000:
sdl_il9163.width = 128;
sdl_il9163.height = 128;
break;
case 0b00000011:
sdl_il9163.width = 128;
sdl_il9163.height = 160;
break;
default:
break;
}
return 1;
}
s_lcd_type = data;
detected = (data == SDL_LCD_IL9163) || (data == SDL_LCD_ST7735);
return 0;
}
static uint8_t s_verticalMode = 0;
static void sdl_il9163_commands(uint8_t data)
{
// if ((s_verticalMode & 0b00100000) && (s_cmdArgIndex < 0))
// {
// if (s_commandId == 0x2A) s_commandId = 0x2B;
// else if (s_commandId == 0x2B) s_commandId = 0x2A;
// }
switch (s_commandId)
{
case 0x36:
if (s_cmdArgIndex == 0)
{
s_verticalMode = data;
s_commandId = SSD_COMMAND_NONE;
}
break;
case 0x2A:
switch (s_cmdArgIndex)
{
case 0:
case 2:
break;
case 1:
if (!(s_verticalMode & 0b00100000))
{
s_columnStart = data;
s_activeColumn = data;
}
else
{
s_pageStart = data;
s_activePage = data;
}
break;
case 3:
if (!(s_verticalMode & 0b00100000))
{
s_columnEnd = data;
}
else
{
s_pageEnd = data;
}
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x2B:
switch (s_cmdArgIndex)
{
case 0:
case 2:
break;
case 1:
if (!(s_verticalMode & 0b00100000))
{
if ( s_lcd_type == SDL_LCD_ST7735 )
s_activePage = data;
else
// emulating bug in IL9163 Black display
s_activePage = (s_verticalMode & 0b10000000) ? data - 32 : data;
s_pageStart = s_activePage;
}
else
{
s_columnStart = data;
s_activeColumn = data;
}
break;
case 3:
if (!(s_verticalMode & 0b00100000))
{
if ( s_lcd_type == SDL_LCD_ST7735 )
s_pageEnd = data;
else
// emulating bug in IL9163 Black display
s_pageEnd = (s_verticalMode & 0b10000000) ? data - 32 : data;
}
else
{
s_columnEnd = data;
}
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x2C:
sdl_set_data_mode( SDM_WRITE_DATA );
s_commandId = SSD_COMMAND_NONE;
break;
case 0xC1: // PWCTR2
case 0xB4: // INVCTR display inversion, use by default
case 0xC5: // VMCTR vcom control 1
case 0x3A: // COLMOD set 16-bit pixel format
if (s_cmdArgIndex == 0) s_commandId = SSD_COMMAND_NONE;
break;
case 0xC2: // PWCTR3 power control 3
case 0xC3: // PWCTR4 (C3h): Power Control 4 (in Idle mode/ 8-colors)
case 0xC4: // PWCTR5 (C4h): Power Control 5 (in Partial mode/ full-colors)
case 0xB6: // DISSET5
if (s_cmdArgIndex == 1) s_commandId = SSD_COMMAND_NONE;
break;
case 0xB1: // FRMCTR1 frame rate control 1, use by default
case 0xB2: // FRMCTR2, Frame Rate Control (In Idle mode/ 8-colors)
case 0xC0: // PWCTR1 power control 1
if (s_cmdArgIndex == 2) s_commandId = SSD_COMMAND_NONE;
break;
case 0xB3: // FRMCTR3 (B3h): Frame Rate Control (In Partial mode/ full colors)
if (s_cmdArgIndex == 5) s_commandId = SSD_COMMAND_NONE;
break;
case 0xE0: // GMCTRP1 positive gamma correction
case 0xE1: // GMCTRN1 negative gamma correction
if (s_cmdArgIndex == 15) s_commandId = SSD_COMMAND_NONE;
break;
case 0x01: // SWRESET
case 0x11: // SLPOUT
case 0x20: // INVOFF (20h): Display Inversion Off
default:
s_commandId = SSD_COMMAND_NONE;
break;
}
}
void sdl_il9163_data(uint8_t data)
{
int y = s_activePage;
int x = s_activeColumn;
static uint8_t firstByte = 1; /// il9163
static uint8_t dataFirst = 0x00; /// il9163
if (firstByte)
{
dataFirst = data;
firstByte = 0;
return;
}
firstByte = 1;
int rx, ry;
if (s_verticalMode & 0b00100000)
{
rx = (s_verticalMode & 0b01000000) ? (sdl_il9163.width - 1 - x) : x;
ry = (s_verticalMode & 0b10000000) ? (sdl_il9163.height - 1 - y) : y;
}
else
{
rx = (s_verticalMode & 0b10000000) ? (sdl_il9163.width - 1 - x) : x;
ry = (s_verticalMode & 0b01000000) ? (sdl_il9163.height - 1 - y) : y;
}
sdl_put_pixel(rx, ry, (dataFirst<<8) | data);
if (s_verticalMode & 0b00100000)
{
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
}
}
}
else
{
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
}
}
}
}
sdl_oled_info sdl_il9163 =
{
.width = 128,
.height = 128,
.bpp = 16,
.pixfmt = SDL_PIXELFORMAT_RGB565,
.dataMode = SDMS_CONTROLLER,
.detect = sdl_il9163_detect,
.run_cmd = sdl_il9163_commands,
.run_data = sdl_il9163_data,
.reset = sdl_il9163_reset,
};

View File

@@ -0,0 +1,42 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_IL9163_H_
#define _SDL_IL9163_H_
#include <stdint.h>
#include "sdl_oled_basic.h"
#ifdef __cplusplus
extern "C" {
#endif
extern sdl_oled_info sdl_il9163;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,243 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_ili9341.h"
#include "sdl_oled_basic.h"
#include "sdl_graphics.h"
#include "sdl_core.h"
static int s_activeColumn = 0;
static int s_activePage = 0;
static int s_columnStart = 0;
static int s_columnEnd = 127;
static int s_pageStart = 0;
static int s_pageEnd = 7;
static uint8_t detected = 0;
static int sdl_ili9341_detect(uint8_t data)
{
if (detected)
{
return 1;
}
detected = (data == SDL_LCD_ILI9341);
return 0;
}
static uint8_t s_verticalMode = 0;
static void sdl_ili9341_commands(uint8_t data)
{
// if ((s_verticalMode & 0b00100000) && (s_cmdArgIndex < 0))
// {
// if (s_commandId == 0x2A) s_commandId = 0x2B;
// else if (s_commandId == 0x2B) s_commandId = 0x2A;
// }
switch (s_commandId)
{
case 0x36:
if (s_cmdArgIndex == 0)
{
s_verticalMode = data;
s_commandId = SSD_COMMAND_NONE;
}
break;
case 0x2A:
switch (s_cmdArgIndex)
{
case 0:
if (!(s_verticalMode & 0b00100000))
{
s_columnStart = data;
s_activeColumn = data;
}
else
{
s_pageStart = data;
s_activePage = data;
}
break;
case 1:
if (!(s_verticalMode & 0b00100000))
{
s_columnStart = data | (s_columnStart<<8);
s_activeColumn = data | (s_activeColumn<<8);
}
else
{
s_pageStart = data | (s_pageStart<<8);
s_activePage = data | (s_activePage<<8);
}
break;
case 2:
if (!(s_verticalMode & 0b00100000))
{
s_columnEnd = data;
}
else
{
s_pageEnd = data;
}
break;
case 3:
if (!(s_verticalMode & 0b00100000))
{
s_columnEnd = data | (s_columnEnd << 8);
}
else
{
s_pageEnd = data | (s_pageEnd << 8);
}
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x2B:
switch (s_cmdArgIndex)
{
case 0:
if (!(s_verticalMode & 0b00100000))
{
s_activePage = data;
s_pageStart = s_activePage;
}
else
{
s_columnStart = data;
s_activeColumn = data;
}
break;
case 1:
if (!(s_verticalMode & 0b00100000))
{
s_activePage = data | (s_activePage << 8);
s_pageStart = s_activePage;
}
else
{
s_columnStart = data | (s_columnStart << 8);
s_activeColumn = data | (s_activeColumn << 8);
}
break;
case 2:
if (!(s_verticalMode & 0b00100000))
{
s_pageEnd = data;
}
else
{
s_columnEnd = data;
}
break;
case 3:
if (!(s_verticalMode & 0b00100000))
{
s_pageEnd = data | (s_pageEnd << 8);
}
else
{
s_columnEnd = data | (s_columnEnd << 8);
}
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x2C:
sdl_set_data_mode( SDM_WRITE_DATA );
s_commandId = SSD_COMMAND_NONE;
break;
default:
s_commandId = SSD_COMMAND_NONE;
break;
}
}
void sdl_ili9341_data(uint8_t data)
{
int y = s_activePage;
int x = s_activeColumn;
static uint8_t firstByte = 1; /// ili9341
static uint8_t dataFirst = 0x00; /// ili9341
if (firstByte)
{
dataFirst = data;
firstByte = 0;
return;
}
firstByte = 1;
int rx, ry;
if (s_verticalMode & 0b00100000)
{
rx = (s_verticalMode & 0b01000000) ? x: (sdl_ili9341.width - 1 - x);
ry = (s_verticalMode & 0b10000000) ? (sdl_ili9341.height - 1 - y) : y;
}
else
{
rx = (s_verticalMode & 0b10000000) ? x: (sdl_ili9341.width - 1 - x);
ry = (s_verticalMode & 0b01000000) ? (sdl_ili9341.height - 1 - y) : y;
}
sdl_put_pixel(rx, ry, (dataFirst<<8) | data);
if (s_verticalMode & 0b00100000)
{
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
}
}
}
else
{
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
}
}
}
}
sdl_oled_info sdl_ili9341 =
{
.width = 240,
.height = 320,
.bpp = 16,
.pixfmt = SDL_PIXELFORMAT_RGB565,
.dataMode = SDMS_CONTROLLER,
.detect = sdl_ili9341_detect,
.run_cmd = sdl_ili9341_commands,
.run_data = sdl_ili9341_data,
};

View File

@@ -0,0 +1,42 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_ILI9341_H_
#define _SDL_ILI9341_H_
#include <stdint.h>
#include "sdl_oled_basic.h"
#ifdef __cplusplus
extern "C" {
#endif
extern sdl_oled_info sdl_ili9341;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,91 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_OLED_BASIC_H_
#define _SDL_OLED_BASIC_H_
#include <stdint.h>
#include <SDL2/SDL.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SSD_COMMAND_NONE -1
enum
{
SSD_MODE_NONE,
SSD_MODE_COMMAND,
SSD_MODE_DATA,
};
typedef enum
{
SDMS_AUTO, // Command arg/write data mode is selected by DC pin or i2c command
SDMS_CONTROLLER, // Command arg/write data mode is controlled by LCD controller special command
} sdl_data_mode_selection;
typedef enum
{
SDM_COMMAND_ARG, // data mode interprets all data as command args
SDM_WRITE_DATA, // data mode sends all data to GDRAM
} sdl_data_mode;
typedef struct
{
int width;
int height;
int bpp;
uint32_t pixfmt;
sdl_data_mode_selection dataMode;
int (*detect)(uint8_t data);
void (*run_cmd)(uint8_t data);
void (*run_data)(uint8_t data);
void (*reset)(void);
} sdl_oled_info;
#if defined(SDL_NO_BORDER)
const static int BORDER_SIZE = 0;
const static int TOP_HEADER = 0;
const static int RECT_THICKNESS = 0;
#else
const static int BORDER_SIZE = 8;
const static int TOP_HEADER = 16;
const static int RECT_THICKNESS = 2;
#endif
const static int PIXEL_SIZE = 2;
extern int s_commandId;
extern int s_cmdArgIndex;
extern uint8_t s_detected;
extern void sdl_set_data_mode(sdl_data_mode mode);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,122 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_pcd8544.h"
#include "sdl_oled_basic.h"
#include "sdl_graphics.h"
#include "sdl_core.h"
static int s_activeColumn = 0;
static int s_activePage = 0;
const static int s_columnStart = 0;
const static int s_columnEnd = 83;
const static int s_pageStart = 0;
const static int s_pageEnd = 5;
static int s_verticalMode = 0;
static uint8_t detected = 0;
static int sdl_pcd8544_detect(uint8_t data)
{
if (detected)
{
return 1;
}
detected = (data == SDL_LCD_PCD8544);
return 0;
}
static void sdl_pcd8544_commands(uint8_t data)
{
// printf("%02X\n", data);
switch (s_commandId)
{
case 0x20:
s_verticalMode = 0;
s_commandId = SSD_COMMAND_NONE;
break;
case 0x22:
s_verticalMode = 1;
s_commandId = SSD_COMMAND_NONE;
break;
default:
if ((s_commandId & 0x80) == 0x80 )
{
s_activeColumn = s_commandId & 0x7F;
if (s_activeColumn > s_columnEnd) s_activeColumn = s_columnEnd;
}
if ((s_commandId & 0xC0) == 0x40 )
{
s_activePage = s_commandId & 0x3F;
if (s_activePage > s_pageEnd) s_activePage = s_pageEnd;
}
s_commandId = SSD_COMMAND_NONE;
break;
}
}
void sdl_pcd8544_data(uint8_t data)
{
int x = s_activeColumn;
int y = s_activePage;
for (int i=0; i<8; i++)
{
if (data & (1<<i))
{
sdl_put_pixel(x, (y<<3) + i, 0xAD59);
}
else
{
sdl_put_pixel(x, (y<<3) + i, 0x0000);
}
}
if (s_verticalMode)
{
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
}
}
else
{
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
}
}
}
sdl_oled_info sdl_pcd8544 =
{
.width = 84,
.height = 48,
.bpp = 16,
.pixfmt = SDL_PIXELFORMAT_RGB565,
.dataMode = SDMS_AUTO,
.detect = sdl_pcd8544_detect,
.run_cmd = sdl_pcd8544_commands,
.run_data = sdl_pcd8544_data,
};

View File

@@ -0,0 +1,42 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_PCD8544_H_
#define _SDL_PCD8544_H_
#include <stdint.h>
#include "sdl_oled_basic.h"
#ifdef __cplusplus
extern "C" {
#endif
extern sdl_oled_info sdl_pcd8544;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,222 @@
/*
MIT License
Copyright (c) 2018-2019, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_ssd1306.h"
#include "sdl_oled_basic.h"
#include "sdl_graphics.h"
#include "sdl_core.h"
#define SSD1306_MAX_BANKS 8
static int s_activeColumn = 0;
static int s_activePage = 0;
static int s_columnStart = 0;
static int s_columnEnd = 127;
static int s_pageStart = 0;
static int s_pageEnd = 7;
static uint8_t detected = 0;
static uint8_t gdram[128][64];
static uint8_t displayRemap = 0;
static uint8_t displayStartLine = 0;
static uint8_t displayOffset = 0;
static uint8_t multiplexRatio = 15;
static uint8_t displayOn = 0;
static void blt_single_pixel(uint8_t x, uint8_t y, uint8_t color)
{
uint16_t sdl_color = color ? 0xAD59: 0x0000;
gdram[x & 0x7F ][y & 0x3F] = color;
uint8_t line = (y - displayOffset - displayStartLine) & 0x3F;
if ( displayRemap )
{
line = multiplexRatio - line;
}
if ( line < sdl_ssd1306.height )
{
sdl_put_pixel(x, line, sdl_color);
}
}
static void blt_content()
{
for(uint8_t line = 0; line < sdl_ssd1306.height; line++)
{
uint8_t row = line;
uint8_t ram = line;
if ( displayRemap )
{
row = multiplexRatio - row;
ram = multiplexRatio - ram;
}
ram = (row + displayOffset + displayStartLine) & 0x3F;
row = (row + displayOffset) & 0x3F;
for(uint8_t column = 0; column < sdl_ssd1306.width; column++)
{
uint16_t color = (gdram[column][ram]) ? 0xAD59: 0x0000;
if ( row > (multiplexRatio + displayStartLine) ) color = 0x0000;
sdl_put_pixel(column, line, color);
}
}
}
static void sdl_ssd1306_reset(void)
{
detected = 0;
}
static int sdl_ssd1306_detect(uint8_t data)
{
if (detected)
{
return 1;
}
detected = (data == SDL_LCD_SSD1306) || (data == SDL_LCD_SH1106);
return 0;
}
static void sdl_ssd1306_commands(uint8_t data)
{
// printf("%02X (CMD: %02X)\n", data, s_commandId);
switch (s_commandId)
{
case 0x21:
switch (s_cmdArgIndex)
{
case 0:
s_columnStart = ( data >= sdl_ssd1306.width ? sdl_ssd1306.width - 1: data );
s_activeColumn = s_columnStart;
break;
case 1:
s_columnEnd = ( data >= sdl_ssd1306.width ? sdl_ssd1306.width - 1: data );
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x22:
switch (s_cmdArgIndex)
{
case 0:
s_pageStart = (data >= SSD1306_MAX_BANKS ? SSD1306_MAX_BANKS - 1 : data);
s_activePage = s_pageStart;
break;
case 1:
s_pageEnd = (data >= SSD1306_MAX_BANKS ? SSD1306_MAX_BANKS - 1 : data);
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0xA8:
if (s_cmdArgIndex == 0)
{
multiplexRatio = data;
sdl_ssd1306.height = data + 1;
sdl_graphics_set_oled_params(sdl_ssd1306.width,
sdl_ssd1306.height,
sdl_ssd1306.bpp,
sdl_ssd1306.pixfmt);
if ( displayOn ) blt_content();
s_commandId = SSD_COMMAND_NONE;
}
break;
case 0xAF:
displayOn = 1;
blt_content();
s_commandId = SSD_COMMAND_NONE;
break;
case 0x81:
if ( s_cmdArgIndex == 0 )
{
// Just skip contrast command
s_commandId = SSD_COMMAND_NONE;
}
break;
case 0xD3: // Display offset
if ( s_cmdArgIndex == 0 )
{
displayOffset = data;
if ( displayOn ) blt_content();
s_commandId = SSD_COMMAND_NONE;
}
break;
default:
/* Other ssd1306 commands, many commands are combined with data */
if ((s_commandId >= 0xb0) && (s_commandId <= 0xbf))
{
s_activePage = (uint16_t)(s_commandId & 0x0F);
}
if ((s_commandId <= 0x0F))
{
s_activeColumn = (s_activeColumn & 0xFFF0) | (uint16_t)s_commandId;
}
if ((s_commandId >= 0x40) && (s_commandId <= 0x7F))
{
displayStartLine = s_commandId & 0x3F;
if ( displayOn ) blt_content();
}
if ((s_commandId <= 0x1F) && (s_commandId >= 0x10))
{
s_activeColumn = (s_activeColumn & 0x000F) | ((int16_t)(s_commandId & 0x0F) << 4);
}
s_commandId = SSD_COMMAND_NONE;
break;
}
}
void sdl_ssd1306_data(uint8_t data)
{
int y = s_activePage;
int x = s_activeColumn;
for (int i=0; i<8; i++)
{
blt_single_pixel( x, (y<<3) + i, data & (1<<i) );
}
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
}
}
}
sdl_oled_info sdl_ssd1306 =
{
.width = 128,
.height = 64,
.bpp = 16,
.pixfmt = SDL_PIXELFORMAT_RGB565,
.dataMode = SDMS_AUTO,
.detect = sdl_ssd1306_detect,
.run_cmd = sdl_ssd1306_commands,
.run_data = sdl_ssd1306_data,
.reset = sdl_ssd1306_reset,
};

View File

@@ -0,0 +1,42 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_SSD1306_H_
#define _SDL_SSD1306_H_
#include <stdint.h>
#include "sdl_oled_basic.h"
#ifdef __cplusplus
extern "C" {
#endif
extern sdl_oled_info sdl_ssd1306;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,252 @@
/*
MIT License
Copyright (c) 2018-2019, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_ssd1325.h"
#include "sdl_oled_basic.h"
#include "sdl_graphics.h"
#include "sdl_core.h"
static int s_activeColumn = 0;
static int s_activeRow = 0;
static int s_columnStart = 0;
static int s_columnEnd = 127;
static int s_rowStart = 0;
static int s_rowEnd = 7;
static int s_newColumn;
static int s_newPage;
static uint8_t detected = 0;
static uint8_t s_subtype = SDL_LCD_SSD1325_GENERIC;
static uint8_t s_hwComSplit = 0;
static void copyBlock()
{
if ( s_newColumn < s_columnStart )
{
for( int y = s_rowStart; y <= s_rowEnd; y++)
for( int x = s_newColumn; x <= s_newColumn + s_columnEnd - s_columnStart; x++)
sdl_put_pixel(x, y, sdl_get_pixel( x + s_columnStart - s_newColumn, y ));
}
else
{
for( int y = s_rowStart; y <= s_rowEnd; y++)
for( int x = s_newColumn + s_columnEnd - s_columnStart; x >= s_newColumn; x--)
sdl_put_pixel(x, y, sdl_get_pixel( x + s_columnStart - s_newColumn, y ));
}
}
static int sdl_ssd1325_detect(uint8_t data)
{
if (detected)
{
switch (data)
{
case SDL_LCD_SSD1325_GENERIC:
s_hwComSplit = 1;
sdl_ssd1325.height = 64;
break;
case SDL_LCD_SSD1327_GENERIC:
s_hwComSplit = 1;
sdl_ssd1325.height = 128;
break;
case SDL_LCD_SSD1327_NO_COM_SPLIT:
s_hwComSplit = 0;
sdl_ssd1325.height = 128;
break;
default:
break;
}
s_subtype = data;
return 1;
}
detected = (data == SDL_LCD_SSD1325 || data == SDL_LCD_SSD1327);
return 0;
}
static uint8_t s_verticalMode = 1;
static uint8_t s_nimbleMapping = 0;
static uint8_t s_leftToRight = 0;
static uint8_t s_topToBottom = 0;
static uint8_t s_comSplit = 0;
static void sdl_ssd1325_commands(uint8_t data)
{
switch (s_commandId)
{
case 0xA0:
if (s_cmdArgIndex == 0)
{
// A[0] = Enable column address re-map
// A[1] = Enable Nibble remap
// A[2] = Enable Vertical Address increment
// A[4] = Enable COM-remap
// A[6] = Splitting ODD / Even signals
s_verticalMode = data & 0x04;
s_nimbleMapping = data & 0x02;
s_leftToRight = data & 0x01;
s_topToBottom = data & 0x10;
s_comSplit = data & 0x40;
s_commandId = SSD_COMMAND_NONE;
}
break;
case 0x15:
switch (s_cmdArgIndex)
{
case 0:
s_columnStart = data * 2;
s_activeColumn = data * 2;
break;
case 1:
s_columnEnd = data * 2 + 1;
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x23: // MOVE BLOCK
switch (s_cmdArgIndex)
{
case 0: s_columnStart = data * 2; break;
case 1: s_rowStart = data; break;
case 2: s_columnEnd = data * 2 + 1; break;
case 3: s_rowEnd = data; break;
case 4: s_newColumn = data * 2; break;
case 5:
s_newPage = data;
copyBlock();
s_commandId = SSD_COMMAND_NONE;
break;
default:
break;
}
break;
case 0x75:
switch (s_cmdArgIndex)
{
case 0:
s_activeRow = data;
s_rowStart = data;
break;
case 1:
s_rowEnd = data;
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0xA8: // Multiplex
if ( s_cmdArgIndex == 0 )
{
s_columnEnd = data + 1;
s_commandId = SSD_COMMAND_NONE;
}
break;
case 0xAE: // OFF /* display off */
case 0xA4: // NORMAL
case 0x2E: // Deactivate scroll
case 0xAF: // Display ON
s_commandId = SSD_COMMAND_NONE;
break;
case 0xFD: // Unlock OLED
case 0xA1: // Start line
case 0xA2: // Display offset
case 0xAB: // VDD internal
case 0x81: // CONTRAST
case 0xB1: // PHASE 0x51
case 0xB3: // CLK
case 0xBC: // PRECHARGE
case 0xBE: // VCOMH voltage
case 0xB6: // Second pre-charge
if (s_cmdArgIndex == 0) s_commandId = SSD_COMMAND_NONE;
break;
default:
s_commandId = SSD_COMMAND_NONE;
break;
}
}
static void sdl_ssd1325_data(uint8_t data)
{
for (int i=0; i<2; i++)
{
int y = s_topToBottom ? s_activeRow : (sdl_ssd1325.height - s_activeRow - 1);
int x = s_leftToRight ? s_activeColumn: (sdl_ssd1325.width - s_activeColumn - 1);
if ( (s_comSplit && !s_hwComSplit) || (!s_comSplit && s_hwComSplit) )
{
y = ((y & 0x3F) * 2) + ((y > 0x3F) ? 1: 0);
}
sdl_put_pixel(x, y, ((data & 0x0F) << 28) |
((data & 0x0F) << 20) |
((data & 0x0F) << 12) |
((data & 0x0F) << 4) );
if (s_verticalMode)
{
if (i == 1)
{
s_activeColumn--;
s_activeRow++;
if (s_activeRow > s_rowEnd)
{
s_activeRow = s_rowStart;
s_activeColumn += 2;
}
}
if (i == 0)
{
s_activeColumn++;
}
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
}
}
else
{
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
s_activeRow++;
if (s_activeRow > s_rowEnd)
{
s_activeRow = s_rowStart;
}
}
}
data >>= 4;
}
}
sdl_oled_info sdl_ssd1325 =
{
.width = 128,
.height = 64,
.bpp = 32,
.pixfmt = SDL_PIXELFORMAT_RGBX8888,
.dataMode = SDMS_AUTO,
.detect = sdl_ssd1325_detect,
.run_cmd = sdl_ssd1325_commands,
.run_data = sdl_ssd1325_data,
};

View File

@@ -0,0 +1,42 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_SSD1325_H_
#define _SDL_SSD1325_H_
#include <stdint.h>
#include "sdl_oled_basic.h"
#ifdef __cplusplus
extern "C" {
#endif
extern sdl_oled_info sdl_ssd1325;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,295 @@
/*
MIT License
Copyright (c) 2018-2019, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_ssd1331.h"
#include "sdl_oled_basic.h"
#include "sdl_graphics.h"
#include "sdl_core.h"
#include <stdlib.h>
static int s_activeColumn = 0;
static int s_activePage = 0;
static int s_columnStart = 0;
static int s_columnEnd = 127;
static int s_pageStart = 0;
static int s_pageEnd = 7;
static int s_newColumn;
static int s_newPage;
static uint32_t s_color = 0;
static uint8_t s_verticalMode = 1;
static uint8_t s_leftToRight = 0;
static uint8_t s_topToBottom = 0;
static uint8_t s_16bitmode = 0;
static uint8_t detected_x8 = 0;
static uint8_t detected_x16 = 0;
static void copyBlock()
{
int x_start = s_newColumn;
int x_end = s_newColumn + s_columnEnd - s_columnStart;
int x_dir = s_newColumn < s_columnStart ? 1 : -1;
int y_start = s_newPage;
int y_end = s_newPage + s_pageEnd - s_pageStart;
int y_dir = s_newPage < s_pageStart ? 1 : -1;
for( int y = y_dir > 0 ? y_start: y_end;
((y_dir > 0) && (y <= y_end)) || ((y_dir < 0) && (y >= y_start));
y = y + y_dir)
{
for( int x = x_dir > 0 ? x_start : x_end;
((x_dir > 0) && (x <= x_end)) || ((x_dir < 0) && (x >= x_start));
x = x + x_dir)
{
sdl_put_pixel(x, y, sdl_get_pixel( x + s_columnStart - s_newColumn,
y + s_pageStart - s_newPage ));
}
}
}
static void drawLine()
{
if ( abs(s_columnStart - s_columnEnd) > abs(s_pageStart - s_pageEnd) )
{
int x = s_columnStart;
while (x != s_columnEnd)
{
int y = s_pageStart + (s_pageEnd - s_pageStart)*(x - s_columnStart)/(s_columnEnd - s_columnStart);
sdl_put_pixel(x, y, s_color);
x += (s_columnEnd > s_columnStart ? 1: -1);
}
}
else
{
int y = s_pageStart;
while (y != s_pageEnd)
{
int x = s_columnStart + (s_columnEnd - s_columnStart)*(y - s_pageStart)/(s_pageEnd - s_pageStart);
sdl_put_pixel(x, y, s_color);
y += (s_pageEnd > s_pageStart ? 1: -1);
}
}
}
static void sdl_ssd1331_reset(void)
{
detected_x8 = 0;
detected_x16 = 0;
}
static int sdl_ssd1331_detect_x8(uint8_t data)
{
if (detected_x8)
{
return 1;
}
detected_x8 = (data == SDL_LCD_SSD1331_X8);
return 0;
}
static int sdl_ssd1331_detect_x16(uint8_t data)
{
if (detected_x16)
{
return 1;
}
detected_x16 = (data == SDL_LCD_SSD1331_X16);
return 0;
}
static void sdl_ssd1331_commands(uint8_t data)
{
switch (s_commandId)
{
case 0xA0:
if (s_cmdArgIndex == 0)
{
s_verticalMode = data & 0x01;
s_leftToRight = data & 0x02;
s_topToBottom = data & 0x10;
s_16bitmode = data & 0x40;
s_commandId = SSD_COMMAND_NONE;
}
break;
case 0x15:
switch (s_cmdArgIndex)
{
case 0:
s_columnStart = data;
s_activeColumn = data;
break;
case 1:
s_columnEnd = data;
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x21: // DRAW LINE
switch (s_cmdArgIndex)
{
case 0: s_columnStart = data; s_color = 0; break;
case 1: s_pageStart = data; break;
case 2: s_columnEnd = data; break;
case 3: s_pageEnd = data; break;
case 4:
if (s_16bitmode)
s_color |= ((data & 0x3F) >> 1);
else
s_color |= ((data & 0x30) >> 4);
break;
case 5:
if (s_16bitmode)
s_color |= ((data & 0x3F) << 5);
else
s_color |= ((data & 0x30) >> 1);
break;
case 6:
if (s_16bitmode)
s_color |= ((data & 0x3E) << 10);
else
s_color |= ((data & 0x38) << 2);
drawLine();
s_commandId = SSD_COMMAND_NONE;
break;
default:
break;
}
break;
case 0x23: // MOVE BLOCK
switch (s_cmdArgIndex)
{
case 0: s_columnStart = data; break;
case 1: s_pageStart = data; break;
case 2: s_columnEnd = data; break;
case 3: s_pageEnd = data; break;
case 4: s_newColumn = data; break;
case 5:
s_newPage = data;
copyBlock();
s_commandId = SSD_COMMAND_NONE;
break;
default:
break;
}
break;
case 0x75:
switch (s_cmdArgIndex)
{
case 0:
s_activePage = data;
s_pageStart = data;
break;
case 1:
s_pageEnd = data;
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
default:
s_commandId = SSD_COMMAND_NONE;
break;
}
}
static void sdl_ssd1331_data(uint8_t data)
{
int y = s_topToBottom ? s_activePage : (sdl_ssd1331x8.height - s_activePage - 1);
int x = s_leftToRight ? s_activeColumn: (sdl_ssd1331x8.width - s_activeColumn - 1);
static uint8_t firstByte = 1; /// SSD1331
static uint8_t dataFirst = 0x00; /// SSD1331
if (firstByte && s_16bitmode)
{
dataFirst = data;
firstByte = 0;
return;
}
firstByte = 1;
if ( s_16bitmode )
{
sdl_put_pixel(x, y, (dataFirst<<8) | data);
}
else
{
sdl_put_pixel(x, y, data);
}
if (s_verticalMode)
{
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
}
}
}
else
{
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
}
}
}
}
sdl_oled_info sdl_ssd1331x8 =
{
.width = 96,
.height = 64,
.bpp = 8,
.pixfmt = SDL_PIXELFORMAT_RGB332,
.dataMode = SDMS_AUTO,
.detect = sdl_ssd1331_detect_x8,
.run_cmd = sdl_ssd1331_commands,
.run_data = sdl_ssd1331_data,
.reset = sdl_ssd1331_reset,
};
sdl_oled_info sdl_ssd1331x16 =
{
.width = 96,
.height = 64,
.bpp = 16,
.pixfmt = SDL_PIXELFORMAT_RGB565,
.dataMode = SDMS_AUTO,
.detect = sdl_ssd1331_detect_x16,
.run_cmd = sdl_ssd1331_commands,
.run_data = sdl_ssd1331_data,
.reset = sdl_ssd1331_reset,
};

View File

@@ -0,0 +1,43 @@
/*
MIT License
Copyright (c) 2018-2019, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_SSD1331_H_
#define _SDL_SSD1331_H_
#include <stdint.h>
#include "sdl_oled_basic.h"
#ifdef __cplusplus
extern "C" {
#endif
extern sdl_oled_info sdl_ssd1331x8;
extern sdl_oled_info sdl_ssd1331x16;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,160 @@
/*
MIT License
Copyright (c) 2018-2019, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sdl_ssd1351.h"
#include "sdl_oled_basic.h"
#include "sdl_graphics.h"
#include "sdl_core.h"
static int s_activeColumn = 0;
static int s_activePage = 0;
static int s_columnStart = 0;
static int s_columnEnd = 127;
static int s_pageStart = 0;
static int s_pageEnd = 7;
static uint8_t detected = 0;
static int sdl_ssd1351_detect(uint8_t data)
{
if (detected)
{
return 1;
}
detected = (data == SDL_LCD_SSD1351);
return 0;
}
static uint8_t s_verticalMode = 0;
static void sdl_ssd1351_commands(uint8_t data)
{
switch (s_commandId)
{
case 0xA0:
if (s_cmdArgIndex == 0)
{
s_verticalMode = data & 0x01;
s_commandId = SSD_COMMAND_NONE;
}
break;
case 0x15:
switch (s_cmdArgIndex)
{
case 0:
s_columnStart = data;
s_activeColumn = data;
break;
case 1:
s_columnEnd = data;
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x75:
switch (s_cmdArgIndex)
{
case 0:
s_activePage = data;
s_pageStart = data;
break;
case 1:
s_pageEnd = data;
s_commandId = SSD_COMMAND_NONE;
break;
default: break;
}
break;
case 0x5C:
sdl_set_data_mode( SDM_WRITE_DATA );
s_commandId = SSD_COMMAND_NONE;
break;
case 0xB4:
if ( s_cmdArgIndex == 2)
{
s_commandId = SSD_COMMAND_NONE;
}
break;
default:
s_commandId = SSD_COMMAND_NONE;
break;
}
}
void sdl_ssd1351_data(uint8_t data)
{
int y = s_activePage;
int x = s_activeColumn;
static uint8_t firstByte = 1; /// SSD1351
static uint8_t dataFirst = 0x00; /// SSD1351
if (firstByte)
{
dataFirst = data;
firstByte = 0;
return;
}
firstByte = 1;
sdl_put_pixel(x, y, (dataFirst<<8) | data);
if (s_verticalMode)
{
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
}
}
}
else
{
s_activeColumn++;
if (s_activeColumn > s_columnEnd)
{
s_activeColumn = s_columnStart;
s_activePage++;
if (s_activePage > s_pageEnd)
{
s_activePage = s_pageStart;
}
}
}
}
sdl_oled_info sdl_ssd1351 =
{
.width = 128,
.height = 128,
.bpp = 16,
.pixfmt = SDL_PIXELFORMAT_RGB565,
.dataMode = SDMS_CONTROLLER,
.detect = sdl_ssd1351_detect,
.run_cmd = sdl_ssd1351_commands,
.run_data = sdl_ssd1351_data,
};

View File

@@ -0,0 +1,42 @@
/*
MIT License
Copyright (c) 2018, Alexey Dynda
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _SDL_SSD1351_H_
#define _SDL_SSD1351_H_
#include <stdint.h>
#include "sdl_oled_basic.h"
#ifdef __cplusplus
extern "C" {
#endif
extern sdl_oled_info sdl_ssd1351;
#ifdef __cplusplus
}
#endif
#endif