Other Parts Discussed in Thread: MSP430G2230
I am using the TFP410 to interface with an external HDMI monitor, set to be configured on power-up by an MSP430G2230 micro via the I2C connection (see schematic snippet). The issue I am currently having is that the TFP410 does not ACK any of the commands (see scope screenshot). My SCL is running at approximately 11kHz and I am bit-banging the I2C pins. My code is as follows:
main.c:
/*
* main.c
*
* Created on: Sep 26, 2019
*
*/
#include <msp430.h>
#include <i2c_sw.h>
/* Sub-Addresses for the TFP410 */
#define CTL_1_MODE 0x08
#define CTL_2_MODE 0x09
#define CTL_3_MODE 0x0A
#define DE_DLY 0x32
#define DE_CTL 0x33
#define DE_TOP 0x34
#define DE_CNT_L 0x36
#define DE_CNT_H 0x37
#define DE_LIN_L 0x38
#define DE_LIN_H 0x39
#define SLV_ADDR 0x70 // Write address
unsigned char sData = 0; //Data to be written to slave
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog
/* Initialize clocks */
BCSCTL3 |= LFXT1S_2; // Select VLO as low freq clock
if (CALBC1_1MHZ == 0xFF) { // If calibration constant erased
while (1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
// Wait a bit for the FPGA to initialize
__delay_cycles(10000);
/* Configure TFP410 Digital Transmitter */
// 0x37, T.M.D.S. enable state determined by PD
sData = 0x37;
I2C_WriteData(&sData, SLV_ADDR, CTL_1_MODE, 1);
// 0x39, MSEN out disabled, MDI from HTPLG, MDI logic level stays same
sData = 0x39;
I2C_WriteData(&sData, SLV_ADDR, CTL_2_MODE, 1);
// 0x80,sData de-skew disabled
sData = 0x80;
I2C_WriteData(&sData, SLV_ADDR, CTL_3_MODE, 1);
// 0xD8, 216 pixels (HSYNC + back porch)
sData = 0xD8;
I2C_WriteData(&sData, SLV_ADDR, DE_DLY, 1);
// 0x70, DE generator enabled, VSYNC & HSYNC active high
sData = 0x70;
I2C_WriteData(&sData, SLV_ADDR, DE_CTL, 1);
// 0x1B, 27 pixels (VSYNC + back porch)
sData = 0x1B;
I2C_WriteData(&sData, SLV_ADDR, DE_TOP, 1);
// 0x20, 0x03, 800 pixels wide
sData = 0x20;
I2C_WriteData(&sData, SLV_ADDR, DE_CNT_L, 1);
sData = 0x03;
I2C_WriteData(&sData, SLV_ADDR, DE_CNT_H, 1);
// 0xE0, 0x01 480 lines tall
sData = 0xE0;
I2C_WriteData(&sData, SLV_ADDR, DE_LIN_L, 1);
sData = 0x01;
I2C_WriteData(&sData, SLV_ADDR, DE_LIN_H, 1);
//__delay_cycles(10000);
/* Trap after configuration */;
while (1);
}
i2c_sw.c:
/*
* i2c_sw.c
*
* Created on: Oct 1, 2019
*
*/
#include "msp430.h"
#include "i2c_sw.h"
unsigned char Read_SCL(void);
unsigned char Read_SDA(void);
void Clear_SCL(void);
void Clear_SDA(void);
void I2C_Init(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Writebit(unsigned char bit);
unsigned char I2C_ReadByte(void);
void I2C_WriteByte(unsigned char Data);
unsigned char I2C_ReadByte(void);
void I2C_WriteData(unsigned char *Data, unsigned char DeviceAddr, unsigned char Register, unsigned char nLength);
void I2C_ReadData(unsigned char *Buff, unsigned char DeviceAddr, unsigned char Register, unsigned char nLength);
/*--------------------------------------------------------------------------------
Function : Read_SCL
Purpose : Set SCL as input and return current Logic level of SCL (0 or 1)
normal is 1 because it is pulled up by a resistor
Parameters : None
Return : Logic level of SCL pin
--------------------------------------------------------------------------------*/
unsigned char Read_SCL(void)
{
I2C_PxDIR &= ~SCL;
return((I2C_PxIN & SCL) != 0);
}
/*--------------------------------------------------------------------------------
Function : Read_SDA
Purpose : Set SDA as input and return current Logic level of SDA (0 or 1),
normal is 1 because it is pulled up by a resistor
Parameters : None
Return : Logic level of SDA pin
--------------------------------------------------------------------------------*/
unsigned char Read_SDA(void)
{
I2C_PxDIR &= ~SDA;
return((I2C_PxIN & SDA) != 0);
}
/*--------------------------------------------------------------------------------
Function : Clear_SCL
Purpose : Set SCL as output, logic Low
Parameters : None
Return : None
--------------------------------------------------------------------------------*/
void Clear_SCL(void)
{
I2C_PxDIR |= SCL;
I2C_PxOUT &= ~SCL;
}
/*--------------------------------------------------------------------------------
Function : Clear_SDA
Purpose : Set SDA as output, logic LOW
Parameters : None
Return : None
--------------------------------------------------------------------------------*/
void Clear_SDA(void)
{
I2C_PxDIR |= SDA;
I2C_PxOUT &= ~SDA;
}
/*--------------------------------------------------------------------------------
Function : I2C_Init
Purpose : Initialize I2C block
Parameters : None
Return : None
--------------------------------------------------------------------------------*/
void I2C_Init(void)
{
// Config SCL and SDA as GPIO
I2C_PxSEL &= ~(SCL + SDA);
// Set SCL and SDA as input, pulled logic HIGH by resistors
I2C_PxDIR &= ~(SCL + SDA);
I2C_PxOUT &= ~(SCL + SDA);
}
/*--------------------------------------------------------------------------------
Function : I2C_Start
Purpose : Send start signal
Parameters : None
Return : None
--------------------------------------------------------------------------------*/
void I2C_Start(void)
{
Read_SDA(); //set SDA to 1
I2C_DELAY();
Clear_SDA(); //set SDA to 0, currently SCL is 1
I2C_DELAY();
Clear_SCL(); //set SCL to 0
}
/*--------------------------------------------------------------------------------
Function : I2C_Stop
Purpose : Send Stop signal
Parameters : None
Return : None
--------------------------------------------------------------------------------*/
void I2C_Stop(void)
{
Clear_SDA(); //set SDA to 0
I2C_DELAY();
Read_SCL(); //set SCL to 1
I2C_DELAY();
Read_SDA(); //set SDA to 1
}
/*--------------------------------------------------------------------------------
Function : I2C_Writebit
Purpose : Write bit to I2C bus
Parameters : A bit to write
Return : None
--------------------------------------------------------------------------------*/
void I2C_Writebit(unsigned char bit)
{
if(bit)
Read_SDA();
else
Clear_SDA();
I2C_DELAY();
Read_SCL();
I2C_DELAY();
Clear_SCL();
}
/*--------------------------------------------------------------------------------
Function : I2C_Readbit
Purpose : Read bit on I2C bus
Parameters : None
Return : unsigned char
--------------------------------------------------------------------------------*/
unsigned char I2C_Readbit(void)
{
unsigned char bit;
//Let the slave drive data
Read_SDA();
I2C_DELAY();
Read_SCL();
bit = Read_SDA();
I2C_DELAY();
Clear_SCL();
return bit;
}
/*--------------------------------------------------------------------------------
Function : I2C_WriteByte
Purpose : Write a Byte to I2C bus
Parameters : unsigned char Data
Return : None
--------------------------------------------------------------------------------*/
void I2C_WriteByte(unsigned char Data)
{
unsigned char nBit;
for(nBit = 0; nBit < 8; nBit++)
{
I2C_Writebit((Data & 0x80) != 0);
Data <<= 1;
}
I2C_Readbit(); // Write NACK
}
/*--------------------------------------------------------------------------------
Function : I2C_ReadByte
Purpose : Read a Byte on I2C bus
Parameters : None
Return : unsigned char
--------------------------------------------------------------------------------*/
unsigned char I2C_ReadByte(void)
{
unsigned char Buff = 0;
unsigned char nBit;
for(nBit = 0; nBit < 8; nBit++)
{
Buff = (Buff << 1) | I2C_Readbit();
}
return Buff;
}
/*--------------------------------------------------------------------------------
Function : I2C_WriteData
Purpose : Write n bytes to I2C bus
Parameters : Data - Pointer to data to be written
DeviceAddr - Device Address
Register - Register Address
nLength - Number of bytes to be written
Return : None
--------------------------------------------------------------------------------*/
void I2C_WriteData(unsigned char *Data, unsigned char DeviceAddr, unsigned char Register, unsigned char nLength)
{
unsigned char nIndex;
I2C_Start();
I2C_WriteByte(DeviceAddr << 1); // DeviceAddr is 7 bit and command is write
I2C_WriteByte(Register);
for(nIndex = 0; nIndex < nLength; nIndex++)
{
I2C_WriteByte(*(Data + nIndex));
}
I2C_Readbit();
I2C_Stop();
}
/*--------------------------------------------------------------------------------
Function : I2C_ReadData
Purpose : Read n bytes from I2C bus
Parameters : Buff - Pointer to buffer for storing value
DevideAddr - Device Address
Register - Register Address
nLength - Number of bytes to be read
Return : None
--------------------------------------------------------------------------------*/
void I2C_ReadData(unsigned char *Buff, unsigned char DeviceAddr, unsigned char Register, unsigned char nLength)
{
unsigned char nIndex;
I2C_Start();
I2C_WriteByte(DeviceAddr << 1);
I2C_WriteByte(Register);
I2C_Stop();
_NOP(); // Short delay
I2C_Start();
_NOP(); // Short delay
I2C_WriteByte((DeviceAddr << 1) | 1);
for(nIndex = 0; nIndex < nLength; nIndex++)
{
*(Buff + nIndex) = I2C_ReadByte();
if(nIndex > 0)I2C_Writebit(ACK);
}
I2C_Writebit(NACK);
I2C_Stop();
}
Schematic snippet:
Scope Shot:



