using System; using System.Text; using KiwiSystem; // DJ Greaves, Satnam Singh. Compiled with KiwiC. namespace Chrontel_I2C // FOR Chrontel Set Up { //Needs to be compiled in Kiwi hard pause mode. // Demo IIC operation to read the version register on the Chrontel CH7301C DVI chip public static class I2C_master { // This is a two-net bus where each driver is an open drain output and also an input. // We achieve open drain using a tri-state that never drives logic 1. // Actually, we can drive it when we are sure we are in charge. /* // You need the following structure in your pad ring to use this. wire iic_scl_dvi_out, iic_scl_dvi_openable; wire iic_sda_dvi_out, iic_sda_dvi_openable; bufif1(IIC_SCL_DVI, iic_scl_dvi_out, iic_scl_dvi_openable); bufif1(IIC_SDA_DVI, iic_sda_dvi_out, iic_sda_dvi_openable); wire iic_scl_dvi_in = IIC_SCL_DVI; wire iic_sda_dvi_in = IIC_SDA_DVI; .i2c_sda_in(iic_sda_dvi_in), .i2c_scl_out(iic_scl_dvi_out), .i2c_sda_out(iic_sda_dvi_out), .i2c_scl_openable(iic_scl_dvi_openable), .i2c_sda_openable(iic_sda_dvi_openable), */ // openable: TRUE means write out on the SDA port, FALSE means read from the SDA port [Kiwi.OutputBitPort("i2c_scl_out")] static bool scl_out; [Kiwi.OutputBitPort("i2c_scl_openable")] static bool scl_openable; [Kiwi.InputBitPort("i2c_scl_in")] static bool scl_in; [Kiwi.OutputBitPort("i2c_sda_out")] static bool sda_out; [Kiwi.OutputBitPort("i2c_sda_openable")] static bool sda_openable; [Kiwi.InputBitPort("i2c_sda_in")] static bool sda_in; [Kiwi.OutputBitPort("done")] static bool done; private static void SendDeviceID(int id, bool read_flag) { int deviceID = id; Console.WriteLine("Sending device ID"); // Send out 7-bit device ID 0x76 for chrontel for (int i = 7; i > 0; i--) { scl_out = false; sda_out = (deviceID & 64) != 0; Kiwi.Pause(); // Set it i-th bit of the device ID scl_out = true; Kiwi.Pause(); // Pulse SCL scl_out = false; deviceID = deviceID << 1; Kiwi.Pause(); } // Indicate read/write operation Console.WriteLine("Indicate write operation."); sda_out = read_flag; Kiwi.Pause(); scl_out = true; Kiwi.Pause(); scl_out = false; Kiwi.Pause(); } private static void ProcessACK() { Console.WriteLine("Processing ACK"); sda_out = true; sda_openable = false; // Read from SDA port Kiwi.Pause(); scl_out = true; // Start pulse on SCL Kiwi.Pause(); bool ack1 = sda_in; // The bi-directional SDA port now has the ack flag on it from the slave. scl_out = false;//End pulse on SCL Kiwi.Pause(); sda_openable = true; Kiwi.Pause(); } private static void SendByte(int d) // Send a byte, msb first. { int ID = d; for (int i = 8; i > 0; i--) { scl_out = false; sda_out = (ID & 128) != 0; Kiwi.Pause(); scl_out = true; Kiwi.Pause(); // Pulse SCL scl_out = false; ID = ID << 1; Kiwi.Pause(); } ProcessACK(); // Absorb ACK } public static void i2c_chrontel_cmd(int registerID, int data) { // Perform start condition by making SDA fall high to low while SCL is high Console.WriteLine("Start condition"); done = false; scl_out = true; sda_out = true; sda_openable = true; scl_openable = true; Kiwi.Pause(); sda_out = false; // Start condtion Kiwi.Pause(); scl_out = false; Kiwi.Pause(); // First step is to send the DeviceID followed by setting RW to 0 to indicate a write operaiton SendDeviceID(0x76, false); // Absorb first ACK ProcessACK(); // Now write the Chrontel device read address from which we wish to access Console.WriteLine("Sending device register address"); SendByte(128 + registerID); // Must set top bit SendByte(data); // turn chip on with a zero to all bits for VGA output (no DVI PLL). // Generate stop condition Console.WriteLine("Generate stop condition."); sda_out = false; scl_out = true; Kiwi.Pause(); sda_out = true; Kiwi.Pause(); // Now idle. sda_openable = false; scl_openable = false; Kiwi.Pause(); done = true; } } class I2CTest { [Kiwi.InputBitPort("checker")] static bool checker; [Kiwi.HardwareEntryPoint()] static void Main() { I2C_master.i2c_chrontel_cmd(0x49, 0xC0); // DVI Off, VGA ON. I2C_master.i2c_chrontel_cmd(0x21, 0x09); // Enable H synch output + 1 I2C_master.i2c_chrontel_cmd(0x22, 0x16); // Enable V synch output while(true) { while(!checker) Kiwi.Pause(); // nb: not debounced: so a bit weak! I2C_master.i2c_chrontel_cmd(0x48, 16+8+1); while(checker) Kiwi.Pause(); while(!checker) Kiwi.Pause(); I2C_master.i2c_chrontel_cmd(0x48, 16+8+2); while(checker) Kiwi.Pause(); while(!checker) Kiwi.Pause(); I2C_master.i2c_chrontel_cmd(0x48, 16+8+0); // Normal operation. while(checker) Kiwi.Pause(); } } } } // eof