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


