SOLVED! m328 SPI and .96inch OLED can't set pixels

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SOLVED IT! Was not correctly setting the color mode. I bought this from aliexpress: https://www.aliexpress.com/item/32859042892.html First tries in clearing the display via SPI on an atmega328 seem to suggest it's closer to 110*160? Display clearing works, but I am unable to set any pixel values, nor does PixelTest work. Does anyone have ideas?

 

spilcd.h

#include "spi.h"

#define DCPORT PORTC
#define DCDDR DDRC
#define DCDDRPIN DDC2
#define DCPIN PINC2

#define RSTPORT PORTC
#define RSTDDR DDRC
#define RSTDDRPIN DDC3
#define RSTPIN PINC3
#define NORON 0x13
#define SWRESET 0x01 // software reset
#define SLPOUT 0x11 // sleep out
#define DISPOFF 0x28 // display off
#define DISPON 0x29 // display on
#define CASET 0x2A // column address set
#define RASET 0x2B // row address set
#define RAMWR 0x2C // RAM write
#define MADCTL 0x36 // axis control
#define COLMOD 0x3A // color mode

// Color constants
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x0400
#define LIME 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF

void write_cmd(uint8_t  command) {
    DCPORT &= ~(1 << DCPIN);
    send_recieve_spi_byte(command);
    DCPORT |= (1 << DCPIN);
}

void write_word (uint16_t w)
{
 send_recieve_spi_byte(w >> 8); // write upper 8 bits
 send_recieve_spi_byte(w & 0xFF); // write lower 8 bits
}

void hardware_reset() {
    RSTPORT &= ~(1<< RSTPIN);
    _delay_ms(1);
    RSTPORT |= (1<< RSTPIN);
    _delay_ms(200);
}

void initialize_lcd() {
    DCDDR |= (1 << DCDDRPIN);
    RSTDDR |= (1 << RSTDDRPIN);

    DCPORT |= (1 << DCPIN);
    RSTPORT |= (1<< RSTPIN);

    hardware_reset();

    write_cmd(SLPOUT);
    _delay_ms(150);
    write_cmd(COLMOD);
    write_cmd(0x05);
}

void set_addr_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
    write_cmd(CASET); // set column range (x0,x1)
    write_word(x0);
    write_word(x1);
    write_cmd(RASET); // set row range (y0,y1)
    write_word(y0);
    write_word(y1);
}

void clear_screen()
{
    set_addr_window(0,0,110, 160); // set window to entire display
    write_cmd(RAMWR);
    for (unsigned int i=53800;i>0;--i) // byte count = some magic number
    {
       send_recieve_spi_byte(0);
    }
}

spi.h

uint8_t send_recieve_spi_byte(uint8_t data)
{
    PORTB &= ~(1 << PINB2);
    // Load data into the buffer
    SPDR = data;
    //Wait until transmission complete
    while(!(SPSR & (1<<SPIF) ));
    PORTB |= (1 << PINB2);
    // Return received data
    return(SPDR);
}

void init_spi_oneway() {
    DDRB = (1 << DDB2) | (1 << DDB3) | (1 << DDB5);
    SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0);
        PORTB |= (1 << PINB2);
   // SPCR = 0x50;
}

void init_spi_twoway() {
    DDRB &= ~(1 << DDB4);
    init_spi_oneway();
}

and main.c 

/*
 */

#include <avr/io.h>
#include <util/delay.h>
#include "spilcd.h"
#include <stdint.h>
#include <stdlib.h>
void Write565 (uint16_t data, uint16_t count)
{
 while(count--)
 {
    send_recieve_spi_byte(data >> 8);
    send_recieve_spi_byte(data & 0xFF);
}
}

void DrawPixel (uint8_t x, uint8_t y, uint16_t color)
{
 set_addr_window(x,y,x,y); // set active region = 1 pixel
 write_cmd(RAMWR); // memory write
 Write565(color,1); // send color for this pixel
}

void PixelTest()
// draws 4000 pixels on the screen
{
 for (int i=4000; i>0; i--) // do a whole bunch:
 {
 int x = rand() % 110; // random x coordinate
 int y = rand() % 160; // random y coordinate
 DrawPixel(x,y,RED); // draw pixel at x,y
 }
}

int main() {

    init_spi_oneway();
    initialize_lcd();
    write_cmd(DISPON);
    clear_screen();

    PixelTest();
    while(1) {

    }

    return 0;
}

 

Last Edited: Wed. Oct 2, 2019 - 07:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Glad you got it working, did you post the solution for others to see?

 

Jim

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The link (and your code) suggests a ST7735 controller.   ST7735 is for TFT not OLED.

 

I am intrigued by you saying 110x160.

ST7735 can control up to 132x162

If your physical panel is 110x160 I am surprised that a shop would say 80x160.

 

From memory,  the ST7735 can't be configured in hardware for 80x160.   So the software might need to make some "adjustments" for PORTRAIT_REV and LANDSCAPE_REV rotations.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

randoh wrote:
SOLVED IT!

See Tip #5

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...