Skip to content
Snippets Groups Projects
Commit 85f9f0a2 authored by Eric Brombaugh's avatar Eric Brombaugh
Browse files

Updated to support more types of OLED displays

parent 03b71e77
No related branches found
No related tags found
No related merge requests found
# I2C OLED demonstration
This example code demonstrates use of the CH32V003 I2C peripheral with an SSD1306
OLED (128x32 pixel type). It provides a generic I2C port initialization and
transmit (write-only) low level interface and a high-level graphics driver with
pixels, lines, circles, rectangles and 8x8 character font rendering. Out of the
box this demo cycles through a few different graphic screens to test out the
various drawing primitives.
OLED. Three different OLED sizes are supported - 64x32, 128x32, and 128x64.
It provides a generic I2C port initialization and transmit (write-only) low level
interface and a high-level graphics driver with pixels, lines, circles, rectangles
and 8x8 character font rendering. Out of the box this demo cycles through a few
different graphic screens to test out the various drawing primitives.
https://user-images.githubusercontent.com/1132011/230734071-dee305de-5aad-4ca0-a422-5fb31d2bb0e0.mp4
......@@ -27,13 +27,23 @@ mysterious effects and less error checking.
* IRQ_DIAG - enables timing analysis via GPIO toggling. Don't enable this unless
you know what you're doing.
There are a few build-time options in the oled.h source:
* OLED_ADDR - the I2C address of your OLED display. The default is 0x3c which
should work for most devices. Use 0x3d if you've pulled the SA0 line high.
* OLED_PSZ - the number of bytes to send per I2C data packet. The default value
of 32 seems to work well. Smaller values are allowed but may result in slower
refresh rates.
* OLED_64X32, OLED_128X32, OLED_128X64 - choose only one of these depending on
the type of OLED you've got.
## Use
Connect an SSD1306-based OLED in I2C interface mode to pins PC1 (SDA) and PC2 (SCL)
of the CH32V003 with proper I2C pullup resistors and observe the various graphic
images that cycle at approximately 2 second intervals.
Note - I used an Adafruit 0.91" 128x32 OLED breakout (stock #4440) for my testing
and found that the built-in 10k pullup resistors were too weak for reliable I2C
bus transactions. I had to add 2.2k resistors to the SCL and SDA pads to allow
proper operation.
Note - for part of my testing I used an Adafruit 0.91" 128x32 OLED breakout
(stock #4440) and found that the built-in 10k pullup resistors were too weak for
reliable I2C bus transactions. I had to add 2.2k resistors to the SCL and SDA
pads to allow proper operation. Generic OLED boards from ebay had stronger pullups
and did not need modification.
......@@ -31,7 +31,7 @@ int main()
printf("Looping on test modes...");
while(1)
{
for(uint8_t mode=0;mode<=6;mode++)
for(uint8_t mode=0;mode<(OLED_H>32?8:7);mode++)
{
// clear buffer for next mode
oled_setbuf(0);
......@@ -39,53 +39,75 @@ int main()
switch(mode)
{
case 0:
printf("buffer fill with binary\n\r");
for(int i=0;i<sizeof(oled_buffer);i++)
oled_buffer[i] = i;
break;
case 1:
printf("pixel plots\n\r");
for(int i=0;i<OLED_W;i++)
{
oled_drawPixel(i, i>>2, 1);
oled_drawPixel(i, OLED_H-1-(i>>2), 1);
oled_drawPixel(i, i/(OLED_W/OLED_H), 1);
oled_drawPixel(i, OLED_H-1-(i/(OLED_W/OLED_H)), 1);
}
break;
case 2:
{
printf("Line plots\n\r");
uint8_t y= 0;
for(uint8_t x=0;x<OLED_W;x+=16)
{
oled_drawLine(x, 0, OLED_W, y, 1);
oled_drawLine(OLED_W-x, OLED_H, 0, OLED_H-y, 1);
y+= 4;
y+= OLED_H/8;
}
}
break;
case 3:
printf("Circles empty and filled\n\r");
for(uint8_t x=0;x<OLED_W;x+=16)
if(x<64)
oled_drawCircle(x,16, 15, 1);
oled_drawCircle(x, OLED_H/2, 15, 1);
else
oled_fillCircle(x,16, 15, 1);
oled_fillCircle(x, OLED_H/2, 15, 1);
break;
case 4:
printf("Unscaled Text\n\r");
oled_drawstr(0,0, "This is a test", 1);
oled_drawstr(0,8, "of the emergency", 1);
oled_drawstr(0,16,"broadcasting", 1);
oled_drawstr(0,24,"system.",1);
oled_xorrect(64, 0, 64, 32);
if(OLED_H>32)
{
oled_drawstr(0,32, "Lorem ipsum", 1);
oled_drawstr(0,40, "dolor sit amet,", 1);
oled_drawstr(0,48,"consectetur", 1);
oled_drawstr(0,56,"adipiscing",1);
}
oled_xorrect(OLED_W/2, 0, OLED_W/2, OLED_W);
break;
case 5:
printf("Scaled Text 1, 2\n\r");
oled_drawstr_sz(0,0, "sz 8x8", 1, fontsize_8x8);
oled_drawstr_sz(0,16, "16x16", 1, fontsize_16x16);
break;
case 6:
printf("Scaled Text 4\n\r");
oled_drawstr_sz(0,0, "32x32", 1, fontsize_32x32);
break;
case 7:
printf("Scaled Text 8\n\r");
oled_drawstr_sz(0,0, "64", 1, fontsize_64x64);
break;
default:
break;
}
......
......@@ -14,6 +14,35 @@
// OLED I2C address
#define OLED_ADDR 0x3c
// comfortable I2C packet size for this OLED
#define OLED_PSZ 32
// what type of OLED - uncomment just one
//#define OLED_64X32
#define OLED_128X32
//#define OLED_128X64
// characteristics of each type
#ifdef OLED_64X32
#define OLED_W 64
#define OLED_H 32
#define OLED_FULLUSE
#define OLED_OFFSET 32
#endif
#ifdef OLED_128X32
#define OLED_W 128
#define OLED_H 32
#define OLED_OFFSET 0
#endif
#ifdef OLED_128X64
#define OLED_W 128
#define OLED_H 64
#define OLED_FULLUSE
#define OLED_OFFSET 0
#endif
/*
* send OLED command byte
*/
......@@ -81,7 +110,11 @@ const uint8_t oled_init_array[] =
SSD1306_SETDISPLAYCLOCKDIV, // 0xD5
0x80, // the suggested ratio 0x80
SSD1306_SETMULTIPLEX, // 0xA8
0x3F, // different for tiny
#ifdef OLED_64X32
0x1F, // for 64-wide displays
#else
0x3F, // for 128-wide displays
#endif
SSD1306_SETDISPLAYOFFSET, // 0xD3
0x00, // no offset
SSD1306_SETSTARTLINE | 0x0, // 0x40 | line
......@@ -92,7 +125,7 @@ const uint8_t oled_init_array[] =
SSD1306_SEGREMAP | 0x1, // 0xA0 | bit
SSD1306_COMSCANDEC,
SSD1306_SETCOMPINS, // 0xDA
0x12,
0x12, //
SSD1306_SETCONTRAST, // 0x81
0x8F,
SSD1306_SETPRECHARGE, // 0xd9
......@@ -104,11 +137,9 @@ const uint8_t oled_init_array[] =
SSD1306_DISPLAYON, // 0xAF --turn on oled panel
SSD1306_TERMINATE_CMDS // 0xFF --fake command to mark end
};
#define OLED_W 128
#define OLED_H 32
// the display buffer
uint8_t oled_buffer[128*32/8];
uint8_t oled_buffer[OLED_W*OLED_H/8];
/*
* set the buffer to a color
......@@ -118,6 +149,7 @@ void oled_setbuf(uint8_t color)
memset(oled_buffer, color ? 0xFF : 0x00, sizeof(oled_buffer));
}
#ifndef OLED_FULLUSE
/*
* expansion array for OLED with every other row unused
*/
......@@ -128,24 +160,24 @@ const uint8_t expand[16] =
0x80,0x82,0x88,0x8a,
0xa0,0xa2,0xa8,0xaa,
};
#endif
/*
* Send the frame buffer
*/
#define OLED_PSZ 32 // comfortable I2C packet size for this OLED
void oled_refresh(void)
{
uint16_t i;
oled_cmd(SSD1306_COLUMNADDR);
oled_cmd(0); // Column start address (0 = reset)
oled_cmd(OLED_W-1); // Column end address (127 = reset)
oled_cmd(OLED_OFFSET); // Column start address (0 = reset)
oled_cmd(OLED_OFFSET+OLED_W-1); // Column end address (127 = reset)
oled_cmd(SSD1306_PAGEADDR);
oled_cmd(0); // Page start address (0 = reset)
oled_cmd(7); // Page end address
#if 0
#ifdef OLED_FULLUSE
/* for fully used rows just plow thru everything */
for(i=0;i<sizeof(oled_buffer);i+=OLED_PSZ)
{
......@@ -489,7 +521,8 @@ void oled_drawstr(uint8_t x, uint8_t y, char *str, uint8_t color)
typedef enum {
fontsize_8x8 = 1,
fontsize_16x16 = 2,
fontsize_32x32 = 4
fontsize_32x32 = 4,
fontsize_64x64 = 8,
} font_size_t;
/*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment