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
* initialization request
`<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>`
Requests the specified data byte in `d` to be sent to the eBUS.
@@ -32,12 +34,19 @@ first second
`<START> <master>`
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.
* 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
* initialization response
`<RESETTED> <features>`
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
`<RECEIVED> <data>`
Indicates that the specified data byte in `d` was received from the eBUS.
@@ -51,6 +60,12 @@ first second
`<FAILED> <master>`
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
`<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
`<ERROR_EBUS> <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
* 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
### 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|`<RECEIVED> <0xAA>`|0xC6 0xAA|
|2|`QQ`|0x10|interface|`<0x10>`|0x10|
|3|`ZZ`|0x08|interface|`<0x08>`|0x08|
|4|`PB`|0x95|interface|`<RECEIVED> <0x95>`|0xC6 0x95|
|5|`SB`|0x12|interface|`<0x12>`|0x12|
|6|`NN`|0x00|interface|`<0x00>`|0x00|
|7|`CRC`|0xB1|interface|`<RECEIVED> <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|`<RECEIVED> <0xFF>`|0xC7 0xBF|
|12|`ACK`|0x00|interface|`<0x00>`|0x00|
|13|`SYN`|0xAA|interface|`<RECEIVED> <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|`<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|
### 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
+4
View File
@@ -1911,6 +1911,10 @@ result_t MainLoop::executeInfo(const vector<string>& 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";
}
+97 -4
View File
@@ -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<symbol_t*>(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<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;
case ENH_RES_ERROR_EBUS:
+18
View File
@@ -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];
};