From 53b537bb506106f6d240e02a00a053d2f42b2996 Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Thu, 28 Jun 2018 15:38:42 +0200 Subject: [PATCH] Initial commit --- .gitignore | 1 + Makefile | 1 + app/application.cpp | 284 ++++++++++++++++++++++++++++++++++++++++++ include/user_config.h | 45 +++++++ 4 files changed, 331 insertions(+) create mode 100644 .gitignore create mode 120000 Makefile create mode 100644 app/application.cpp create mode 100644 include/user_config.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1fcb152 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +out diff --git a/Makefile b/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/app/application.cpp b/app/application.cpp new file mode 100644 index 0000000..2f2648c --- /dev/null +++ b/app/application.cpp @@ -0,0 +1,284 @@ +#include +#include "twi.h" + +uint8_t edidbuf[] = { + 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 +}; + +class EP9442Matrix { + Timer pollTimer; + + enum reg49_sel { PRIMARY=0, SECONDARY }; + + struct { + uint8_t primary_sel :2; + uint8_t secondary_sel :2; + uint8_t tx0_oe :1; + uint8_t tx1_oe :1; + enum reg49_sel tx0_sel :1; + enum reg49_sel tx1_sel :1; + } reg49 = {1, 1, true, true, reg49_sel::SECONDARY, reg49_sel::PRIMARY}; + + struct { + uint8_t rx0_on :1; + uint8_t rx1_on :1; + uint8_t rx2_on :1; + uint8_t rx3_on :1; + uint8_t _ :1; + uint8_t audio_on :1; + uint8_t tx0_on :1; + uint8_t tx1_on :1; + } reg4a = {1, 1, 1, 1, 0, 1, 1, 1}; + + uint8_t rxphy[4] = {0x4c, 0x02, 0x50, 0x00}; + uint8_t txphy[3] = {0x4d, 0x16, 0x01}; + + 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", 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) { + debugf("transmission end failed?"); + } + + Wire.requestFrom((int) addr, (int) cnt); + + return Wire.read(); + } + + uint8_t setEDID(uint8_t port, uint8_t* edid) + { + uint8_t err, address; + + if ((err = i2cWrite(0x64, 0x42, port)) != 0) { + debugf("start error occured: %d", err); + return err; + } + + uint8_t edidData[257]; + edidData[0] = 0xff; + memcpy(edidData+1, edid, 256); + if ((err = twi_writeTo(0x64, edidData, 257, true)) != 0) { + debugf("Edid write failed: %d", err); + } + + if ((err = i2cWrite(0x64, 0x42, 0x3c)) != 0) { + debugf("end error occured: %d", err); + return err; + } + + return 0; + } +public: + EP9442Matrix() { } + + void init() { + uint8_t err; + + Wire.begin(4, 5); + Wire.setClock(300000); + Wire.setClockStretchLimit(5*230); + + debugf("basic registers"); + // Disable RX on all inputs + //delay(1000); + 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, 0x4b, 0b111111); + + i2cWrite(0x64, 0x4a, 0x00); + i2cWrite(0x64, 0x4a, *(uint8_t*)®4a); // 0xff + i2cWrite(0x64, 0x4a, 0x00); + i2cWrite(0x64, 0x4a, *(uint8_t*)®4a); // 0xff + + + debugf("setup phy"); + if ((err = twi_writeTo(0x64, rxphy, sizeof(rxphy), true)) != 0) { + debugf("rx phy settings failed: %d", err); + } + + if ((err = twi_writeTo(0x64, txphy, sizeof(txphy), true)) != 0) { + debugf("tx phy settings failed: %d", err); + } + + debugf("setting edid..."); + for (int i = 0; i < 4; i++) { + setEDID(i, edidbuf); + } + debugf("updating routing..."); + updateRouting(); + debugf("done"); + + pollTimer.initializeMs(500, TimerDelegate(&EP9442Matrix::pollStatus, this)).start(); + } + + void updateRouting() { + uint8_t new_reg = *(uint8_t*)®49; + i2cWrite(0x64, 0x49, new_reg); + debugf("new reg49: %02x", new_reg); + } + + void pollStatus() { + 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)); + } + } + + void routeAudio(uint8_t source) { + // TODO + + if (source == 0) { + } else if (source == 1) { + } else { + // mute + } + } + + void routeVideo(uint8_t source, uint8_t target) { + enum reg49_sel sel = (target == 0) ? reg49.tx0_sel : reg49.tx1_sel; + // TODO video mute + if (sel == reg49_sel::PRIMARY) { + reg49.primary_sel = source; + } else { + reg49.secondary_sel = source; + } + + updateRouting(); + } +}; + + +class MatrixEndpoint: public Endpoint { + EP9442Matrix matrix; + +public: + MatrixEndpoint() : Endpoint("matrix") { } + + void bind(String _name, SpejsNode* _parent) { + Endpoint::bind(_name, _parent); + + // FIXME + matrix.init(); + matrix.init(); + //matrix.init(); + } + + EndpointResult onValue(String property, String value) { + if (property == "sourceA") { + matrix.routeVideo(value.toInt(), 0); + } + + if (property == "sourceB") { + matrix.routeVideo(value.toInt(), 1); + } + + if (property == "audioSource") { + int source = 0xff; + + value.toLowerCase(); + + if (value == "a") + source = 0; + else if (value == "b") + source = 1; + + matrix.routeAudio(source); + } + + return 400; + } +}; + +SpejsNode node("hdmi-matrix"); + +void init() { + node.statusLED.config(2, LOW); + node.init(true); + + node.registerEndpoint("matrix", new MatrixEndpoint()); +} diff --git a/include/user_config.h b/include/user_config.h new file mode 100644 index 0000000..1c6ac36 --- /dev/null +++ b/include/user_config.h @@ -0,0 +1,45 @@ +#ifndef __USER_CONFIG_H__ +#define __USER_CONFIG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + // UART config + #define SERIAL_BAUD_RATE 115200 + + // ESP SDK config + #define LWIP_OPEN_SRC + #define USE_US_TIMER + + // Default types + #define __CORRECT_ISO_CPP_STDLIB_H_PROTO + #include + #include + + // Override c_types.h include and remove buggy espconn + #define _C_TYPES_H_ + #define _NO_ESPCON_ + + // Updated, compatible version of c_types.h + // Just removed types declared in + #include + + // System API declarations + #include + + // C++ Support + #include + // Extended string conversion for compatibility + #include + // Network base API + #include + + // Beta boards + #define BOARD_ESP01 + +#ifdef __cplusplus +} +#endif + +#endif