SSD1306 support example

master
Schoumi 9 months ago
parent 285f9acfb5
commit 52ed0f0ee7

@ -0,0 +1,7 @@
{
"microbit-dal": {
"bluetooth": {
"enabled": 0
}
}
}

@ -0,0 +1,184 @@
/************************************************************************
* font.h
*
* Copyright (C) Lisa Milne 2014 <lisa@ltmnet.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
************************************************************************/
/*
* The font has been found on opengameart.org:
* http://opengameart.org/content/8x8-ascii-bitmap-font-with-c-source
*/
#ifndef FONT_H
#define FONT_H
#include <cstdint>
#define NB_FONT_TILES 95
#define FIRST_FONT_CHAR 0x20
#define NORMAL(x) (x)
/*
* Actual font data is written in "human drawing order", but must be sent in revers bit order
* for some drivers (Epaper for example).
* This macro takes care of bit reversal for each font byte once and for all.
* This is a little bit ugly, but made at compile time, which allows storage of modified font
* in FLASH memory.
*/
#define REV1(x) ( (((x) >> 1) & 0x5555555555555555) | (((x) & 0x5555555555555555) << 1) )
#define REV2(x) ( ((REV1(x) >> 2) & 0x3333333333333333) | ((REV1(x) & 0x3333333333333333) << 2) )
#define REVERSE(x) ( ((REV2(x) >> 4) & 0x0F0F0F0F0F0F0F0F) | ((REV2(x) & 0x0F0F0F0F0F0F0F0F) << 4) )
/*
* Actual font data is written in "human drawing order", but must be sent in a "vertical" way
* for some drivers (Oled for example).
* This macro takes care of bit reversal for each font byte once and for all.
* This is a little bit ugly, but made at compile time, which allows storage of modified font
* in FLASH memory.
*/
#define SBV(x, n) ( ((x) & (0x01ULL << (n * 8))) >> (n * 7) )
#define VER1(x) ( SBV(x, 7) | SBV(x, 6) | SBV(x, 5) | SBV(x, 4) | SBV(x, 3) | SBV(x, 2) | SBV(x, 1) | SBV(x, 0) )
#define VER2(x, n) ( (VER1((x) >> n)) << (n * 8) )
#define VERTICAL(x) ( VER2(x, 0) | VER2(x, 1) | VER2(x, 2)| VER2(x, 3)| VER2(x, 4)| VER2(x, 5)| VER2(x, 6)| VER2(x, 7) )
/*
* Actual font data is written in "human drawing order", but must be sent in a "vertical" way
* for some drivers (Oled for example).
* This macro takes care of bit reversal for each font byte once and for all.
* This is a little bit ugly, but made at compile time, which allows storage of modified font
* in FLASH memory.
*/
#define SBR(x, n) REVERSE( SBV(x, n) )
#define VR1(x) ( SBR(x, 7) | SBR(x, 6) | SBR(x, 5) | SBR(x, 4) | SBR(x, 3) | SBR(x, 2) | SBR(x, 1) | SBR(x, 0) )
#define VR2(x, n) ( (VR1((x) >> (7 - n))) << (n * 8) )
#define VERTICAL_REV(x) ( VR2(x, 0) | VR2(x, 1) | VR2(x, 2)| VR2(x, 3)| VR2(x, 4)| VR2(x, 5)| VR2(x, 6)| VR2(x, 7) )
/*
* The values in this array are a 8x8 bitmap font for ascii characters
* As memory is a very precious ressource on a micro-controller all chars
* before "space" (0x20) have been removed.
*/
#define FONT_TABLE \
ROW(0x0000000000000000), /* (space) */ /* 0x20 */ \
ROW(0x0808080800080000), /* ! */ \
ROW(0x2828000000000000), /* " */ \
ROW(0x00287C287C280000), /* # */ \
ROW(0x081E281C0A3C0800), /* $ */ \
ROW(0x6094681629060000), /* % */ \
ROW(0x1C20201926190000), /* & */ \
ROW(0x0808000000000000), /* ' */ \
ROW(0x0810202010080000), /* ( */ \
ROW(0x1008040408100000), /* ) */ \
ROW(0x2A1C3E1C2A000000), /* * */ \
ROW(0x0008083E08080000), /* + */ \
ROW(0x0000000000081000), /* , */ \
ROW(0x0000003C00000000), /* - */ \
ROW(0x0000000000080000), /* . */ \
ROW(0x0204081020400000), /* / */ \
ROW(0x1824424224180000), /* 0 */ /*x30 */ \
ROW(0x08180808081C0000), /* 1 */ \
ROW(0x3C420418207E0000), /* 2 */ \
ROW(0x3C420418423C0000), /* 3 */ \
ROW(0x081828487C080000), /* 4 */ \
ROW(0x7E407C02423C0000), /* 5 */ \
ROW(0x3C407C42423C0000), /* 6 */ \
ROW(0x7E04081020400000), /* 7 */ \
ROW(0x3C423C42423C0000), /* 8 */ \
ROW(0x3C42423E023C0000), /* 9 */ \
ROW(0x0000080000080000), /* : */ \
ROW(0x0000080000081000), /* ; */ \
ROW(0x0006186018060000), /* < */ \
ROW(0x00007E007E000000), /* = */ \
ROW(0x0060180618600000), /* > */ \
ROW(0x3844041800100000), /* ? */ \
ROW(0x003C449C945C201C), /* @ */ /* 0x40 */ \
ROW(0x1818243C42420000), /* A */ \
ROW(0x7844784444780000), /* B */ \
ROW(0x3844808044380000), /* C */ \
ROW(0x7844444444780000), /* D */ \
ROW(0x7C407840407C0000), /* E */ \
ROW(0x7C40784040400000), /* F */ \
ROW(0x3844809C44380000), /* G */ \
ROW(0x42427E4242420000), /* H */ \
ROW(0x3E080808083E0000), /* I */ \
ROW(0x1C04040444380000), /* J */ \
ROW(0x4448507048440000), /* K */ \
ROW(0x40404040407E0000), /* L */ \
ROW(0x4163554941410000), /* M */ \
ROW(0x4262524A46420000), /* N */ \
ROW(0x1C222222221C0000), /* O */ \
ROW(0x7844784040400000), /* P */ /* 0x50 */ \
ROW(0x1C222222221C0200), /* Q */ \
ROW(0x7844785048440000), /* R */ \
ROW(0x1C22100C221C0000), /* S */ \
ROW(0x7F08080808080000), /* T */ \
ROW(0x42424242423C0000), /* U */ \
ROW(0x8142422424180000), /* V */ \
ROW(0x4141495563410000), /* W */ \
ROW(0x4224181824420000), /* X */ \
ROW(0x4122140808080000), /* Y */ \
ROW(0x7E040810207E0000), /* Z */ \
ROW(0x3820202020380000), /* [ */ \
ROW(0x4020100804020000), /* \ */ \
ROW(0x3808080808380000), /* ] */ \
ROW(0x1028000000000000), /* ^ */ \
ROW(0x00000000007E0000), /* _ */ \
ROW(0x1008000000000000), /* ` */ /* 0x60 */ \
ROW(0x003C023E463A0000), /* a */ \
ROW(0x40407C42625C0000), /* b */ \
ROW(0x00001C20201C0000), /* c */ \
ROW(0x02023E42463A0000), /* d */ \
ROW(0x003C427E403C0000), /* e */ \
ROW(0x0018103810100000), /* f */ \
ROW(0x0000344C44340438), /* g */ \
ROW(0x2020382424240000), /* h */ \
ROW(0x0800080808080000), /* i */ \
ROW(0x0800180808080870), /* j */ \
ROW(0x20202428302C0000), /* k */ \
ROW(0x1010101010180000), /* l */ \
ROW(0x0000665A42420000), /* m */ \
ROW(0x00002E3222220000), /* n */ \
ROW(0x00003C42423C0000), /* o */ \
ROW(0x00005C62427C4040), /* p */ /* 0x70 */ \
ROW(0x00003A46423E0202), /* q */ \
ROW(0x00002C3220200000), /* r */ \
ROW(0x001C201804380000), /* s */ \
ROW(0x00103C1010180000), /* t */ \
ROW(0x00002222261A0000), /* u */ \
ROW(0x0000424224180000), /* v */ \
ROW(0x000081815A660000), /* w */ \
ROW(0x0000422418660000), /* x */ \
ROW(0x0000422214081060), /* y */ \
ROW(0x00003C08103C0000), /* z */ \
ROW(0x1C103030101C0000), /* { */ \
ROW(0x0808080808080800), /* | */ \
ROW(0x38080C0C08380000), /* } */ \
ROW(0x000000324C000000), /* ~ */
/* End of Table */
#define DECLARE_FONT(font_name) \
const uint64_t font_name[NB_FONT_TILES] = { \
FONT_TABLE \
};
#endif /* FONT_H */

@ -0,0 +1,56 @@
/*
The MIT License (MIT)
Copyright (c) 2016 British Broadcasting Corporation.
This software is provided by Lancaster University by arrangement with the BBC.
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 "MicroBit.h"
#include "ssd1306.h"
MicroBit uBit;
MicroBitI2C i2c(I2C_SDA0,I2C_SCL0);
MicroBitPin P0(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_DIGITAL_OUT);
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
ssd1306 screen(&uBit, &i2c, &P0);
while(true)
{
screen.display_line(0,0,"ABCDEFGHIJKLMNOP");
screen.display_line(1,0,"BCDEFGHIJKLMNOP");
screen.display_line(2,0,"CDEFGHIJKLMNOP");
screen.display_line(3,0,"DEFGHIJKLMNOP");
screen.display_line(4,0,"EFGHIJKLMNOP");
screen.display_line(5,0,"FGHIJKLMNOP");
screen.display_line(6,0,"GHIJKLMNOP");
screen.display_line(7,0,"HIJKLMNOP");
screen.update_screen();
uBit.sleep(1000);
}
release_fiber();
}

@ -0,0 +1,335 @@
#include "MicroBit.h"
#include <errno.h>
#include "ssd1306.h"
#include "font.h"
#define ROW(x) VERTICAL_REV(x)
DECLARE_FONT(font);
ssd1306::ssd1306(MicroBit* uB, MicroBitI2C* uBi2c, MicroBitPin* pin_reset, uint8_t addr):uBit(uB),i2c(uBi2c),reset(pin_reset), address(addr)
{
buffer_set(gddram, 0x00);
video_mode = SSD130x_DISP_NORMAL;
contrast = 128;
scan_dir = SSD130x_SCAN_BOTTOM_TOP;
read_dir = SSD130x_RIGHT_TO_LEFT;
offset_dir = SSD130x_MOVE_TOP;
offset = 4;
fullscreen = true;
charge_pump = SSD130x_INTERNAL_PUMP;
initialize();
}
int ssd1306::initialize()
{
int ret = 0;
uint8_t val = 0;
fullscreen = 1;
reset->setDigitalValue(1);
uBit->sleep(1);
reset->setDigitalValue(0);
uBit->sleep(10);
reset->setDigitalValue(1);
ret = display_power(SSD130x_DISP_OFF);//AE
if (ret != 0)
{
uBit->display.scroll("Power Error");
return ret;
}
ret = set_display_on(SSD130x_DISP_RAM);//A4
if (ret != 0)
{
uBit->display.scroll("DISP RAM Error");
return ret;
}
//0xD5 0xF0
set_display_clock(0x00,0x0F);
//0xA8 0x3F
set_mux_ratio(0x3F);
//0xD3 0x00
set_display_offset(offset_dir, offset);
//0|0x00
send_command(SSD130x_CMD_COL_LOW_NIBLE(0x00),NULL,0);
//0x8D 0x14
if (charge_pump == SSD130x_INTERNAL_PUMP)
{
val = SSD130x_CMD_CHARGE_INTERN;
send_command(SSD130x_CMD_CHARGE_PUMP,&val,1);
}
//0x20 0x00
ret = set_mem_addressing_mode(SSD130x_ADDR_TYPE_HORIZONTAL);
if (ret != 0) {
uBit->display.scroll("Mem Mode");
return ret;
}
//0x21,0,127
set_column_address(0,127);
//return 0;
//0x22,0,63
set_page_address(0,7);
//0xa0|0x1
ret = set_read_direction();
if (ret != 0) {
uBit->display.scroll("Read Dir");
return ret;
}
//0xC8
ret = set_scan_direction();
if (ret != 0) {
uBit->display.scroll("Scan Dir");
return ret;
}
//0xDA,0x12
val = 0x12;
send_command(SSD130x_CMD_COM_PIN_CONF,&val,1);
set_contrast(0xFF);
//0xd9 0xF1
//0DB 0x40
if (charge_pump == SSD130x_INTERNAL_PUMP)
{
val = 0xF1;
send_command(SSD130x_CMD_SET_PRECHARGE, &val,1);
val = SSD130x_VCOM_083;
send_command(SSD130x_CMD_VCOM_LEVEL, &val,1);
}
send_command(SSD130x_CMD_PAGE_START_ADDR(0),NULL,0);
ret = set_display_on(SSD130x_DISP_NORMAL);//A6
return display_power(SSD130x_DISP_ON);
}
int ssd1306::power_off()
{
return display_power(SSD130x_DISP_OFF);
}
int ssd1306::power_on()
{
return display_power(SSD130x_DISP_ON);
}
int ssd1306::set_contrast(uint8_t ctrst)
{
contrast = ctrst;
return send_command(SSD130x_CMD_CONTRAST, &contrast,1);
}
int ssd1306::display_video_reverse()//FIXME params
{
if (video_mode == SSD130x_DISP_REVERSE)
return send_command(SSD130x_CMD_DISP_REVERSE, NULL, 0);
else
return send_command(SSD130x_CMD_DISP_NORMAL, NULL, 0);
}
#define CMD_BUF_SIZE 24
int ssd1306::send_command(uint8_t cmd, uint8_t* data, uint8_t len)
{
char cmd_buf[CMD_BUF_SIZE] = {SSD130x_NEXT_BYTE_CMD,cmd};
if (2*len > CMD_BUF_SIZE-2)
{
return -EINVAL;
}
int ret;
if (len != 0)
{
for(int i = 0; i < len; i++)
{
cmd_buf[2+(2*i)] = SSD130x_NEXT_BYTE_CMD;
cmd_buf[3+(2*i)] = data[i];
}
}
ret = i2c->write(SSD130x_ADDR, cmd_buf, 2+(len*2));
if( ret != MICROBIT_OK)
{
uBit->display.scroll("Command Error");
return ret;
}
return 0;
}
int ssd1306::set_mem_addressing_mode(uint8_t mode)
{
return send_command(SSD130x_CMD_ADDR_MODE,&mode,1);
}
int ssd1306::set_column_address(uint8_t col_start, uint8_t col_end)
{
uint8_t buf[2] = {col_start,col_end};
return send_command(SSD130x_CMD_COL_ADDR, buf, 2);
}
int ssd1306::set_page_address(uint8_t page_start, uint8_t page_end)
{
uint8_t buf[2] = {page_start,page_end};
return send_command(SSD130x_CMD_PAGE_ADDR, buf, 2);
}
int ssd1306::set_display_on(uint8_t use_ram)
{
if (use_ram == SSD130x_DISP_BLANK)
{
return send_command(SSD130x_CMD_DISP_NORMAL, NULL,0);
}
else
{
return send_command(SSD130x_CMD_DISP_RAM, NULL,0);
}
}
int ssd1306::display_power(uint8_t status)
{
if (status == SSD130x_DISP_OFF)
{
return send_command(SSD130x_CMD_DISP_OFF, NULL,0);
}
else
{
return send_command(SSD130x_CMD_DISP_ON, NULL,0);
}
}
int ssd1306::set_scan_direction() //FIXME
{
if (scan_dir == SSD130x_SCAN_TOP_BOTTOM)
{
return send_command(SSD130x_CMD_COM_SCAN_NORMAL, NULL,0);
}
else
{
return send_command(SSD130x_CMD_COM_SCAN_REVERSE, NULL,0);
}
}
int ssd1306::set_read_direction()
{
if(read_dir == SSD130x_RIGHT_TO_LEFT)
return send_command(SSD130x_CMD_SEG0_MAP_RIGHT, NULL,0);
else
return send_command(SSD130x_CMD_SEG0_MAP_LEFT, NULL,0);
}
int ssd1306::set_mux_ratio(uint8_t ratio)
{
uint8_t data = SSD130x_MUX_DATA(ratio);
return send_command(SSD130x_CMD_PAGE_ADDR, &data, 1);
}
int ssd1306::set_display_clock(uint8_t divide, uint8_t frequency)
{
uint8_t data = SSD130x_CLK_DIV(divide) | SSD130x_CLK_FREQ(frequency);
if (data != 0xF0)
uBit->display.scroll("Error Clock");
return send_command(SSD130x_CMD_DISP_CLK_DIV, &data, 1);
}
int ssd1306::set_display_offset(uint8_t dir, uint8_t nb_lines)
{
uint8_t offset = 0;
if (nb_lines >= SSD130x_NB_LINES)
{
return -EINVAL;
}
if (dir == SSD130x_MOVE_TOP)
offset = SSD130x_OFFSET_DATA(nb_lines);
else
offset = SSD130x_OFFSET_DATA(SSD130x_NB_LINES - nb_lines);
return send_command(SSD130x_CMD_DISPLAY_OFFSET, &offset, 1);
}
int ssd1306::update_screen()
{
int ret;
if (!fullscreen) {
ret = set_column_address(0, 127);
if (ret != 0)
return ret;
ret = set_page_address(0, 7);
if (ret != 0)
return ret;
fullscreen = 1;
}
/* Setup I2C transfer */
gddram[0] = SSD130x_DATA_ONLY;
/* Send data on I2C bus */
ret = i2c->write(SSD130x_ADDR, (char*) gddram,GDDRAM_SIZE+1);
if (ret != MICROBIT_OK)
{
uBit->display.scroll("Full Screen Error");
}
return ret;
}
void ssd1306::display_char(uint8_t line, uint8_t col, uint8_t c)
{
uint8_t tile = (c > FIRST_FONT_CHAR) ? (c - FIRST_FONT_CHAR) : 0;
uint8_t* tile_data = (uint8_t*)(&font[tile]);
buffer_set_tile(gddram, col, line, tile_data);
}
int ssd1306::display_line(uint8_t line, uint8_t col, const char* text)
{
int len = strlen((char*)text);
int i = 0;
for (i = 0; i < len; i++) {
uint8_t tile = (text[i] > FIRST_FONT_CHAR) ? (text[i] - FIRST_FONT_CHAR) : 0;
uint8_t* tile_data = (uint8_t*)(&font[tile]);
buffer_set_tile(gddram, col++, line, tile_data);
if (col >= (OLED_LINE_CHAR_LENGTH)) {
col = 0;
line++;
if (line >= SSD130x_NB_PAGES) {
return i;
}
}
}
return len;
}
/* Set whole display to given value */
int ssd1306::buffer_set(uint8_t *gddram, uint8_t val)
{
memset(gddram + 1, val, GDDRAM_SIZE);
return 0;
}
/* Change our internal buffer, without actually displaying the changes */
int ssd1306::buffer_set_pixel(uint8_t* gddram, uint8_t x0, uint8_t y0, uint8_t state)
{
uint8_t* addr = gddram + 1 + ((y0 / 8) * 128) + x0;
if (state != 0) {
*addr |= (0x01 << (y0 % 8));
} else {
*addr &= ~(0x01 << (y0 % 8));
}
return 0;
}
/* Change a "tile" in the bitmap memory.
* A tile is a 8x8 pixels region, aligned on a 8x8 grid representation of the display.
* x0 and y0 are in number of tiles.
*/
int ssd1306::buffer_set_tile(uint8_t* gddram, uint8_t x0, uint8_t y0, uint8_t* tile)
{
uint8_t* addr = gddram + 1 + (y0 * 128) + (x0 * 8);
memcpy(addr, tile, 8);
return 0;
}

@ -0,0 +1,248 @@
/****************************************************************************
* ssd1306.h
*
* I2C Driver for 128x64 oled display drivers
*
* Copyright 2016 Nathael Pajani <nathael.pajani@ed3l.fr>
* Copyright 2022 Chomienne Anthony <anthony@mob-dev.fr>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*************************************************************************** */
/**
* This code is mainly an adaptation of code provided by Techno-Innov (Nathael Pajani <nathael.pajani@ed3l.fr>)
* www.techno-innov.fr
* http://git.techno-innov.fr
*/
#ifndef SSD1306
#define SSD1306
#define SSD130x_ADDR 0x7A
#define SSD130x_NB_LINES 64
#define SSD130x_NB_PAGES 8
#define SSD130x_NB_COL 128
enum ssd130x_defs {
SSD130x_DISP_OFF = 0,
SSD130x_DISP_ON,
SSD130x_DISP_RAM,
SSD130x_DISP_BLANK,
/* For reverse video */
SSD130x_DISP_NORMAL,
SSD130x_DISP_REVERSE,
/* For scan dirrection */
SSD130x_SCAN_TOP_BOTTOM,
SSD130x_SCAN_BOTTOM_TOP,
SSD130x_RIGHT_TO_LEFT,
SSD130x_LEFT_TO_RIGHT,
/* For display offset */
SSD130x_MOVE_TOP,
SSD130x_MOVE_BOTTOM,
};
#define SSD130x_DATA_ONLY 0x40
#define SSD130x_NEXT_BYTE_DATA 0xC0
#define SSD130x_NEXT_BYTE_CMD 0x80
/* Display controll */
#define SSD130x_CMD_CONTRAST 0x81
#define SSD130x_CMD_DISP_RAM 0xA4
#define SSD130x_CMD_DISP_NORAM 0xA5
#define SSD130x_CMD_DISP_NORMAL 0xA6
#define SSD130x_CMD_DISP_REVERSE 0xA7
#define SSD130x_CMD_DISP_OFF 0xAE
#define SSD130x_CMD_DISP_ON 0xAF
/* Scrolling controll */
#define SSD130x_CMD_SCROLL_RIGHT 0x26
#define SSD130x_CMD_SCROLL_LEFT 0x27
#define SSD130x_CMD_VSCROLL_RIGHT 0x29
#define SSD130x_CMD_VSCROLL_LEFT 0x2A
#define SSD130x_CMD_STOP_SCROLL 0x2E
#define SSD130x_CMD_START_SCROLL 0x2F
#define SSD130x_CMD_VSCROLL_REGION 0xA3
/* Data bytes for scrolling controll */
#define SSD130x_SCROLL_DATA_DUMMY 0x00
#define SSD130x_SCROLL_DATA_END 0xFF
#define SSD130x_SCROLL_DATA_START_PAGE(x) ((x) & 0x07)
#define SSD130x_SCROLL_DATA_END_PAGE(x) ((x) & 0x07)
#define SSD130x_SCROLL_DATA_ROWS(x) ((x) & 0x3F)
#define SSD130x_SCROLL_DATA_STEP(x) ((x) & 0x07)
/* Scroll steps definitions */
#define SSD130x_SCROLL_2_FRAMES 0x07
#define SSD130x_SCROLL_3_FRAMES 0x04
#define SSD130x_SCROLL_4_FRAMES 0x05
#define SSD130x_SCROLL_5_FRAMES 0x00
#define SSD130x_SCROLL_25_FRAMES 0x06
#define SSD130x_SCROLL_64_FRAMES 0x01
#define SSD130x_SCROLL_128_FRAMES 0x02
#define SSD130x_SCROLL_256_FRAMES 0x03
/* GDDRAM Adressing */
#define SSD130x_CMD_ADDR_MODE 0x20
/* Data bytes for adressing mode election */
#define SSD130x_ADDR_TYPE_HORIZONTAL 0x00
#define SSD130x_ADDR_TYPE_VERTICAL 0x01
#define SSD130x_ADDR_TYPE_PAGE 0x02
/* GDDRAM Page adressing mode */
#define SSD130x_CMD_COL_LOW_NIBLE(x) (0x00 + ((x) & 0x0F))
#define SSD130x_CMD_COL_HIGH_NIBLE(x) (0x10 + ((x) & 0x0F))
#define SSD130x_CMD_PAGE_START_ADDR(x) (0xB0 + ((x) & 0x07))
/* GDDRAM horizontal or vertical addressing mode */
#define SSD130x_CMD_COL_ADDR 0x21
#define SSD130x_CMD_PAGE_ADDR 0x22
/* Data bytes for horizontal or vertical adressing mode */
#define SSD130x_ADDR_COL(x) ((x) & 0x7F)
#define SSD130x_ADDR_PAGE(x) ((x) & 0x07)
/* Charge pump */
#define SSD130x_EXT_VCC 0x01
#define SSD130x_INTERNAL_PUMP 0x00
#define SSD130x_CMD_CHARGE_PUMP 0x8D
#define SSD130x_CMD_CHARGE_EXT 0x10
#define SSD130x_CMD_CHARGE_INTERN 0x14
/* Hardware configuration */
#define SSD130x_CMD_START_LINE(x) (0x40 + ((x) & 0x3F))
#define SSD130x_CMD_SEG0_MAP_RIGHT 0xA1
#define SSD130x_CMD_SEG0_MAP_LEFT 0xA0
/* Hardware configuration : Mux ratio */
#define SSD130x_CMD_SET_MUX 0xA8
/* Set mux ratio Data to N+1 (Values for N from 0 to 14 are invalid) */
#define SSD130x_MUX_DATA(x) ((x) & 0x3F) /* Reset is N=63 (64 mux) */
/* Hardware configuration : COM Scan */
#define SSD130x_CMD_COM_SCAN_NORMAL 0xC0 /* Reset mode : top to bottom */
#define SSD130x_CMD_COM_SCAN_REVERSE 0xC8 /* Bottom to top */
#define SSD130x_CMD_DISPLAY_OFFSET 0xD3
/* Data for display offset (COM shift) */
#define SSD130x_OFFSET_DATA(x) ((x) & 0x3F)
#define SSD130x_CMD_COM_PIN_CONF 0xDA
/* Data for COM pins hardware configuration */
#define SSD130x_COM_SEQUENTIAL (0x00 << 4)
#define SSD130x_COM_ALTERNATIVE (0x01 << 4) /* Reset mode */
#define SSD130x_COM_NO_REMAP (0x00 << 5) /* Reset mode */
#define SSD130x_COM_REMAP (0x01 << 5)
/* Timing and driving scheme : Clock */
#define SSD130x_CMD_DISP_CLK_DIV 0xD5
#define SSD130x_CLK_DIV(x) ((x) & 0x0F) /* Set to N+1 (Default is 0+1) */
#define SSD130x_CLK_FREQ(x) (((x) & 0x0F) << 4) /* Reset is 0x80 */
/* Timing and driving scheme : Precharge */
#define SSD130x_CMD_SET_PRECHARGE 0xD9
#define SSD130x_PRECHARGE_PHASE1(x) ((x) & 0x0F) /* Default to 2, 0 is invalid */
#define SSD130x_PRECHARGE_PHASE2(x) (((x) & 0x0F) << 4) /* Default to 2, 0 is invalid */
/* Timing and driving scheme : Voltage */
#define SSD130x_CMD_VCOM_LEVEL 0xDB
#define SSD130x_VCOM_065 0x00
#define SSD130x_VCOM_077 0x20
#define SSD130x_VCOM_083 0x30
/* NO-OP */
#define SSD130x_CMD_NOP 0xE3
/* Status register read */
#define SSD130x_STATUS_ON (0x01 << 6)
#define GDDRAM_SIZE (128 * 8)
#define OLED_LINE_CHAR_LENGTH (SSD130x_NB_COL / 8)
#define DISPLAY_LINE_LENGTH (OLED_LINE_CHAR_LENGTH + 1)
#include <cstdint>
#include <MicroBit.h>
class ssd1306 {
public:
/**
*
*/
ssd1306(MicroBit* uB, MicroBitI2C* uBi2c, MicroBitPin* pin_reset,uint8_t addr = SSD130x_ADDR);
/**
* Power Off the screen
*/
int power_off();
/**
* Power On the screen
*/
int power_on();
/**
* Display a single char a position (line, col)
*/
void display_char(uint8_t line, uint8_t col, uint8_t c);
/**
* Display a text at position (line, col)
*/
int display_line(uint8_t line, uint8_t col, const char* text);
/**
* update screen display
* should be called after a series of display change
*/
int update_screen();
private:
int initialize();
int send_command(uint8_t cmd, uint8_t* data, uint8_t len);
int set_mem_addressing_mode(uint8_t mode);
int set_column_address(uint8_t col_start, uint8_t col_end);
int set_page_address(uint8_t page_start, uint8_t page_end);
int set_display_on(uint8_t use_ram);
int display_power(uint8_t status);
int set_scan_direction();
int set_read_direction();
int set_display_offset(uint8_t dir, uint8_t nb_lines);
int set_mux_ratio(uint8_t ratio);
int set_display_clock(uint8_t divide, uint8_t frequency);
int set_contrast(uint8_t contrast);
int display_video_reverse();
int buffer_set(uint8_t *gddram, uint8_t val);
int buffer_set_pixel(uint8_t* gddram, uint8_t x0, uint8_t y0, uint8_t state);
int buffer_set_tile(uint8_t* gddram, uint8_t x0, uint8_t y0, uint8_t* tile);
MicroBit* uBit;
MicroBitI2C* i2c;
MicroBitPin* reset;
uint8_t gddram[ 1 + GDDRAM_SIZE ];
uint8_t address;
uint8_t video_mode;
uint8_t contrast;
uint8_t scan_dir;
uint8_t read_dir;
uint8_t offset_dir;
uint8_t offset;
uint8_t charge_pump;
bool fullscreen;
};
#endif
Loading…
Cancel
Save