Skip to content

Commit

Permalink
prepare upcoming adapter3 firmware enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
john30 committed Sep 11, 2021
1 parent c69dfa7 commit 3f347d0
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 79 deletions.
126 changes: 51 additions & 75 deletions docs/enhanced_proto.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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|`<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|
* 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

4 changes: 4 additions & 0 deletions src/ebusd/mainloop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
101 changes: 97 additions & 4 deletions src/lib/ebus/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions src/lib/ebus/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ class Device {
*/
void setListener(DeviceListener* listener) { m_listener = listener; }

result_t requestEnhancedInfo(symbol_t infoId);

string getEnhancedInfos();

protected:
/**
Expand Down Expand Up @@ -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];
};


Expand Down

0 comments on commit 3f347d0

Please sign in to comment.