I2C port 1: Anyone got this working on their Seed?

I can’t seem to get it working.

I created a very basic CubeMX test app and managed to to get it working. I’m using an I2C (4 pin) Oled display, “Hello World.” I’m using a 3rd party lib to talk to the Oled, works fine.

When I port the code into the Daisy Seed app, nothing.
I think the problem might be the clocking from the internal oscillators. but not sure.

In the original libDaisy the I2C initialization was included with the Seed, so I followed that.but no joy.
With the later versions of libDaisy I2C was removed.from the Seed.
I’ve looked at the Petal code which uses I2C to drive the leds and tried to figure out that piece of code.

Anyone got any ideas ?

Here’s the Cube repo

Cheers

You definitely won’t be able to just port code as is using different oscillator settings. The issue is I2C timing settings are based on oscillator clock and I2C bus frequency. So what you should probably do is use the same clock settings as Daisy, would be using matching timing parameter.

I think that for 100k I2C you’ll need to use 0x10C0ECFF as timing for Daisy’s clock settings

OK cheers, I’ll hack about

Please share your findings once you get it to work. I’ve had my eye on connecting an i2c oled to the Seed for a while as well.

Yes, using libdaisy. Not sure how close to metal you’re aiming for as I think libdaisy goes via HAL.

Is this any help:

I2CHandle i2c;

void Start_ST7036()
{
// This has two functions:
// 1. Activates I2C_1 via Daisy and HAL
// 2. Initialises the MIDAS display for use at 3.3V (based on data sheet sequence)
//
// The Follower and Contrast settings have been adjusted to work with this particular unit at 3.3V
// Seems like they are quite critical. Too much of either gives white squares as all pixels fire regardless

uint8_t midas_initialize[]={
		ST_COMMAND,
		ST_FUN_SET | 1<<DL | 1<<N,
		ST_FUN_SET | 1<<DL | 1<<N | 1<<IS,
		ST_OSC_FRQ | 1<<BS,
		ST_CONTRAST | 0x0a,
		ST_PO_IC_CO | 1<<BO | 0x01,
		ST_FOLLOWER | 1<<FON | 0x0c,
		ST_DIS_ON | 1<<D,
		ST_CLEAR,
		ST_ENT_MODE | 1<<ID,
		ST_FUN_SET | 1<<DL | 1<<N,
		ST_RET_HOME
	};

static constexpr I2CHandle::Config petal_led_i2c_config
    = {I2CHandle::Config::Peripheral::I2C_1,
       {{DSY_GPIOB, 8}, {DSY_GPIOB, 9}},		// I have failed to place GetPin() successfully in these locations
       I2CHandle::Config::Speed::I2C_100KHZ};	// PB8 and PB9 are pins that come out as D11 and D12 on Daisy for I2C_1

    i2c.Init(petal_led_i2c_config);

    // now i2c points to the corresponding peripheral and can be used.
  i2c.TransmitBlocking(ST_ADDRESS,midas_initialize,12,1000); // timeout maybe in ms, doesn't seem to block on wrong address

  dsy_system_delay(20); // wait for clear

} // End of Start_ST7036

// Takes a 16 char array and places across one line of I2C LCD unit
// Although this may waste some write cycles it’s quicker on START & STOP
// Use offset of 0x00 for first line and SECOND_LINE_OFFSET for second
void Show_Line(char *line,unsigned char offset)
{
int position;
unsigned char showline_header[3+LINE_LENGTH]={ // set MIDAS for one byte command followed by data
ST_COMMAND | ST_CO, // header space set t
static_cast(ST_SET_DDRAM | offset), // this must be 8 bit stream and is explicitly cast
ST_DATA
};

for (position=0; position<LINE_LENGTH;position++)
    {
        showline_header[position+3]=line[position];		// make a single array starting with commands and ending with text to show
    }

i2c.TransmitBlocking(ST_ADDRESS,showline_header,3+LINE_LENGTH,1000);

} // End of Show_Line()

Sorry formatting so awful, can send code and .h if you need it…

Have you tried to ‘block quote’ (quote as a block) the lines of code? Then the formatting it already has remains unchanged.

Can you post a project on GitHub ?

Hi, I’ve tried 0x10C0ECFF , unfortunately didn’t work.
I’ve altered other params as well, nothing.
I’m a bit stuck
I’ll have another try after digging deeper into Seeds timings

Sorry not that professional, hopefully putting in quoted will suffice.

void Start_ST7036()
{
		// This has two functions:
		// 1. Activates I2C_1 via Daisy and HAL
		// 2. Initialises the MIDAS display for use at 3.3V (based on data sheet sequence)
		//
		// The Follower and Contrast settings have been adjusted to work with this particular unit at 3.3V
		// Seems like they are quite critical. Too much of either gives white squares as all pixels fire regardless

	uint8_t midas_initialize[]={
			ST_COMMAND,
			ST_FUN_SET | 1<<DL | 1<<N,
			ST_FUN_SET | 1<<DL | 1<<N | 1<<IS,
			ST_OSC_FRQ | 1<<BS,
			ST_CONTRAST | 0x0a,
			ST_PO_IC_CO | 1<<BO | 0x01,
			ST_FOLLOWER | 1<<FON | 0x0c,
			ST_DIS_ON | 1<<D,
			ST_CLEAR,
			ST_ENT_MODE | 1<<ID,
			ST_FUN_SET | 1<<DL | 1<<N,
			ST_RET_HOME
		};

	static constexpr I2CHandle::Config petal_led_i2c_config
	    = {I2CHandle::Config::Peripheral::I2C_1,
	       {{DSY_GPIOB, 8}, {DSY_GPIOB, 9}},		// I have failed to place GetPin() successfully in these locations
	       I2CHandle::Config::Speed::I2C_100KHZ};	// PB8 and PB9 are pins that come out as D11 and D12 on Daisy for I2C_1

	    i2c.Init(petal_led_i2c_config);

	    // now i2c points to the corresponding peripheral and can be used.
      i2c.TransmitBlocking(ST_ADDRESS,midas_initialize,12,1000); // timeout maybe in ms, doesn't seem to block on wrong address

      dsy_system_delay(20); // wait for clear

This is the .h for the controller:

#ifndef DAIEX_SEED_OSC_INC_ST7036_AKJ_H_
#define DAIEX_SEED_OSC_INC_ST7036_AKJ_H_

// Definitions for the ST7036 LCD Driver
// AKJ June 2020 from MIDAS datasheet
#define ST_ADDRESS  (0b0111110)   // Daisy per_i2c.cpp does <<1 on line #222 so use address raw here
#define ST_COMMAND  0x00
#define ST_DATA     0x40        // This sets RS in Control Byte so data follows
#define ST_CO       0x80        // Sets Co bit to say another Control Byte will follow data
// NORMAL COMMANDS
#define ST_CLEAR    0x01
#define ST_RET_HOME 0x02
#define ST_ENT_MODE 0x04
    #define S  0
    #define ID 1
#define ST_DIS_ON   0x08
    #define B  0        // blink
    #define C  1        // cursor
    #define D  2        // display visibility
#define ST_CUR_SHF  0x10
    #define SC 3        // screen or cursor
    #define RL 2        // right or left
#define ST_FUN_SET  0x20
    #define DL 4
    #define N  3
    #define DH 2
    #define IS 0        // table 1
#define ST_SET_DDRAM 0x80
// INSTRUCTION TABLE 0 COMMANDS
#define ST_SHIFT    0x10
#define ST_SET_CGRM 0x40
// INSTRUCTION TABLE 1 COMMANDS, IS=1 in ST_FUN_SET
#define ST_OSC_FRQ  0x10
    #define BS 3
#define ST_ICO_ADD  0x40
#define ST_PO_IC_CO 0x50
    #define IC 3        // Icon on
    #define BO 2        // Booster on
#define ST_FOLLOWER 0x60
    #define FON 3
#define ST_CONTRAST 0x70

#define LINE_LENGTH 16              // How many characters across the display
#define SECOND_LINE_OFFSET  0x40    // How much further in memory that second line is

// Function prototypes
void Start_ST7036();
void Show_Line(char *,unsigned char);
void Erase_Line(char *);



#endif

and I’m writing to it like this:

// Takes a 16 char array and places across one line of I2C LCD unit
// Although this may waste some write cycles it's quicker on START & STOP
// Use offset of 0x00 for first line and SECOND_LINE_OFFSET for second
void Show_Line(char *line,unsigned char offset)
{
    int position;
    unsigned char showline_header[3+LINE_LENGTH]={					// set MIDAS for one byte command followed by data
    			ST_COMMAND | ST_CO,									// header space set t
				static_cast<unsigned char>(ST_SET_DDRAM | offset),	// this must be 8 bit stream and is explicitly cast
				ST_DATA
    		};

    for (position=0; position<LINE_LENGTH;position++)
        {
            showline_header[position+3]=line[position];		// make a single array starting with commands and ending with text to show
        }

    i2c.TransmitBlocking(ST_ADDRESS,showline_header,3+LINE_LENGTH,1000);

} // End of Show_Line()

Cheers, I’ll copy your code and see what I come up.
If I get it working, I’ll post the project.
Thanks :slight_smile:

Fine, equally feel free to check a point. I must get into GitHub!