#include #include #include "twi.h" Timer procTimer; uint8_t reg49_shadow = 0xc0; uint8_t input_a = 0; uint8_t input_b = 0; static uint8_t get_reg49_value(void) { uint8_t val; // Enable only plugged-in ouputs. //val = (P0 & 0xc) << 4; val = 0xc << 4; // Prefer existing routings. if (input_a == ((reg49_shadow >> 2) & 3)) { val |= 0x10; // Select secondary RX for output A } if (input_b == ((reg49_shadow >> 2) & 3)) { val |= 0x20; // Select secondary RX for output B } // Update routing. switch (val & 0x30) { case 0x00: if (input_a == input_b) { val |= input_a; val |= (~input_a & 3) << 2; } else { if (input_a == ((reg49_shadow >> 2) & 3)) { val |= input_b; val |= input_a << 2; val |= 0x10; // Select secondary RX for output A } else { val |= input_a; val |= input_b << 2; val |= 0x20; // Select secondary RX for output B } } break; case 0x30: val |= ~input_a & 3; val |= input_a << 2; break; case 0x10: val |= input_b; val |= input_a << 2; break; case 0x20: val |= input_a; val |= input_b << 2; break; } return val; } uint8_t edidbuf[256] = { //0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 'x', 'D', 0x00 /*0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x13, 0x02, 0x31, 0x32, 0x50, 0x44, 0x2a, 0x11, 0x01, 0x03, 0x80, 0x00, 0x00, 0x78, 0x2a, 0xee, 0x95, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0x21, 0x08, 0x00, 0x61, 0x40, 0x81, 0xc0, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x19, 0x64, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0xa0, 0x18, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfc, 0x00, 'M' , 'a' , 't' , 'r' , 'i' , 'x' , 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x17, 0x48, 0x01, 0xff, 0x1a, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xdc, 0x02, 0x03, 0x1b, 0xc1, 0x46, 0x84, 0x02, 0x03, 0x11, 0x12, 0x01, 0x23, 0x09, 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x80, 0x1e, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20, 0x0c, 0x40, 0x55, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x18, 0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20, 0x0c, 0x40, 0x55, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x18, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x18, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7,*/ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x34, 0xa9, 0x76, 0xd0, 0x11, 0x00, 0x46, 0x14, 0x00, 0x11, 0x01, 0x03, 0x80, 0x00, 0x00, 0x78, 0x0a, 0x69, 0xbe, 0xa6, 0x57, 0x53, 0xa6, 0x23, 0x0c, 0x48, 0x55, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, 0x25, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x9e, 0x01, 0x1d, 0x80, 0xd0, 0x72, 0x1c, 0x16, 0x20, 0x10, 0x2c, 0x25, 0x80, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x41, 0x58, 0x2d, 0x32, 0x30, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3d, 0x1c, 0x44, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x67, 0x02, 0x03, 0x16, 0x31, 0x4a, 0x05, 0x14, 0x04, 0x13, 0x20, 0x02, 0x11, 0x01, 0x10, 0x1f, 0x66, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x01, 0x1d, 0x80, 0x3e, 0x73, 0x38, 0x2d, 0x40, 0x7e, 0x2c, 0x45, 0x80, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0x13, 0x8e, 0x21, 0x00, 0x00, 0x18, 0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20, 0x0c, 0x40, 0x55, 0x00, 0x13, 0x8e, 0x21, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28, 0x55, 0x40, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6 }; uint8_t i2cWrite(uint8_t addr, uint8_t reg, uint8_t value) { uint8_t err; Wire.beginTransmission(addr); Wire.write(reg); Wire.write(value); if ((err = Wire.endTransmission()) != 0) { debugf("i2c: write %02x:%02x = %02x - error %02x\r\n", addr, reg, value, err); } return err; } uint8_t i2cRead(uint8_t addr, uint8_t reg, uint8_t cnt = 1) { Wire.beginTransmission(addr); Wire.write(reg); if (Wire.endTransmission(false) != 0) { Serial.println("transmission end failed?"); } Wire.requestFrom((int) addr, (int) cnt); //Serial.printf("Available: %d\r\n", Wire.available()); return Wire.read(); } uint8_t setEDID(uint8_t port, uint8_t* edid) { byte err, address; int nDevices; if ((err = i2cWrite(0x64, 0x42, port)) != 0) { Serial.print("start error occured: "); Serial.println(err); return err; } uint8_t edidData[257]; edidData[0] = 0xff; memcpy(edidData+1, edid, 256); if ((err = twi_writeTo(0x64, edidData, 257, true)) != 0) { Serial.printf("Edid write failed: %d\r\n", err); } if ((err = i2cWrite(0x64, 0x42, 0x3c)) != 0) { Serial.print("end error occured: "); Serial.println(err); return err; } return 0; } void select_output(char output) { if (output == 0) { // Output A if (reg49_shadow & 0x10) { i2cWrite(0x65, 0x07, 0x02); } else { i2cWrite(0x65, 0x07, 0x00); } } else { // Output B if (reg49_shadow & 0x20) { i2cWrite(0x65, 0x07, 0x03); } else { i2cWrite(0x65, 0x07, 0x01); } } } uint8_t matrixInit() { debugf("Logic reset..."); i2cWrite(0x64, 0x40, 0x08); delay(500); debugf("Reset, clearing..."); i2cWrite(0x64, 0x40, 0x00); setEDID(0, edidbuf); setEDID(1, edidbuf); setEDID(2, edidbuf); setEDID(3, edidbuf); i2cWrite(0x64, 0x2d, 0x82); i2cWrite(0x64, 0x40, 0x00); i2cWrite(0x64, 0x41, 0x00); i2cWrite(0x64, 0x42, 0x3f); i2cWrite(0x64, 0x43, 0x01); i2cWrite(0x64, 0x44, 0x43); i2cWrite(0x64, 0x45, 0x14); i2cWrite(0x64, 0x46, 0xe4); i2cWrite(0x64, 0x47, 0x80); i2cWrite(0x64, 0x48, 0x04); i2cWrite(0x64, 0x49, 0b01110000); i2cWrite(0x64, 0x4a, 0xcf); // 0xff //i2cWrite(0x64, 0x49, 0xc0); i2cWrite(0x64, 0x4b, 0b111111); uint8_t err; uint8_t physettings[4] = {0x4c, 0x02, 0x50, 0x00}; if ((err = twi_writeTo(0x64, physettings, 4, true)) != 0) { Serial.printf("rxphy write failed: %d\r\n", err); } physettings[0] = 0x4d; physettings[1] = 0x16; physettings[2] = 0x41; if ((err = twi_writeTo(0x64, physettings, 3, true)) != 0) { Serial.printf("txphy write failed: %d\r\n", err); } Serial.printf("discharging txphy..."); delay(1000); physettings[2] = 0x01; if ((err = twi_writeTo(0x64, physettings, 3, true)) != 0) { Serial.printf("txphy write failed: %d\r\n", err); } //i2cWrite(0x64, 0x4c, 0x76); /*debugf("reg49: %02x", get_reg49_value()); reg49_shadow = get_reg49_value(); i2cWrite(0x64, 0x49, reg49_shadow);*/ //select_output(0); //i2cWrite(0x64, 0x0e, 0x01); //select_output(1); //i2cWrite(0x64, 0x0e, 0x01); // selectOutput(0); /*for (int i = 0; i < 4; i++) { i2cWrite(0x65, 0x07, i); i2cWrite(0x65, 0x0e, 0x01); }*/ //i2cWrite(0x64, 0x49, 0xc0); //i2cWrite(0x64, 0x4a, 0b11000000); //i2cWrite(0x65, 0x0f, 0x10); //i2cWrite(0x64, 0x4a, 0b11101111); } void i2cDump(uint8_t addr) { for (int i = 0; i < 0x80; i++) { if (i % 16 == 0) Serial.printf("\r\n%02x: ", i); Serial.printf("%02x ", i2cRead(addr, i)); } Serial.println(); } void init() { Serial.begin(SERIAL_BAUD_RATE); // 115200 by default Serial.systemDebugOutput(true); // Disable debug output Serial.setCallback(*[](Stream& src, char arrived, uint16_t available) { debugf("arrived: %02x", arrived); input_a = (arrived - 0x31) & 0x3; input_b = (arrived - 0x31) & 0x3; debugf("setting: %d", input_a); i2cWrite(0x64, 0x49, (0b01010000 | 0) | (input_b << 2)); }); WDT.enable(false); // First (but not the best) option: fully disable watch dog timer // Default I2C pins (SDA: 2, SCL:0) // You can change pins: //Wire.pins(14, 12); // SDA, SCL Wire.begin(4, 5); Wire.setClock(300000); Wire.setClockStretchLimit(5*230); for ( int i = 0 ; i < 2; i++) { Serial.printf("Doing things in %d...\r\n", 2-i); delay(1000); } matrixInit(); procTimer.initializeMs(500, *[]() { Serial.println(millis()); Serial.println("Hello!"); debugf(" int: %02x %02x %02x", i2cRead(0x64, 0x29, 3), Wire.read(), Wire.read()); debugf("stat0: %02x", i2cRead(0x64, 0x3c)); debugf("stat1: %02x", i2cRead(0x64, 0x3d)); debugf("stat2: %02x", i2cRead(0x64, 0x3f)); debugf("ctrl0: %02x", i2cRead(0x64, 0x40)); debugf("ctrl1: %02x", i2cRead(0x64, 0x41)); debugf("ctrl2: %02x", i2cRead(0x64, 0x42)); debugf("ctrl3: %02x", i2cRead(0x64, 0x43)); debugf("ctrl4: %02x", i2cRead(0x64, 0x44)); debugf("ctrl5: %02x", i2cRead(0x64, 0x45)); debugf("ctrl6: %02x", i2cRead(0x64, 0x46)); debugf("ctrl7: %02x", i2cRead(0x64, 0x47)); debugf("ctrl8: %02x", i2cRead(0x64, 0x48)); debugf("ctrl9: %02x", i2cRead(0x64, 0x49)); debugf("ctrl10: %02x", i2cRead(0x64, 0x4a)); debugf("ctrl11: %02x", i2cRead(0x64, 0x4b)); debugf("rxphy: %02x %02x %02x", i2cRead(0x64, 0x4c, 3), Wire.read(), Wire.read()); debugf("txphy: %02x %02x", i2cRead(0x64, 0x4d, 2), Wire.read()); //i2cDump(0x64); /*setEDID(0, edidbuf); setEDID(1, edidbuf); setEDID(2, edidbuf); setEDID(3, edidbuf);*/ //Serial.println("====\n\n0x65 (0):"); //select_output(0); //i2cDump(0x65); for (int port = 0; port < 4; port++) { Serial.printf("RX Port %d: ", port); i2cWrite(0x65, 0x07, port); uint8_t status = i2cRead(0x65, 0x07); if (status & 0x80) Serial.printf("online "); if (status & 0x40) Serial.printf("de "); if (status & 0x20) Serial.printf("hdmi "); if (status & 0x10) Serial.printf("enc "); uint8_t status2 = i2cRead(0x65, 0x08); if (status2 & 0x40) Serial.printf("vsync "); Serial.printf("[%02x ", i2cRead(0x65, 0x07)); Serial.printf("%02x ", i2cRead(0x65, 0x08)); Serial.printf("%02x ", i2cRead(0x65, 0x09)); Serial.printf("%02x ", i2cRead(0x65, 0x0a)); Serial.printf("%02x ", i2cRead(0x65, 0x0e)); Serial.printf("%02x] \r\n", i2cRead(0x65, 0x0f)); } for (int port = 0; port < 2; port++) { Serial.printf("TX Port %d: ", port); i2cWrite(0x65, 0x07, port << 2); uint8_t status = i2cRead(0x65, 0x08); if (status & 0x80) Serial.printf("mute "); if (status & 0x02) Serial.printf("enc_opt "); uint8_t status3 = i2cRead(0x65, 0x09); if (status3 & 0x04) Serial.printf("rsen "); uint8_t status4 = i2cRead(0x65, 0x0f); if (status4 & 0x01) Serial.printf("enc "); if (status4 & 0x02) Serial.printf("ri_rdy "); if (status4 & 0x10) Serial.printf("rptr "); uint8_t status5 = i2cRead(0x65, 0x0e); if (status5 & 0x01) Serial.printf("hdmi "); Serial.printf("[%02x ", i2cRead(0x65, 0x07)); Serial.printf("%02x ", i2cRead(0x65, 0x08)); Serial.printf("%02x ", i2cRead(0x65, 0x09)); Serial.printf("%02x ", i2cRead(0x65, 0x0a)); Serial.printf("%02x ", i2cRead(0x65, 0x0e)); Serial.printf("%02x]\r\n", i2cRead(0x65, 0x0f)); } //Serial.println("====\n\n0x65 (1):"); //select_output(1); //i2cDump(0x65); //Serial.printf("%02x ", i2cRead(0x65, 0x07)); //Serial.printf("%02x ", i2cRead(0x65, 0x09)); //Serial.printf("%02x \r\n", i2cRead(0x65, 0x0f)); }).start(); }