crteensy
-
Posts
111 -
Joined
-
Last visited
Content Type
Forums
Store
Downloads
Blogs
Posts posted by crteensy
-
-
Of course you need see code - here are my current driver files.
gdisp_lld_config.h:
#ifndef GDISP_LLD_CONFIG_H
#define GDISP_LLD_CONFIG_H
#if GFX_USE_GDISP
/*===========================================================================*/
/* Driver hardware support. */
/*===========================================================================*/
#define GDISP_HARDWARE_DRAWPIXEL TRUE
#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
#endif /* GFX_USE_GDISP */
#endif // GDISP_LLD_CONFIG_Hgdisp_lld_ssd1351.c: (see gdisp_lld_draw_pixel(), please)
#include
#if GFX_USE_GDISP
#define GDISP_DRIVER_VMT GDISPVMT_SSD1351
#include "gdisp_lld_config.h"
#include "src/gdisp/gdisp_driver.h"
#include "board_ssd1351.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#ifndef GDISP_SCREEN_HEIGHT
#define GDISP_SCREEN_HEIGHT 128
#endif
#ifndef GDISP_SCREEN_WIDTH
#define GDISP_SCREEN_WIDTH 128
#endif
#ifndef GDISP_INITIAL_CONTRAST
#define GDISP_INITIAL_CONTRAST 100
#endif
#ifndef GDISP_INITIAL_BACKLIGHT
#define GDISP_INITIAL_BACKLIGHT 100
#endif
#define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0)
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
// none
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
LLDSPEC bool_t gdisp_lld_init(GDisplay *g)
{
init_board(g);
return TRUE;
}
#if GDISP_HARDWARE_DRAWPIXEL
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g)
{
board_drawPixel(g, g->p.x, g->p.y, g->p.color); <- // NOT called, apparently
}
#endif
#endif // GFX_USE_GDISPboard_ssd1351.h: declares my board_drawPixel() function
#ifndef BOARD_SSD1351_H
#define BOARD_SSD1351_H
// pin numbers for teensyduino code
#define SSD1351_DC 14
#define SSD1351_R 15
#define SSD1351_CS 16
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void init_board(GDisplay *g);
void board_drawPixel(GDisplay* g, coord_t x, coord_t y, color_t c);
void post_init_board(GDisplay *g);
void setpin_reset(GDisplay *g, bool_t state);
void acquire_bus(GDisplay *g);
void release_bus(GDisplay *g);
void write_cmd(GDisplay *g, uint8_t cmd);
void write_data(GDisplay *g, uint8_t data);
void write_datap(GDisplay *g, const uint8_t* data, uint16_t length);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // BOARD_SSD1351_Hand the board_ssd1351.cpp: implements board_drawPixel(), which draws on the display I connected to my controller. I have verified that the function works; I can draw pixels when I call it in my main().
#include
#include
#include
#include "board_ssd1351.h"
static SPISettings settings(12000000, MSBFIRST, SPI_MODE0);
void select()
{
digitalWriteFast(SSD1351_CS, 0);
}
void deselect()
{
digitalWriteFast(SSD1351_CS, 1);
}
void command()
{
digitalWriteFast(SSD1351_DC, 0);
}
void data()
{
digitalWriteFast(SSD1351_DC, 1);
}
void write_data(GDisplay *g, uint8_t data); // see below
void home(GDisplay *g)
{
acquire_bus(g);
write_cmd(g, 0x15); // set column address
write_data(g, 0x00); // start
write_data(g, 0x7F); // end
write_cmd(g, 0x75); // set row address
write_data(g, 0x00); // start
write_data(g, 0x7F); // end
write_cmd(g, 0x5C); // write to RAM
release_bus(g);
}
void init_board(GDisplay *g)
{
pinMode(SSD1351_R, OUTPUT);
setpin_reset(g, TRUE);
pinMode(SSD1351_CS, OUTPUT);
deselect();
pinMode(SSD1351_DC, OUTPUT);
delay(50);
setpin_reset(g, FALSE);
delay(50);
acquire_bus(g);
write_cmd(g, 0xFD); // set command lock
write_data(g, 0x12); // unlock OLED driver IC
write_cmd(g, 0xFD); // set command lock
write_data(g, 0xB1); // make commands A1, B1, B3, BB, BE, C1 accesible in unlocked state
write_cmd(g, 0xAE); // sleep mode ON (display off)
write_cmd(g, 0xB3); // Front clock divider / osc freq
write_data(g, 0xF1); // Osc = 0xF; div = 2
write_cmd(g, 0xCA); // set MUX ratio
write_data(g, 127);
write_cmd(g, 0xA0); // Set re-map / color depth
write_data(g, 0b01110100);
// [0] : address increment (0: horizontal, 1: vertical, reset 0)
// [1] : column remap (0: 0..127, 1: 127..0, reset 0)
// [2] : color remap (0: A->B->C, 1: C->B->A, reset 0)
// [3] : reserved
// [4] : column scan direction (0: top->down, 1: bottom->up, reset 0)
// [5] : odd/even split COM (0: disable, 1: enable, reset 1)
// [6..7] : color depth (00,01: 65k, 10: 262k, 11: 262k format 2)
write_cmd(g, 0x15); // Set Column address
write_data(g, 0x00); // start
write_data(g, 0x7F); // end
write_cmd(g, 0x75); // set row address
write_data(g, 0x00); // start
write_data(g, 0x7F); // end
write_cmd(g, 0xA1); // set display start line
write_data(g, 0x00); // 0
write_cmd(g, 0xA2); // set display offset
write_data(g, 0x00); // 0
write_cmd(g, 0xB5); // set GPIO
write_data(g, 0x00); // both HiZ, input disabled
write_cmd(g, 0xAB); // function select
write_data(g, 0x01); // enable internal VDD regulator
write_cmd(g, 0xB1); // set reset / pre-charge period
write_data(g, 0x32); // phase 2: 3 DCLKs, phase 1: 5 DCLKs
write_cmd(g, 0xBE); // set VComH voltage
write_data(g, 0x05); // 0.82*Vcc
write_cmd(g, 0xBB); // set pre-charge voltage
write_data(g, 0x17); // 0.6*Vcc
write_cmd(g, 0xA6); // set display mode: reset to normal display
write_cmd(g, 0xC1); // set contrast current for A,B,C
write_data(g, 0xC8);
write_data(g, 0x80);
write_data(g, 0xC8);
write_cmd(g, 0xC7); // master contrast current control
write_data(g, 0x0F); // no change
write_cmd(g, 0xB4); // set segment low voltage
write_data(g, 0xA0); // external VSL
write_data(g, 0xB5); // hard value
write_data(g, 0x55); // hard value
write_cmd(g, 0xB6); // set second pre-charge period
write_data(g, 0x01); // 1 DCLKs
write_cmd(g, 0xAF); // sleep mode OFF (display on)
// write_cmd(g, 0x5C); // write to RAM
release_bus(g);
delay(50);
home(g);
Serial.println("board init");
}
void post_init_board(GDisplay *g)
{
(void) g;
}
void setpin_reset(GDisplay *g, bool_t state)
{
(void) g;
(void) state;
if(state)
{
digitalWriteFast(SSD1351_R, 0);
}
else
{
digitalWriteFast(SSD1351_R, 1);
}
}
void acquire_bus(GDisplay *g)
{
SPI.beginTransaction(settings);
select();
(void) g;
}
void release_bus(GDisplay *g)
{
deselect();
SPI.endTransaction();
(void) g;
}
void write_cmd(GDisplay *g, uint8_t cmd)
{
(void) g;
(void) cmd;
command();
SPI.transfer(cmd);
data();
}
void write_data(GDisplay *g, uint8_t data)
{
SPI.transfer(data);
}
void write_data(GDisplay *g, const uint8_t* data, uint16_t length)
{
(void) g;
(void) data;
(void) length;
for (uint8_t i = 0; i < length; i++)
while(length)
{
SPI.transfer(data[i]);
}
}
void write_datap(GDisplay *g, const uint8_t* data, uint16_t length)
{
write_data(g, data, length);
}
void board_drawPixel(GDisplay* g, coord_t x, coord_t y, color_t c)
{
Serial.printf("pixel @ %d %d : %4x\n", x, y, c);
acquire_bus(g);
write_cmd(g, 0x15);
write_data(g, x);
write_data(g, 127);
write_cmd(g, 0x75);
write_data(g, y);
write_data(g, 127);
write_cmd(g, 0x5C);
write_data(g, c >> 8);
write_data(g, c & 0xFF);
release_bus(g);
}main.cpp: this is where I draw "manually" in loop()
#include
#include
#include
#include
void setup()
{
// pinMode(LED_BUILTIN, OUTPUT);
while(!Serial.available());
while(Serial.available())
{
Serial.read();
}
Serial.println("Start");
SPI.begin();
coord_t width, height;
coord_t i, j;
// Initialize and clear the display
gfxInit();
// Get the screen size
width = gdispGetWidth();
height = gdispGetHeight();
// Code Here
gdispDrawBox(10, 10, width/2, height/2, Yellow);
gdispFillArea(width/2, height/2, width/2-10, height/2-10, Blue);
gdispDrawLine(5, 30, width-50, height-40, Red);
for(i = 5, j = 0; i < width && j < height; i += 7, j += i/20)
gdispDrawPixel(i, j, White);
// while(TRUE) {
// gfxSleepMilliseconds(500);
// }
}
void loop()
{
static uint8_t x = 0;
static uint8_t y = 0;
// board_drawPixel(nullptr, x, y, Red); // <- WORKS
gdispDrawPixel(x, y, Red); // <- nothing happens
x++;
if (x >= 0x80)
{
x = 0;
y++;
if (y >= 0x80)
{
y = 0;
}
}
} -
Looks like ugfx is calling my init_board() just fine: I can draw pixels "manually" at any coordinate using my board functions), but it doesn't use my gdisp_lld_draw_pixel() function to actually draw anything. Any ideas?
Regards
Christoph
-
OK, at least I have a compiling set of files now, at least for the Teensy LC.
When I try to compile for Teensy 3.1, something in my build setup is hiding _ebss, which is defined in the linker script for both platforms (LC and 3.1 have different linker scripts, but both scripts define _ebss). I'll also post this problem in PJRC's forum where the teensyduino people are.
Here are my files for a dummy driver that calls the C++ interface via the board header.
ugfxconf.h:
#ifndef _GFXCONF_H
#define _GFXCONF_H
#define GFX_USE_OS_RAW32 TRUE
#define GFX_NO_OS_INIT TRUE
#define GFX_USE_GDISP TRUE
#endif /* _GFXCONF_H */os.c:
#include
#include
systemticks_t gfxSystemTicks(void)
{
return millis();
}
systemticks_t gfxMillisecondsToTicks(delaytime_t ms)
{
return ms;
}gdisp_lld_config.h:
#ifndef GDISP_LLD_CONFIG_H
#define GDISP_LLD_CONFIG_H
#if GFX_USE_GDISP
/*===========================================================================*/
/* Driver hardware support. */
/*===========================================================================*/
#define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing
#define GDISP_HARDWARE_DRAWPIXEL TRUE
#define GDISP_HARDWARE_PIXELREAD FALSE
#define GDISP_HARDWARE_CONTROL FALSE
#define GDISP_HARDWARE_FILLS FALSE
#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565
// This controller supports a special gdispControl() to inverse the display.
// Pass a parameter of 1 for inverse and 0 for normal.
#define GDISP_CONTROL_INVERSE (GDISP_CONTROL_LLD+0)
#endif /* GFX_USE_GDISP */
#endif // GDISP_LLD_CONFIG_Hgdisp_lld_ssd1351.c: minimal, but should provide the required interface; the low-level magic will be in the board file as suggested
#include
#if GFX_USE_GDISP
#define GDISP_DRIVER_VMT GDISPVMT_SSD1351
#include "gdisp_lld_config.h"
#include "src/gdisp/gdisp_driver.h"
#include "board_ssd1351.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#ifndef GDISP_SCREEN_HEIGHT
#define GDISP_SCREEN_HEIGHT 128
#endif
#ifndef GDISP_SCREEN_WIDTH
#define GDISP_SCREEN_WIDTH 128
#endif
#ifndef GDISP_INITIAL_CONTRAST
#define GDISP_INITIAL_CONTRAST 100
#endif
#ifndef GDISP_INITIAL_BACKLIGHT
#define GDISP_INITIAL_BACKLIGHT 100
#endif
#define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER<<0)
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
// Some common routines and macros
#define RAM(g) ((uint8_t *)g->priv)
#define write_cmd2(g, cmd1, cmd2) { write_cmd(g, cmd1); write_cmd(g, cmd2); }
#define write_cmd3(g, cmd1, cmd2, cmd3) { write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
// Some common routines and macros
#define delay(us) gfxSleepMicroseconds(us)
#define delayms(ms) gfxSleepMilliseconds(ms)
#define xyaddr(x, y) (SSD1306_PAGE_OFFSET + (x) + ((y)>>3)*SSD1306_PAGE_WIDTH)
#define xybit(y) (1<<((y)&7))
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
LLDSPEC bool_t gdisp_lld_init(GDisplay *g)
{
init_board(g);
return TRUE;
}
#if GDISP_HARDWARE_DRAWPIXEL
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g)
{
}
#endif
#if GDISP_HARDWARE_FLUSH
LLDSPEC void gdisp_lld_flush(GDisplay *g)
{
}
#endif
#endif // GFX_USE_GDISPboard_ssd1351.h: just declarations, most of them are probably not necessary
#ifndef BOARD_SSD1351_H
#define BOARD_SSD1351_H
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void init_board(GDisplay *g);
void post_init_board(GDisplay *g);
void setpin_reset(GDisplay *g, bool_t state);
void acquire_bus(GDisplay *g);
void release_bus(GDisplay *g);
void write_cmd(GDisplay *g, uint8_t cmd);
void write_data(GDisplay *g, uint8_t* data, uint16_t length);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // BOARD_SSD1351_Hboard_ssd1351.cpp: currently just dummy implementations to see what happens
#include
#include
#include "board_ssd1351.h"
void init_board(GDisplay *g)
{
(void) g;
Serial.println("board init");
}
void post_init_board(GDisplay *g)
{
(void) g;
}
void setpin_reset(GDisplay *g, bool_t state)
{
(void) g;
(void) state;
}
void acquire_bus(GDisplay *g)
{
(void) g;
}
void release_bus(GDisplay *g)
{
(void) g;
}
void write_cmd(GDisplay *g, uint8_t cmd)
{
(void) g;
(void) cmd;
}
void write_data(GDisplay *g, uint8_t* data, uint16_t length)
{
(void) g;
(void) data;
(void) length;
}That linker issue is surely a bit disturbing, but I can keep on writing useful code for the LC.
-
Turns out the undefined reference was related to C/C++ mixing - nevermind.
This is going to be the hardest part of my afternoon because I need teensyduino functions and classes, which are mainly written in C++. I can't see a way of keeping them apart completely, but I'll do my best to make a clean split. C++ does not by itself mean that memory usage will be higher, or that hidden things happen. Of course, if I try to use a bunch of std::vectors then I'll run into problems. But bad code can be written just as easily in C.
-
Yes, starting with a similar driver (I picked the SSD1306) seems to be a good starting point. However, I'm having one problem during the linking stage (I solved some others, they were easier to fix):
The linker complains
disp.c:(.text._gdispInit+0x40): undefined reference to `GDISPVMT_OnlyOne'
I have not added any define in gfxconf.h, so ugfx should default to an external declaration of
extern const GDISPVMT const GDISPVMT_OnlyOne[1];
in _gdispInit. I can't find the place where it is actually defined.
-
For starting you really just need the init() and the setPixel() routine.
You mean gdisp_lld_init() and gdisp_lld_draw_pixel() in the point-and-block-model?
When I want to mix with the Window model, can I just add functions like e.g. gdisp_lld_write_start(), gdisp_lld_write_color() and gdisp_lld_write_stop()? This is not 100% clear in the source (src/gdisp/gdisp_driver.h, lines 127..135):
Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be provided by the driverIs that an exclusive or?
Either way, if I'm understanding this correctly I have to define GDISP_HARDWARE_DRAWPIXEL and/or GDISP_HARDWARE_STREAM_WRITE in my gdisp_lld_config.h for ugfx to understand how to draw on my display. If that is the case then I think I'm slowly getting it...
Some more questions:
- What effect should GDISP_HARDWARE_FLUSH have on my display and when exactly is gdisp_lld_flush() called? Is the purpose of this function to push all pending pixel writes or other commands to the display before any further drawing is done?
- How does ugfx know which driver to use? In the demos (ugfx/demos/modules/gdisp/basics/main.c or gfxconf.h) I see no sign of an actual display being used.
-
I don't quite understand what you say about the defines in gdisp_lld_config.h. Take for example line 17 in ugfx/drivers/gdisp/PCD8544/gdisp_lld_config.h:
#define GDISP_HARDWARE_FLUSH TRUE // This controller requires flushing
By the comment this line seems to tell ugfx something about the controller. OTOH, you say
If you write your own driver then you're free to do it as you like.but I'm certainly not free to do as I like when I want ugfx to understand my controller features. Or am I getting this totally wrong?
-
When I create a gdisp_lld_config.h, what defines does ugfx look for in that file? I can't seem to find a list of common flags or options apart from the pixel format. I'd like to write a driver for the SSD1351. How can I bring that chip, gdisp_lld_config.h and the model descriptions at http://wiki.ugfx.org/index.php?title=Di ... iver_Model together?
-
Thank you, so for now I'll just try to write a driver that works without a framebuffer.
How can I mix C++ into my ugfx display driver? Is there a commonly recommended, documented way of doing that? I've gotten ugfx to compile with teensyduino up to the point where I need to write the actual display driver. Now it gets tricky because it's common to call C functions in C++, but not the other way around.
-
Hi,
I'm new to ugfx and considered writing my own graphics library after trying u8lib and adafruit_gfx. Before I really do that I'd like to give it a try with ugfx. I already found the wiki and looked for buffers and paging. I'm not sure if I really need that, but the Teensy hardware I'd like to use doesn't have enough RAM for a whole frame. So my first question is:
Is it possible to have a paged frame buffer (1/4th or 1/8th) with ugfx? If not, is the window display driver model a suitable workaround? (Would you recommend not to use a paged buffer?)
I have applications that use only one color channel of an OLED display (dimmable red, for eyes adapted to darkness). My canvas can essentially be monochrome in such a case, and the mapping form monochrome to dimmed color is done by the display driver. Is that possible with ugfx? Are monochrome (or less-than-8-bit in general) colors packed in memory or does a pixel always occupy at least one byte?
Regards
Christoph
Using ugfx on a Teensy 3.1 or Teensy LC
in Support
Posted
I see. Thanks for your effort! With that explanation I might have come up with a suitable solution as well, but if you want to work on it that's great.
Even with the ILI9341 I would have probably made the same mistake. There was no sign of the static-inline-ness in the board header being that important, so I would have pushed as much logic into the cpp file as I have now. Also I'm not aiming for speed now, just for a working implementation. The one pixel function looked more attractive than three for streaming...