prepare upcoming adapter3 firmware enhancements

This commit is contained in:
John
2021-09-11 08:59:20 +02:00
parent c69dfa7b99
commit 3f347d059a
4 changed files with 168 additions and 77 deletions
+49 -73
View File
@@ -23,7 +23,9 @@ first second
#### from ebusd to interface #### from ebusd to interface
* initialization request * initialization request
`<INIT> <features>` `<INIT> <features>`
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 * send data request
`<SEND> <data>` `<SEND> <data>`
Requests the specified data byte in `d` to be sent to the eBUS. Requests the specified data byte in `d` to be sent to the eBUS.
@@ -32,12 +34,19 @@ first second
`<START> <master>` `<START> <master>`
Requests the start of the arbitration process after the next received `<SYN>` symbol with the specified master address in `d`. Requests the start of the arbitration process after the next received `<SYN>` symbol with the specified master address in `d`.
If the master address is `<SYN>`, the current arbitration is supposed to be cancelled. If the master address is `<SYN>`, the current arbitration is supposed to be cancelled.
* information request
`<INFO> <info_id>`
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 #### from interface to ebusd
* initialization response * initialization response
`<RESETTED> <features>` `<RESETTED> <features>`
Indicates a reboot or an initial ebusd connection on the interface and is expected to be returned after an `<INIT`> request. Indicates a reboot or an initial ebusd connection on the interface and is expected to be returned after an `<INIT`> 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 * receive data notification
`<RECEIVED> <data>` `<RECEIVED> <data>`
Indicates that the specified data byte in `d` was received from the eBUS. Indicates that the specified data byte in `d` was received from the eBUS.
@@ -51,6 +60,12 @@ first second
`<FAILED> <master>` `<FAILED> <master>`
Indicates that the last arbitration request failed (arbitration was lost or sending failed). 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. The data byte in `d` contains the master address that has won the arbitration.
* information response
`<INFO> <data>`
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 * eBUS communication error
`<ERROR_EBUS> <error>` `<ERROR_EBUS> <error>`
Indicates an error in the eBUS UART. Indicates an error in the eBUS UART.
@@ -72,86 +87,47 @@ These are the predefined symbols as used above.
* INIT 0x0 * INIT 0x0
* SEND 0x1 * SEND 0x1
* START 0x2 * START 0x2
* INFO 0x3
### Command response symbols (from interface to ebusd) ### Command response symbols (from interface to ebusd)
* RESETTED 0x0 * RESETTED 0x0
* RECEIVED 0x1 * RECEIVED 0x1
* STARTED 0x2 * STARTED 0x2
* INFO 0x3
* FAILED 0xa * FAILED 0xa
### Error codes (from interface to ebusd) ### Error codes (from interface to ebusd)
* ERR_FRAMING 0x00: framing error * ERR_FRAMING 0x00: framing error
* ERR_OVERRUN 0x00: buffer overrun error * 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.)
## Examples ### Information IDs (both directions)
The first level below is the `info_id` value and the second level describes the response data byte sequence.
### Passive receive The first byte transferred in response is always the number of data bytes to be transferred (excluding the length itself).
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): * 0x00: version
* `length`: =2
|order|eBUS proto|eBUS byte|sender|enhanced proto|enhanced bytes| * `version`: version number
|----:|-----|-----|-----|-----|-----| * `features`: feature bits
|1|`SYN`|0xAA|interface|`<RECEIVED> <0xAA>`|0xC6 0xAA| * 0x01: PIC ID
|2|`QQ`|0x10|interface|`<0x10>`|0x10| * `length`: =9
|3|`ZZ`|0x08|interface|`<0x08>`|0x08| * 9*`mui`: PIC MUI
|4|`PB`|0x95|interface|`<RECEIVED> <0x95>`|0xC6 0x95| * 0x02: PIC config
|5|`SB`|0x12|interface|`<0x12>`|0x12| * `length`: =8
|6|`NN`|0x00|interface|`<0x00>`|0x00| * 8*`config_H` `config_L`: PIC config
|7|`CRC`|0xB1|interface|`<RECEIVED> <0xB1>`|0xC6 0xB1| * 0x03: PIC temperature
|8|`ACK`|0x00|interface|`<0x00>`|0x00| * `length`: =1
|9|`NN`|0x01|interface|`<0x01>`|0x01| * `temp`: temperature in degrees Celsius
|10|`DD`|0x64|interface|`<0x64>`|0x64| * 0x04: PIC supply voltage
|11|`CRC`|0xFF|interface|`<RECEIVED> <0xFF>`|0xC7 0xBF| * `length`: =2
|12|`ACK`|0x00|interface|`<0x00>`|0x00| * `millivolt_H` `millivolt_L`: voltage value in mV
|13|`SYN`|0xAA|interface|`<RECEIVED> <0xAA>`|0xC6 0xAA| * 0x05: bus voltage
* `length`: =2
### Active successful send * `voltage_max`: maximum bus voltage in 10th volts
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): * `voltage_min`: minimum bus voltage in 10th volts
|order|eBUS proto|eBUS byte|sender|enhanced proto|enhanced bytes|
|----:|-----|-----|-----|-----|-----|
|1| | |ebusd|`<START> <0x10>`|0xC8 0x90|
|2|`SYN`|0xAA|interface|`<RECEIVED> <0xAA>`|0xC6 0xAA|
|3|`QQ`|0x10|interface|`<STARTED> <0x10>`|0xC8 0x90|
|4|`ZZ`|0x08|ebusd|`<0x08>`|0x08|
|5|`ZZ`|0x08|interface|`<0x08>`|0x08|
|6|`PB`|0x95|ebusd|`<SEND> <0x95>`|0xC6 0x95|
|7|`PB`|0x95|interface|`<RECEIVED> <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|`<SEND> <0xB1>`|0xC6 0xB1|
|13|`CRC`|0xB1|interface|`<RECEIVED> <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|`<RECEIVED> <0xFF>`|0xC7 0xBF|
|18|`ACK`|0x00|ebusd|`<0x00>`|0x00|
|19|`ACK`|0x00|interface|`<0x00>`|0x00|
|20|`SYN`|0xAA|interface|`<RECEIVED> <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|`<START> <0x10>`|0xC8 0x90|
|2|`SYN`|0xAA|ebusd|`<SEND> <0xAA>`|0xC6 0xAA|
|3|`SYN`|0xAA|interface|`<RECEIVED> <0xAA>`|0xC6 0xAA|
|4|`QQ`|0x10|interface|`<STARTED> <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|`<START> <0x10>`|0xC8 0x90|
|2|`SYN`|0xAA|interface|`<RECEIVED> <0xAA>`|0xC6 0xAA|
|3| |0x10|ebusd|`<FAILED> <0x10>`|0xE0 0x90|
|4|`QQ`|0x03|interface|`<0x03>`|0x03|
+4
View File
@@ -1911,6 +1911,10 @@ result_t MainLoop::executeInfo(const vector<string>& args, const string& user, o
if (!m_updateCheck.empty()) { if (!m_updateCheck.empty()) {
*ostream << "update check: " << m_updateCheck << "\n"; *ostream << "update check: " << m_updateCheck << "\n";
} }
string info = m_device->getEnhancedInfos();
if (!info.empty()) {
*ostream << "device: " << info << "\n";
}
if (!user.empty()) { if (!user.empty()) {
*ostream << "user: " << user << "\n"; *ostream << "user: " << user << "\n";
} }
+97 -4
View File
@@ -60,6 +60,8 @@ namespace ebusd {
#define ENH_RES_RECEIVED ((uint8_t)0x1) #define ENH_RES_RECEIVED ((uint8_t)0x1)
#define ENH_REQ_START ((uint8_t)0x2) #define ENH_REQ_START ((uint8_t)0x2)
#define ENH_RES_STARTED ((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_FAILED ((uint8_t)0xa)
#define ENH_RES_ERROR_EBUS ((uint8_t)0xb) #define ENH_RES_ERROR_EBUS ((uint8_t)0xb)
#define ENH_RES_ERROR_HOST ((uint8_t)0xc) #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_name(name), m_checkDevice(checkDevice),
m_latency(HOST_LATENCY_MS+latency), m_readOnly(readOnly), m_initialSend(initialSend), 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_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<symbol_t*>(malloc(m_bufSize)); m_buffer = reinterpret_cast<symbol_t*>(malloc(m_bufSize));
if (!m_buffer) { if (!m_buffer) {
m_bufSize = 0; m_bufSize = 0;
@@ -141,8 +144,9 @@ result_t Device::open() {
result_t Device::afterOpen() { result_t Device::afterOpen() {
m_bufLen = 0; m_bufLen = 0;
m_extraFatures = 0;
if (m_enhancedProto) { 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 #ifdef DEBUG_RAW_TRAFFIC
fprintf(stdout, "raw enhanced > %2.2x %2.2x\n", buf[0], buf[1]); fprintf(stdout, "raw enhanced > %2.2x %2.2x\n", buf[0], buf[1]);
#endif #endif
@@ -176,6 +180,47 @@ bool Device::isValid() {
return m_fd != -1; 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) { result_t Device::send(symbol_t value) {
if (!isValid()) { if (!isValid()) {
return RESULT_ERR_DEVICE; return RESULT_ERR_DEVICE;
@@ -528,9 +573,57 @@ bool Device::read(symbol_t* value, bool isAvailable, ArbitrationState* arbitrati
m_arbitrationMaster = SYN; m_arbitrationMaster = SYN;
m_arbitrationCheck = false; m_arbitrationCheck = false;
} }
// TODO define additional feature flags m_extraFatures = data;
if (m_listener != nullptr) { 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<unsigned>(m_infoBuf[0]) << "." << std::hex << static_cast<unsigned>(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_infoPos; pos++) {
stream << " " << std::setw(2) << static_cast<unsigned>(m_infoBuf[pos]);
}
break;
case 0x0203:
val = (static_cast<unsigned>(m_infoBuf[0])<<8) | static_cast<unsigned>(m_infoBuf[1]);
stream << "temperature " << static_cast<unsigned>(val) << " °C";
break;
case 0x0204:
val = (static_cast<unsigned>(m_infoBuf[0])<<8) | static_cast<unsigned>(m_infoBuf[1]);
stream << "supply voltage " << static_cast<unsigned>(val) << " mV";
break;
case 0x0205:
stream << "bus voltage " << std::fixed << std::setprecision(1)
<< static_cast<float>(m_infoBuf[1] / 10.0) << " V - "
<< static_cast<float>(m_infoBuf[0] / 10.0) << " V";
break;
default:
stream << "unknown 0x" << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned>(m_infoId)
<< ", len " << std::dec << std::setw(0) << static_cast<unsigned>(m_infoPos);
break;
}
m_listener->notifyStatus(false, stream.str().c_str());
m_infoLen = 0;
m_infoId = 0xff;
}
} }
break; break;
case ENH_RES_ERROR_EBUS: case ENH_RES_ERROR_EBUS:
+18
View File
@@ -206,6 +206,9 @@ class Device {
*/ */
void setListener(DeviceListener* listener) { m_listener = listener; } void setListener(DeviceListener* listener) { m_listener = listener; }
result_t requestEnhancedInfo(symbol_t infoId);
string getEnhancedInfos();
protected: protected:
/** /**
@@ -288,6 +291,21 @@ class Device {
/** the read buffer read position. */ /** the read buffer read position. */
size_t m_bufPos; 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];
}; };