This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LAUNCHXL-F28027F: F28027F I2C with FIFO interrupt

Part Number: LAUNCHXL-F28027F

Hi

I am adapting my 69M code that displays on OLED SSD1308, information

Unfortunately on 27F which is running much slower and has no FPU, my ADC ISR take a lot of time so, it happens to cut the transmission of the main loop that sends the screen on I2C.

After running through hardware issues  now I am adapting the code and changing it to use TX FIFO interrupt

The code must sends, command (2 bytes or 3 bytes, and data 9 bytes) so the FIFO can't be used at once and I need to generate an Interrupt on FIFO TX to see if it is empty to send the 9 bytes 4 by 4...

I managed to have the TX FIFO interrupts (it is fired) but It does not slice the 9 bytes and send only 4 bytes...

  ENABLE_PROTECTED_REGISTER_WRITE_MODE;
  PieCtrlRegs.PIEIER8.bit.INTx2 = 1; // Enable I2C interrupt 2 in the PIE: Group 8 interrupt 2
  IER |= M_INT8; // Enable CPU INT8 which is connected to PIE group 8
  DISABLE_PROTECTED_REGISTER_WRITE_MODE;
//-----------------------------------------------------------------------------
// InitI2C - This function initializes the I2C to a known state.
void InitI2C()
{
    // Initialize I2C-A
   I2caRegs.I2CMDR.all = 0x0000;
   I2caRegs.I2CSAR = I2C_SLAVE_ADDR;		// Slave address
   // 90 MHz/( (8+1)(10+5 + 5+5)) = 400 kHz
   // 60 MHz/( (5+1)(10+5 + 5+5)) = 400 kHz
   //
   // I2CCLK = SYSCLK/(I2CPSC+1)
   I2caRegs.I2CPSC.all = 5;		    		// Prescaler - need 7-12 Mhz on module clk
   I2caRegs.I2CCLKL = 10;					// NOTE: must be non zero
   I2caRegs.I2CCLKH = 5;					// NOTE: must be non zero

   //I2caRegs.I2CIER.all = 0x24;			// Enable SCD & ARDY interrupts  0010 0100
   I2caRegs.I2CIER.all = 0x00;				// No interrupt
//   I2caRegs.I2CIER.bit.AAS = 0;				// Addressed as slave interrupt enable bit
//   I2caRegs.I2CIER.bit.SCD = 1;				// Stop condition detected interrupt enable bit
//   I2caRegs.I2CIER.bit.XRDY = 0;			// Transmit-data-ready interrupt enable bit
//   I2caRegs.I2CIER.bit.RRDY = 0;			// Receive-data-ready interrupt enable bit
//   I2caRegs.I2CIER.bit.ARDY = 1;			// Register-access-ready interrupt enable bit
//   I2caRegs.I2CIER.bit.NACK = 0;			// No-acknowledgment interrupt enable bit
//   I2caRegs.I2CIER.bit.ARBL = 0;			// Arbitration-lost interrupt enable bit

   //I2caRegs.I2CFFTX.all = 0x6000;			// Enable FIFO mode and TXFIFO
   I2caRegs.I2CFFTX.bit.I2CFFEN = 1;		// Enable the I2C FIFO mode
   I2caRegs.I2CFFTX.bit.TXFFRST = 1;		// Enable the transmit FIFO operation
   I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;		// Clear the TXFFINT flag
   I2caRegs.I2CFFTX.bit.TXFFIENA = 1;		// TXFFINT flag generates an interrupt when set
   I2caRegs.I2CFFTX.bit.TXFFIL = 0;			// Transmit FIFO interrupt level

   //I2caRegs.I2CFFRX.all = 0x0000;			// No RXFIFO, no clear RXFFINT
   I2caRegs.I2CFFRX.bit.RXFFRST = 0;		// **Disable** the receive FIFO operation
   I2caRegs.I2CFFRX.bit.RXFFINTCLR = 0;		// Clear the RXFFINT flag
   I2caRegs.I2CFFRX.bit.RXFFIENA = 0;		// RXFFINT flag does generate an interrupt when set
   I2caRegs.I2CFFRX.bit.RXFFIL = 0;			// Receive FIFO interrupt level

   //I2caRegs.I2CMDR.all = 0x0020;			// Take I2C out of reset,Stop I2C when suspended
   I2caRegs.I2CMDR.bit.NACKMOD = 0;			// NACK mode bit
   I2caRegs.I2CMDR.bit.FREE = 0;			// Stop I2C when suspended
   I2caRegs.I2CMDR.bit.STT = 0;				// START condition bit
   I2caRegs.I2CMDR.bit.STP = 0;				// STOP condition bit
   I2caRegs.I2CMDR.bit.MST = 0;				// Slave mode
   I2caRegs.I2CMDR.bit.TRX = 0;				// Receiver mode
   I2caRegs.I2CMDR.bit.XA = 0;				// 7-bit addressing mode
   I2caRegs.I2CMDR.bit.RM = 0;				// Nonrepeat mode
   I2caRegs.I2CMDR.bit.DLB = 0;				// Digital loopback mode is disabled
   I2caRegs.I2CMDR.bit.IRS = 1;				// The I2C module is enabled
   I2caRegs.I2CMDR.bit.STB = 0;				// The I2C module is not in the START byte mode
   I2caRegs.I2CMDR.bit.FDF = 0;				// Free data format mode is disabled
   I2caRegs.I2CMDR.bit.BC = 0;				// 8 bits per data byte
   I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;		// Clear the TXFFINT flag

	oledInit();
//	oledClear();
}
//-----------------------------------------------------------------------------
// i2c_int2a_isr - I2C-A	TX FIFO is int2a
interrupt void i2c_int2a_isr(void)
{
Uint8 fin, i;
Uint16 IntSource = I2caRegs.I2CISRC.all; // Read interrupt source
	//GPIO_setHigh(halHandle->gpioHandle,GPIO_Number_34);	//RunLED
	GpioDataRegs.GPBSET.bit.GPIO34 = 1; //RunLED

	// Interrupt source = stop condition detected
	// if(IntSource == I2C_SCD_ISRC)   ;

	// Interrupt source = Register Access Ready
	// This interrupt is used to determine when the EEPROM address setup
	// portion of the read data communication is complete. Since no stop bit is
	// commanded, this flag tells us when the message has been sent instead of
	// the SCD flag. If a NACK is received, clear the NACK bit and command a
	// stop. Otherwise, move on to the read data portion of the communication.

	if (bufferpos >= bufferend)		I2caRegs.I2CMDR.bit.STP = 1;  				//  manual set of Stop

//	if ((IntSource == I2C_TX_ISRC) && (bufferpos < bufferend))
	if ((I2caRegs.I2CFFTX.bit.TXFFINT) && (bufferpos < bufferend))
		{
		I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;	// clear Flag
		fin = bufferend-bufferpos;
		if (fin>4) fin=4; //start transfer of 4 bytes max
		for (i=0; i<fin; i++)
			I2caRegs.I2CDXR = I2C_TXbuffer[bufferpos+i];
		bufferpos += fin;
		if (bufferpos >= bufferend)		I2caRegs.I2CMDR.bit.STP = 1;	// manual set of Stop
		}

	// Enable future I2C (PIE Group 8) interrupts
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
	//GPIO_setLow(halHandle->gpioHandle,GPIO_Number_34);
	GpioDataRegs.GPBCLEAR.bit.GPIO34 = 1;
}
//-----------------------------------------------------------------------------
void i2c_Xfer(
	Uint8 address,
	Uint8* wdata, int wsize,
	Uint8* rdata, int rsize )
{
Uint16 i;
//	I2caRegs.I2CMDR.bit.IRS = 0;
//	usDelay(10);
//	I2caRegs.I2CMDR.bit.IRS = 1;
//	usDelay(10);
//	// Make sure I2C is not busy and has stopped
//	while (I2caRegs.I2CSTR.bit.BB == 1);		// busy loop
//	I2caRegs.I2CSTR.bit.SCD = 1;				// Clear the SCD bit (stop condition bit)
//	while(I2caRegs.I2CMDR.bit.STP == 1);		// stop bit loop

	I2caRegs.I2CSAR = address;           			// I2C slave address
//	while (I2caRegs.I2CSTR.bit.BB == 1);		// still busy?

    I2caRegs.I2CCNT = wsize;					// Setup number of bytes to send

//	I2caRegs.I2CMDR.all = 0x6E20; 				// Send the TX FIFO :   0110 1110 0010 0000
 // 	I2caRegs.I2CMDR.all = 0x6620; 				// STT=1 			:   0110 0110 0010 0000
  	I2caRegs.I2CMDR.all = 0x66A0; 				// STT=1 			:   0110 0110 1010 0000	RM, STT
  	I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;		// Clear the TXFFINT flag

//		I2caRegs.I2CMDR.bit.NACKMOD = 0;			// NACK mode bit
//		I2caRegs.I2CMDR.bit.FREE = 1;				// Run free I2C when suspended
//		I2caRegs.I2CMDR.bit.STT = 1;				// START condition bit
//		I2caRegs.I2CMDR.bit.STP = 1;				// STOP condition bit
//		I2caRegs.I2CMDR.bit.MST = 1;				// Master mode
//		I2caRegs.I2CMDR.bit.TRX = 1;				// Transmitter mode
//		I2caRegs.I2CMDR.bit.XA = 0;					// 7-bit addressing mode
//		I2caRegs.I2CMDR.bit.RM = 0;					// Nonrepeat mode
//		I2caRegs.I2CMDR.bit.DLB = 0;				// Digital loopback mode is disabled
//		I2caRegs.I2CMDR.bit.IRS = 1;				// The I2C module is enabled
//		I2caRegs.I2CMDR.bit.STB = 0;				// The I2C module is not in the START byte mode
//		I2caRegs.I2CMDR.bit.FDF = 0;				// Free data format mode is disabled
//		I2caRegs.I2CMDR.bit.BC = 0;					// 8 bits per data byte
//	int WaitTimeOut=0;

	bufferpos = 0;
	bufferend = wsize;
	//start transfer of 4 bytes max
	for (i=0; i<wsize; i++)
		I2C_TXbuffer[i] = *(wdata+i);
	Uint8 fin = bufferend;
	if (fin>4) fin=4;

	I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;	// clear Flag
	for (i=0; i<fin; i++)
		I2caRegs.I2CDXR = I2C_TXbuffer[bufferpos+i];
	bufferpos += fin;

//	if (bufferpos >= bufferend)		I2caRegs.I2CMDR.bit.STP = 1;	// manual set of Stop

}
//-----------------------------------------------------------------------------
void i2c_Wait(int cycles)
{
	I2C_WaitCount = 0;
	while (I2C_WaitCount < cycles) ;
}
//-----------------------------------------------------------------------------
void i2c_Reset()
{
}
//-----------------------------------------------------------------------------
// SSD1308 OLED Routines
//

#define SSD1308_Address                 I2C_SLAVE_ADDR
#define SSD1308_Command_Mode		0x80
#define SSD1308_Data_Mode               0x40
#define SSD1308_Display_Off_Cmd         0xAE
#define SSD1308_Display_On_Cmd          0xAF
#define SSD1308_Normal_Display_Cmd      0xA6
#define SSD1308_Inverse_Display_Cmd	0xA7
#define SSD1308_Activate_Scroll_Cmd	0x2F
#define SSD1308_Dectivate_Scroll_Cmd	0x2E
#define SSD1308_Set_Brightness_Cmd      0x81

const Uint8 OledFont[][8] =
{..
...
};

void oledCommand( Uint8 ch )
{
    Uint8 bytes[2];
    bytes[0] = SSD1308_Command_Mode;
    bytes[1] = ch;
    i2c_Xfer( SSD1308_Address, bytes, 2, NULL, 0 );
    i2c_Wait(2);
}


void oledDisplayOffset( Uint8 offset )
{
    Uint8 bytes[3];
    bytes[0] = SSD1308_Command_Mode;
    bytes[1] = 0xD3;
    bytes[2] = offset;
    i2c_Xfer( SSD1308_Address, bytes, 3, NULL, 0 );
    i2c_Wait(3);
}


void oledData( Uint8 data )
{
    Uint8 bytes[2];
    bytes[0] = SSD1308_Data_Mode;
    bytes[1] = data;
    i2c_Xfer( SSD1308_Address, bytes, 2, NULL, 0 );
    i2c_Wait(3);
}


void oledGotoYX(unsigned char Row, unsigned char Column)
{
    oledCommand( 0xB0 + Row);
    oledCommand( 0x00 + (8*Column & 0x0F) );
    oledCommand( 0x10 + ((8*Column>>4)&0x0F) );
}


void oledPutChar( char ch )
{
    if ( ( ch < 32 ) || ( ch > 127 ) )
        ch = ' ';

    const Uint8 *base = &OledFont[ch - 32][0];

    Uint8 bytes[9];
    bytes[0] = SSD1308_Data_Mode;
    memmove( bytes + 1, base, 8 );
    i2c_Xfer( SSD1308_Address, bytes, 9, NULL, 0 );
    i2c_Wait(9);
}

..
...
// I call the routines with

	oledPutChar('A');

it seems that it enters 2 times the ISR TX FIFO at the beginning, where I expect to enter it only when the 4 first bytes where Transmitted, so I can add the 4 bytes, then the 1 remaining

(the i2c_Wait function is there to wait until the command or data are sent, to go to next block of bytes,if  things go wrong

the I2C_WaitCount are updated by ADC ISR, but is of no need actually, _just from previous use/try with Interrupt XRDY that was not working)

Any ideas or advices on how I can solve that or another solution?

Thanks

  • Lotfi,

    It also seems like you have a few places in your code where you set the STOP condition. Are you certain that one of these is not set too early? (Note: Please clarify if in your capture, the 'P' at the end of the SCL data is indicating a STOP, correct?)

    Additionally, You might consider using the Non-Repeat mode, but setting up the I2CCNT register to tell the I2C how many bytes to transmit. Just a thought. This way you can allow the I2C to handle the STOP bit setting on it's own after the desired amount of data has been transmitted.

    -Mark
  • Hi Mark

    yes P is stop on the logic analysis device, A is Acknowelge, S is Start, W:3Ch is a Write order to addy 0x3C device

    if (bufferpos >= bufferend)      I2caRegs.I2CMDR.bit.STP = 1; 

    is used to terminate the order when the 9 bytes (of the example) are sent by the FIFO TX ISR

    before doing that I was using non repeat mode (RM=0) but the I2C module fail to out the stop bit and I found the I2C stream begin with 2 bytes of old package then addy is out followed byt some bytes, which is erroneous.

    So I went for RM=1, outputting my own Stop.

    My actual problem is that I don't see the 9 bytes

    What I want is that the first 4 bytes are sent to the FIFO (without the TX FIFO ISR) then, when the FIFO is empty, the ISR is called, send another 4 bytes, then the ISR will enter again to send the remaining 1 byte.

    RunLed_34 indicates whenever we enter the TX FIFO ISR

    InfoLED_12 indicates the beginning of the process.

  • Solved my Issue by not using ISR at all, used the old way, but with RM=1 and using FIFO, and I control the Stop bit by myself, send the bytes, wait XRDY at each TX

    then Send Stop bit and wait for it to appear (very important) and then return to send next data on I2C

    Here is the code, but I will also release the complete updated code for OLED on github

    //-----------------------------------------------------------------------------
    // InitI2C - This function initializes the I2C to a known state.
    void InitI2C()
    {
        // Initialize I2C-A
    /*
        I2caRegs.I2CSAR = I2C_SLAVE_ADDR;		// Slave address - OLED control code
    // ( I2C_SLAVE_ADDR << 1 ) | ( hasWrite ? 0x00 : 0x01 );
        I2caRegs.I2CPSC.all = 6;		// Prescaler - need 7-12 Mhz on module clk
        I2caRegs.I2CCLKL = 10;			// NOTE: must be non zero
        I2caRegs.I2CCLKH = 5;			// NOTE: must be non zero
        I2caRegs.I2CIER.all = 0x24;		// Enable SCD & ARDY interrupts
        // Take I2C out of reset. Stop I2C when suspended
        I2caRegs.I2CMDR.all = 0x0020;
    
        I2caRegs.I2CFFTX.all = 0x6000;	// Enable FIFO mode and TXFIFO
        I2caRegs.I2CFFRX.all = 0x2040;	// Enable RXFIFO, clear RXFFINT,
    
    	i2c1Reset();
    //	i2c1Enable( kI2C_400KHZ );
    */
       I2caRegs.I2CMDR.all = 0x0000;
       I2caRegs.I2CSAR = I2C_SLAVE_ADDR;		// Slave address
       // 90 MHz/( (8+1)(10+5 + 5+5)) = 400 kHz
       // 60 MHz/( (5+1)(10+5 + 5+5)) = 400 kHz
       //
       // I2CCLK = SYSCLK/(I2CPSC+1)
       I2caRegs.I2CPSC.all = 5;		    		// Prescaler - need 7-12 Mhz on module clk
       I2caRegs.I2CCLKL = 10;					// NOTE: must be non zero
       I2caRegs.I2CCLKH = 5;					// NOTE: must be non zero
    
       //I2caRegs.I2CIER.all = 0x24;			// Enable SCD & ARDY interrupts  0010 0100
       I2caRegs.I2CIER.all = 0x00;				// No interrupt
    //   I2caRegs.I2CIER.bit.AAS = 0;				// Addressed as slave interrupt enable bit
    //   I2caRegs.I2CIER.bit.SCD = 1;				// Stop condition detected interrupt enable bit
    //   I2caRegs.I2CIER.bit.XRDY = 0;			// Transmit-data-ready interrupt enable bit
    //   I2caRegs.I2CIER.bit.RRDY = 0;			// Receive-data-ready interrupt enable bit
    //   I2caRegs.I2CIER.bit.ARDY = 1;			// Register-access-ready interrupt enable bit
    //   I2caRegs.I2CIER.bit.NACK = 0;			// No-acknowledgment interrupt enable bit
    //   I2caRegs.I2CIER.bit.ARBL = 0;			// Arbitration-lost interrupt enable bit
    
       //I2caRegs.I2CFFTX.all = 0x6000;			// Enable FIFO mode and TXFIFO
       I2caRegs.I2CFFTX.bit.I2CFFEN = 1;		// Enable the I2C FIFO mode
       I2caRegs.I2CFFTX.bit.TXFFRST = 1;		// Enable the transmit FIFO operation
       I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;		// Clear the TXFFINT flag
       I2caRegs.I2CFFTX.bit.TXFFIENA = 0;		// TXFFINT flag generates an interrupt when set
       I2caRegs.I2CFFTX.bit.TXFFIL = 0;			// Transmit FIFO interrupt level
    
       //I2caRegs.I2CFFRX.all = 0x0000;			// No RXFIFO, no clear RXFFINT
       I2caRegs.I2CFFRX.bit.RXFFRST = 0;		// **Disable** the receive FIFO operation
       I2caRegs.I2CFFRX.bit.RXFFINTCLR = 0;		// Clear the RXFFINT flag
       I2caRegs.I2CFFRX.bit.RXFFIENA = 0;		// RXFFINT flag does generate an interrupt when set
       I2caRegs.I2CFFRX.bit.RXFFIL = 0;			// Receive FIFO interrupt level
    
       //I2caRegs.I2CMDR.all = 0x0020;			// Take I2C out of reset,Stop I2C when suspended
       I2caRegs.I2CMDR.bit.NACKMOD = 0;			// NACK mode bit
       I2caRegs.I2CMDR.bit.FREE = 0;			// Stop I2C when suspended
       I2caRegs.I2CMDR.bit.STT = 0;				// START condition bit
       I2caRegs.I2CMDR.bit.STP = 0;				// STOP condition bit
       I2caRegs.I2CMDR.bit.MST = 0;				// Slave mode
       I2caRegs.I2CMDR.bit.TRX = 0;				// Receiver mode
       I2caRegs.I2CMDR.bit.XA = 0;				// 7-bit addressing mode
       I2caRegs.I2CMDR.bit.RM = 0;				// Nonrepeat mode
       I2caRegs.I2CMDR.bit.DLB = 0;				// Digital loopback mode is disabled
       I2caRegs.I2CMDR.bit.IRS = 1;				// The I2C module is enabled
       I2caRegs.I2CMDR.bit.STB = 0;				// The I2C module is not in the START byte mode
       I2caRegs.I2CMDR.bit.FDF = 0;				// Free data format mode is disabled
       I2caRegs.I2CMDR.bit.BC = 0;				// 8 bits per data byte
    
    	oledInit();
    	oledClear();
    	oledGotoYX( 0, 0 );
    	oledPrint( "Ring" );
    	oledGotoYX( 1, 0 );
    	oledPrint( "Thompson" );
    	oledGotoYX( 2, 0 );
    	oledPrint("Vs: ");
    	oledGotoYX( 2, 14 );
    	oledPrint("V");
    	oledGotoYX( 3, 0 );
    	oledPrint("fs: ");
    	oledGotoYX( 3, 14 );
    	oledPrint("Hz");
    }
    //-----------------------------------------------------------------------------
    void i2c_Xfer(
    	Uint8 address,
    	Uint8* wdata, int wsize,
    	Uint8* rdata, int rsize )
    {
    Uint16 i;
    //	I2caRegs.I2CMDR.bit.IRS = 0;
    //	usDelay(10);
    //	I2caRegs.I2CMDR.bit.IRS = 1;
    //	usDelay(10);
    //	// Make sure I2C is not busy and has stopped
    //	while (I2caRegs.I2CSTR.bit.BB == 1);		// busy loop
    //	I2caRegs.I2CSTR.bit.SCD = 1;				// Clear the SCD bit (stop condition bit)
    //	while(I2caRegs.I2CMDR.bit.STP == 1);		// stop bit loop
    
    	I2caRegs.I2CSAR = address;           			// I2C slave address
    //	while (I2caRegs.I2CSTR.bit.BB == 1);		// still busy?
    
        I2caRegs.I2CCNT = wsize;					// Setup number of bytes to send
    
    //	I2caRegs.I2CMDR.all = 0x6E20; 				// Send the TX FIFO :   0110 1110 0010 0000
     // 	I2caRegs.I2CMDR.all = 0x6620; 				// STT=1 			:   0110 0110 0010 0000
      	I2caRegs.I2CMDR.all = 0x66A0; 				// STT=1 			:   0110 0110 1010 0000	RM, STT
    
    //		I2caRegs.I2CMDR.bit.NACKMOD = 0;			// NACK mode bit
    //		I2caRegs.I2CMDR.bit.FREE = 1;				// Run free I2C when suspended
    //		I2caRegs.I2CMDR.bit.STT = 1;				// START condition bit
    //		I2caRegs.I2CMDR.bit.STP = 1;				// STOP condition bit
    //		I2caRegs.I2CMDR.bit.MST = 1;				// Master mode
    //		I2caRegs.I2CMDR.bit.TRX = 1;				// Transmitter mode
    //		I2caRegs.I2CMDR.bit.XA = 0;					// 7-bit addressing mode
    //		I2caRegs.I2CMDR.bit.RM = 0;					// Nonrepeat mode
    //		I2caRegs.I2CMDR.bit.DLB = 0;				// Digital loopback mode is disabled
    //		I2caRegs.I2CMDR.bit.IRS = 1;				// The I2C module is enabled
    //		I2caRegs.I2CMDR.bit.STB = 0;				// The I2C module is not in the START byte mode
    //		I2caRegs.I2CMDR.bit.FDF = 0;				// Free data format mode is disabled
    //		I2caRegs.I2CMDR.bit.BC = 0;					// 8 bits per data byte
    //	int WaitTimeOut=0;
    
    	//start transfer of 4 bytes max
    	for (i=0; i<wsize; i++)
    		{
    		I2caRegs.I2CDXR = *(wdata+i);
    		while(!I2caRegs.I2CSTR.bit.XRDY);
    		}
    	I2caRegs.I2CMDR.bit.STP = 1;	// manual set of Stop
    	while(I2caRegs.I2CMDR.bit.STP == 1);		// stop bit loop
    }
    //-----------------------------------------------------------------------------
    
    
    ...
    
    
    void oledCommand( Uint8 ch )
    {
        Uint8 bytes[2];
        bytes[0] = SSD1308_Command_Mode;
        bytes[1] = ch;
        i2c_Xfer( SSD1308_Address, bytes, 2, NULL, 0 );
    }
    
    void oledDisplayOffset( Uint8 offset )
    {
        Uint8 bytes[3];
        bytes[0] = SSD1308_Command_Mode;
        bytes[1] = 0xD3;
        bytes[2] = offset;
        i2c_Xfer( SSD1308_Address, bytes, 3, NULL, 0 );
    }
    
    void oledData( Uint8 data )
    {
        Uint8 bytes[2];
        bytes[0] = SSD1308_Data_Mode;
        bytes[1] = data;
        i2c_Xfer( SSD1308_Address, bytes, 2, NULL, 0 );
    }
    
    void oledGotoYX(unsigned char Row, unsigned char Column)
    {
        oledCommand( 0xB0 + Row);
        oledCommand( 0x00 + (8*Column & 0x0F) );
        oledCommand( 0x10 + ((8*Column>>4)&0x0F) );
    }
    
    void oledPutChar( char ch )
    {
        if ( ( ch < 32 ) || ( ch > 127 ) )  ch = ' ';
        const Uint8 *base = &OledFont[ch - 32][0];
        Uint8 bytes[9];
        bytes[0] = SSD1308_Data_Mode;
        memmove( bytes + 1, base, 8 );
        i2c_Xfer( SSD1308_Address, bytes, 9, NULL, 0 );
    }
    

  • Thanks for the post Lotfi! I am glad that you were able to get it to work.