implemented get
This commit is contained in:
@@ -16,7 +16,7 @@ ebusd_SOURCES = bushandler.cpp \
|
||||
|
||||
ebusd_LDADD = $(top_srcdir)/src/lib/utils/libutils.a \
|
||||
$(top_srcdir)/src/lib/ebus/libebus.a \
|
||||
-lpthread
|
||||
-lpthread -lrt
|
||||
|
||||
distclean-local:
|
||||
-rm -f Makefile.in
|
||||
|
||||
+223
-134
@@ -35,28 +35,31 @@ extern Logger& L;
|
||||
extern Appl& A;
|
||||
|
||||
/**
|
||||
* @brief Return the string corresponding to the @a BusState and send position.
|
||||
* @brief Return the string corresponding to the @a BusState.
|
||||
* @param state the @a BusState.
|
||||
* @param sendPos >=0 while sending data, -1 while receiving data.
|
||||
* @return the string corresponding to the @a BusState.
|
||||
*/
|
||||
const char* getStateCode(BusState state, int sendPos) {
|
||||
const char* getStateCode(BusState state) {
|
||||
switch (state)
|
||||
{
|
||||
case bs_skip: return "skip";
|
||||
case bs_ready: return "ready";
|
||||
case bs_command: return sendPos < 0 ? "receive command" : "send command";
|
||||
case bs_commandAck: return sendPos < 0 ? "receive command ACK" : "send command ACK";
|
||||
case bs_response: return sendPos < 0 ? "receive response" : "send response";
|
||||
case bs_responseAck: return sendPos < 0 ? "receive response ACK" : "send response ACK";
|
||||
//case bs_validTransfer: return sendPos < 0 ? "after complete receive" : "after complete send";
|
||||
default: return "unknown state";
|
||||
case bs_skip: return "skip";
|
||||
case bs_ready: return "ready";
|
||||
case bs_sendCmd: return "send command";
|
||||
case bs_recvCmdAck: return "receive command ACK";
|
||||
case bs_recvRes: return "receive response";
|
||||
case bs_sendResAck: return "send response ACK";
|
||||
case bs_recvCmd: return "receive command";
|
||||
case bs_recvResAck: return "receive response ACK";
|
||||
// case bs_sendRes: return "send response";
|
||||
// case bs_sendCmdAck: return "send command ACK";
|
||||
case bs_sendSyn: return "send SYN";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BusRequest::BusRequest(SymbolString& master, SymbolString& slave)
|
||||
: m_master(master), m_slave(slave), m_finished(false)
|
||||
: m_master(master), m_slave(slave), m_finished(false), m_result(RESULT_SYN)
|
||||
{
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
pthread_cond_init(&m_cond, NULL);
|
||||
@@ -88,11 +91,12 @@ bool BusRequest::wait(int timeout)
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
void BusRequest::notify(bool finished)
|
||||
void BusRequest::notify(result_t result)
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
|
||||
m_finished = finished;
|
||||
m_result = result;
|
||||
m_finished = true;
|
||||
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
@@ -103,29 +107,24 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave)
|
||||
BusRequest* request = new BusRequest(master, slave);
|
||||
|
||||
m_requests.add(request);
|
||||
bool result = request->wait(5);
|
||||
if (result == false)
|
||||
bool success = request->wait(5);
|
||||
if (success == false)
|
||||
m_requests.remove(request);
|
||||
result_t result = request->m_result;
|
||||
delete request;
|
||||
|
||||
return result == true ? RESULT_OK : RESULT_ERR_TIMEOUT;
|
||||
return success == true ? result : RESULT_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
void BusHandler::run()
|
||||
{
|
||||
result_t result = RESULT_OK;
|
||||
do {
|
||||
if (m_port->isOpen() == true) {
|
||||
result = receiveSymbol();
|
||||
|
||||
if (result != RESULT_OK)
|
||||
L.log(bus, error, " %s", getResultCode(result));
|
||||
|
||||
}
|
||||
if (m_port->isOpen() == true)
|
||||
handleSymbol();
|
||||
else {
|
||||
// TODO: define max reopen
|
||||
sleep(10);
|
||||
result = m_port->open();
|
||||
result_t result = m_port->open();
|
||||
|
||||
if (result != RESULT_OK)
|
||||
L.log(bus, error, "can't open %s", A.getOptVal<const char*>("device"));
|
||||
@@ -135,46 +134,72 @@ void BusHandler::run()
|
||||
} while (isRunning() == true);
|
||||
}
|
||||
|
||||
result_t BusHandler::receiveSymbol()
|
||||
#define RECV_TIMEOUT 4500
|
||||
|
||||
result_t BusHandler::handleSymbol()
|
||||
{
|
||||
long timeout;
|
||||
ssize_t count;
|
||||
unsigned char sentSymbol = SYN;
|
||||
BusRequest* startRequest = NULL;
|
||||
if (m_state == bs_skip)
|
||||
timeout = 0;
|
||||
else if (m_sendPos >= 0) {
|
||||
timeout = SLAVE_RECV_TIMEOUT;
|
||||
if (m_sendPos+1 < m_request->m_master.size()) {
|
||||
m_sendPos++;
|
||||
sentSymbol = m_request->m_master[m_sendPos];
|
||||
if (m_port->send(&sentSymbol) != 1) {
|
||||
sentSymbol = SYN; // try again later // TODO error: send failed, abort send
|
||||
m_request->notify(false);
|
||||
m_request = NULL;
|
||||
m_sendPos = -1;
|
||||
}
|
||||
long timeout = SYN_TIMEOUT;
|
||||
unsigned char sendSymbol = ESC;
|
||||
bool sending = false;
|
||||
|
||||
// check if another symbol has to be sent and determine timeout for receive
|
||||
switch (m_state)
|
||||
{
|
||||
case bs_skip:
|
||||
timeout = 0; // endless
|
||||
break;
|
||||
|
||||
case bs_ready:
|
||||
m_request = m_requests.next(false);
|
||||
if (m_request != NULL) { // initiate arbitration
|
||||
sendSymbol = m_request->m_master[0];
|
||||
sending = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case bs_recvCmd:
|
||||
case bs_recvCmdAck:
|
||||
case bs_recvRes:
|
||||
case bs_recvResAck:
|
||||
timeout = SLAVE_RECV_TIMEOUT;
|
||||
break;
|
||||
|
||||
case bs_sendCmd:
|
||||
if (m_request != NULL) {
|
||||
sendSymbol = m_request->m_master[m_nextSendPos];
|
||||
sending = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case bs_sendResAck:
|
||||
if (m_request != NULL) {
|
||||
sendSymbol = m_responseCrcValid ? ACK : NAK;
|
||||
sending = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case bs_sendSyn:
|
||||
sendSymbol = SYN;
|
||||
sending = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
timeout = SYN_TIMEOUT;
|
||||
if (m_state == bs_ready && m_request == NULL) {
|
||||
startRequest = m_requests.next(false);
|
||||
if (startRequest != NULL) {
|
||||
// initiate arbitration
|
||||
sentSymbol = startRequest->m_master[0];
|
||||
if (m_port->send(&sentSymbol) != 1) {
|
||||
sentSymbol = SYN; // try again later // TODO error: send failed
|
||||
startRequest = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// send symbol if necessary
|
||||
if (sending == true) {
|
||||
if (m_port->send(&sendSymbol, 1) == 1)
|
||||
timeout = RECV_TIMEOUT;
|
||||
else {
|
||||
sending = false;
|
||||
timeout = 0;
|
||||
setState(bs_skip, RESULT_ERR_SEND);
|
||||
}
|
||||
}
|
||||
|
||||
count = m_port->recv(timeout, 1);
|
||||
// receive next symbol (optionally check reception of sent symbol)
|
||||
ssize_t count = m_port->recv(timeout, 1);
|
||||
|
||||
if (count < 0)
|
||||
return setState(bs_skip, RESULT_ERR_DEVICE);
|
||||
return setState(bs_skip, count);
|
||||
|
||||
if (count == 0) {
|
||||
if (m_state == bs_ready)
|
||||
@@ -182,11 +207,9 @@ result_t BusHandler::receiveSymbol()
|
||||
return setState(bs_skip, RESULT_ERR_TIMEOUT);
|
||||
}
|
||||
|
||||
unsigned char symbol = m_port->byte();
|
||||
if (symbol == SYN) {
|
||||
m_repeat = false;
|
||||
return setState(bs_ready, RESULT_OK);
|
||||
}
|
||||
unsigned char recvSymbol = m_port->byte();
|
||||
if (recvSymbol == SYN)
|
||||
return setState(bs_ready, RESULT_SYN);
|
||||
|
||||
unsigned char headerLen, crcPos;
|
||||
result_t result;
|
||||
@@ -197,128 +220,185 @@ result_t BusHandler::receiveSymbol()
|
||||
return RESULT_OK;
|
||||
|
||||
case bs_ready:
|
||||
if (symbol == ESC)
|
||||
return setState(bs_skip, RESULT_ERR_ESC);
|
||||
if (m_sendPos < 0 && sentSymbol != SYN) {
|
||||
if (m_request != NULL && sending == true) {
|
||||
// check arbitration
|
||||
if (symbol == sentSymbol) { // arbitration successful
|
||||
if (m_requests.remove(startRequest) == false) {
|
||||
sentSymbol = SYN; // try again later // TODO error: send failed, abort send
|
||||
} else {
|
||||
m_request = startRequest;
|
||||
m_sendPos = 0;
|
||||
if (recvSymbol == sendSymbol) { // arbitration successful
|
||||
if (m_requests.remove(m_request) == false) {
|
||||
// request already timed out
|
||||
m_request = NULL;
|
||||
return setState(bs_sendSyn, RESULT_ERR_TIMEOUT);
|
||||
}
|
||||
} else { // arbitration lost
|
||||
sentSymbol = SYN; // try again later // TODO error: lost arbitration
|
||||
m_nextSendPos = 1;
|
||||
m_repeat = false;
|
||||
return setState(bs_sendCmd, RESULT_OK);
|
||||
}
|
||||
// arbitration lost
|
||||
setState(m_state, RESULT_ERR_BUS_LOST); // try again later
|
||||
}
|
||||
result = m_command.push_back(symbol);
|
||||
result = m_command.push_back(recvSymbol, false); // expect no escaping for master address
|
||||
if (result < RESULT_OK)
|
||||
return setState(bs_skip, result);
|
||||
|
||||
return setState(bs_command, RESULT_OK);
|
||||
m_repeat = false;
|
||||
return setState(bs_recvCmd, RESULT_OK);
|
||||
|
||||
case bs_command:
|
||||
case bs_recvCmd:
|
||||
headerLen = 4;
|
||||
crcPos = m_command.size() > headerLen ? headerLen + 1 + m_command[headerLen] : 0xff;
|
||||
result = m_command.push_back(symbol, true, m_command.size() < crcPos);
|
||||
result = m_command.push_back(recvSymbol, true, m_command.size() < crcPos);
|
||||
if (result < RESULT_OK)
|
||||
return setState(bs_skip, result);
|
||||
|
||||
if (result == RESULT_OK && m_command.size() == crcPos + 1) { // CRC received
|
||||
if (result == RESULT_OK && crcPos != 0xff && m_command.size() == crcPos + 1) { // CRC received
|
||||
unsigned char dstAddress = m_command[1];
|
||||
//if (isValidAddress(dstAddress) == false || isMaster(m_command[0]) == false)
|
||||
// return setState(bs_skip, RESULT_ERR_INVALID_ADDR);
|
||||
|
||||
m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC();
|
||||
if (m_command[1] == BROADCAST) {
|
||||
if (m_commandCrcValid) {
|
||||
if (m_commandCrcValid) {
|
||||
if (dstAddress == BROADCAST) {
|
||||
transferCompleted(tt_broadcast);
|
||||
return setState(bs_skip, RESULT_OK);
|
||||
}
|
||||
//if (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)
|
||||
// return setState(bs_sendCmdAck, RESULT_OK);
|
||||
|
||||
return setState(bs_skip, RESULT_ERR_CRC);
|
||||
return setState(bs_recvCmdAck, RESULT_OK);
|
||||
}
|
||||
/*if (m_command[1] == m_ownSlaveAddress || m_command[1] == m_ownMasterAddress) {
|
||||
setState(bs_commandAck, RESULT_OK);
|
||||
m_sendPos = 0;
|
||||
symbol = m_commandCrcValid ? ACK : NAK;
|
||||
if (m_port->send(&symbol) <= 0)
|
||||
return setState(bs_skip, RESULT_ERR_SEND);
|
||||
}*/
|
||||
return setState(bs_commandAck, RESULT_OK);
|
||||
if (dstAddress == BROADCAST)
|
||||
return setState(bs_skip, RESULT_OK);
|
||||
|
||||
//if (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)
|
||||
// return setState(bs_sendCmdAck, RESULT_ERR_CRC);
|
||||
if (m_repeat == true)
|
||||
return setState(bs_skip, RESULT_ERR_CRC);
|
||||
return setState(bs_recvCmdAck, RESULT_ERR_CRC);
|
||||
}
|
||||
return RESULT_OK;
|
||||
|
||||
case bs_commandAck:
|
||||
if (symbol == ESC)
|
||||
return setState(bs_skip, RESULT_ERR_ESC);
|
||||
/*if (m_sendPos >= 0) {
|
||||
if (symbol == ACK && m_commandCrcValid == true)
|
||||
return setState();
|
||||
|
||||
return setState()
|
||||
}*/
|
||||
if (symbol == ACK) {
|
||||
case bs_recvCmdAck:
|
||||
if (recvSymbol == ACK) {
|
||||
if (m_commandCrcValid == false)
|
||||
return setState(bs_skip, RESULT_ERR_ACK);
|
||||
|
||||
if (isMaster(m_command[1]) == true) {
|
||||
if (m_request != NULL) {
|
||||
if (isMaster(m_request->m_master[1]) == true) {
|
||||
transferCompleted(tt_masterMaster);
|
||||
return setState(bs_sendSyn, RESULT_OK);
|
||||
}
|
||||
} else if (isMaster(m_command[1]) == true) {
|
||||
transferCompleted(tt_masterMaster);
|
||||
return setState(bs_skip, RESULT_OK);
|
||||
}
|
||||
|
||||
return setState(bs_response, RESULT_OK);
|
||||
m_repeat = false;
|
||||
return setState(bs_recvRes, RESULT_OK);
|
||||
}
|
||||
if (symbol == NAK) {
|
||||
if (recvSymbol == NAK) {
|
||||
if (m_repeat == false) {
|
||||
m_repeat = true;
|
||||
return setState(bs_ready, RESULT_ERR_NAK);
|
||||
m_nextSendPos = 0;
|
||||
m_command.clear();
|
||||
if (m_request != NULL)
|
||||
return setState(bs_sendCmd, RESULT_ERR_NAK);
|
||||
|
||||
return setState(bs_recvCmd, RESULT_ERR_NAK);
|
||||
}
|
||||
if (m_request != NULL)
|
||||
return setState(bs_sendSyn, RESULT_ERR_NAK);
|
||||
|
||||
return setState(bs_skip, RESULT_ERR_NAK);
|
||||
}
|
||||
if (m_request != NULL)
|
||||
return setState(bs_sendSyn, RESULT_ERR_ACK);
|
||||
|
||||
return setState(bs_skip, RESULT_ERR_ACK);
|
||||
|
||||
case bs_response:
|
||||
case bs_recvRes:
|
||||
headerLen = 0;
|
||||
crcPos = m_response.size() > headerLen ? headerLen + 1 + m_response[headerLen] : 0xff;
|
||||
result = m_response.push_back(symbol, true, m_response.size() < crcPos);
|
||||
if (result < RESULT_OK)
|
||||
return setState(bs_skip, result);
|
||||
result = m_response.push_back(recvSymbol, true, m_response.size() < crcPos);
|
||||
if (result < RESULT_OK) {
|
||||
if (m_request != NULL)
|
||||
return setState(bs_sendSyn, result);
|
||||
|
||||
if (result == RESULT_OK && m_response.size() == crcPos + 1) { // CRC received
|
||||
return setState(bs_skip, result);
|
||||
}
|
||||
if (result == RESULT_OK && crcPos != 0xff && m_response.size() == crcPos + 1) { // CRC received
|
||||
m_responseCrcValid = m_response[headerLen + 1 + m_response[headerLen]] == m_response.getCRC();
|
||||
/*if (m_command[1] == m_ownSlaveAddress || m_command[1] == m_ownMasterAddress) {
|
||||
setState(bs_responseAck, RESULT_OK);
|
||||
m_sendPos = 0;
|
||||
symbol = m_responseCrcValid ? ACK : NAK;
|
||||
if (m_port->send(&symbol) <= 0)
|
||||
return setState(bs_skip, RESULT_ERR_SEND);
|
||||
}*/
|
||||
return setState(bs_responseAck, RESULT_OK);
|
||||
if (m_responseCrcValid) {
|
||||
if (m_request != NULL)
|
||||
return setState(bs_sendResAck, RESULT_OK);
|
||||
|
||||
return setState(bs_recvResAck, RESULT_OK);
|
||||
}
|
||||
if (m_repeat == true) {
|
||||
if (m_request != NULL)
|
||||
return setState(bs_sendSyn, RESULT_ERR_CRC);
|
||||
|
||||
return setState(bs_skip, RESULT_ERR_CRC);
|
||||
}
|
||||
if (m_request != NULL)
|
||||
return setState(bs_sendResAck, RESULT_ERR_CRC);
|
||||
|
||||
return setState(bs_recvResAck, RESULT_ERR_CRC);
|
||||
}
|
||||
return RESULT_OK;
|
||||
|
||||
case bs_responseAck:
|
||||
if (symbol == ESC)
|
||||
return setState(bs_skip, RESULT_ERR_ESC);
|
||||
/*if (m_sendPos >= 0) {
|
||||
if (symbol == ACK && m_responseCrcValid == true)
|
||||
return setState();
|
||||
|
||||
return setState()
|
||||
}*/
|
||||
if (symbol == ACK) {
|
||||
case bs_recvResAck:
|
||||
if (recvSymbol == ACK) {
|
||||
if (m_responseCrcValid == false)
|
||||
return setState(bs_skip, RESULT_ERR_ACK);
|
||||
|
||||
transferCompleted(tt_masterSlave);
|
||||
return setState(bs_skip, RESULT_OK);
|
||||
}
|
||||
if (symbol == NAK) {
|
||||
if (recvSymbol == NAK) {
|
||||
if (m_repeat == false) {
|
||||
m_repeat = true;
|
||||
return setState(bs_response, RESULT_ERR_NAK);
|
||||
m_response.clear();
|
||||
return setState(bs_recvRes, RESULT_ERR_NAK);
|
||||
}
|
||||
return setState(bs_skip, RESULT_ERR_NAK);
|
||||
}
|
||||
return setState(bs_skip, RESULT_ERR_ACK);
|
||||
|
||||
case bs_sendCmd:
|
||||
if (m_request != NULL && sending == true) {
|
||||
if (recvSymbol == sendSymbol) {
|
||||
// successfully sent
|
||||
m_nextSendPos++;
|
||||
if (m_nextSendPos >= m_request->m_master.size()) {
|
||||
// master data completely sent
|
||||
if (m_request->m_master[1] == BROADCAST)
|
||||
return setState(bs_sendSyn, RESULT_OK);
|
||||
|
||||
m_commandCrcValid = true;
|
||||
return setState(bs_recvCmdAck, RESULT_OK);
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
}
|
||||
return setState(bs_sendSyn, RESULT_ERR_INVALID_ARG);
|
||||
|
||||
case bs_sendResAck:
|
||||
if (m_request != NULL && sending == true) {
|
||||
if (recvSymbol == sendSymbol) {
|
||||
// successfully sent
|
||||
return setState(bs_sendSyn, RESULT_OK);
|
||||
}
|
||||
}
|
||||
return setState(bs_sendSyn, RESULT_ERR_INVALID_ARG);
|
||||
|
||||
case bs_sendSyn:
|
||||
if (sending == true) {
|
||||
if (recvSymbol == sendSymbol) {
|
||||
// successfully sent
|
||||
return setState(bs_skip, RESULT_OK);
|
||||
}
|
||||
}
|
||||
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
|
||||
|
||||
}
|
||||
|
||||
return RESULT_OK;
|
||||
@@ -330,18 +410,27 @@ result_t BusHandler::setState(BusState state, result_t result)
|
||||
return result;
|
||||
|
||||
if (result < RESULT_OK || (result != RESULT_OK && state == bs_skip))
|
||||
L.log(bus, error, " %s during %s, switching to %s", getResultCode(result), getStateCode(m_state, m_sendPos), getStateCode(state, m_sendPos));
|
||||
L.log(bus, error, " %s during %s, switching to %s", getResultCode(result), getStateCode(m_state), getStateCode(state));
|
||||
|
||||
m_state = state;
|
||||
if (m_request != NULL) {
|
||||
if (state == bs_sendSyn) {
|
||||
m_request->m_slave = m_response; // TODO nicer
|
||||
m_request->notify(result);
|
||||
m_request = NULL;
|
||||
} else if (result != RESULT_OK) {
|
||||
m_request->notify(result);
|
||||
m_request = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == bs_ready || state == bs_skip) {
|
||||
m_command.clear();
|
||||
m_commandCrcValid = false;
|
||||
m_response.clear();
|
||||
m_responseCrcValid = false;
|
||||
m_sendPos = -1;
|
||||
m_nextSendPos = 0;
|
||||
}
|
||||
if (state == bs_skip)
|
||||
m_repeat = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -367,7 +456,7 @@ void BusHandler::transferCompleted(TransferType type)
|
||||
ostringstream output;
|
||||
result_t result = msg->decode(m_command, m_response, output);
|
||||
if (result != RESULT_OK)
|
||||
L.log(bus, error, "unable to parse %s %s: %s", msg->getClass().c_str(), msg->getName().c_str(), getResultCode(result));
|
||||
L.log(bus, error, "unable to parse %s %s from %s / %s: %s", msg->getClass().c_str(), msg->getName().c_str(), m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result));
|
||||
else
|
||||
L.log(bus, trace, "%s %s: %s", msg->getClass().c_str(), msg->getName().c_str(), output.str().c_str());
|
||||
}
|
||||
|
||||
+42
-26
@@ -36,18 +36,22 @@ using namespace std;
|
||||
|
||||
/** the maximum allowed time [us] for retrieval of a single symbol from an addressed slave. */
|
||||
#define SLAVE_RECV_TIMEOUT 10000
|
||||
/** the maximum allowed time [us] for retrieval of an AUTO-SYN symbol. */
|
||||
/** the maximum allowed time [us] for retrieval of an AUTO-SYN symbol (should be generated in <45ms). */
|
||||
#define SYN_TIMEOUT 50000
|
||||
|
||||
/** the possible bus states. */
|
||||
enum BusState {
|
||||
bs_skip, // skip all symbols until next @a SYN
|
||||
bs_ready, // ready for next master (after @a SYN symbol, send/receive QQ)
|
||||
bs_command, // receive/send command (ZZ, PBSB, master data)
|
||||
bs_commandAck, // receive/send command ACK/NACK
|
||||
bs_response, // receive/send response (slave data)
|
||||
bs_responseAck, // receive/send response ACK/NACK
|
||||
//bs_validTransfer,// completed a valid message transfer
|
||||
bs_skip, // skip all symbols until next @a SYN
|
||||
bs_ready, // ready for next master (after @a SYN symbol, send/receive QQ)
|
||||
bs_recvCmd, // receive command (ZZ, PBSB, master data) [passive set]
|
||||
bs_recvCmdAck, // receive command ACK/NACK [passive set + active set+get]
|
||||
bs_recvRes, // receive response (slave data) [passive set + active get]
|
||||
bs_recvResAck, // receive response ACK/NACK [passive set]
|
||||
bs_sendCmd, // send command (ZZ, PBSB, master data) [active set+get]
|
||||
bs_sendResAck, // send response ACK/NACK [active get]
|
||||
// bs_sendRes, // send response (slave data) [passive get] // TODO implement
|
||||
// bs_sendCmdAck, // send command ACK/NACK [passive get] // TODO implement
|
||||
bs_sendSyn, // send SYN for completed transfer [active set+get]
|
||||
};
|
||||
|
||||
/** the possible message transfer types. */
|
||||
@@ -62,9 +66,9 @@ enum MessageDirection {
|
||||
md_thisToAll, // message from us to all (broadcast)
|
||||
md_thisToMaster, // message from us to another master
|
||||
md_thisToSlave, // message from us to another slave
|
||||
md_otherToAll, // message from a master (other than us) to all (broadcast): @a bs_ready, @a bs_recvCmd
|
||||
md_otherToMaster, // message from a master (other than us) to another master (other than us): @a bs_ready, @a bs_recvCmd, @a bs_recvAck
|
||||
md_otherToSlave, // message from a master (other than us) to another slave (other than us): @a bs_ready, @a bs_recvCmd, @a bs_recvAck, @a bs_recvResp, @a bs_recvAck
|
||||
md_otherToAll, // message from a master (other than us) to all (broadcast)
|
||||
md_otherToMaster, // message from a master (other than us) to another master (other than us)
|
||||
md_otherToSlave, // message from a master (other than us) to another slave (other than us)
|
||||
md_otherToThisMaster, // message from a master (other than us) to us (as master)
|
||||
md_otherToThisSlave, // message from a master (other than us) to us (as slave)
|
||||
md_undefined,
|
||||
@@ -72,6 +76,9 @@ enum MessageDirection {
|
||||
|
||||
class BusHandler;
|
||||
|
||||
/**
|
||||
* @brief Handles input from and output to the bus with respect to the ebus protocol.
|
||||
*/
|
||||
class BusRequest
|
||||
{
|
||||
friend class BusHandler;
|
||||
@@ -79,6 +86,8 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
* @param master the master data @a SymbolString to send.
|
||||
* @param slave the slave data @a SymbolString received.
|
||||
*/
|
||||
BusRequest(SymbolString& master, SymbolString& slave);
|
||||
|
||||
@@ -96,16 +105,22 @@ public:
|
||||
/**
|
||||
* @brief Notify all waiting threads.
|
||||
*/
|
||||
void notify(bool finished);
|
||||
void notify(result_t result);
|
||||
|
||||
private:
|
||||
|
||||
/** the master data @a SymbolString to send. */
|
||||
SymbolString& m_master;
|
||||
|
||||
/** the slave data @a SymbolString received. */
|
||||
SymbolString& m_slave;
|
||||
|
||||
/** true once the request is finished. */
|
||||
bool m_finished;
|
||||
|
||||
/** the result of handling the request. */
|
||||
result_t m_result;
|
||||
|
||||
/** a mutex for wait/notify. */
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
@@ -132,8 +147,9 @@ public:
|
||||
BusHandler(Port* port, MessageMap* messages, unsigned char ownMasterAddress,
|
||||
unsigned char ownSlaveAddress)
|
||||
: m_port(port), m_messages(messages), m_ownMasterAddress(ownMasterAddress),
|
||||
m_ownSlaveAddress(ownSlaveAddress), m_state(bs_skip), m_repeat(false),
|
||||
m_sendPos(-1), m_commandCrcValid(false), m_responseCrcValid(false), m_request(NULL) {}
|
||||
m_ownSlaveAddress(ownSlaveAddress), m_request(NULL), m_nextSendPos(0),
|
||||
m_state(bs_skip), m_repeat(false),
|
||||
m_commandCrcValid(false), m_responseCrcValid(false) {}
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
@@ -155,10 +171,10 @@ public:
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Receive another symbol from the bus.
|
||||
* @brief Handle the next symbol on the bus.
|
||||
* @return RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t receiveSymbol();
|
||||
result_t handleSymbol();
|
||||
|
||||
/**
|
||||
* @brief Set a new @a BusState and add a log message if necessary.
|
||||
@@ -186,18 +202,22 @@ private:
|
||||
/** the own slave address to react on master-slave messages, or @a SYN to ignore. */
|
||||
unsigned char m_ownSlaveAddress;
|
||||
|
||||
/** the queue of @a BusRequests that shall be handled. */
|
||||
WQueue<BusRequest*> m_requests;
|
||||
|
||||
/** the currently handled BusRequest, or NULL. */
|
||||
BusRequest* m_request;
|
||||
|
||||
/** the offset of the next symbol that needs to be sent from the command or response,
|
||||
* (only relevant if m_request is set and state is bs_command or bs_response). */
|
||||
unsigned char m_nextSendPos;
|
||||
|
||||
/** the current @a BusState. */
|
||||
BusState m_state;
|
||||
|
||||
/** whether the current message part is being repeated. */
|
||||
bool m_repeat;
|
||||
|
||||
/*
|
||||
* the offset of the last sent symbol while sending command/response,
|
||||
* or 0 while sending ACK/NACK, or -1 if not sending.
|
||||
*/
|
||||
int m_sendPos;
|
||||
|
||||
/** the received/sent command. */
|
||||
SymbolString m_command;
|
||||
|
||||
@@ -210,10 +230,6 @@ private:
|
||||
/** whether the response CRC is valid. */
|
||||
bool m_responseCrcValid;
|
||||
|
||||
WQueue<BusRequest*> m_requests;
|
||||
|
||||
BusRequest* m_request;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user