Jump to content

crteensy

Members
  • Posts

    111
  • Joined

  • Last visited

Everything posted by crteensy

  1. 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...
  2. 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_H gdisp_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_GDISP board_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_H and 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; } } }
  3. 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
  4. 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_H gdisp_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_GDISP board_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_H board_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.
  5. 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.
  6. 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.
  7. 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): Is 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.
  8. 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 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?
  9. 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?
  10. 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.
  11. 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
×
×
  • Create New...