diff --git a/docs/enhanced_proto.md b/docs/enhanced_proto.md index e16af1a76..716fd3ce5 100644 --- a/docs/enhanced_proto.md +++ b/docs/enhanced_proto.md @@ -23,7 +23,9 @@ first second #### from ebusd to interface * initialization request ` ` - Requests an initialization of the interface and requests special features in the data byte (tbd). + Requests an initialization of the interface and optionally requests special features. + The data byte `d` indicates interest in certain features (like full message sending instead of arbitration only). + The feature bits are defined below in the symbols section. * send data request ` ` Requests the specified data byte in `d` to be sent to the eBUS. @@ -32,12 +34,19 @@ first second ` ` Requests the start of the arbitration process after the next received `` symbol with the specified master address in `d`. If the master address is ``, the current arbitration is supposed to be cancelled. + * information request + ` ` + Requests the transfer of additional info identified by `info_id`. + The possible `info_id` values are defined below in the symbols section. + Sending a new info request while the response for the previous one is still in progress immediately terminates the + transfer of the previous response. #### from interface to ebusd * initialization response ` ` Indicates a reboot or an initial ebusd connection on the interface and is expected to be returned after an ` request. - The data byte `d` indicates availability of certain features (like full message sending instead of arbitration only, tbd). + The data byte `d` indicates availability of certain features (like full message sending instead of arbitration only). + The feature bits are defined below in the symbols section. * receive data notification ` ` Indicates that the specified data byte in `d` was received from the eBUS. @@ -51,6 +60,12 @@ first second ` ` Indicates that the last arbitration request failed (arbitration was lost or sending failed). The data byte in `d` contains the master address that has won the arbitration. + * information response + ` ` + Transfers one data byte in response to the INFO request. The first byte transferred in response is the number of + data bytes to be transferred (excluding the length itself). The format of the data sequence depends on the `info_id` + value from the request. + The possible `info_id` values are defined below in the symbols section. * eBUS communication error ` ` Indicates an error in the eBUS UART. @@ -72,86 +87,47 @@ These are the predefined symbols as used above. * INIT 0x0 * SEND 0x1 * START 0x2 + * INFO 0x3 ### Command response symbols (from interface to ebusd) * RESETTED 0x0 * RECEIVED 0x1 * STARTED 0x2 + * INFO 0x3 * FAILED 0xa ### Error codes (from interface to ebusd) * ERR_FRAMING 0x00: framing error - * ERR_OVERRUN 0x00: buffer overrun error - - -## Examples - -### Passive receive -The master-slave data sequence (without SYN, ACK, and CRC) `1008951200 / 0164` when ebusd is only listening to traffic on the bus would usually be transferred as follows (with all extra symbols seen on the bus): - -|order|eBUS proto|eBUS byte|sender|enhanced proto|enhanced bytes| -|----:|-----|-----|-----|-----|-----| -|1|`SYN`|0xAA|interface|` <0xAA>`|0xC6 0xAA| -|2|`QQ`|0x10|interface|`<0x10>`|0x10| -|3|`ZZ`|0x08|interface|`<0x08>`|0x08| -|4|`PB`|0x95|interface|` <0x95>`|0xC6 0x95| -|5|`SB`|0x12|interface|`<0x12>`|0x12| -|6|`NN`|0x00|interface|`<0x00>`|0x00| -|7|`CRC`|0xB1|interface|` <0xB1>`|0xC6 0xB1| -|8|`ACK`|0x00|interface|`<0x00>`|0x00| -|9|`NN`|0x01|interface|`<0x01>`|0x01| -|10|`DD`|0x64|interface|`<0x64>`|0x64| -|11|`CRC`|0xFF|interface|` <0xFF>`|0xC7 0xBF| -|12|`ACK`|0x00|interface|`<0x00>`|0x00| -|13|`SYN`|0xAA|interface|` <0xAA>`|0xC6 0xAA| - -### Active successful send -The same data sequence `1008951200 / 0164` when initiated by ebusd as master (with address 0x10) would usually be transferred as follows (with all extra symbols seen on the bus): - -|order|eBUS proto|eBUS byte|sender|enhanced proto|enhanced bytes| -|----:|-----|-----|-----|-----|-----| -|1| | |ebusd|` <0x10>`|0xC8 0x90| -|2|`SYN`|0xAA|interface|` <0xAA>`|0xC6 0xAA| -|3|`QQ`|0x10|interface|` <0x10>`|0xC8 0x90| -|4|`ZZ`|0x08|ebusd|`<0x08>`|0x08| -|5|`ZZ`|0x08|interface|`<0x08>`|0x08| -|6|`PB`|0x95|ebusd|` <0x95>`|0xC6 0x95| -|7|`PB`|0x95|interface|` <0x95>`|0xC6 0x95| -|8|`SB`|0x12|ebusd|`<0x12>`|0x12| -|9|`SB`|0x12|interface|`<0x12>`|0x12| -|10|`NN`|0x00|ebusd|`<0x00>`|0x00| -|11|`NN`|0x00|interface|`<0x00>`|0x00| -|12|`CRC`|0xB1|ebusd|` <0xB1>`|0xC6 0xB1| -|13|`CRC`|0xB1|interface|` <0xB1>`|0xC6 0xB1| -|14|`ACK`|0x00|interface|`<0x00>`|0x00| -|15|`NN`|0x01|interface|`<0x01>`|0x01| -|16|`DD`|0x64|interface|`<0x64>`|0x64| -|17|`CRC`|0xFF|interface|` <0xFF>`|0xC7 0xBF| -|18|`ACK`|0x00|ebusd|`<0x00>`|0x00| -|19|`ACK`|0x00|interface|`<0x00>`|0x00| -|20|`SYN`|0xAA|interface|` <0xAA>`|0xC6 0xAA| - - -### Active successful send as SYN generator -The same data sequence `1008951200 / 0164` when initiated by ebusd as master (with address 0x10) and acting as SYN generator would usually be transferred as follows (with all extra symbols seen on the bus): - -|order|eBUS proto|eBUS byte|sender|enhanced proto|enhanced bytes| -|----:|-----|-----|-----|-----|-----| -|1| | |ebusd|` <0x10>`|0xC8 0x90| -|2|`SYN`|0xAA|ebusd|` <0xAA>`|0xC6 0xAA| -|3|`SYN`|0xAA|interface|` <0xAA>`|0xC6 0xAA| -|4|`QQ`|0x10|interface|` <0x10>`|0xC8 0x90| -|...|see above| | | | | -The rest of the communcation is the same as before (from 4.) - - -### Active failed traffic -A failed arbitration when initiated by ebusd as master (with address 0x10) would usually be transferred as follows (with all extra symbols seen on the bus): - -|order|eBUS proto|eBUS byte|sender|enhanced proto|enhanced byte| -|----:|-----|-----|-----|-----|-----| -|1| | |ebusd|` <0x10>`|0xC8 0x90| -|2|`SYN`|0xAA|interface|` <0xAA>`|0xC6 0xAA| -|3| |0x10|ebusd|` <0x10>`|0xE0 0x90| -|4|`QQ`|0x03|interface|`<0x03>`|0x03| + * ERR_OVERRUN 0x01: buffer overrun error + +### Feature bits (both directions) + * bit 7-1: tbd + * bit 2: full message sending (complete sequence instead of single bytes) + * bit 1: high speed transfer at 115200 Bd + When requested, the UART speed is changed to 115200 Bd immediately after sending the complete RESETTED reponse. + * bit 0: additional infos (version, PIC ID, etc.) + +### Information IDs (both directions) +The first level below is the `info_id` value and the second level describes the response data byte sequence. +The first byte transferred in response is always the number of data bytes to be transferred (excluding the length itself). + * 0x00: version + * `length`: =2 + * `version`: version number + * `features`: feature bits + * 0x01: PIC ID + * `length`: =9 + * 9*`mui`: PIC MUI + * 0x02: PIC config + * `length`: =8 + * 8*`config_H` `config_L`: PIC config + * 0x03: PIC temperature + * `length`: =1 + * `temp`: temperature in degrees Celsius + * 0x04: PIC supply voltage + * `length`: =2 + * `millivolt_H` `millivolt_L`: voltage value in mV + * 0x05: bus voltage + * `length`: =2 + * `voltage_max`: maximum bus voltage in 10th volts + * `voltage_min`: minimum bus voltage in 10th volts diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index 9d9c02cdc..6d8dab7f9 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -1911,6 +1911,10 @@ result_t MainLoop::executeInfo(const vector& args, const string& user, o if (!m_updateCheck.empty()) { *ostream << "update check: " << m_updateCheck << "\n"; } + string info = m_device->getEnhancedInfos(); + if (!info.empty()) { + *ostream << "device: " << info << "\n"; + } if (!user.empty()) { *ostream << "user: " << user << "\n"; } diff --git a/src/lib/ebus/device.cpp b/src/lib/ebus/device.cpp index 7988e9c65..40944248c 100755 --- a/src/lib/ebus/device.cpp +++ b/src/lib/ebus/device.cpp @@ -60,6 +60,8 @@ namespace ebusd { #define ENH_RES_RECEIVED ((uint8_t)0x1) #define ENH_REQ_START ((uint8_t)0x2) #define ENH_RES_STARTED ((uint8_t)0x2) +#define ENH_REQ_INFO ((uint8_t)0x3) +#define ENH_RES_INFO ((uint8_t)0x3) #define ENH_RES_FAILED ((uint8_t)0xa) #define ENH_RES_ERROR_EBUS ((uint8_t)0xb) #define ENH_RES_ERROR_HOST ((uint8_t)0xc) @@ -79,7 +81,8 @@ Device::Device(const char* name, bool checkDevice, unsigned int latency, bool re : m_name(name), m_checkDevice(checkDevice), m_latency(HOST_LATENCY_MS+latency), m_readOnly(readOnly), m_initialSend(initialSend), m_enhancedProto(enhancedProto), m_fd(-1), m_listener(nullptr), m_arbitrationMaster(SYN), - m_arbitrationCheck(false), m_bufSize(((MAX_LEN+1+3)/4)*4), m_bufLen(0), m_bufPos(0) { + m_arbitrationCheck(false), m_bufSize(((MAX_LEN+1+3)/4)*4), m_bufLen(0), m_bufPos(0), + m_extraFatures(0), m_infoId(0xff), m_infoLen(0), m_infoPos(0) { m_buffer = reinterpret_cast(malloc(m_bufSize)); if (!m_buffer) { m_bufSize = 0; @@ -141,8 +144,9 @@ result_t Device::open() { result_t Device::afterOpen() { m_bufLen = 0; + m_extraFatures = 0; if (m_enhancedProto) { - symbol_t buf[2] = makeEnhancedSequence(ENH_REQ_INIT, 0); // TODO define additional feature flags + symbol_t buf[2] = makeEnhancedSequence(ENH_REQ_INIT, 0x01); // extra feature: info #ifdef DEBUG_RAW_TRAFFIC fprintf(stdout, "raw enhanced > %2.2x %2.2x\n", buf[0], buf[1]); #endif @@ -176,6 +180,47 @@ bool Device::isValid() { return m_fd != -1; } +result_t Device::requestEnhancedInfo(symbol_t infoId) { + if (!m_enhancedProto || m_extraFatures == 0 || infoId == 0xff) { + return RESULT_ERR_INVALID_ARG; + } + if (m_infoId != 0xff) { + usleep(40000); + if (m_infoId != 0xff) { + return RESULT_ERR_DUPLICATE; + } + } + symbol_t buf[2] = makeEnhancedSequence(ENH_REQ_INFO, infoId); +#ifdef DEBUG_RAW_TRAFFIC + fprintf(stdout, "raw enhanced > %2.2x %2.2x\n", buf[0], buf[1]); +#endif + m_infoPos = 0; + m_infoId = infoId; + if (::write(m_fd, buf, 2) != 2) { + return RESULT_ERR_DEVICE; + } + return RESULT_OK; +} + +string Device::getEnhancedInfos() { + if (!m_enhancedProto || m_extraFatures == 0) { + return ""; + } + result_t res = requestEnhancedInfo(0); + if (res != RESULT_OK) { + return "cannot request info"; + } + res = requestEnhancedInfo(1); + res = requestEnhancedInfo(2); + res = requestEnhancedInfo(3); + res = requestEnhancedInfo(4); + res = requestEnhancedInfo(5); + if (m_infoPos == 0) { + return "did not get info"; + } + return ""; +} + result_t Device::send(symbol_t value) { if (!isValid()) { return RESULT_ERR_DEVICE; @@ -528,9 +573,57 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati m_arbitrationMaster = SYN; m_arbitrationCheck = false; } - // TODO define additional feature flags + m_extraFatures = data; if (m_listener != nullptr) { - m_listener->notifyStatus(false, "reset"); + m_listener->notifyStatus(false, (m_extraFatures&0x01) ? "reset, supports info" : "reset"); + } + break; + case ENH_RES_INFO: + if (m_infoLen == 0) { + if (data<=16) { // max length + m_infoLen = data; + m_infoPos = 0; + } + } else if (m_infoPos < m_infoLen) { + m_infoBuf[m_infoPos++] = data; + if (m_infoPos >= m_infoLen) { + unsigned int val; + ostringstream stream; + stream << "extra info: "; + switch ((m_infoLen<<8) | m_infoId) { + case 0x0200: + stream << "firmware " << static_cast(m_infoBuf[0]) << "." << std::hex << static_cast(m_infoBuf[1]) << "."; + break; + case 0x0901: + case 0x0802: + stream << (m_infoId == 1 ? "ID" : "config"); + stream << std::hex << std::setfill('0'); + for (uint8_t pos = 0; pos(m_infoBuf[pos]); + } + break; + case 0x0203: + val = (static_cast(m_infoBuf[0])<<8) | static_cast(m_infoBuf[1]); + stream << "temperature " << static_cast(val) << " °C"; + break; + case 0x0204: + val = (static_cast(m_infoBuf[0])<<8) | static_cast(m_infoBuf[1]); + stream << "supply voltage " << static_cast(val) << " mV"; + break; + case 0x0205: + stream << "bus voltage " << std::fixed << std::setprecision(1) + << static_cast(m_infoBuf[1] / 10.0) << " V - " + << static_cast(m_infoBuf[0] / 10.0) << " V"; + break; + default: + stream << "unknown 0x" << std::hex << std::setfill('0') << std::setw(2) << static_cast(m_infoId) + << ", len " << std::dec << std::setw(0) << static_cast(m_infoPos); + break; + } + m_listener->notifyStatus(false, stream.str().c_str()); + m_infoLen = 0; + m_infoId = 0xff; + } } break; case ENH_RES_ERROR_EBUS: diff --git a/src/lib/ebus/device.h b/src/lib/ebus/device.h index 997b40af8..6edd000f3 100755 --- a/src/lib/ebus/device.h +++ b/src/lib/ebus/device.h @@ -206,6 +206,9 @@ class Device { */ void setListener(DeviceListener* listener) { m_listener = listener; } + result_t requestEnhancedInfo(symbol_t infoId); + + string getEnhancedInfos(); protected: /** @@ -288,6 +291,21 @@ class Device { /** the read buffer read position. */ size_t m_bufPos; + + /** the extra features supported by the device. */ + symbol_t m_extraFatures; + + /** the ID of the last requested info. */ + symbol_t m_infoId; + + /** the info buffer expected length. */ + size_t m_infoLen; + + /** the info buffer write position. */ + size_t m_infoPos; + + /** the info buffer. */ + symbol_t m_infoBuf[16]; };